source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/MultScatter_MonteCarlo_2D.ipf @ 472

Last change on this file since 472 was 472, checked in by srkline, 14 years ago

A large number of changes and fixes:

--168/169/170: panels and windows are now at least on-screen for all packages. Tested
with 1024x768 resolution.
-- closed ticket 176 which was a question about resampling data to generate error estimates
on fitted parameters. Useful for reflectometry, not needed for SANS.
--157: bug of low Q power law extrapolation in Invariant fixed by avoiding q==0
--178/180: Tr/Tw? notification in USANS. log/lin checkbox for display.
--167: saveData checkbox for USANS not behaving well. turns off/on better now.
--197: changed all (?) 1D writing routines to enforce 26 characters as the maximum length
to make sure that file loading will never exceed 31 characters

-- lots of changes to MonteCarlo? and SASCALC

  • SASCALC now enforces *exact* lens conditions, rather than a close approximation
  • improved MonteCarlo? interface panel
  • added writer for simlulated VAX binary data file
  • can save 2D as ABS or raw counts
  • can freeze w/no offset
File size: 38.7 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2
3//
4// Monte Carlo simulator for SASCALC
5// October 2008 SRK
6//
7// This code simulates the scattering for a selected model based on the instrument configuration
8// This code is based directly on John Barker's code, which includes multiple scattering effects.
9// A lot of the setup, wave creation, and post-calculations are done in SASCALC->ReCalculateInten()
10//
11//
12// - Why am I off by a factor of 2.7 - 3.7 (MC too high) relative to real data?
13//   I need to include efficiency (70%?) - do I knock these off before the simulation or do I
14//    really simulate that some fraction of neutrons on the detector don't actually get counted?
15//   Is the flux estimate up-to-date? !! Flux estimates at NG3 are out-of-date....
16// - my simulated transmission is larger than what is measured, even after correcting for the quartz cell.
17//   Why? Do I need to include absorption? Just inherent problems with incoherent cross sections?
18
19// - Most importantly, this needs to be checked for correctness of the MC simulation
20// X how can I get the "data" on absolute scale? This would be a great comparison vs. the ideal model calculation
21// X why does my integrated tau not match up with John's analytical calculations? where are the assumptions?
22// - get rid of all small angle assumptions - to make sure that the calculation is correct at all angles
23
24//
25// X at the larger angles, is the "flat" detector being properly accounted for - in terms of
26//   the solid angle and how many counts fall in that pixel. Am I implicitly defining a spherical detector
27//   so that what I see is already "corrected"?
28// X the MC will, of course benefit greatly from being XOPized. Maybe think about parallel implementation
29//   by allowing the data arrays to accumulate. First pass at the XOP is done. Not pretty, not the speediest (5.8x)
30//   but it is functional. Add spinCursor() for long calculations. See WaveAccess XOP example.
31// X the background parameter for the model MUST be zero, or the integration for scattering
32//    power will be incorrect. (now the LAST point in a copy of the coef wave is set to zero, only for the rad_dev calculation
33// X fully use the SASCALC input, most importantly, flux on sample.
34// X if no MC desired, still use the selected model
35// X better display of MC results on panel
36// X settings for "count for X seconds" or "how long to 1E6 cts on detector" (but 1E6 is typically too many counts...)
37// X warn of projected simulation time
38// - add quartz window scattering to the simulation somehow
39// -?- do smeared models make any sense?? Yes, John agrees that they do, and may be used in a more realistic simulation
40//   -?- but the random deviate can't be properly calculated...
41// - make sure that the ratio of scattering coherent/incoherent is properly adjusted for the sample composition
42//   or the volume fraction of solvent.
43//
44// X add to the results the fraction of coherently scattered neutrons that are singly scattered, different than
45//   the overall fraction of singly scattered, and maybe more important to know.
46//
47// X change the fraction reaching the detector to exclude those that don't interact. These transmitted neutrons
48//   aren't counted. Is the # that interact a better number?
49//
50// - do we want to NOT offset the data by a multiplicative factor as it is "frozen" , so that the
51//   effects on the absolute scale can be seen?
52//
53// X why is "pure" incoherent scattering giving me a q^-1 slope, even with the detector all the way back?
54// -NO- can I speed up by assuming everything interacts? This would compromise the ability to calculate multiple scattering
55// X ask John how to verify what is going on
56// - a number of models are now found to be ill-behaved when q=1e-10. Then the random deviate calculation blows up.
57//   a warning has been added - but some models need a proper limiting value, and some (power-law) are simply unuseable
58//   unless something else can be done. Using a log-spacing of points doesn't seem to help, and it introduces a lot of
59//   other problems. Not the way to go.
60// - if the MC gags on a simulation, it often gets "stuck" and can't do the normal calculation from the model, which it
61//   should always default to...
62//
63//
64
65// threaded call to the main function, adds up the individual runs, and returns what is to be displayed
66// results is calculated and sent back for display
67Function Monte_SANS_Threaded(inputWave,ran_dev,nt,j1,j2,nn,linear_data,results)
68        WAVE inputWave,ran_dev,nt,j1,j2,nn,linear_data,results
69
70        //initialize ran1 in the XOP by passing a negative integer
71        // does nothing in the Igor code
72        Duplicate/O results retWave
73
74        Variable NNeutron=inputWave[0]
75        Variable i,nthreads= ThreadProcessorCount
76        if(nthreads>2)          //only support 2 processors until I can figure out how to properly thread the XOP and to loop it
77                nthreads=2
78        endif
79       
80//      nthreads = 1
81       
82        variable mt= ThreadGroupCreate(nthreads)
83        NVAR gInitTime = root:Packages:NIST:SAS:gRanDateTime            //time that SASCALC was started
84
85       
86        inputWave[0] = NNeutron/nthreads                //split up the number of neutrons
87       
88        for(i=0;i<nthreads;i+=1)
89                Duplicate/O nt $("nt"+num2istr(i))              //new instance for each thread
90                Duplicate/O j1 $("j1"+num2istr(i))
91                Duplicate/O j2 $("j2"+num2istr(i))
92                Duplicate/O nn $("nn"+num2istr(i))
93                Duplicate/O linear_data $("linear_data"+num2istr(i))
94                Duplicate/O retWave $("retWave"+num2istr(i))
95                Duplicate/O inputWave $("inputWave"+num2istr(i))
96                Duplicate/O ran_dev $("ran_dev"+num2istr(i))
97                               
98                // ?? I need explicit wave references?
99                // maybe I need to have everything in separate data folders - bu tI haven't tried that. seems like a reach.
100                // more likely there is something bad going on in the XOP code.
101                if(i==0)
102                        WAVE inputWave0,ran_dev0,nt0,j10,j20,nn0,linear_data0,retWave0
103                        retWave0 = 0            //clear the return wave
104                        retWave0[0] = -1*(datetime-gInitTime)           //to initialize ran3
105                        ThreadStart mt,i,Monte_SANS_W1(inputWave0,ran_dev0,nt0,j10,j20,nn0,linear_data0,retWave0)
106                        Print "started thread 0"
107                endif
108                if(i==1)
109                        WAVE inputWave1,ran_dev1,nt1,j11,j21,nn1,linear_data1,retWave1
110                        retWave1 = 0                    //clear the return wave
111                        retWave1[0] = -1*(datetime-gInitTime)           //to initialize ran1
112                        ThreadStart mt,i,Monte_SANS_W2(inputWave1,ran_dev1,nt1,j11,j21,nn1,linear_data1,retWave1)
113                        Print "started thread 1"
114                endif
115//              if(i==2)
116//                      WAVE inputWave2,ran_dev2,nt2,j12,j22,nn2,linear_data2,retWave2
117//                      retWave2[0] = -1*datetime               //to initialize ran3
118//                      ThreadStart mt,i,Monte_SANS_W(inputWave2,ran_dev2,nt2,j12,j22,nn2,linear_data2,retWave2)
119//              endif
120//              if(i==3)
121//                      WAVE inputWave3,ran_dev3,nt3,j13,j23,nn3,linear_data3,retWave3
122//                      retWave3[0] = -1*datetime               //to initialize ran3
123//                      ThreadStart mt,i,Monte_SANS_W(inputWave3,ran_dev3,nt3,j13,j23,nn3,linear_data3,retWave3)
124//              endif
125        endfor
126
127// wait until done
128        do
129                variable tgs= ThreadGroupWait(mt,100)
130        while( tgs != 0 )
131        variable dummy= ThreadGroupRelease(mt)
132        Print "done with all threads"
133
134        // calculate all of the bits for the results
135        if(nthreads == 1)
136                nt = nt0                // add up each instance
137                j1 = j10
138                j2 = j20
139                nn = nn0
140                linear_data = linear_data0
141                retWave = retWave0
142        endif
143        if(nthreads == 2)
144                nt = nt0+nt1            // add up each instance
145                j1 = j10+j11
146                j2 = j20+j21
147                nn = nn0+nn1
148                linear_data = linear_data0+linear_data1
149                retWave = retWave0+retWave1
150        endif
151//      if(nthreads == 3)
152//              nt = nt0+nt1+nt2                // add up each instance
153//              j1 = j10+j11+j12
154//              j2 = j20+j21+j22
155//              nn = nn0+nn1+nn2
156//              linear_data = linear_data0+linear_data1+linear_data2
157//              retWave = retWave0+retWave1+retWave2
158//      endif
159//      if(nthreads == 4)
160//              nt = nt0+nt1+nt2+nt3            // add up each instance
161//              j1 = j10+j11+j12+j13
162//              j2 = j20+j21+j22+j23
163//              nn = nn0+nn1+nn2+nn3
164//              linear_data = linear_data0+linear_data1+linear_data2+linear_data3
165//              retWave = retWave0+retWave1+retWave2+retWave3
166//      endif
167       
168        // fill up the results wave
169        Variable xc,yc
170        xc=inputWave[3]
171        yc=inputWave[4]
172        results[0] = inputWave[9]+inputWave[10]         //total XS
173        results[1] = inputWave[10]                                              //SAS XS
174        results[2] = retWave[1]                                                 //number that interact n2
175        results[3] = retWave[2] - linear_data[xc][yc]                           //# reaching detector minus Q(0)
176        results[4] = retWave[3]/retWave[1]                              //avg# times scattered
177        results[5] = retWave[4]/retWave[1]                                              //single coherent fraction
178        results[6] = retWave[5]/retWave[1]                              //double coherent fraction
179        results[7] = retWave[6]/retWave[1]                              //multiple scatter fraction
180        results[8] = (retWave[0]-retWave[1])/retWave[0]                 //transmitted fraction
181       
182        return(0)
183End
184
185// worker function for threads, does nothing except switch between XOP and Igor versions
186//
187// uses ran3
188ThreadSafe Function Monte_SANS_W1(inputWave,ran_dev,nt,j1,j2,nn,linear_data,results)
189        WAVE inputWave,ran_dev,nt,j1,j2,nn,linear_data,results
190       
191#if exists("Monte_SANSX")
192        Monte_SANSX(inputWave,ran_dev,nt,j1,j2,nn,linear_data,results)
193#else
194        Monte_SANS(inputWave,ran_dev,nt,j1,j2,nn,linear_data,results)
195#endif
196
197        return (0)
198End
199
200// worker function for threads, does nothing except switch between XOP and Igor versions
201//
202// uses ran1
203ThreadSafe Function Monte_SANS_W2(inputWave,ran_dev,nt,j1,j2,nn,linear_data,results)
204        WAVE inputWave,ran_dev,nt,j1,j2,nn,linear_data,results
205       
206#if exists("Monte_SANSX2")
207        Monte_SANSX2(inputWave,ran_dev,nt,j1,j2,nn,linear_data,results)
208#else
209        Monte_SANS(inputWave,ran_dev,nt,j1,j2,nn,linear_data,results)
210#endif
211
212        return (0)
213End
214
215// NON-threaded call to the main function returns what is to be displayed
216// results is calculated and sent back for display
217Function Monte_SANS_NotThreaded(inputWave,ran_dev,nt,j1,j2,nn,linear_data,results)
218        WAVE inputWave,ran_dev,nt,j1,j2,nn,linear_data,results
219
220        //initialize ran1 in the XOP by passing a negative integer
221        // does nothing in the Igor code, enoise is already initialized
222        Duplicate/O results retWave
223        WAVE retWave
224        retWave[0] = -1*abs(trunc(100000*enoise(1)))
225       
226#if exists("Monte_SANSX")
227        Monte_SANSX(inputWave,ran_dev,nt,j1,j2,nn,linear_data,retWave)
228#else
229        Monte_SANS(inputWave,ran_dev,nt,j1,j2,nn,linear_data,retWave)
230#endif
231
232        // fill up the results wave
233        Variable xc,yc
234        xc=inputWave[3]
235        yc=inputWave[4]
236        results[0] = inputWave[9]+inputWave[10]         //total XS
237        results[1] = inputWave[10]                                              //SAS XS
238        results[2] = retWave[1]                                                 //number that interact n2
239        results[3] = retWave[2] - linear_data[xc][yc]                           //# reaching detector minus Q(0)
240        results[4] = retWave[3]/retWave[1]                              //avg# times scattered
241        results[5] = retWave[4]/retWave[1]                                              //single coherent fraction
242        results[6] = retWave[5]/retWave[1]                              //double coherent fraction
243        results[7] = retWave[6]/retWave[1]                              //multiple scatter fraction
244        results[8] = (retWave[0]-retWave[1])/retWave[0]                 //transmitted fraction
245       
246        return(0)
247End
248
249
250
251//////////
252//    PROGRAM Monte_SANS
253//    PROGRAM simulates multiple SANS.
254//       revised 2/12/99  JGB
255//            added calculation of random deviate, and 2D 10/2008 SRK
256
257//    N1 = NUMBER OF INCIDENT NEUTRONS.
258//    N2 = NUMBER INTERACTED IN THE SAMPLE.
259//    N3 = NUMBER ABSORBED.
260//    THETA = SCATTERING ANGLE.
261
262//        IMON = 'Enter number of neutrons to use in simulation.'
263//        NUM_BINS = 'Enter number of THETA BINS TO use. (<5000).'
264//        R1 = 'Enter beam radius. (cm)'
265//        R2 = 'Enter sample radius. (cm)'
266//        thick = 'Enter sample thickness. (cm)'
267//        wavelength = 'Enter neutron wavelength. (A)'
268//        R0 = 'Enter sphere radius. (A)'
269//
270
271ThreadSafe Function Monte_SANS(inputWave,ran_dev,nt,j1,j2,nn,MC_linear_data,results)
272        WAVE inputWave,ran_dev,nt,j1,j2,nn,MC_linear_data,results
273
274        Variable imon,r1,r2,xCtr,yCtr,sdd,pixSize,thick,wavelength,sig_incoh,sig_sas
275        Variable NUM_BINS,N_INDEX
276        Variable RHO,SIGSAS,SIGABS_0
277        Variable ii,jj,IND,idum,INDEX,IR,NQ
278        Variable qmax,theta_max,R_DAB,R0,BOUND,I0,q0,zpow
279        Variable N1,N2,N3,DTH,zz,tt,SIG_SINGLE,xx,yy,PHI,UU,SIG
280        Variable THETA,Ran,ll,D_OMEGA,RR,Tabs,Ttot,I1_sumI
281        Variable G0,E_NT,E_NN,TRANS_th,Trans_exp,rat
282        Variable GG,GG_ED,dS_dW,ds_dw_double,ds_dw_single
283        Variable DONE,FIND_THETA,err            //used as logicals
284
285        Variable Vx,Vy,Vz,Theta_z,qq
286        Variable Sig_scat,Sig_abs,Ratio,Sig_total
287        Variable isOn=0,testQ,testPhi,xPixel,yPixel
288        Variable NSingleIncoherent,NSingleCoherent,NScatterEvents,incoherentEvent,coherentEvent
289        Variable NDoubleCoherent,NMultipleScatter,countIt,detEfficiency
290       
291        detEfficiency = 1.0             //70% counting efficiency = 0.7
292       
293        imon = inputWave[0]
294        r1 = inputWave[1]
295        r2 = inputWave[2]
296        xCtr = inputWave[3]
297        yCtr = inputWave[4]
298        sdd = inputWave[5]
299        pixSize = inputWave[6]
300        thick = inputWave[7]
301        wavelength = inputWave[8]
302        sig_incoh = inputWave[9]
303        sig_sas = inputWave[10]
304       
305//      SetRandomSeed 0.1               //to get a reproduceable sequence
306
307//scattering power and maximum qvalue to bin
308//      zpow = .1               //scattering power, calculated below
309        qmax = 4*pi/wavelength          //maximum Q to bin 1D data. (A-1) (not really used, so set to a big value)
310        sigabs_0 = 0.0          // ignore absorption cross section/wavelength [1/(cm A)]
311        N_INDEX = 50            // maximum number of scattering events per neutron
312        num_bins = 200          //number of 1-D bins (not really used)
313       
314// my additions - calculate the random deviate function as needed
315// and calculate the scattering power from the model function (passed in as a wave)
316//
317        Variable left = leftx(ran_dev)
318        Variable delta = deltax(ran_dev)
319       
320//c       total SAS cross-section
321//      SIG_SAS = zpow/thick
322        zpow = sig_sas*thick                    //since I now calculate the sig_sas from the model
323        SIG_ABS = SIGABS_0 * WAVElength
324        sig_abs = 0.0           //cm-1
325        SIG_TOTAL =SIG_ABS + SIG_SAS + sig_incoh
326//      Print "The TOTAL XSECTION. (CM-1) is ",sig_total
327//      Print "The TOTAL SAS XSECTION. (CM-1) is ",sig_sas
328//      results[0] = sig_total          //assign these after everything's done
329//      results[1] = sig_sas
330//      variable ratio1,ratio2
331//      ratio1 = sig_abs/sig_total
332//      ratio2 = sig_incoh/sig_total
333//      // 0->ratio1 = abs
334//      // ratio1 -> ratio2 = incoh
335//      // > ratio2 = coherent
336        RATIO = sig_incoh / SIG_TOTAL
337       
338//c       assuming theta = sin(theta)...OK
339        theta_max = wavelength*qmax/(2*pi)
340//C     SET Theta-STEP SIZE.
341        DTH = Theta_max/NUM_BINS
342//      Print "theta bin size = dth = ",dth
343
344//C     INITIALIZE COUNTERS.
345        N1 = 0
346        N2 = 0
347        N3 = 0
348        NSingleIncoherent = 0
349        NSingleCoherent = 0
350        NDoubleCoherent = 0
351        NMultipleScatter = 0
352        NScatterEvents = 0
353
354//C     INITIALIZE ARRAYS.
355        j1 = 0
356        j2 = 0
357        nt = 0
358        nn=0
359       
360//C     MONITOR LOOP - looping over the number of incedent neutrons
361//note that zz, is the z-position in the sample - NOT the scattering power
362
363// NOW, start the loop, throwing neutrons at the sample.
364        do
365                Vx = 0.0                        // Initialize direction vector.
366                Vy = 0.0
367                Vz = 1.0
368               
369                Theta = 0.0             //      Initialize scattering angle.
370                Phi = 0.0                       //      Intialize azimuthal angle.
371                N1 += 1                 //      Increment total number neutrons counter.
372                DONE = 0                        //      True when neutron is scattered out of the sample.
373                INDEX = 0                       //      Set counter for number of scattering events.
374                zz = 0.0                        //      Set entering dimension of sample.
375                incoherentEvent = 0
376                coherentEvent = 0
377               
378                do                                      //      Makes sure position is within circle.
379                        ran = abs(enoise(1))            //[0,1]
380                        xx = 2.0*R1*(Ran-0.5)           //X beam position of neutron entering sample.
381                        ran = abs(enoise(1))            //[0,1]
382                        yy = 2.0*R1*(Ran-0.5)           //Y beam position ...
383                        RR = SQRT(xx*xx+yy*yy)          //Radial position of neutron in incident beam.
384                while(rr>r1)
385
386                do    //Scattering Loop, will exit when "done" == 1
387                                // keep scattering multiple times until the neutron exits the sample
388                        ran = abs(enoise(1))            //[0,1]  RANDOM NUMBER FOR DETERMINING PATH LENGTH
389                        ll = PATH_len(ran,Sig_total)
390                        //Determine new scattering direction vector.
391                        err = NewDirection(vx,vy,vz,Theta,Phi)          //vx,vy,vz is updated, theta, phi unchanged by function
392
393                        //X,Y,Z-POSITION OF SCATTERING EVENT.
394                        xx += ll*vx
395                        yy += ll*vy
396                        zz += ll*vz
397                        RR = sqrt(xx*xx+yy*yy)          //radial position of scattering event.
398
399                        //Check whether interaction occurred within sample volume.
400                        IF (((zz > 0.0) && (zz < THICK)) && (rr < r2))
401                                //NEUTRON INTERACTED.
402                                ran = abs(enoise(1))            //[0,1]
403                               
404//                              if(ran<ratio1)
405//                                      //absorption event
406//                                      n3 +=1
407//                                      done=1
408//                              else
409
410                                INDEX += 1                      //Increment counter of scattering events.
411                                IF(INDEX == 1)
412                                        N2 += 1                 //Increment # of scat. neutrons
413                                Endif
414                                //Split neutron interactions into scattering and absorption events
415//                              IF(ran > (ratio1+ratio2) )              //C             NEUTRON SCATTERED coherently
416                                IF(ran > ratio)         //C             NEUTRON SCATTERED coherently
417                                        coherentEvent = 1
418                                        FIND_THETA = 0                  //false
419                                        DO
420                                                //ran = abs(enoise(1))          //[0,1]
421                                                //theta = Scat_angle(Ran,R_DAB,wavelength)      // CHOOSE DAB ANGLE -- this is 2Theta
422                                                //Q0 = 2*PI*THETA/WAVElength                                    // John chose theta, calculated Q
423
424                                                // pick a q-value from the deviate function
425                                                // pnt2x truncates the point to an integer before returning the x
426                                                // so get it from the wave scaling instead
427                                                Q0 =left + binarysearchinterp(ran_dev,abs(enoise(1)))*delta
428                                                theta = Q0/2/Pi*wavelength              //SAS approximation
429                                               
430                                                //Print "q0, theta = ",q0,theta
431                                               
432                                                FIND_THETA = 1          //always accept
433
434                                        while(!find_theta)
435                                        ran = abs(enoise(1))            //[0,1]
436                                        PHI = 2.0*PI*Ran                        //Chooses azimuthal scattering angle.
437                                ELSE
438                                        //NEUTRON scattered incoherently
439                   // N3 += 1
440                  // DONE = 1
441                  // phi and theta are random over the entire sphere of scattering
442                  // !can't just choose random theta and phi, won't be random over sphere solid angle
443                        incoherentEvent = 1
444                       
445                        ran = abs(enoise(1))            //[0,1]
446                                        theta = acos(2*ran-1)           
447                       
448                        ran = abs(enoise(1))            //[0,1]
449                                        PHI = 2.0*PI*Ran                        //Chooses azimuthal scattering angle.
450                                ENDIF           //(ran > ratio)
451//                              endif           // event was absorption
452                        ELSE
453                                //NEUTRON ESCAPES FROM SAMPLE -- bin it somewhere
454                                DONE = 1                //done = true, will exit from loop
455                               
456//                              countIt = 1
457//                              if(abs(enoise(1)) > detEfficiency)              //efficiency of 70% wired @top
458//                                      countIt = 0                                     //detector does not register
459//                              endif
460                               
461                                //Increment #scattering events array
462                                If (index <= N_Index)
463                                        NN[INDEX] += 1
464                                Endif
465                               
466                                if(index != 0)          //the neutron interacted at least once, figure out where it ends up
467
468                                        Theta_z = acos(Vz)              // Angle WITH respect to z axis.
469                                        testQ = 2*pi*sin(theta_z)/wavelength
470                                       
471                                        // pick a random phi angle, and see if it lands on the detector
472                                        // since the scattering is isotropic, I can safely pick a new, random value
473                                        // this would not be true if simulating anisotropic scattering.
474                                        //testPhi = abs(enoise(1))*2*Pi
475                                        testPhi = FindPhi(Vx,Vy)                //use the exiting phi value as defined by Vx and Vy
476                                       
477                                        // is it on the detector?       
478                                        FindPixel(testQ,testPhi,wavelength,sdd,pixSize,xCtr,yCtr,xPixel,yPixel)
479                                       
480                                        if(xPixel != -1 && yPixel != -1)
481                                                //if(index==1)  // only the single scattering events
482                                                        MC_linear_data[xPixel][yPixel] += 1             //this is the total scattering, including multiple scattering
483                                                //endif
484                                                        isOn += 1               // neutron that lands on detector
485                                        endif
486       
487                                        If(theta_z < theta_max)
488                                                //Choose index for scattering angle array.
489                                                //IND = NINT(THETA_z/DTH + 0.4999999)
490                                                ind = round(THETA_z/DTH + 0.4999999)            //round is eqivalent to nint()
491                                                NT[ind] += 1                    //Increment bin for angle.
492                                                //Increment angle array for single scattering events.
493                                                IF(INDEX == 1)
494                                                        j1[ind] += 1
495                                                Endif
496                                                //Increment angle array for double scattering events.
497                                                IF (INDEX == 2)
498                                                        j2[ind] += 1
499                                                Endif
500                                        EndIf
501                                       
502                                        // increment all of the counters now since done==1 here and I'm sure to exit and get another neutron
503                                        NScatterEvents += index         //total number of scattering events
504                                        if(index == 1 && incoherentEvent == 1)
505                                                NSingleIncoherent += 1
506                                        endif
507                                        if(index == 1 && coherentEvent == 1)
508                                                NSingleCoherent += 1
509                                        endif
510                                        if(index == 2 && coherentEvent == 1 && incoherentEvent == 0)
511                                                NDoubleCoherent += 1
512                                        endif
513                                        if(index > 1)
514                                                NMultipleScatter += 1
515                                        endif
516                                        //Print "n1,index (x,y) = ",n1,index, xpixel,ypixel
517                                       
518                                else    // if neutron escaped without interacting
519                               
520                                        // then it must be a transmitted neutron
521                                        // don't need to calculate, just increment the proper counters
522                                        MC_linear_data[xCtr][yCtr] += 1
523                                        isOn += 1
524                                        nt[0] += 1
525                                       
526                                endif           //if interacted
527                        ENDIF
528                while (!done)
529        while(n1 < imon)
530
531//      Print "Monte Carlo Done"
532        results[0] = n1
533        results[1] = n2
534        results[2] = isOn
535        results[3] = NScatterEvents             //sum of # of times that neutrons scattered
536        results[4] = NSingleCoherent            //# of events that are single, coherent
537        results[5] = NDoubleCoherent
538        results[6] = NMultipleScatter           //# of multiple scattering events
539       
540//      Print "# absorbed = ",n3
541
542//      trans_th = exp(-sig_total*thick)
543//      TRANS_exp = (N1-N2) / N1                        // Transmission
544        // dsigma/domega assuming isotropic scattering, with no absorption.
545//      Print "trans_exp = ",trans_exp
546//      Print "total # of neutrons reaching 2D detector",isOn
547//      Print "fraction of incident neutrons reaching detector ",isOn/iMon
548       
549//      Print "Total number of neutrons = ",N1
550//      Print "Total number of neutrons that interact = ",N2
551//      Print "Fraction of singly scattered neutrons = ",sum(j1,-inf,inf)/N2
552//      results[2] = N2                                         //number that scatter
553//      results[3] = isOn - MC_linear_data[xCtr][yCtr]                  //# scattered reaching detector minus zero angle
554
555       
556//      Tabs = (N1-N3)/N1
557//      Ttot = (N1-N2)/N1
558//      I1_sumI = NN[0]/(N2-N3)
559//      Print "Tabs = ",Tabs
560//      Print "Transmitted neutrons = ",Ttot
561//      results[8] = Ttot
562//      Print "I1 / all I1 = ", I1_sumI
563
564End
565////////        end of main function for calculating multiple scattering
566
567
568// returns the random deviate as a wave
569// and the total SAS cross-section [1/cm] sig_sas
570Function CalculateRandomDeviate(func,coef,lam,outWave,SASxs)
571        FUNCREF SANSModelAAO_MCproto func
572        WAVE coef
573        Variable lam
574        String outWave
575        Variable &SASxs
576
577        Variable nPts_ran=10000,qu
578        qu = 4*pi/lam           
579       
580// hard-wired into the Simulation directory rather than the SAS folder.
581// plotting resolution-smeared models won't work any other way
582        Make/O/N=(nPts_ran)/D root:Simulation:Gq,root:Simulation:xw             // if these waves are 1000 pts, the results are "pixelated"
583        WAVE Gq = root:Simulation:gQ
584        WAVE xw = root:Simulation:xw
585        SetScale/I x (0+1e-4),qu*(1-1e-10),"", Gq,xw                    //don't start at zero or run up all the way to qu to avoid numerical errors
586
587/// if all of the coefficients are well-behaved, then the last point is the background
588// and I can set it to zero here (only for the calculation)
589        Duplicate/O coef,tmp_coef
590        Variable num=numpnts(coef)
591        tmp_coef[num-1] = 0
592       
593        xw=x                                                                                            //for the AAO
594        func(tmp_coef,Gq,xw)                                                                    //call as AAO
595
596//      Gq = x*Gq                                                                                                       // SAS approximation
597        Gq = Gq*sin(2*asin(x/qu))/sqrt(1-(x/qu))                        // exact
598        //
599        //
600        Integrate/METH=1 Gq/D=Gq_INT
601       
602//      SASxs = lam*lam/2/pi*Gq_INT[nPts_ran-1]                 //if the approximation is used
603        SASxs = lam*Gq_INT[nPts_ran-1]
604       
605        Gq_INT /= Gq_INT[nPts_ran-1]
606       
607        Duplicate/O Gq_INT $outWave
608
609        return(0)
610End
611
612// returns the random deviate as a wave
613// and the total SAS cross-section [1/cm] sig_sas
614//
615// uses a log spacing of x for better coverage
616// downside is that it doesn't use built-in integrate, which is automatically cumulative
617//
618// --- Currently does not work - since the usage of the random deviate in the MC routine is based on the
619// wave properties of ran_dev, that is it must have the proper scaling and be equally spaced.
620//
621// -- not really sure that this will solve any of the problems with some functions (notably those with power-laws)
622// giving unreasonably large SAS cross sections. (>>10)
623//
624Function CalculateRandomDeviate_log(func,coef,lam,outWave,SASxs)
625        FUNCREF SANSModelAAO_MCproto func
626        WAVE coef
627        Variable lam
628        String outWave
629        Variable &SASxs
630
631        Variable nPts_ran=1000,qu,qmin,ii
632        qmin=1e-5
633        qu = 4*pi/lam           
634
635// hard-wired into the Simulation directory rather than the SAS folder.
636// plotting resolution-smeared models won't work any other way
637        Make/O/N=(nPts_ran)/D root:Simulation:Gq,root:Simulation:xw             // if these waves are 1000 pts, the results are "pixelated"
638        WAVE Gq = root:Simulation:gQ
639        WAVE xw = root:Simulation:xw
640//      SetScale/I x (0+1e-4),qu*(1-1e-10),"", Gq,xw                    //don't start at zero or run up all the way to qu to avoid numerical errors
641        xw =  alog(log(qmin) + x*((log(qu)-log(qmin))/nPts_ran))
642
643/// if all of the coefficients are well-behaved, then the last point is the background
644// and I can set it to zero here (only for the calculation)
645        Duplicate/O coef,tmp_coef
646        Variable num=numpnts(coef)
647        tmp_coef[num-1] = 0
648       
649        func(tmp_coef,Gq,xw)                                                                    //call as AAO
650        Gq = Gq*sin(2*asin(xw/qu))/sqrt(1-(xw/qu))                      // exact
651
652       
653        Duplicate/O Gq Gq_INT
654        Gq_INT = 0
655        for(ii=0;ii<nPts_ran;ii+=1)
656                Gq_INT[ii] = AreaXY(xw,Gq,qmin,xw[ii])
657        endfor
658       
659        SASxs = lam*Gq_INT[nPts_ran-1]
660       
661        Gq_INT /= Gq_INT[nPts_ran-1]
662       
663        Duplicate/O Gq_INT $outWave
664
665        return(0)
666End
667
668ThreadSafe Function FindPixel(testQ,testPhi,lam,sdd,pixSize,xCtr,yCtr,xPixel,yPixel)
669        Variable testQ,testPhi,lam,sdd,pixSize,xCtr,yCtr,&xPixel,&yPixel
670
671        Variable theta,dy,dx,qx,qy
672        //decompose to qx,qy
673        qx = testQ*cos(testPhi)
674        qy = testQ*sin(testPhi)
675
676        //convert qx,qy to pixel locations relative to # of pixels x, y from center
677        theta = 2*asin(qy*lam/4/pi)
678        dy = sdd*tan(theta)
679        yPixel = round(yCtr + dy/pixSize)
680       
681        theta = 2*asin(qx*lam/4/pi)
682        dx = sdd*tan(theta)
683        xPixel = round(xCtr + dx/pixSize)
684
685        //if on detector, return xPix and yPix values, otherwise -1
686        if(yPixel > 127 || yPixel < 0)
687                yPixel = -1
688        endif
689        if(xPixel > 127 || xPixel < 0)
690                xPixel = -1
691        endif
692       
693        return(0)
694End
695
696Function MC_CheckFunctionAndCoef(funcStr,coefStr)
697        String funcStr,coefStr
698       
699        SVAR/Z listStr=root:Packages:NIST:coefKWStr
700        if(SVAR_Exists(listStr) == 1)
701                String properCoefStr = StringByKey(funcStr, listStr  ,"=",";",0)
702                if(cmpstr("",properCoefStr)==0)
703                        return(0)               //false, no match found, so properCoefStr is returned null
704                endif
705                if(cmpstr(coefStr,properCoefStr)==0)
706                        return(1)               //true, the coef is the correct match
707                endif
708        endif
709        return(0)                       //false, wrong coef
710End
711
712Function/S MC_getFunctionCoef(funcStr)
713        String funcStr
714
715        SVAR/Z listStr=root:Packages:NIST:coefKWStr
716        String coefStr=""
717        if(SVAR_Exists(listStr) == 1)
718                coefStr = StringByKey(funcStr, listStr  ,"=",";",0)
719        endif
720        return(coefStr)
721End
722
723Function SANSModelAAO_MCproto(w,yw,xw)
724        Wave w,yw,xw
725       
726        Print "in SANSModelAAO_MCproto function"
727        return(1)
728end
729
730Function/S MC_FunctionPopupList()
731        String list,tmp
732        list = FunctionList("*",";","KIND:10")          //get every user defined curve fit function
733
734        //now start to remove everything the user doesn't need to see...
735               
736        tmp = FunctionList("*_proto",";","KIND:10")             //prototypes
737        list = RemoveFromList(tmp, list  ,";")
738        //prototypes that show up if GF is loaded
739        list = RemoveFromList("GFFitFuncTemplate", list)
740        list = RemoveFromList("GFFitAllAtOnceTemplate", list)
741        list = RemoveFromList("NewGlblFitFunc", list)
742        list = RemoveFromList("NewGlblFitFuncAllAtOnce", list)
743        list = RemoveFromList("GlobalFitFunc", list)
744        list = RemoveFromList("GlobalFitAllAtOnce", list)
745        list = RemoveFromList("GFFitAAOStructTemplate", list)
746        list = RemoveFromList("NewGF_SetXWaveInList", list)
747        list = RemoveFromList("NewGlblFitFuncAAOStruct", list)
748       
749        // more to remove as a result of 2D/Gizmo
750        list = RemoveFromList("A_WMRunLessThanDelta", list)
751        list = RemoveFromList("WMFindNaNValue", list)
752        list = RemoveFromList("WM_Make3DBarChartParametricWave", list)
753        list = RemoveFromList("UpdateQxQy2Mat", list)
754        list = RemoveFromList("MakeBSMask", list)
755       
756        // MOTOFIT/GenFit bits
757        tmp = "GEN_allatoncefitfunc;GEN_fitfunc;GetCheckBoxesState;MOTO_GFFitAllAtOnceTemplate;MOTO_GFFitFuncTemplate;MOTO_NewGF_SetXWaveInList;MOTO_NewGlblFitFunc;MOTO_NewGlblFitFuncAllAtOnce;"
758        list = RemoveFromList(tmp, list  ,";")
759
760        // SANS Reduction bits
761        tmp = "ASStandardFunction;Ann_1D_Graph;Avg_1D_Graph;BStandardFunction;CStandardFunction;Draw_Plot1D;MyMat2XYZ;NewDirection;SANSModelAAO_MCproto;Monte_SANS_Threaded;Monte_SANS_NotThreaded;Monte_SANS_W1;Monte_SANS_W2;"
762        list = RemoveFromList(tmp, list  ,";")
763        list = RemoveFromList("Monte_SANS", list)
764
765        tmp = FunctionList("f*",";","NPARAMS:2")                //point calculations
766        list = RemoveFromList(tmp, list  ,";")
767       
768        tmp = FunctionList("fSmear*",";","NPARAMS:3")           //smeared dependency calculations
769        list = RemoveFromList(tmp, list  ,";")
770       
771        //non-fit functions that I can't seem to filter out
772        list = RemoveFromList("BinaryHS_PSF11;BinaryHS_PSF12;BinaryHS_PSF22;EllipCyl_Integrand;PP_Inner;PP_Outer;Phi_EC;TaE_Inner;TaE_Outer;",list,";")
773////////////////
774
775        //more functions from analysis models (2008)
776        tmp = "Barbell_Inner;Barbell_Outer;Barbell_integrand;BCC_Integrand;Integrand_BCC_Inner;Integrand_BCC_Outer;"
777        list = RemoveFromList(tmp, list  ,";")
778        tmp = "CapCyl;CapCyl_Inner;CapCyl_Outer;ConvLens;ConvLens_Inner;ConvLens_Outer;"
779        list = RemoveFromList(tmp, list  ,";")
780        tmp = "Dumb;Dumb_Inner;Dumb_Outer;FCC_Integrand;Integrand_FCC_Inner;Integrand_FCC_Outer;"
781        list = RemoveFromList(tmp, list  ,";")
782        tmp = "Integrand_SC_Inner;Integrand_SC_Outer;SC_Integrand;SphCyl;SphCyl_Inner;SphCyl_Outer;"
783        list = RemoveFromList(tmp, list  ,";")
784
785        //simplify the display, forcing smeared calculations behind the scenes
786        tmp = FunctionList("Smear*",";","NPARAMS:1")            //smeared dependency calculations
787        list = RemoveFromList(tmp, list  ,";")
788
789        if(strlen(list)==0)
790                list = "No functions plotted"
791        endif
792       
793        list = SortList(list)
794       
795        list = "default;"+list
796        return(list)
797End             
798
799
800//Function Scat_Angle(Ran,R_DAB,wavelength)
801//      Variable Ran,r_dab,wavelength
802//
803//      Variable qq,arg,theta
804//      qq = 1. / ( R_DAB*sqrt(1.0/Ran - 1.0) )
805//      arg = qq*wavelength/(4*pi)
806//      If (arg < 1.0)
807//              theta = 2.*asin(arg)
808//      else
809//              theta = pi
810//      endif
811//      Return (theta)
812//End
813
814//calculates new direction (xyz) from an old direction
815//theta and phi don't change
816ThreadSafe Function NewDirection(vx,vy,vz,theta,phi)
817        Variable &vx,&vy,&vz
818        Variable theta,phi
819       
820        Variable err=0,vx0,vy0,vz0
821        Variable nx,ny,mag_xy,tx,ty,tz
822       
823        //store old direction vector
824        vx0 = vx
825        vy0 = vy
826        vz0 = vz
827       
828        mag_xy = sqrt(vx0*vx0 + vy0*vy0)
829        if(mag_xy < 1e-12)
830                //old vector lies along beam direction
831                nx = 0
832                ny = 1
833                tx = 1
834                ty = 0
835                tz = 0
836        else
837                Nx = -Vy0 / Mag_XY
838                Ny = Vx0 / Mag_XY
839                Tx = -Vz0*Vx0 / Mag_XY
840                Ty = -Vz0*Vy0 / Mag_XY
841                Tz = Mag_XY
842        endif
843       
844        //new scattered direction vector
845        Vx = cos(phi)*sin(theta)*Tx + sin(phi)*sin(theta)*Nx + cos(theta)*Vx0
846        Vy = cos(phi)*sin(theta)*Ty + sin(phi)*sin(theta)*Ny + cos(theta)*Vy0
847        Vz = cos(phi)*sin(theta)*Tz + cos(theta)*Vz0
848       
849        Return(err)
850End
851
852ThreadSafe Function path_len(aval,sig_tot)
853        Variable aval,sig_tot
854       
855        Variable retval
856       
857        retval = -1*ln(1-aval)/sig_tot
858       
859        return(retval)
860End
861
862// globals are initialized in SASCALC.ipf
863// coordinates if I make this part of the panel - but this breaks other things...
864//
865//Proc MC_SASCALC()
866////    PauseUpdate; Silent 1           // building window...
867//
868////    NewPanel /W=(92,556,390,1028)/K=1 as "SANS Simulator"
869//      SetVariable MC_setvar0,pos={491,73},size={144,15},bodyWidth=80,title="# of neutrons"
870//      SetVariable MC_setvar0,format="%5.4g"
871//      SetVariable MC_setvar0,limits={-inf,inf,100},value= root:Packages:NIST:SAS:gImon
872//      SetVariable MC_setvar0_1,pos={491,119},size={131,15},bodyWidth=60,title="Thickness (cm)"
873//      SetVariable MC_setvar0_1,limits={-inf,inf,0.1},value= root:Packages:NIST:SAS:gThick
874//      SetVariable MC_setvar0_2,pos={491,96},size={149,15},bodyWidth=60,title="Incoherent XS (cm)"
875//      SetVariable MC_setvar0_2,limits={-inf,inf,0.1},value= root:Packages:NIST:SAS:gSig_incoh
876//      SetVariable MC_setvar0_3,pos={491,142},size={150,15},bodyWidth=60,title="Sample Radius (cm)"
877//      SetVariable MC_setvar0_3,limits={-inf,inf,0.1},value= root:Packages:NIST:SAS:gR2
878//      PopupMenu MC_popup0,pos={476,13},size={165,20},proc=MC_ModelPopMenuProc,title="Model Function"
879//      PopupMenu MC_popup0,mode=1,value= #"MC_FunctionPopupList()"
880//      Button MC_button0,pos={480,181},size={130,20},proc=MC_DoItButtonProc,title="Do MC Simulation"
881//      Button MC_button1,pos={644,181},size={80,20},proc=MC_Display2DButtonProc,title="Show 2D"
882//      SetVariable setvar0_3,pos={568,484},size={50,20},disable=1
883//      GroupBox group0,pos={478,42},size={267,130},title="Monte Carlo"
884//      SetVariable cntVar,pos={653,73},size={80,15},proc=CountTimeSetVarProc,title="time(s)"
885//      SetVariable cntVar,format="%d"
886//      SetVariable cntVar,limits={1,10,1},value= root:Packages:NIST:SAS:gCntTime
887//     
888//      String fldrSav0= GetDataFolder(1)
889//      SetDataFolder root:Packages:NIST:SAS:
890//      Edit/W=(476,217,746,450)/HOST=#  results_desc,results
891//      ModifyTable format(Point)=1,width(Point)=0,width(results_desc)=150
892//      SetDataFolder fldrSav0
893//      RenameWindow #,T_results
894//      SetActiveSubwindow ##
895EndMacro
896
897// as a stand-alone panel, extra control bar  (right) and subwindow implementations don't work right
898// for various reasons...
899Window MC_SASCALC() : Panel
900        PauseUpdate; Silent 1           // building window...
901        NewPanel /W=(92,556,713,818)/K=1 as "SANS Simulator"
902        SetVariable MC_setvar0,pos={28,73},size={144,15},bodyWidth=80,title="# of neutrons"
903        SetVariable MC_setvar0,format="%5.4g"
904        SetVariable MC_setvar0,limits={-inf,inf,100},value= root:Packages:NIST:SAS:gImon
905        SetVariable MC_setvar0_1,pos={28,119},size={131,15},bodyWidth=60,title="Thickness (cm)"
906        SetVariable MC_setvar0_1,limits={-inf,inf,0.1},value= root:Packages:NIST:SAS:gThick
907        SetVariable MC_setvar0_2,pos={28,96},size={149,15},bodyWidth=60,title="Incoherent XS (cm)"
908        SetVariable MC_setvar0_2,limits={-inf,inf,0.1},value= root:Packages:NIST:SAS:gSig_incoh
909        SetVariable MC_setvar0_3,pos={28,142},size={150,15},bodyWidth=60,title="Sample Radius (cm)"
910        SetVariable MC_setvar0_3,limits={-inf,inf,0.1},value= root:Packages:NIST:SAS:gR2
911        PopupMenu MC_popup0,pos={13,13},size={165,20},proc=MC_ModelPopMenuProc,title="Model Function"
912        PopupMenu MC_popup0,mode=1,value= #"MC_FunctionPopupList()"
913        Button MC_button0,pos={17,181},size={130,20},proc=MC_DoItButtonProc,title="Do MC Simulation"
914        Button MC_button0,fColor=(3,52428,1)
915        Button MC_button1,pos={17,208},size={80,20},proc=MC_Display2DButtonProc,title="Show 2D"
916        SetVariable setvar0_3,pos={105,484},size={50,20},disable=1
917        GroupBox group0,pos={15,42},size={267,130},title="Monte Carlo"
918        SetVariable cntVar,pos={190,73},size={80,15},proc=CountTimeSetVarProc,title="time(s)"
919        SetVariable cntVar,format="%d"
920        SetVariable cntVar,limits={1,60,1},value= root:Packages:NIST:SAS:gCntTime
921        Button MC_button2,pos={17,234},size={100,20},proc=SaveAsVAXButtonProc,title="Save 2D VAX"
922        CheckBox check0,pos={216,180},size={68,14},title="Raw counts",variable = root:Packages:NIST:SAS:gRawCounts
923        CheckBox check0_1,pos={216,199},size={60,14},title="Yes Offset",variable= root:Packages:NIST:SAS:gDoTraceOffset
924       
925        String fldrSav0= GetDataFolder(1)
926        SetDataFolder root:Packages:NIST:SAS:
927        Edit/W=(344,23,606,248)/HOST=#  results_desc,results
928        ModifyTable format(Point)=1,width(Point)=0,width(results_desc)=150
929        SetDataFolder fldrSav0
930        RenameWindow #,T_results
931        SetActiveSubwindow ##
932EndMacro
933
934Function CountTimeSetVarProc(sva) : SetVariableControl
935        STRUCT WMSetVariableAction &sva
936
937        switch( sva.eventCode )
938                case 1: // mouse up
939                case 2: // Enter key
940                case 3: // Live update
941                        Variable dval = sva.dval
942
943                        // get the neutron flux, multiply, and reset the global for # neutrons
944                        NVAR imon=root:Packages:NIST:SAS:gImon
945                        imon = dval*beamIntensity()
946                       
947                        break
948        endswitch
949
950        return 0
951End
952
953
954Function MC_ModelPopMenuProc(pa) : PopupMenuControl
955        STRUCT WMPopupAction &pa
956
957        switch( pa.eventCode )
958                case 2: // mouse up
959                        Variable popNum = pa.popNum
960                        String popStr = pa.popStr
961                        SVAR gStr = root:Packages:NIST:SAS:gFuncStr
962                        gStr = popStr
963                       
964                        break
965        endswitch
966
967        return 0
968End
969
970Function MC_DoItButtonProc(ba) : ButtonControl
971        STRUCT WMButtonAction &ba
972
973        switch( ba.eventCode )
974                case 2: // mouse up
975                        // click code here
976                        NVAR doMC = root:Packages:NIST:SAS:gDoMonteCarlo
977                        doMC = 1
978                        ReCalculateInten(1)
979                        doMC = 0                //so the next time won't be MC
980                        break
981        endswitch
982
983        return 0
984End
985
986
987Function MC_Display2DButtonProc(ba) : ButtonControl
988        STRUCT WMButtonAction &ba
989
990        switch( ba.eventCode )
991                case 2: // mouse up
992                        // click code here
993                        Execute "ChangeDisplay(\"SAS\")"
994                        break
995        endswitch
996
997        return 0
998End
999
1000// after a 2d data image is averaged in the usual way, take the waves and generate a "fake" folder of the 1d
1001// data, to appear as if it was loaded from a real data file.
1002//
1003// currently only works with SANS data, but can later be expanded to generate fake USANS data sets
1004//
1005Function        Fake1DDataFolder(qval,aveint,sigave,sigmaQ,qbar,fSubs,dataFolder)
1006        WAVE qval,aveint,sigave,sigmaQ,qbar,fSubs
1007        String dataFolder
1008
1009        String baseStr=dataFolder
1010        if(DataFolderExists("root:"+baseStr))
1011                SetDataFolder $("root:"+baseStr)
1012        else
1013                NewDataFolder/S $("root:"+baseStr)
1014        endif
1015
1016        ////overwrite the existing data, if it exists
1017        Duplicate/O qval, $(baseStr+"_q")
1018        Duplicate/O aveint, $(baseStr+"_i")
1019        Duplicate/O sigave, $(baseStr+"_s")
1020//      Duplicate/O sigmaQ, $(baseStr+"sq")
1021//      Duplicate/O qbar, $(baseStr+"qb")
1022//      Duplicate/O fSubS, $(baseStr+"fs")
1023
1024        // need to switch based on SANS/USANS
1025        if (isSANSResolution(sigave[0]))                //checks to see if the first point of the wave is <0]
1026                // make a resolution matrix for SANS data
1027                Variable np=numpnts(qval)
1028                Make/D/O/N=(np,4) $(baseStr+"_res")
1029                Wave res=$(baseStr+"_res")
1030               
1031                res[][0] = sigmaQ[p]            //sigQ
1032                res[][1] = qBar[p]              //qBar
1033                res[][2] = fSubS[p]             //fShad
1034                res[][3] = qval[p]              //Qvalues
1035               
1036                // keep a copy of everything in SAS too... the smearing wrapper function looks for
1037                // data in folders based on waves it is passed - an I lose control of that
1038                Duplicate/O res, $("root:Packages:NIST:SAS:"+baseStr+"_res")
1039                Duplicate/O qval,  $("root:Packages:NIST:SAS:"+baseStr+"_q")
1040                Duplicate/O aveint,  $("root:Packages:NIST:SAS:"+baseStr+"_i")
1041                Duplicate/O sigave,  $("root:Packages:NIST:SAS:"+baseStr+"_s")
1042        else
1043                //the data is USANS data
1044                // nothing done here yet
1045//              dQv = -$w3[0]
1046               
1047//              USANS_CalcWeights(baseStr,dQv)
1048               
1049        endif
1050
1051        //clean up             
1052        SetDataFolder root:
1053       
1054End
1055
1056// writes out a VAX binary data file
1057// automatically generates a name
1058// will prompt for the sample label
1059//
1060Function SaveAsVAXButtonProc(ctrlName) : ButtonControl
1061        String ctrlName
1062
1063        WriteVAXData("SAS","",0)
1064End
1065
1066
1067
1068
1069/////UNUSED, testing routines that have not been updated to work with SASCALC
1070//
1071//Macro Simulate2D_MonteCarlo(imon,r1,r2,xCtr,yCtr,sdd,thick,wavelength,sig_incoh,funcStr)
1072//      Variable imon=100000,r1=0.6,r2=0.8,xCtr=100,yCtr=64,sdd=400,thick=0.1,wavelength=6,sig_incoh=0.1
1073//      String funcStr
1074//      Prompt funcStr, "Pick the model function", popup,       MC_FunctionPopupList()
1075//     
1076//      String coefStr = MC_getFunctionCoef(funcStr)
1077//      Variable pixSize = 0.5          // can't have 11 parameters in macro!
1078//     
1079//      if(!MC_CheckFunctionAndCoef(funcStr,coefStr))
1080//              Abort "The coefficients and function type do not match. Please correct the selections in the popup menus."
1081//      endif
1082//     
1083//      Make/O/D/N=10 root:Packages:NIST:SAS:results
1084//      Make/O/T/N=10 root:Packages:NIST:SAS:results_desc
1085//     
1086//      RunMonte(imon,r1,r2,xCtr,yCtr,sdd,pixSize,thick,wavelength,sig_incoh,funcStr,coefStr,results)
1087//     
1088//End
1089//
1090//Function RunMonte(imon,r1,r2,xCtr,yCtr,sdd,pixSize,thick,wavelength,sig_incoh,funcStr,coefStr)
1091//      Variable imon,r1,r2,xCtr,yCtr,sdd,pixSize,thick,wavelength,sig_incoh
1092//      String funcStr,coefStr
1093//      WAVE results
1094//     
1095//      FUNCREF SANSModelAAO_MCproto func=$funcStr
1096//     
1097//      Monte_SANS(imon,r1,r2,xCtr,yCtr,sdd,pixSize,thick,wavelength,sig_incoh,sig_sas,ran_dev,linear_data,results)
1098//End
1099//
1100////// END UNUSED BLOCK
Note: See TracBrowser for help on using the repository browser.