1 | #pragma rtGlobals=1 // Use modern global access method. |
---|
2 | #pragma version=5.0 |
---|
3 | #pragma IgorVersion=4.0 |
---|
4 | |
---|
5 | |
---|
6 | //******************** |
---|
7 | // Vers. 1.2 092101 |
---|
8 | // |
---|
9 | // Procedures to create a "DIV" file for use as a detector sensitivity file |
---|
10 | // Follows the same procedure as PRODIV on the VAX |
---|
11 | // -requires two "full" reduced runs from plexiglass or water |
---|
12 | // -prompts the user for the locations of the offset and no-offset files |
---|
13 | // and for the range of data to replace |
---|
14 | // - then writes of the "div" file and fake-VAX format, which is rather ugly |
---|
15 | // since the DIV file is floating point... |
---|
16 | // |
---|
17 | // |
---|
18 | // 08 AUG 03 |
---|
19 | // allowed for creation of DIV files on 8m SANS with two beamstops |
---|
20 | // |
---|
21 | // JAN2006 - not modified! still hard-wired to take a 128x128 detector image |
---|
22 | // |
---|
23 | //********************* |
---|
24 | |
---|
25 | //writes an VAX-style WORK file, "exactly" as it would be output from the VAX |
---|
26 | //except for the "dummy" header and the record markers - the record marker bytes are |
---|
27 | // in the files - they are just written as zeros and are meaningless |
---|
28 | //file is: |
---|
29 | // 516 bytes header |
---|
30 | // 128x128=16384 (x4) bytes of data |
---|
31 | // + 2 byte record markers interspersed just for fun |
---|
32 | // = 66116 bytes |
---|
33 | //prompts for name of the output file. |
---|
34 | // |
---|
35 | Function WriteVAXWorkFile(type) |
---|
36 | String type |
---|
37 | |
---|
38 | Wave data=$("root:"+type+":data") |
---|
39 | |
---|
40 | Variable refnum,ii=0,hdrBytes=516,a,b,offset |
---|
41 | String fullpath="" |
---|
42 | |
---|
43 | Duplicate/O data,tempData |
---|
44 | Redimension/S/N=(128*128) tempData |
---|
45 | tempData *= 4 |
---|
46 | |
---|
47 | Open/D refnum as fullpath //won't actually open the file |
---|
48 | If(cmpstr(S_filename,"")==0) |
---|
49 | //user cancel, don't write out a file |
---|
50 | Close/A |
---|
51 | Abort "no data file was written" |
---|
52 | Endif |
---|
53 | fullpath = S_filename |
---|
54 | |
---|
55 | Make/B/O/N=(hdrBytes) hdrWave |
---|
56 | hdrWave=0 |
---|
57 | FakeDIVHeader(hdrWave) |
---|
58 | |
---|
59 | Make/Y=2/O/N=(510) bw510 //Y=2 specifies 32 bit (=4 byte) floating point |
---|
60 | Make/Y=2/O/N=(511) bw511 |
---|
61 | Make/Y=2/O/N=(48) bw48 |
---|
62 | |
---|
63 | Make/O/B/N=2 recWave //two bytes |
---|
64 | |
---|
65 | //actually open the file |
---|
66 | Open/C="????"/T="TEXT" refNum as fullpath |
---|
67 | FSetPos refNum, 0 |
---|
68 | //write header bytes (to be skipped when reading the file later) |
---|
69 | |
---|
70 | FBinWrite /F=1 refnum,hdrWave |
---|
71 | |
---|
72 | ii=0 |
---|
73 | a=0 |
---|
74 | do |
---|
75 | //write 511 4-byte values (little-endian order), 4* true value |
---|
76 | bw511[] = tempData[p+a] |
---|
77 | FBinWrite /B=3/F=4 refnum,bw511 |
---|
78 | a+=511 |
---|
79 | //write a 2-byte record marker |
---|
80 | FBinWrite refnum,recWave |
---|
81 | |
---|
82 | //write 510 4-byte values (little-endian) 4* true value |
---|
83 | bw510[] = tempData[p+a] |
---|
84 | FBinWrite /B=3/F=4 refnum,bw510 |
---|
85 | a+=510 |
---|
86 | |
---|
87 | //write a 2-byte record marker |
---|
88 | FBinWrite refnum,recWave |
---|
89 | |
---|
90 | ii+=1 |
---|
91 | while(ii<16) |
---|
92 | //write out last 48 4-byte values (little-endian) 4* true value |
---|
93 | bw48[] = tempData[p+a] |
---|
94 | FBinWrite /B=3/F=4 refnum,bw48 |
---|
95 | //close the file |
---|
96 | Close refnum |
---|
97 | |
---|
98 | //go back through and make it look like a VAX datafile |
---|
99 | Make/W/U/O/N=(511*2) int511 // /W=16 bit signed integers /U=unsigned |
---|
100 | Make/W/U/O/N=(510*2) int510 |
---|
101 | Make/W/U/O/N=(48*2) int48 |
---|
102 | |
---|
103 | //skip the header for now |
---|
104 | Open/A/T="????TEXT" refnum as fullPath |
---|
105 | FSetPos refnum,0 |
---|
106 | |
---|
107 | offset=hdrBytes |
---|
108 | ii=0 |
---|
109 | do |
---|
110 | //511*2 integers |
---|
111 | FSetPos refnum,offset |
---|
112 | FBinRead/B=2/F=2 refnum,int511 |
---|
113 | Swap16BWave(int511) |
---|
114 | FSetPos refnum,offset |
---|
115 | FBinWrite/B=2/F=2 refnum,int511 |
---|
116 | |
---|
117 | //skip 511 4-byte FP = (511*2)*2 2byte int + 2 bytes record marker |
---|
118 | offset += 511*2*2 + 2 |
---|
119 | |
---|
120 | //510*2 integers |
---|
121 | FSetPos refnum,offset |
---|
122 | FBinRead/B=2/F=2 refnum,int510 |
---|
123 | Swap16BWave(int510) |
---|
124 | FSetPos refnum,offset |
---|
125 | FBinWrite/B=2/F=2 refnum,int510 |
---|
126 | |
---|
127 | // |
---|
128 | offset += 510*2*2 + 2 |
---|
129 | |
---|
130 | ii+=1 |
---|
131 | while(ii<16) |
---|
132 | //48*2 integers |
---|
133 | FSetPos refnum,offset |
---|
134 | FBinRead/B=2/F=2 refnum,int48 |
---|
135 | Swap16BWave(int48) |
---|
136 | FSetPos refnum,offset |
---|
137 | FBinWrite/B=2/F=2 refnum,int48 |
---|
138 | |
---|
139 | //move to EOF and close |
---|
140 | FStatus refnum |
---|
141 | FSetPos refnum,V_logEOF |
---|
142 | |
---|
143 | Close refnum |
---|
144 | |
---|
145 | Killwaves/Z hdrWave,bw48,bw511,bw510,recWave,temp16,int511,int510,int48 |
---|
146 | End |
---|
147 | |
---|
148 | // given a 16 bit integer wave, read in as 2-byte pairs of 32-bit FP data |
---|
149 | // swap the order of the 2-byte pairs |
---|
150 | // |
---|
151 | Function Swap16BWave(w) |
---|
152 | Wave w |
---|
153 | |
---|
154 | Duplicate/O w,temp16 |
---|
155 | //Variable num=numpnts(w),ii=0 |
---|
156 | |
---|
157 | //elegant way to swap even/odd values, using wave assignments |
---|
158 | w[0,*;2] = temp16[p+1] |
---|
159 | w[1,*;2] = temp16[p-1] |
---|
160 | |
---|
161 | //crude way, using a loop |
---|
162 | // for(ii=0;ii<num;ii+=2) |
---|
163 | // w[ii] = temp16[ii+1] |
---|
164 | // w[ii+1] = temp16[ii] |
---|
165 | // endfor |
---|
166 | |
---|
167 | return(0) |
---|
168 | End |
---|
169 | |
---|
170 | // writes a fake label into the header of the DIV file |
---|
171 | // |
---|
172 | Function FakeDIVHeader(hdrWave) |
---|
173 | WAVE hdrWave |
---|
174 | |
---|
175 | //put some fake text into the sample label position (60 characters=60 bytes) |
---|
176 | String day=date(),tim=time(),lbl="" |
---|
177 | Variable start=98,num,ii |
---|
178 | |
---|
179 | lbl = "Sensitivity (DIV) created "+day +" "+tim |
---|
180 | num=strlen(lbl) |
---|
181 | for(ii=0;ii<num;ii+=1) |
---|
182 | hdrWave[start+ii] = char2num(lbl[ii]) |
---|
183 | endfor |
---|
184 | |
---|
185 | return(0) |
---|
186 | End |
---|
187 | |
---|
188 | //works on the data in "type" folder |
---|
189 | //sums all of the data, and normalizes by the number of cells (=128*128) |
---|
190 | // calling procedure must make sure that the folder is on linear scale FIRST |
---|
191 | Function NormalizeDIV(type) |
---|
192 | String type |
---|
193 | |
---|
194 | WAVE data=$("root:"+type+":data") |
---|
195 | Variable totCts=sum(data,Inf,-Inf) //sum all of the data |
---|
196 | |
---|
197 | data /= totCts |
---|
198 | data *= 128*128 |
---|
199 | |
---|
200 | return(0) |
---|
201 | End |
---|
202 | |
---|
203 | // prompts the user for the location of the "COR" -level data |
---|
204 | // data can be copied to any data folder (except DIV) for use here... |
---|
205 | // |
---|
206 | // then there is a "pause for user" to allow the user to select the "box" |
---|
207 | // in the ON-AXIS datset that is to be replaced by the data in the off-axis data |
---|
208 | // |
---|
209 | // corrections are done... |
---|
210 | // |
---|
211 | // finally, the DIV file is written to disk |
---|
212 | Function MakeDIVFile(ctrType,offType) |
---|
213 | String ctrType,offType |
---|
214 | |
---|
215 | Prompt ctrType,"On-Center Plex data (corrected)",popup,"STO;SUB;BGD;COR;CAL;SAM;EMP;" |
---|
216 | Prompt offType,"Offset Plex data (corrected)",popup,"STO;SUB;BGD;COR;CAL;SAM;EMP;" |
---|
217 | DoPrompt "Pick the data types",ctrType,offType |
---|
218 | //"COR" data in both places - reduction must be done ahead of time |
---|
219 | |
---|
220 | //temporarily set data display to linear |
---|
221 | NVAR gLog = root:myGlobals:gLogScalingAsDefault |
---|
222 | Variable oldState = gLog |
---|
223 | gLog=0 //linear |
---|
224 | |
---|
225 | if(V_Flag==1) |
---|
226 | //user cancelled |
---|
227 | return(1) |
---|
228 | endif |
---|
229 | |
---|
230 | //show the ctrType |
---|
231 | //get the xy range to replace |
---|
232 | Execute "ChangeDisplay(\""+ctrType+"\")" |
---|
233 | |
---|
234 | NewPanel/K=2/W=(139,341,382,432) as "Get XY Range" |
---|
235 | DoWindow/C tmp_GetXY |
---|
236 | AutoPositionWindow/E/M=1/R=SANS_Data |
---|
237 | DrawText 15,20,"Find the (X1,X2) and (Y1,Y2) range to" |
---|
238 | DrawText 15,40,"replace and press continue" |
---|
239 | Button button0, pos={80,58},size={92,20},title="Continue" |
---|
240 | Button button0,proc=XYContinueButtonProc |
---|
241 | |
---|
242 | PauseForUser tmp_GetXY,SANS_Data |
---|
243 | |
---|
244 | //replace the center section of the "on" data with the center of the "off" data |
---|
245 | Variable x1,x2,y1,y2 |
---|
246 | GetXYRange(x1,x2,y1,y2) |
---|
247 | Printf "X=(%d,%d) Y=(%d,%d)\r", x1,x2,y1,y2 |
---|
248 | ReplaceDataBlock(ctrType,offType,x1,x2,y1,y2) |
---|
249 | |
---|
250 | DoAlert 1,"Is this NG1 data with a second beamstop?" |
---|
251 | if(V_flag==1) |
---|
252 | GetXYRange(x1,x2,y1,y2) |
---|
253 | Printf "X=(%d,%d) Y=(%d,%d)\r", x1,x2,y1,y2 |
---|
254 | ReplaceDataBlock(ctrType,offType,x1,x2,y1,y2) |
---|
255 | endif |
---|
256 | |
---|
257 | //normalize the new data (and show it) |
---|
258 | NormalizeDiv(ctrtype) |
---|
259 | UpdateDisplayInformation(ctrtype) |
---|
260 | //write out the new data file |
---|
261 | WriteVAXWorkFile(ctrtype) |
---|
262 | gLog = oldState //set log/lin pref back to user - set preference |
---|
263 | Return(0) |
---|
264 | End |
---|
265 | |
---|
266 | //ctrData is changed -- offData is not touched |
---|
267 | //simple replacement of the selected data... |
---|
268 | // |
---|
269 | Function ReplaceDataBlock(ctrType,offType,x1,x2,y1,y2) |
---|
270 | String ctrType,offType |
---|
271 | Variable x1,x2,y1,y2 |
---|
272 | |
---|
273 | //do it crudely, with nested for loops |
---|
274 | WAVE ctrData=$("root:"+ctrtype+":data") |
---|
275 | WAVE offData=$("root:"+offtype+":data") |
---|
276 | Variable ii,jj |
---|
277 | |
---|
278 | for(ii=x1;ii<=x2;ii+=1) |
---|
279 | for(jj=y1;jj<=y2;jj+=1) |
---|
280 | ctrData[ii][jj] = offData[ii][jj] |
---|
281 | endfor |
---|
282 | endfor |
---|
283 | |
---|
284 | return(0) |
---|
285 | End |
---|
286 | |
---|
287 | //continue button waiting for the user to pick the range, and continue the execution |
---|
288 | // |
---|
289 | Function XYContinueButtonProc(ctrlName) |
---|
290 | String ctrlName |
---|
291 | |
---|
292 | DoWindow/K tmp_GetXY |
---|
293 | End |
---|
294 | |
---|
295 | // prompts the user to enter the XY range for the box replacement |
---|
296 | // user can get these numbers by printing out marquee coordinates to the command window |
---|
297 | // |
---|
298 | Function GetXYRange(x1,x2,y1,y2) |
---|
299 | Variable &x1,&x2,&y1,&y2 |
---|
300 | |
---|
301 | Variable x1p,x2p,y1p,y2p |
---|
302 | Prompt x1p,"X1" |
---|
303 | Prompt x2p,"X2" |
---|
304 | Prompt y1p,"Y1" |
---|
305 | Prompt y2p,"Y2" |
---|
306 | DoPrompt "Enter the range to replace",x1p,x2p,y1p,y2p |
---|
307 | x1=x1p |
---|
308 | x2=x2p |
---|
309 | y1=y1p |
---|
310 | y2=y2p |
---|
311 | |
---|
312 | // Print x1,x2,y1,y2 |
---|
313 | Return(0) |
---|
314 | End |
---|