1 | #pragma rtGlobals=1 // Use modern global access method. |
---|
2 | |
---|
3 | // utility functions and procedures for displaying information |
---|
4 | // setting the matrix, and doing the calculations |
---|
5 | // |
---|
6 | |
---|
7 | |
---|
8 | |
---|
9 | /////////// |
---|
10 | // |
---|
11 | // put the SLD multiplier on the panel somewhere - only 2 values are allowed - so use |
---|
12 | // radio buttons, or just display the value of the global, make the change at the command |
---|
13 | // line -- or keep the multiplier at 10^-7 and always use 2 digits |
---|
14 | // |
---|
15 | //////////// |
---|
16 | |
---|
17 | // |
---|
18 | |
---|
19 | //*********** |
---|
20 | //For a 3D slicer view of dmat: |
---|
21 | // |
---|
22 | //Duplicate/O dmat dmatView |
---|
23 | // |
---|
24 | //Open a New 3D voxelgram. Don't set any of the levels |
---|
25 | //Open the 3D Slicer under the Gizmo menu |
---|
26 | //Make the X, Y, and Z slices |
---|
27 | //(Yellow Hot seems to be the best) |
---|
28 | // |
---|
29 | //// for a better view |
---|
30 | //dmatView = log(dmat) |
---|
31 | // |
---|
32 | //// if it all goes blank after the log transform get rid of the INF |
---|
33 | //dmatView = numtype(dmatView)== 0 ? dmatView : 0 |
---|
34 | //************* |
---|
35 | |
---|
36 | |
---|
37 | ///PANEL |
---|
38 | ///// panel procedures |
---|
39 | |
---|
40 | Proc Init_FFT() |
---|
41 | DoWindow/F FFT_Panel |
---|
42 | if(V_flag==0) |
---|
43 | SetDataFolder root: |
---|
44 | //init the globals |
---|
45 | Variable/G root:FFT_N=128 |
---|
46 | Variable/G root:FFT_T=5 |
---|
47 | Variable/G root:FFT_Qmax = 0 |
---|
48 | Variable/G root:FFT_QmaxReal = 0 |
---|
49 | Variable/G root:FFT_DQ=0 |
---|
50 | Variable/G root:FFT_estTime = 0 |
---|
51 | |
---|
52 | Variable/G root:FFT_SolventSLD = 0 |
---|
53 | Variable/G root:FFT_delRho = 1e-6 //multiplier for SLD (other value is 1e-7) |
---|
54 | |
---|
55 | FFT_Qmax :=2*pi/FFT_T |
---|
56 | FFT_QmaxReal := FFT_Qmax/2 |
---|
57 | FFT_DQ := pi/(FFT_N*FFT_T) |
---|
58 | //empirical fit (cubic) of time vs N=50 to N=256 |
---|
59 | FFT_estTime := 0.56 - 0.0156*FFT_N + 0.000116*FFT_N^2 + 8e-7*FFT_N^3 |
---|
60 | // FFT_estTime := FFT_N/128 |
---|
61 | |
---|
62 | FFT_Panel() |
---|
63 | endif |
---|
64 | End |
---|
65 | |
---|
66 | Proc FFT_Panel() |
---|
67 | PauseUpdate; Silent 1 // building window... |
---|
68 | NewPanel /W=(1452,44,1768,531)/K=1 as "FFT_Panel" |
---|
69 | DoWindow/C FFT_Panel |
---|
70 | SetDrawLayer UserBack |
---|
71 | DrawLine 5,68,311,68 |
---|
72 | DrawLine 5,142,311,142 |
---|
73 | DrawLine 5,250,311,250 |
---|
74 | SetVariable FFTSetVar_0,pos={7,7},size={150,15},title="Cells per edge (N)" |
---|
75 | SetVariable FFTSetVar_0,limits={50,512,2},value= FFT_N,live= 1 |
---|
76 | SetVariable FFTSetVar_1,pos={7,33},size={150,15},title="Length per Cell (T)" |
---|
77 | SetVariable FFTSetVar_1,limits={1,500,0.2},value= FFT_T,live= 1 |
---|
78 | SetVariable FFTSetVar_2,pos={183,26},size={120,15},title="Real Qmax" |
---|
79 | SetVariable FFTSetVar_2,limits={0,0,0},value= FFT_QmaxReal,noedit= 1,live= 1 |
---|
80 | SetVariable FFTSetVar_3,pos={183,48},size={120,15},title="delta Q (A)" |
---|
81 | SetVariable FFTSetVar_3,limits={0,0,0},value= FFT_DQ,noedit= 1,live= 1 |
---|
82 | Button FFTButton_0,pos={15,79},size={90,20},proc=FFT_MakeMatrixButtonProc,title="Make Matrix" |
---|
83 | Button FFTButton_1,pos={14,157},size={90,20},proc=FFTMakeGizmoButtonProc,title="Make Gizmo" |
---|
84 | Button FFTButton_2,pos={14,187},size={100,20},proc=FFTDrawSphereButtonProc,title="Draw Sphere" |
---|
85 | Button FFTButton_3,pos={14,265},size={70,20},proc=DoTheFFT_ButtonProc,title="Do FFT" |
---|
86 | Button FFTButton_4,pos={191,264},size={110,20},proc=FFT_PlotResultsButtonProc,title="Plot 1D Results" |
---|
87 | Button FFTButton_5,pos={13,218},size={120,20},proc=FFTDrawZCylinderButtonProc,title="Draw Cylinder" |
---|
88 | Button FFTButton_6,pos={134,79},size={90,20},proc=FFTEraseMatrixButtonProc,title="Erase Matrix" |
---|
89 | Button FFTButton_7,pos={13,329},size={130,20},proc=FFT_BinnedSpheresButtonProc,title="Do Binned Debye" |
---|
90 | Button FFTButton_8,pos={13,297},size={130,20},proc=FFT_AltiSpheresButtonProc,title="Do Debye Spheres" |
---|
91 | Button FFTButton_14,pos={13,360},size={130,20},proc=FFT_BinnedSLDButtonProc,title="Do Binned SLD" |
---|
92 | SetVariable FFTSetVar_4,pos={201,4},size={100,15},title="FFT time(s)" |
---|
93 | SetVariable FFTSetVar_4,limits={0,0,0},value= FFT_estTime,noedit= 1,live= 1,format="%d" |
---|
94 | Button FFTButton_9,pos={200,295},size={100,20},proc=FFT_Get2DSlice,title="Get Slice" |
---|
95 | Button FFTButton_10,pos={169,156},size={130,20},proc=FFT_TransposeMat,title="Transpose Matrix" |
---|
96 | Button FFTButton_11,pos={169,189},size={130,20},proc=FFT_RotateMat,title="Rotate Matrix" |
---|
97 | Button FFTButton_12,pos={168,219},size={130,20},proc=FFT_AddRotatedObject,title="Add Rotated Obj" |
---|
98 | Button FFTButton_13,pos={14,109},size={120,20},proc=FFTFillSolventMatrixProc,title="Solvent Matrix" |
---|
99 | SetVariable FFTSetVar_5,pos={155,111},size={100,15},title="Solvent SLD" |
---|
100 | SetVariable FFTSetVar_5,limits={-99,99,1},value= FFT_SolventSLD,live= 1 |
---|
101 | Button FFTButton_15,pos={209,327},size={90,20},proc=Interp2DSliceButton,title="Interp 2D" |
---|
102 | EndMacro |
---|
103 | |
---|
104 | Function Interp2DSliceButton(ba) : ButtonControl |
---|
105 | STRUCT WMButtonAction &ba |
---|
106 | |
---|
107 | switch( ba.eventCode ) |
---|
108 | case 2: // mouse up |
---|
109 | // click code here |
---|
110 | String folderStr="" |
---|
111 | Prompt folderStr, "Pick a 2D data folder" // Set prompt for x param |
---|
112 | DoPrompt "Enter data folder", folderStr |
---|
113 | if (V_Flag || strlen(folderStr) == 0) |
---|
114 | return -1 // User canceled, null string entered |
---|
115 | endif |
---|
116 | |
---|
117 | Interpolate2DSliceToData(folderStr) |
---|
118 | |
---|
119 | //display the 2D plane |
---|
120 | DoWindow FFT_Interp2D_log |
---|
121 | if(V_flag == 0) |
---|
122 | Execute "Display2DInterpSlice_log()" |
---|
123 | endif |
---|
124 | |
---|
125 | break |
---|
126 | endswitch |
---|
127 | |
---|
128 | return 0 |
---|
129 | End |
---|
130 | |
---|
131 | |
---|
132 | |
---|
133 | Function FFT_Get2DSlice(ctrlName) : ButtonControl |
---|
134 | String ctrlName |
---|
135 | |
---|
136 | WAVE/Z dmat = root:dmat |
---|
137 | if(WaveExists(dmat)==1) |
---|
138 | get2DSlice(dmat) |
---|
139 | endif |
---|
140 | |
---|
141 | //display the 2D plane |
---|
142 | DoWindow FFT_Slice2D |
---|
143 | if(V_flag == 0) |
---|
144 | Execute "Display2DSlice()" |
---|
145 | endif |
---|
146 | |
---|
147 | //display the 2D plane |
---|
148 | DoWindow FFT_Slice2D_log |
---|
149 | if(V_flag == 0) |
---|
150 | Execute "Display2DSlice_log()" |
---|
151 | endif |
---|
152 | |
---|
153 | //display the 1D binning of the 2D plane |
---|
154 | DoWindow FFT_Slice1D |
---|
155 | if(V_flag == 0) |
---|
156 | Execute "Slice2_1D()" |
---|
157 | endif |
---|
158 | |
---|
159 | return(0) |
---|
160 | End |
---|
161 | |
---|
162 | Proc Display2DSlice() |
---|
163 | PauseUpdate; Silent 1 // building window... |
---|
164 | Display /W=(1038,44,1404,403) |
---|
165 | DoWindow/C FFT_Slice2D |
---|
166 | AppendImage/T detPlane |
---|
167 | ModifyImage detPlane ctab= {*,*,YellowHot,0} |
---|
168 | ModifyGraph margin(left)=14,margin(bottom)=14,margin(top)=14,margin(right)=14 |
---|
169 | ModifyGraph mirror=2 |
---|
170 | ModifyGraph nticks=4 |
---|
171 | ModifyGraph minor=1 |
---|
172 | ModifyGraph fSize=9 |
---|
173 | ModifyGraph standoff=0 |
---|
174 | ModifyGraph tkLblRot(left)=90 |
---|
175 | ModifyGraph btLen=3 |
---|
176 | ModifyGraph tlOffset=-2 |
---|
177 | SetAxis/A/R left |
---|
178 | End |
---|
179 | |
---|
180 | Proc Display2DInterpSlice_log() |
---|
181 | PauseUpdate; Silent 1 // building window... |
---|
182 | Display /W=(1038,44,1404,403) |
---|
183 | DoWindow/C FFT_Interp2D_log |
---|
184 | AppendImage/T interp2DSlice_log |
---|
185 | ModifyImage interp2DSlice_log ctab= {*,*,YellowHot,0} |
---|
186 | ModifyGraph margin(left)=14,margin(bottom)=14,margin(top)=14,margin(right)=14 |
---|
187 | ModifyGraph mirror=2 |
---|
188 | ModifyGraph nticks=4 |
---|
189 | ModifyGraph minor=1 |
---|
190 | ModifyGraph fSize=9 |
---|
191 | ModifyGraph standoff=0 |
---|
192 | ModifyGraph tkLblRot(left)=90 |
---|
193 | ModifyGraph btLen=3 |
---|
194 | ModifyGraph tlOffset=-2 |
---|
195 | SetAxis/A/R left |
---|
196 | End |
---|
197 | |
---|
198 | Proc Display2DSlice_log() |
---|
199 | PauseUpdate; Silent 1 // building window... |
---|
200 | Display /W=(1038,44,1404,403) |
---|
201 | DoWindow/C FFT_Slice2D_log |
---|
202 | AppendImage/T logP |
---|
203 | ModifyImage logP ctab= {*,*,YellowHot,0} |
---|
204 | ModifyGraph margin(left)=14,margin(bottom)=14,margin(top)=14,margin(right)=14 |
---|
205 | ModifyGraph mirror=2 |
---|
206 | ModifyGraph nticks=4 |
---|
207 | ModifyGraph minor=1 |
---|
208 | ModifyGraph fSize=9 |
---|
209 | ModifyGraph standoff=0 |
---|
210 | ModifyGraph tkLblRot(left)=90 |
---|
211 | ModifyGraph btLen=3 |
---|
212 | ModifyGraph tlOffset=-2 |
---|
213 | SetAxis/A/R left |
---|
214 | End |
---|
215 | Proc Slice2_1D() |
---|
216 | PauseUpdate; Silent 1 // building window... |
---|
217 | Display /W=(1034,425,1406,763) iBin_2d vs qBin_2d |
---|
218 | DoWindow/C FFT_Slice1D |
---|
219 | ModifyGraph mode=4 |
---|
220 | ModifyGraph marker=19 |
---|
221 | ModifyGraph msize=2 |
---|
222 | ModifyGraph grid=1 |
---|
223 | ModifyGraph log=1 |
---|
224 | ModifyGraph mirror=2 |
---|
225 | Legend |
---|
226 | EndMacro |
---|
227 | |
---|
228 | |
---|
229 | Function FFT_TransposeMat(ctrlName) : ButtonControl |
---|
230 | String ctrlName |
---|
231 | |
---|
232 | Variable mode=1 |
---|
233 | Prompt mode,"Transform XYZ to:",popup,"XZY;ZXY;ZYX;YZX;YXZ;" |
---|
234 | DoPrompt "Transform mode",mode |
---|
235 | if (V_Flag) |
---|
236 | return 0 // user canceled |
---|
237 | endif |
---|
238 | |
---|
239 | fFFT_TransposeMat(mode) |
---|
240 | |
---|
241 | return (0) |
---|
242 | End |
---|
243 | |
---|
244 | // starting in XYZ |
---|
245 | // mode 1;2;3;4;5; |
---|
246 | //correspond to |
---|
247 | // "XZY;ZXY;ZYX;YZX;YXZ;" |
---|
248 | // |
---|
249 | Function fFFT_TransposeMat(mode) |
---|
250 | Variable mode |
---|
251 | |
---|
252 | WAVE/Z mat=mat |
---|
253 | ImageTransform /G=(mode) transposeVol mat |
---|
254 | WAVE M_VolumeTranspose=M_VolumeTranspose |
---|
255 | Duplicate/O M_VolumeTranspose mat |
---|
256 | |
---|
257 | return(0) |
---|
258 | End |
---|
259 | |
---|
260 | Function FFT_RotateMat(ctrlName) : ButtonControl |
---|
261 | String ctrlName |
---|
262 | |
---|
263 | Variable degree=45,sense=1 |
---|
264 | Prompt degree, "Degrees of rotation around Z-axis:" |
---|
265 | // Prompt sense, "Direction of rotation:",popup,"CW;CCW;" |
---|
266 | DoPrompt "Enter paramters for rotation", degree |
---|
267 | |
---|
268 | if (V_Flag) |
---|
269 | return 0 // user canceled |
---|
270 | endif |
---|
271 | |
---|
272 | fFFT_RotateMat(degree) |
---|
273 | return(0) |
---|
274 | End |
---|
275 | // note that the rotation is not perfect. if the rotation produces an |
---|
276 | // odd number of pixels, then the object will "walk" one pixel. Also, some |
---|
277 | // small artifacts are introduced, simply due to the voxelization of the object |
---|
278 | // as it is rotated. rotating a cylinder 10 then 350 shows a few extra "bumps" on |
---|
279 | // the surface, but the calculated scattering is virtually identical. |
---|
280 | // |
---|
281 | // these issues, may be correctable, if needed |
---|
282 | // |
---|
283 | Function fFFT_RotateMat(degree) |
---|
284 | Variable degree |
---|
285 | |
---|
286 | Variable fill=0 |
---|
287 | |
---|
288 | WAVE mat = mat |
---|
289 | Variable dx,dy,dz,nx,ny,nz |
---|
290 | dx = DimSize(mat,0) |
---|
291 | dy = DimSize(mat,1) |
---|
292 | dz = DimSize(mat,2) |
---|
293 | |
---|
294 | //? the /W and /C flags seem to be special cases for 90 deg rotations |
---|
295 | ImageRotate /A=(degree)/E=(fill) mat //mat is not overwritten, unless /O |
---|
296 | |
---|
297 | nx = DimSize(M_RotatedImage,0) |
---|
298 | ny = DimSize(M_RotatedImage,1) |
---|
299 | nz = DimSize(M_RotatedImage,2) |
---|
300 | // Print "rotated dims = ",dx,dy,dz,nx,ny,nz |
---|
301 | Variable delx,dely,odd=0 |
---|
302 | delx = nx-dx |
---|
303 | dely = ny-dy |
---|
304 | |
---|
305 | if(mod(delx,2) != 0) //sometimes the new x,y dims are odd! |
---|
306 | odd = 1 |
---|
307 | endif |
---|
308 | // delx = (delx + odd)/2 |
---|
309 | // dely = (dely + odd)/2 |
---|
310 | delx = trunc(delx/2) |
---|
311 | dely = trunc(dely/2) |
---|
312 | |
---|
313 | //+odd removes an extra point if there is one |
---|
314 | Duplicate/O/R=[delx+odd,nx-delx-1][dely+odd,ny-dely-1][0,nz-1] M_RotatedImage mat |
---|
315 | |
---|
316 | // - not sure why the duplicate operation changes the start and delta of mat, but I |
---|
317 | // need to reset the start and delta to be sure that the display is correct, and that the scaling |
---|
318 | // is read correctly later |
---|
319 | SetScale/P x 0,1,"", mat |
---|
320 | SetScale/P y 0,1,"", mat |
---|
321 | |
---|
322 | nx = DimSize(mat,0) |
---|
323 | ny = DimSize(mat,1) |
---|
324 | nz = DimSize(mat,2) |
---|
325 | // Print "redim = ",dx,dy,dz,nx,ny,nz |
---|
326 | |
---|
327 | KillWaves/Z M_RotatedImage |
---|
328 | |
---|
329 | End |
---|
330 | |
---|
331 | // also look for ImageTransform operations that will allow translation of the objects. |
---|
332 | // then simple objects could be oriented @0,0,0, and translated to the correct position (and added) |
---|
333 | // |
---|
334 | Function FFT_AddRotatedObject(ctrlName) : ButtonControl |
---|
335 | String ctrlName |
---|
336 | |
---|
337 | Print "Not yet implemented" |
---|
338 | End |
---|
339 | |
---|
340 | |
---|
341 | Function FFT_MakeMatrixButtonProc(ctrlName) : ButtonControl |
---|
342 | String ctrlName |
---|
343 | |
---|
344 | NVAR nn=root:FFT_N |
---|
345 | if(mod(nn, 2 ) ==1) //force an even number for FFT |
---|
346 | nn +=1 |
---|
347 | endif |
---|
348 | MakeMatrix("mat",nn,nn,nn) |
---|
349 | End |
---|
350 | |
---|
351 | Function FFTMakeGizmoButtonProc(ctrlName) : ButtonControl |
---|
352 | String ctrlName |
---|
353 | |
---|
354 | DoWindow/F Gizmo_VoxelMat |
---|
355 | if(V_flag==0) |
---|
356 | Execute "Gizmo_VoxelMat()" |
---|
357 | endif |
---|
358 | End |
---|
359 | |
---|
360 | Function FFTDrawSphereButtonProc(ctrlName) : ButtonControl |
---|
361 | String ctrlName |
---|
362 | |
---|
363 | Execute "FFTDrawSphereProc()" |
---|
364 | End |
---|
365 | |
---|
366 | Proc FFTDrawSphereProc(matStr,rad,xc,yc,zc,fill) |
---|
367 | String matStr="mat" |
---|
368 | Variable rad=25,xc=50,yc=50,zc=50,fill=1 |
---|
369 | Prompt matStr,"the wave" //,popup,WaveList("*",";","") |
---|
370 | Prompt rad,"enter real radius (A)" |
---|
371 | Prompt xc,"enter the X-center" |
---|
372 | Prompt yc,"enter the Y-center" |
---|
373 | Prompt zc,"enter the Z-center" |
---|
374 | Prompt fill,"1= fill, 0 = erase" |
---|
375 | |
---|
376 | Variable grid=root:FFT_T |
---|
377 | |
---|
378 | FillSphereRadius($matStr,grid,rad,xc,yc,zc,fill) |
---|
379 | |
---|
380 | End |
---|
381 | |
---|
382 | Function FFTDrawZCylinderButtonProc(ctrlName) : ButtonControl |
---|
383 | String ctrlName |
---|
384 | |
---|
385 | Execute "FFTDrawCylinder()" |
---|
386 | End |
---|
387 | |
---|
388 | Proc FFTDrawCylinder(direction,matStr,rad,len,xc,yc,zc,fill) |
---|
389 | String direction |
---|
390 | String matStr="mat" |
---|
391 | Variable rad=25,len=300,xc=50,yc=50,zc=50,fill=1 |
---|
392 | Prompt direction, "Direction", popup "X;Y;Z;" |
---|
393 | Prompt matStr,"the wave" //,popup,WaveList("*",";","") |
---|
394 | Prompt rad,"enter real radius (A)" |
---|
395 | Prompt len,"enter length (A)" |
---|
396 | Prompt xc,"enter the X-center" |
---|
397 | Prompt yc,"enter the Y-center" |
---|
398 | Prompt zc,"enter the Z-center" |
---|
399 | Prompt fill,"1= fill, 0 = erase" |
---|
400 | |
---|
401 | |
---|
402 | Variable grid=root:FFT_T |
---|
403 | |
---|
404 | if(cmpstr(direction,"X")==0) |
---|
405 | FillXCylinder($matStr,grid,rad,xc,yc,zc,len,fill) |
---|
406 | endif |
---|
407 | if(cmpstr(direction,"Y")==0) |
---|
408 | FillYCylinder($matStr,grid,rad,xc,yc,zc,len,fill) |
---|
409 | endif |
---|
410 | if(cmpstr(direction,"Z")==0) |
---|
411 | FillZCylinder($matStr,grid,rad,xc,yc,zc,len,fill) |
---|
412 | endif |
---|
413 | |
---|
414 | End |
---|
415 | |
---|
416 | |
---|
417 | Function DoTheFFT_ButtonProc(ctrlName) : ButtonControl |
---|
418 | String ctrlName |
---|
419 | |
---|
420 | Execute "DoFFT()" |
---|
421 | End |
---|
422 | |
---|
423 | Function FFT_PlotResultsButtonProc(ctrlName) : ButtonControl |
---|
424 | String ctrlName |
---|
425 | |
---|
426 | DoWindow/F FFT_IQ |
---|
427 | if(V_flag==0) |
---|
428 | Execute "FFT_IQ()" |
---|
429 | Endif |
---|
430 | End |
---|
431 | |
---|
432 | |
---|
433 | Function FFTEraseMatrixButtonProc(ctrlName) : ButtonControl |
---|
434 | String ctrlName |
---|
435 | |
---|
436 | Wave mat=root:mat |
---|
437 | FastOp mat=0 |
---|
438 | return(0) |
---|
439 | End |
---|
440 | |
---|
441 | Function FFTFillSolventMatrixProc(ctrlName) : ButtonControl |
---|
442 | String ctrlName |
---|
443 | |
---|
444 | Wave mat=root:mat |
---|
445 | NVAR val=root:FFT_SolventSLD |
---|
446 | mat=val |
---|
447 | return(0) |
---|
448 | End |
---|
449 | |
---|
450 | Function FFT_AltiSpheresButtonProc(ctrlName) : ButtonControl |
---|
451 | String ctrlName |
---|
452 | |
---|
453 | Execute "DoSpheresCalcFFTPanel()" |
---|
454 | End |
---|
455 | |
---|
456 | Function FFT_BinnedSpheresButtonProc(ctrlName) : ButtonControl |
---|
457 | String ctrlName |
---|
458 | |
---|
459 | Execute "DoBinnedSpheresCalcFFTPanel()" |
---|
460 | End |
---|
461 | |
---|
462 | Function FFT_BinnedSLDButtonProc(ctrlName) : ButtonControl |
---|
463 | String ctrlName |
---|
464 | |
---|
465 | Execute "DoBinnedSLDCalcFFTPanel()" |
---|
466 | End |
---|
467 | |
---|
468 | |
---|
469 | Proc FFT_IQ() : Graph |
---|
470 | PauseUpdate; Silent 1 // building window... |
---|
471 | Display /W=(295,44,627,302) iBin vs qBin |
---|
472 | DoWindow/C FFT_IQ |
---|
473 | ModifyGraph mode=4 |
---|
474 | ModifyGraph marker=19 |
---|
475 | ModifyGraph msize=2 |
---|
476 | ModifyGraph gaps=0 |
---|
477 | ModifyGraph grid=1 |
---|
478 | ModifyGraph log=1 |
---|
479 | ModifyGraph mirror=2 |
---|
480 | Legend/N=text0/J "\\s(iBin) iBin" |
---|
481 | EndMacro |
---|
482 | |
---|
483 | |
---|
484 | |
---|
485 | |
---|
486 | /////UTILITIES |
---|
487 | |
---|
488 | // inverts the values in the matrix 0<->1 |
---|
489 | Function InvertMatrixFill(mat) |
---|
490 | Wave mat |
---|
491 | |
---|
492 | mat = (mat==1) ? 0 : 1 |
---|
493 | End |
---|
494 | |
---|
495 | //overwrites any existing matrix |
---|
496 | // matrix is byte, to save space |
---|
497 | //forces the name to be "mat" |
---|
498 | // |
---|
499 | // switched to signed byte |
---|
500 | // |
---|
501 | Function MakeMatrix(nam,xd,yd,zd) |
---|
502 | String nam |
---|
503 | Variable xd,yd,zd |
---|
504 | |
---|
505 | nam="mat" |
---|
506 | Print "Matrix has been created and named \"mat\"" |
---|
507 | // Make/O/U/B/N=(xd,yd,zd) $nam |
---|
508 | Make/O/B/N=(xd,yd,zd) $nam |
---|
509 | End |
---|
510 | |
---|
511 | |
---|
512 | // calculate the average center-to-center distance between points |
---|
513 | // assumes evenly spaced on a cubic grid |
---|
514 | // |
---|
515 | Proc Center_to_Center(np) |
---|
516 | Variable np = 100 |
---|
517 | |
---|
518 | Variable Nedge = root:FFT_N |
---|
519 | Variable Tscale = root:FFT_T |
---|
520 | |
---|
521 | Variable davg |
---|
522 | |
---|
523 | davg = (Nedge*Tscale)^3 / np |
---|
524 | davg = davg^(1/3) |
---|
525 | Print "Average separation (A) = ",davg |
---|
526 | |
---|
527 | End |
---|
528 | |
---|
529 | // calculate the number of points required on a grid |
---|
530 | // to yield a given average center-to-center distance between points |
---|
531 | // assumes evenly spaced on a cubic grid |
---|
532 | // |
---|
533 | // davg and Tscale are the same units, Angstroms |
---|
534 | // |
---|
535 | Proc Davg_to_Np(davg) |
---|
536 | Variable davg = 400 |
---|
537 | |
---|
538 | Variable Nedge = root:FFT_N |
---|
539 | Variable Tscale = root:FFT_T |
---|
540 | |
---|
541 | Variable np |
---|
542 | |
---|
543 | np = (Nedge*Tscale)^3 / davg^3 |
---|
544 | Print "Number of points required = ",np |
---|
545 | |
---|
546 | End |
---|
547 | |
---|
548 | // The matrix is not necessarily 0|1, this reports the number of filled voxels |
---|
549 | // - needed to estimate the time required for the AltiVec_Spheres calculation |
---|
550 | Proc NumberOfPoints() |
---|
551 | |
---|
552 | Print "Number of points = ",NumberOfPoints_Occ(root:mat) |
---|
553 | Print "Fraction occupied = ",VolumeFraction_Occ(root:mat) |
---|
554 | Print "Overall Cube Edge [A] = ",root:FFT_T * root:FFT_N |
---|
555 | |
---|
556 | End |
---|
557 | |
---|
558 | Function NumberOfPoints_Occ(m) |
---|
559 | Wave m |
---|
560 | |
---|
561 | Variable num = NonZeroValues(m) |
---|
562 | |
---|
563 | return(num) |
---|
564 | End |
---|
565 | |
---|
566 | |
---|
567 | Function VolumeFraction_Occ(m) |
---|
568 | Wave m |
---|
569 | |
---|
570 | Variable num = NonZeroValues(m) |
---|
571 | Variable dim = DimSize(m,0) |
---|
572 | |
---|
573 | return(num/dim^3) |
---|
574 | End |
---|
575 | |
---|
576 | //it's a byte wave, so I can't use the trick of setting the zero values to NaN |
---|
577 | // since NaN can't be expressed as byte. So make it binary 0|1 |
---|
578 | // |
---|
579 | // - the assumption here is that the defined solvent value is not part of the |
---|
580 | // particle volume. |
---|
581 | // |
---|
582 | Function NonZeroValues(m) |
---|
583 | Wave m |
---|
584 | |
---|
585 | Variable num |
---|
586 | NVAR val = root:FFT_SolventSLD |
---|
587 | |
---|
588 | // Variable t1=ticks,dim |
---|
589 | // dim = DimSize(m, 0 ) //assume NxNxN |
---|
590 | Duplicate/O m,mz |
---|
591 | |
---|
592 | MultiThread mz = (m[p][q] != val) ? 1 : 0 |
---|
593 | |
---|
594 | WaveStats/Q/M=1 mz // NaN and Inf are not reported in V_npnts |
---|
595 | |
---|
596 | num = V_npnts*V_avg |
---|
597 | |
---|
598 | KillWaves/Z mz |
---|
599 | // Print "Number of points = ",num |
---|
600 | // Print "Fraction occupied = ",num/V_npnts |
---|
601 | |
---|
602 | // Print "time = ",(ticks-t1)/60.15 |
---|
603 | return(num) |
---|
604 | End |
---|
605 | |
---|
606 | // returns estimate in seconds |
---|
607 | // |
---|
608 | // updated for quad-core iMac, 2010 |
---|
609 | // |
---|
610 | // type 3 = binned distances and SLD |
---|
611 | // type 2 = binned distances |
---|
612 | // type 1 is rather meaningless |
---|
613 | // type 0 = is the Debye, double sum (multithreaded) |
---|
614 | // |
---|
615 | // |
---|
616 | // - types 2 and 3, the binned methods are inherently AAO, so there is no significant |
---|
617 | // dependence on the number of q-values (unless it's >> 1000). So values reported are |
---|
618 | // for 100 q-values. |
---|
619 | // |
---|
620 | // There is a function Timing_Method(type) in FFT_ConcentratedSpheres.ipf to automate some of this |
---|
621 | // |
---|
622 | Function EstimatedTime(nx,nq,type) |
---|
623 | Variable nx,nq,type |
---|
624 | |
---|
625 | Variable est=0 |
---|
626 | |
---|
627 | if(type==0) // "full" XOP |
---|
628 | est = 0.4 + 1.622e-5*nx+4.86e-7*nx^2 |
---|
629 | est /= 100 |
---|
630 | est *= nq |
---|
631 | endif |
---|
632 | |
---|
633 | if(type==1) //Igor function (much slower, 9x) |
---|
634 | est = (nx^2)*0.0000517 //empirical values (seconds) for igor code, 100 q-values |
---|
635 | est /= 100 // per q now... |
---|
636 | est *= nq |
---|
637 | endif |
---|
638 | |
---|
639 | if(type==2) //binned distances, slow parts XOPed |
---|
640 | est = 0.0680 + 2.94e-6*nx+4.51e-9*nx^2 //with threading |
---|
641 | |
---|
642 | // est /= 100 // per q now... |
---|
643 | // est *= nq |
---|
644 | endif |
---|
645 | |
---|
646 | if(type==3) //binned distances AND sld, slow parts XOPed |
---|
647 | est = 0.576 + 4.22e-7*nx+1.76e-8*nx^2 //with threading |
---|
648 | |
---|
649 | // est /= 100 // per q now... |
---|
650 | // est *= nq |
---|
651 | endif |
---|
652 | |
---|
653 | return(est) |
---|
654 | End |
---|