source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/Polarization/Pol_PolarizationPanels.ipf @ 1094

Last change on this file since 1094 was 916, checked in by srkline, 10 years ago

Changes to the panel sizes to accommodate smaller screens on laptops. Resized some panels and reorganized some of the controls. Help files have been updated to reflect these changes.

Added function to rename raw data files by copying file on disk, then writing in the new file number to the header. Solves the ICE problem of duplicated run numbers. In NCNR_DataReadWrite. See RenumberRunNumber?

Added new functions to the EventModeProcessing? to split large files (stream mode) and decimate when they are read back in. Added features to the event editing to automatically detect steps, and to show the differential with the data. Panel has improved layout. Still in the beta phase with these new features.

File size: 47.5 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma IgorVersion=6.1
3
4
5
6// **** search for TODO to find items still to be fixed in other procedures  **********
7
8// TODO:
9// x- on the decay panel. need to be able to manually enter a date that is to or an offset
10//              number of hours. currently it takes the first file as t=0, which is often not correct
11//
12
13
14// Polarized Beam Reduction Procedures
15//
16//
17// input panels to set and calculate polarization parameters necessary for the
18// matrix corrections to the cross sections
19//
20// -1- Fundamental Cell Parameters -- these are constants, generally not editable. (this file)
21// -2- Decay Parameters -- these are fitted values based on transmission mearurements (this file)
22// -3- Flipper Panel is in its own procedure (Pol_FlipperPanel.ipf)
23// -4- PolCor_Panel is in Pol_PolarizationCorrection.ipf
24//
25//
26// Driven by 4 panels to get the necessary information from the users
27// -1- Fundamental cell parameters: root:Packages:NIST:Polarization:Cells
28//              - default cell parameters are loaded. More cell definitions can be added as more cells are used
29//              - changes are saved per experiment
30//              - important parameters are held in global key=value strings gCell_<name>
31//              - cell names and parameters are used by the 2nd panel for calculation of the Decay constant
32//
33// -2- Decay Constant Panel
34//              - decay constant determined for each cell.
35//              - popping the cell name makes 2 waves, Decay_<cellname> and DecayCalc_<cellname>
36//              - Decay_ is the wave presented in the table. Specified transmission run numbers are entered
37//                      and "Calc Sel Row" does the calculation of mu and Pcell (for all rows, actually)
38//              - DimLabels are used for the arrays to make the column identity more readable than simply an index
39//              - time=0 is taken from the first file
40//              - Calculations are based on the count rate of the file, corrected for monitor and attenuation
41//              - alerts are posted for files in any row that are not at the same attenuation or SDD
42//              - if "include" column is == 1, that row will be included in the fit of the decay data
43//              - excluded points are plotted in red
44//              - results of the fit are printed on the panel, and written to the wave note of the Decay_ wave
45//                      (not DecayCalc_) for use in the next panel
46//              - manual entry of all of the parameters in the wave note is allowed.
47//
48//
49// -3- Flipper Panel (not in this procedure - in Pol_FlipperPanel.ipf)
50//              - calculates the flipper and supermirror efficiencies for a given "condition"
51//              - this "condition" may have contributions from multiple cells
52//              - start by entering a condition name
53//              - Waves Cond_<condition> and CondCalc_<condition>, and CondCell are created
54//              - DimLabels are used for the arrays to make the column identity more readable than simply an index
55//              - Enter the name of the cell in the first column (the cell must be defined and decay calculated)
56//              - enter transmission run numbers as specified in the table
57//              - Do Average will calculate the Psm and PsmPfl values (and errors) and average if more than
58//                      one row of data is present (and included)
59//              - results are printed on the panel, and written to the wave note of Cond_<condition>
60//              - results are used in the calculation of the polarization matrix
61//              - (the cell name is not entered using a contextual menu, since this is difficult for a subwindow)
62//              - (the wave note no longer needs the cell name)
63//
64// -4- PolCor_Panel (not in this procedure - in Pol_PolarizationCorrection.ipf)
65//              - gets all of the parameters from the user to do the polariztion correction, then the "normal" SANS reduction
66//              - up to 10 files can be added together for each of the different spin states (more than this??)
67//              - one polarization condition is set for everything with the popup @ the top
68//              - two-column list boxes for each state hold the run number and the cell name
69//              - the same list boxes are duplicated (hidden) for the SAM/EMP/BGD tabs as needed
70//              - on loading of the data, the 2-letter spin state is tagged onto the loaded waves (all of them)
71//              - displayed data is simply re-pointed to the desired data
72//              - on loading, the raw files are added together as ususal, normalized to monitor counts. Then each contribution
73//                      of the file to the polarization matrix is added (scaling each by mon/1e8)
74//              - loaded data and PolMatrix are stored in the ususal SAM, EMP, BGD folders.
75//              - Polarization correction is done with one click (one per tab). "_pc" tags are added to the resulting names,
76//                      and copies of all of the associated waves are again copied (wasteful), but makes switching display very easy
77//              - Once all of the polarization correction is done, then the UU_pc (etc.) data can be reduced as usual (xx_pc = 4 passes)
78//              - protocol is built as ususal, from this panel only (since the SAM, EMP, and BGD need to be switched, rather than loaded
79//              - protocols can be saved/recalled.
80//              - reduction will always ask for a protocol rather than using what's on the panel.
81//              - closing the panel will save the state (except the protocol). NOT initializing when re-opening will restore the
82//                      state of the entered runs and the popups of conditions.
83//
84//
85//
86//
87
88
89
90// for the menu
91Menu "Macros"
92        "Flipping Ratio",ShowFlippingRatioPanel()
93        "1 Fundamental Cell Parameters",ShowCellParamPanel()
94        "2 Cell Decay",ShowCellDecayPanel()
95        "3 Flipper States",ShowFlipperPanel()
96        "4 Polarization Correction",ShowPolCorSetup()
97        "-"
98        Submenu "Save State of..."
99                "Fundamental Cell Parameters",SaveCellParameterTable()
100                "Cell Decay Panel",SaveCellDecayTable()
101                "Flipper Condition Panel",SaveFlipperTable()
102                "Polarization Correction Panel",SavePolCorPanelState()
103        End
104        Submenu "Restore State of..."
105                "Fundamental Cell Parameters",RestoreCellParameterTable()
106                "Cell Decay Panel",RestoreCellDecayTable()
107                "Flipper Condition Panel",RestoreFlipperTable()
108                "Polarization Correction Panel",RestorePolCorPanelState()
109        End
110End
111
112
113//
114// Panel -1-
115//
116// Fundamental He cell parameters. Most of these are pre-defined, so that they are supplied as a
117// static table, only edited as parameters are refined.
118//
119// work with this as kwString
120// cell=nameStr
121// lambda=num
122// Te=num
123// err_Te=num
124// mu=num
125// err_mu=num
126//
127//
128// for this panel, the cell parameters are stored as kw strings
129// all of the strings start w/ "gCell_"
130//
131Proc ShowCellParamPanel()
132       
133        // init folders
134        // ASK before initializing cell constants
135        // open the panel
136        DoWindow/F CellParamPanel
137        if(V_flag == 0)
138                InitPolarizationFolders()
139                DoAlert 1,"Do you want to use default parameters?"
140                if(V_flag == 1)
141                        InitPolarizationGlobals()
142                endif
143                Make_HeCell_ParamWaves()
144                DrawCellParamPanel()
145        endif
146        // be sure that the panel is onscreen
147        DoIgorMenu "Control","Retrieve Window"
148end
149
150// setup the data folder, etc
151//
152//
153Function InitPolarizationFolders()
154
155        NewDataFolder/O root:Packages:NIST:Polarization
156        NewDataFolder/O root:Packages:NIST:Polarization:Cells                   //holds the cell constants and waves
157       
158        SetDataFolder root:
159        return(0)
160End
161
162//
163// add more cells here as they are defined,
164//
165// first clear out the list, then rebuild it
166//
167Function InitPolarizationGlobals()
168
169        SetDataFolder root:Packages:NIST:Polarization:Cells
170       
171        String listStr=StringList("gCell_*",";"),item
172        Variable        ii,num=ItemsInList(listStr,";")
173
174        for(ii=0;ii<num;ii+=1)
175                item = StringFromList(ii, listStr,";")
176                SVAR gStr = $item
177                KillStrings/Z gStr
178        endfor
179       
180        //rebuild the list
181        // cell constants
182        String/G gCell_Maverick = "cell=Maverick,lambda=5.0,Te=0.87,err_Te=0.01,mu=3.184,err_mu=0.02,"
183        String/G gCell_Burgundy = "cell=Burgundy,lambda=5.0,Te=0.86,err_Te=0.01,mu=3.138,err_mu=0.015,"
184        String/G gCell_Olaf = "cell=Olaf,lambda=7.5,Te=0.86,err_Te=0.005,mu=2.97,err_mu=0.018,"
185       
186       
187        SetDataFolder root:
188        return(0)
189End
190
191
192// parse strings to fill in waves
193//
194//
195Function Make_HeCell_ParamWaves()
196
197        SetDataFolder root:Packages:NIST:Polarization:Cells
198       
199        String listStr,item
200        Variable num,ii
201       
202        // get a list of the strings
203        listStr=StringList("gCell_*",";")
204        num=ItemsInList(listStr,";")
205        print listStr
206       
207        Make/O/T/N=0 CellName
208        Make/O/D/N=0 lambda,Te,err_Te,mu,err_mu
209
210// when the values are reverted, necessary to get back to zero elements
211        Redimension/N=0 CellName
212        Redimension/N=0 lambda,Te,err_Te,mu,err_mu
213               
214        // parse the strings to fill the table
215        for(ii=0;ii<num;ii+=1)
216                item = StringFromList(ii, listStr,";")
217                SVAR gStr = $item
218                InsertPoints  ii, 1, CellName,lambda,Te,err_Te,mu,err_mu
219                CellName[ii] = StringByKey("cell", gStr, "=", ",", 0)
220                lambda[ii] = NumberByKey("lambda", gStr, "=", ",", 0)
221                Te[ii] = NumberByKey("Te", gStr, "=", ",", 0)
222                err_Te[ii] = NumberByKey("err_Te", gStr, "=", ",", 0)
223                mu[ii] = NumberByKey("mu", gStr, "=", ",", 0)
224                err_mu[ii] = NumberByKey("err_mu", gStr, "=", ",", 0)
225               
226        endfor
227
228       
229        SetDataFolder root:
230        return(0)
231End
232
233// take the waves from the table and write these back to the string, only for the current experiment
234//
235Function Save_HeCell_ParamWaves()
236
237        SetDataFolder root:Packages:NIST:Polarization:Cells
238       
239        String listStr,item,dummyStr
240        Variable num,ii
241       
242        // get a list of the strings
243        listStr=StringList("gCell_*",";")
244        num=ItemsInList(listStr,";")
245        KillStrings/Z listStr
246       
247        Wave/T CellName
248        Wave lambda,Te,err_Te,mu,err_mu
249       
250        dummyStr = "cell=Maverick,lambda=5.0,Te=0.87,err_Te=0.01,mu=3.184,err_mu=0.2,"
251       
252        num=numpnts(CellName)
253       
254        // parse the table to fill the Strings
255        for(ii=0;ii<num;ii+=1)
256                item = "gCell_"+CellName[ii]
257                String/G $item = dummyStr
258                SVAR kwListStr = $item
259               
260                kwListStr = ReplaceStringByKey("cell", kwListStr, CellName[ii], "=", ",", 0)
261                kwListStr = ReplaceNumberByKey("lambda", kwListStr, lambda[ii], "=", ",", 0)
262                kwListStr = ReplaceNumberByKey("Te", kwListStr, Te[ii], "=", ",", 0)
263                kwListStr = ReplaceNumberByKey("err_Te", kwListStr, err_Te[ii], "=", ",", 0)
264                kwListStr = ReplaceNumberByKey("mu", kwListStr, mu[ii], "=", ",", 0)
265                kwListStr = ReplaceNumberByKey("err_mu", kwListStr, err_mu[ii], "=", ",", 0)
266               
267        endfor
268
269        SetDataFolder root:
270        return(0)
271End
272
273
274// makes the panel after the waves are generated
275//
276// allow edits of the cells to update the string values
277// add a button to "revert" (with warning)
278// add a button to add new cells (insert a new row in the table, then update)
279//
280Function DrawCellParamPanel()
281
282        SetDataFolder root:Packages:NIST:Polarization:Cells
283       
284        PauseUpdate; Silent 1           // building window...
285        NewPanel /W=(150,44,750,377)/N=CellParamPanel/K=1 as "Fundamental Cell Parameters"
286        ModifyPanel cbRGB=(65535,49151,55704)
287        ModifyPanel fixedSize=1
288
289//      ShowTools/A
290        Button button_0,pos={10,10},size={90,20},proc=AddCellButtonProc,title="Add Cell"
291        Button button_1,pos={118,10},size={160,20},proc=SaveCellParButtonProc,title="Update Parameters"
292        Button button_2,pos={118,35},size={130,20},proc=RevertCellParButtonProc,title="Revert Parameters"
293        Button button_3,pos={520,10},size={35,20},proc=CellHelpParButtonProc,title="?"
294
295        Button button_4,pos={324,10},size={100,20},proc=SaveCellPanelButton,title="Save State"
296        Button button_5,pos={324,35},size={100,20},proc=RestoreCellPanelButton,title="Restore State"
297       
298        Edit/W=(14,60,582,318)/HOST=#
299        ModifyTable width(Point)=0
300        RenameWindow #,T0
301
302        WAVE/T CellName
303        WAVE lambda,Te,err_Te,mu,err_mu
304
305        AppendtoTable/W=# CellName,lambda,Te,err_Te,mu,err_mu
306        SetActiveSubwindow ##
307
308        SetDataFolder root:
309        return(0)
310End
311
312
313Function SaveCellPanelButton(ba) : ButtonControl
314        STRUCT WMButtonAction &ba
315
316        switch( ba.eventCode )
317                case 2: // mouse up
318                        // click code here
319                        SaveCellParameterTable()
320                        break
321                case -1: // control being killed
322                        break
323        endswitch
324
325        return 0
326End
327
328Function RestoreCellPanelButton(ba) : ButtonControl
329        STRUCT WMButtonAction &ba
330
331        switch( ba.eventCode )
332                case 2: // mouse up
333                        // click code here
334                        RestoreCellParameterTable()
335                        break
336                case -1: // control being killed
337                        break
338        endswitch
339
340        return 0
341End
342
343
344
345
346Function CellHelpParButtonProc(ba) : ButtonControl
347        STRUCT WMButtonAction &ba
348
349        switch( ba.eventCode )
350                case 2: // mouse up
351                        // click code here
352                        DisplayHelpTopic/Z/K=1 "Fundamental Cell Parameters"
353                        if(V_flag !=0)
354                                DoAlert 0,"The Cell Parameter Help file could not be found"
355                        endif
356                        break
357                case -1: // control being killed
358                        break
359        endswitch
360
361        return 0
362End
363
364
365Function AddCellButtonProc(ba) : ButtonControl
366        STRUCT WMButtonAction &ba
367
368        switch( ba.eventCode )
369                case 2: // mouse up
370                        // click code here
371                        SetDataFolder root:Packages:NIST:Polarization:Cells
372
373                        WAVE/T CellName
374                        WAVE lambda,Te,err_Te,mu,err_mu
375                        Variable ii= numpnts(CellName)
376                       
377                        InsertPoints  ii, 1, CellName,lambda,Te,err_Te,mu,err_mu
378                       
379                        SetDataFolder root:
380                        break
381                case -1: // control being killed
382                        break
383        endswitch
384
385        return 0
386End
387
388Function SaveCellParButtonProc(ba) : ButtonControl
389        STRUCT WMButtonAction &ba
390
391        switch( ba.eventCode )
392                case 2: // mouse up
393                        // click code here
394                        Save_HeCell_ParamWaves()
395                        break
396                case -1: // control being killed
397                        break
398        endswitch
399
400        return 0
401End
402
403Function RevertCellParButtonProc(ba) : ButtonControl
404        STRUCT WMButtonAction &ba
405
406        switch( ba.eventCode )
407                case 2: // mouse up
408                        // click code here
409                        InitPolarizationGlobals()
410                        Make_HeCell_ParamWaves()
411                        break
412                case -1: // control being killed
413                        break
414        endswitch
415
416        return 0
417End
418
419// END PROCEDURES for He cell parameters
420/////////////////////////////////
421
422
423
424
425
426
427// Decay parameters for each cell. Results are stored in a wave note for each cell
428//
429//      muP=
430//      err_muP=
431// P0=
432//      err_P0=         ? is this needed?
433//      T0=
434// gamma=
435//      err_gamma=
436//
437// str = "muP=2,err_muP=0,P0=0.6,err_P0=0,T0=asdf,gamma=200,err_gamma=0,"
438//
439//
440// for this panel, the cell parameters are stored as kw strings
441// all of the strings start w/ "gDecay_"
442//
443Proc ShowCellDecayPanel()
444       
445        // init folders
446        // ASK before initializing cell constants
447        // open the panel
448        DoWindow/F DecayPanel
449        if(V_flag == 0)
450                InitPolarizationFolders()
451                InitDecayGlobals()
452                DecayParamPanel()
453        endif
454        // be sure that the panel is onscreen
455        DoIgorMenu "Control","Retrieve Window"
456end
457
458Function InitDecayGlobals()
459
460        SetDataFolder root:Packages:NIST:Polarization:Cells
461       
462        String/G gMuPo = "muPo"
463        String/G gPo = "Po"
464        String/G gGamma = "gamma"
465        String/G gT0 = "today's the day"
466       
467       
468        SetDataFolder root:
469        return(0)
470End
471
472
473
474
475// makes the panel for the decay parameter and gamma fitting
476//
477Function DecayParamPanel()
478
479        SetDataFolder root:Packages:NIST:Polarization:Cells
480       
481        PauseUpdate; Silent 1           // building window...
482        NewPanel /W=(200,44,1013,664)/N=DecayPanel/K=1 as "Cell Decay Parameters"
483        ModifyPanel cbRGB=(32768,54615,65535)
484//      Button button_3,pos={505,16},size={35,20},proc=DecayHelpParButtonProc,title="?"
485        PopupMenu popup_0,pos={32,8},size={49,20},title="Cell",proc=DecayPanelPopMenuProc
486        PopupMenu popup_0,mode=1,value= #"D_CellNameList()"
487       
488        Button button_0,pos={560,294},size={70,20},proc=DecayFitButtonProc,title="Do Fit"
489       
490        GroupBox group_0,pos={560,329},size={230,149},title="FIT RESULTS",fSize=10
491        GroupBox group_0,fStyle=1
492        SetVariable setvar_0,pos={570,358},size={200,13},title="muPo of 3He"
493        SetVariable setvar_0,fStyle=1,limits={0,0,0},barmisc={0,1000}
494        SetVariable setvar_0,value= root:Packages:NIST:Polarization:Cells:gMuPo
495        SetVariable setvar_1,pos={570,390},size={200,13},title="Po of 3He"
496        SetVariable setvar_1,fStyle=1,limits={0,0,0},barmisc={0,1000}
497        SetVariable setvar_1,value= root:Packages:NIST:Polarization:Cells:gPo
498        SetVariable setvar_2,pos={570,448},size={200,13},title="Gamma (h)",fStyle=1
499        SetVariable setvar_2,limits={0,0,0},barmisc={0,1000}
500        SetVariable setvar_2,value= root:Packages:NIST:Polarization:Cells:gGamma
501        SetVariable setvar_3,pos={570,418},size={200,13},title="T0",fStyle=1
502        SetVariable setvar_3,limits={0,0,0},value= root:Packages:NIST:Polarization:Cells:gT0
503       
504
505        Button button_1,pos={560,262},size={120,20},proc=CalcRowParamButton,title="Calculate Rows"
506        Button button_2,pos={307,8},size={110,20},proc=ClearDecayWavesButton,title="Clear Table"
507        Button button_3,pos={560,519},size={110,20},proc=ShowCalcRowButton,title="Show Calc"
508        Button button_4,pos={440,8},size={110,20},proc=ClearDecayWavesRowButton,title="Clear Row"
509        Button button_5,pos={620,8},size={40,20},proc=DecayHelpParButtonProc,title="?"
510        Button button_6,pos={560,574},size={110,20},proc=WindowSnapshotButton,title="Snapshot"
511        Button button_7,pos={560,547},size={110,20},proc=ManualEnterDecayButton,title="Manual Entry"
512        Button button_8,pos={690,547},size={110,20},proc=SaveDecayPanelButton,title="Save State"
513        Button button_9,pos={690,574},size={110,20},proc=RestoreDecayPanelButton,title="Restore State"
514        CheckBox check0,mode=0,pos={560,480},title="Overrride T0?",value=0
515
516
517        // table
518        Edit/W=(14,35,794,240)/HOST=#
519        ModifyTable format=1,width=0
520        RenameWindow #,T0
521        SetActiveSubwindow ##
522       
523        // graph
524        Display/W=(15,250,540,610)/HOST=#  //root:yy vs root:xx
525        ModifyGraph frameStyle=2
526        ModifyGraph mode=4
527        ModifyGraph marker=19
528        ModifyGraph rgb=(0,0,0)
529        ModifyGraph msize=2
530
531        Legend
532//      ModifyGraph log(left)=1
533//      ErrorBars yy OFF
534        RenameWindow #,G0
535        SetActiveSubwindow ##
536
537        SetDataFolder root:
538        return(0)
539End
540
541// allows manual entry of Decay values
542//
543// see DecayFitButtonProc
544//
545Function ManualEnterDecayButton(ba) : ButtonControl
546        STRUCT WMButtonAction &ba
547
548        Variable selRow,err=0
549        String fname, t0str, condStr,noteStr,t1Str,cellStr
550
551        t0Str = "31-OCT-2012 19:30:00"
552        switch( ba.eventCode )
553                case 2: // mouse up
554                        // click code here
555                        Variable gamma_val,err_gamma,muPo, err_muPo, Po, err_Po, runNum
556
557                        ControlInfo/W=DecayPanel popup_0
558                        cellStr = S_Value
559                               
560//                      SetDataFolder root:Packages:NIST:Polarization:Cells:
561                       
562                        WAVE decay=$("root:Packages:NIST:Polarization:Cells:Decay_"+cellStr)            //the one that is displayed
563//                      WAVE calc=$("root:Packages:NIST:Polarization:Cells:DecayCalc_"+cellStr)         //with the results
564
565
566                        Prompt Po, "Enter Po: "         
567                        Prompt err_Po, "Enter err_Po: "         
568                        Prompt muPo, "Enter muPo: "             
569                        Prompt err_muPo, "Enter err_muPo: "             
570                        Prompt gamma_val, "Enter gamma: "               
571                        Prompt err_gamma, "Enter err_gamma: "
572                        Prompt t0Str,"Enter the t=0 time DD-MMM-YYYY HH:MM:SS"
573//                      Prompt runNum,"Run number for time=0 of decay" 
574                        DoPrompt "Enter Cell Decay Parameters", Po, err_Po, muPo, err_muPo, gamma_val, err_gamma, t0Str
575                        if (V_Flag)
576                                return -1                                                               // User canceled
577                        endif
578       
579        // enter the time as a string now, rather than from a run number               
580//                      fname = FindFileFromRunNumber(runNum)
581//                      t0str = getFileCreationDate(fname)
582                                       
583//              for the wave note
584                        noteStr = note(decay)
585                        noteStr = ReplaceNumberByKey("muP", noteStr, MuPo ,"=", ",", 0)
586                        noteStr = ReplaceNumberByKey("P0", noteStr, Po ,"=", ",", 0)
587                        noteStr = ReplaceNumberByKey("err_muP", noteStr, err_muPo ,"=", ",", 0)
588                        noteStr = ReplaceNumberByKey("err_P0", noteStr, err_Po ,"=", ",", 0)
589                        noteStr = ReplaceNumberByKey("gamma", noteStr, gamma_val ,"=", ",", 0)
590                        noteStr = ReplaceNumberByKey("err_gamma", noteStr, err_gamma ,"=", ",", 0)
591                        noteStr = ReplaceStringByKey("T0", noteStr, t0Str  ,"=", ",", 0)
592                        // replace the string
593                        Note/K decay
594                        Note decay, noteStr
595
596                        // for the panel display
597                        SVAR gGamma  = root:Packages:NIST:Polarization:Cells:gGamma
598                        SVAR gMuPo = root:Packages:NIST:Polarization:Cells:gMuPo
599                        SVAR gPo  = root:Packages:NIST:Polarization:Cells:gPo           
600                        SVAR gT0 = root:Packages:NIST:Polarization:Cells:gT0
601                       
602                        gT0 = t0Str             //for display
603                        sprintf gMuPo, "%g +/- %g",muPo, err_muPo
604                        sprintf gPo, "%g +/- %g",Po,err_Po
605                        sprintf gGamma, "%g +/- %g",gamma_val,err_gamma
606
607                       
608                        break
609                case -1: // control being killed
610                        break
611        endswitch
612
613        return 0
614End
615
616
617Function DecayPanelPopMenuProc(pa) : PopupMenuControl
618        STRUCT WMPopupAction &pa
619
620        switch( pa.eventCode )
621                case 2: // mouse up
622                        Variable popNum = pa.popNum
623                        String popStr = pa.popStr
624                       
625                        SetDataFolder root:Packages:NIST:Polarization:Cells
626
627                        // based on the selected string, display the right set of inputs
628//                      Print "now I need to display the right set of waves (2D text?) for ",popStr
629
630                        // for the given cell name, if the wave(s) exist, declare them
631                        if(exists("Decay_"+popStr) == 1)
632                                WAVE decay = $("Decay_"+popStr)
633                        else
634                                // if not, make it, and the space for the results of the calculation
635                                MakeDecayResultWaves(popStr)
636                                WAVE decay = $("root:Packages:NIST:Polarization:Cells:Decay_"+popStr)
637                        endif                   
638                        // append matrix, clearing the old one first
639                        SetDataFolder root:Packages:NIST:Polarization:Cells
640
641                        KillWindow DecayPanel#T0
642                        Edit/W=(14,35,794,240)/HOST=DecayPanel
643                        RenameWindow #,T0
644                        AppendtoTable/W=DecayPanel#T0 decay.ld                  //show the labels
645                        ModifyTable width(Point)=0
646                        ModifyTable width(decay.l)=20
647                       
648                        SetActiveSubwindow ##
649       
650                        SetDataFolder root:
651                       
652                        //
653                        // now show the fit results, if any, from the wave note
654                        //
655                        SVAR gMuPo = root:Packages:NIST:Polarization:Cells:gMuPo
656                        SVAR gPo  = root:Packages:NIST:Polarization:Cells:gPo
657                        SVAR gGamma  = root:Packages:NIST:Polarization:Cells:gGamma
658                        SVAR gT0  = root:Packages:NIST:Polarization:Cells:gT0
659                        String nStr=note(decay)
660                       
661
662                        // for the panel display
663                        sprintf gMuPo, "%g +/- %g",NumberByKey("muP", nStr, "=",","),NumberByKey("err_muP", nStr, "=",",")
664                        sprintf gPo, "%g +/- %g",NumberByKey("P0", nStr, "=",","),NumberByKey("err_P0", nStr, "=",",")
665                        sprintf gGamma, "%g +/- %g",NumberByKey("gamma", nStr, "=",","),NumberByKey("err_gamma", nStr, "=",",")
666                        gT0 = StringByKey("T0", nStr, "=",",")
667               
668                       
669                        // clear the graph - force the user to update it manually
670                        // clear old data, and plot the new
671                        //
672                        SetDataFolder root:Packages:NIST:Polarization:Cells:
673
674                        CheckDisplayed/W=DecayPanel#G0 tmp_muP,tmp_muP2,fit_tmp_muP
675                        // if both present, bit 0 + bit 1 = 3
676                        if(V_flag & 2^0)                        //check bit 0
677                                RemoveFromGraph/W=DecayPanel#G0 tmp_muP
678                        endif
679                        if(V_flag & 2^1)
680                                RemoveFromGraph/W=DecayPanel#G0 tmp_muP2
681                        endif
682                        if(V_flag & 2^2)
683                                RemoveFromGraph/W=DecayPanel#G0 fit_tmp_muP
684                        endif
685                       
686                        // kill the text box (name is hard-wired)
687                        TextBox/W=DecayPanel#G0/K/N=CF_tmp_muP
688                       
689                        setDataFolder root:
690                       
691                        break
692                case -1: // control being killed
693                        break
694        endswitch
695
696        return 0
697End
698
699Function MakeDecayResultWaves(popStr)
700        String popStr
701
702        SetDataFolder root:Packages:NIST:Polarization:Cells
703
704        Make/O/D/N=(1,9) $("Decay_"+popStr)
705        WAVE decay = $("Decay_"+popStr)
706        // set the column labels
707        SetDimLabel 1,0,'Trans_He_In?',decay
708        SetDimLabel 1,1,'Trans_He_Out?',decay
709        SetDimLabel 1,2,'Blocked?',decay
710        SetDimLabel 1,3,mu_star,decay
711        SetDimLabel 1,4,Effective_Pol,decay
712        SetDimLabel 1,5,Atomic_Pol,decay
713        SetDimLabel 1,6,T_Major,decay
714        SetDimLabel 1,7,'Include?',decay                        //for a mask wave, non-zero is used in the fit
715        SetDimLabel 1,8,elapsed_hr,decay
716        decay[0][7] = 1                 //default to include the point
717       
718        // generate the dummy wave note now, change as needed
719        Note decay, "muP=0,err_muP=0,P0=0,err_P0=0,T0=undefined,gamma=0,err_gamma=0,"
720       
721        // to hold the results of the calculation
722        Make/O/D/N=(1,14) $("DecayCalc_"+popStr)
723        WAVE decayCalc = $("DecayCalc_"+popStr)
724        SetDimLabel 1,0,CR_Trans_He_In,decayCalc
725        SetDimLabel 1,1,err_CR_Trans_He_In,decayCalc
726        SetDimLabel 1,2,CR_Trans_He_Out,decayCalc
727        SetDimLabel 1,3,err_CR_Trans_He_Out,decayCalc
728        SetDimLabel 1,4,CR_Blocked,decayCalc
729        SetDimLabel 1,5,err_CR_Blocked,decayCalc
730        SetDimLabel 1,6,muPo,decayCalc
731        SetDimLabel 1,7,err_muPo,decayCalc
732        SetDimLabel 1,8,Po,decayCalc
733        SetDimLabel 1,9,err_Po,decayCalc
734        SetDimLabel 1,10,Tmaj,decayCalc
735        SetDimLabel 1,11,err_Tmaj,decayCalc
736        SetDimLabel 1,12,gamm,decayCalc
737        SetDimLabel 1,13,err_gamm,decayCalc     
738
739        SetDataFolder root:
740
741        return(0)
742End
743
744
745// since the "Decay_" table can be edited directly to increase the number of rows, it is tough
746// to increase the number of rows in the "DecayCalc_" wave and keep them in sync.
747//
748// --so make sure that the sizes match, and do them all
749//
750Function CalcRowParamButton(ba) : ButtonControl
751        STRUCT WMButtonAction &ba
752
753        Variable selRow,err=0
754        String fname, t0str, cellStr,noteStr,t1Str
755
756        switch( ba.eventCode )
757                case 2: // mouse up
758                        // click code here
759                        Variable cr1,cr2,cr3,err_cr1,err_cr2,err_cr3
760                        Variable muPo,err_muPo,Po,err_Po,Pcell,err_Pcell,Tmaj,err_Tmaj
761                        //Variable Te,err_Te,mu,err_mu
762                               
763                        ControlInfo/W=DecayPanel popup_0
764                        cellStr = S_Value
765                        WAVE w=$("root:Packages:NIST:Polarization:Cells:Decay_"+cellStr)                //the one that is displayed
766                        WAVE calc=$("root:Packages:NIST:Polarization:Cells:DecayCalc_"+cellStr)         // behind the scenes
767                       
768                        Variable numRows,ncalc,diff
769                        numRows = DimSize(w,0)          //rows in the displayed table
770                        ncalc = DimSize(calc,0)
771                       
772                        // add rows to the DecayCalc_ matrix as needed
773                        if(numRows != ncalc)
774                                if(ncalc > numRows)
775                                        DoAlert 0,"The DecayCalc_ is larger than displayed. Seek help."
776                                        err = 1
777                                        return(err)
778                                else
779                                        diff = numRows - ncalc
780                                        InsertPoints/M=0 ncalc, diff, calc
781                                endif
782                        endif
783                       
784                       
785//                      GetSelection table, DecayPanel#T0, 1
786//                      selRow = V_startRow
787
788                        Variable sum_muP, err_avg_muP, sum_Po, err_avg_Po, avg_muP, avg_Po, overrideT0
789                        sum_muP = 0
790                        sum_Po = 0
791                        err_avg_muP = 0
792                        err_avg_Po = 0
793                       
794                        ControlInfo/W=DecayPanel check0
795                        overrideT0 = V_Value
796                       
797                        for(selRow=0;selRow<numRows;selRow+=1)
798                                Print "calculate the row ",selRow
799
800                                if(selRow == 0 && !overrideT0)
801                                        //find T0
802                                        fname = FindFileFromRunNumber(w[0][%'Trans_He_In?'])
803                                        t0str = getFileCreationDate(fname)
804                                        SVAR gT0 = root:Packages:NIST:Polarization:Cells:gT0
805                                        gT0 = t0Str             //for display
806                                        noteStr = note(w)
807                                        noteStr = ReplaceStringByKey("T0", noteStr, gT0  ,"=", ",", 0)
808                                        Note/K w
809                                        Note w, noteStr
810                                        Print t0str
811                                else
812                                        // manually entered on the panel to override the
813                                        SVAR gT0 = root:Packages:NIST:Polarization:Cells:gT0
814                                        t0Str = gT0
815                                        noteStr = note(w)
816                                        noteStr = ReplaceStringByKey("T0", noteStr, gT0  ,"=", ",", 0)
817                                        Note/K w
818                                        Note w, noteStr
819                                        Print t0str
820                                endif
821                               
822                                // parse the rows, report errors (there, not here), exit if any found
823                                err = ParseDecayRow(w,selRow)
824                                if(err)
825                                        return 0
826                                endif
827                               
828                                // do the calculations:
829                                // 1 for each file, return the count rate and err_CR (normalize to atten or not)
830       
831                                cr1 = TotalCR_FromRun(w[selRow][%'Trans_He_In?'],err_cr1,0)
832                                cr2 = TotalCR_FromRun(w[selRow][%'Trans_He_Out?'],err_cr2,0)
833//                              cr3 = TotalCR_FromRun(w[selRow][%'Blocked?'],err_cr3,1)                 //blocked beam is NOT normalized to zero attenuators
834//                              Print "************The Blocked CR is *NOT* rescaled to zero attenuators -- CalcRowParamButton"
835                                cr3 = TotalCR_FromRun(w[selRow][%'Blocked?'],err_cr3,0)                 //blocked beam is normalized to zero attenuators
836                                Print "************The Blocked CR *is* rescaled to zero attenuators -- CalcRowParamButton "
837
838
839                                calc[selRow][%CR_Trans_He_In] = cr1
840                                calc[selRow][%CR_Trans_He_Out] = cr2
841                                calc[selRow][%CR_Blocked] = cr3
842                                calc[selRow][%err_cr_Trans_He_In] = err_cr1
843                                calc[selRow][%err_cr_Trans_He_Out] = err_cr2
844                                calc[selRow][%err_cr_Blocked] = err_cr3
845       
846       
847                                // 2 find the mu and Te values for cellStr
848                                SVAR gCellKW = $("root:Packages:NIST:Polarization:Cells:gCell_"+cellStr)
849
850        //                     
851                                // 3 Calc muPo and error
852                                muPo = Calc_muPo(calc,gCellKW,selRow,err_muPo)
853                                calc[selRow][%muPo] = muPo
854                                calc[selRow][%err_muPo] = err_muPo
855                                w[selRow][%mu_star] = muPo
856                               
857                                // 3.5 calc Polarization of cell (no value or error stored in calc wave?)
858                                PCell = Calc_PCell(muPo,err_muPo,err_PCell)
859                                w[selRow][%Effective_Pol] = PCell
860       
861                                // 4 calc Po and error
862                                Po = Calc_Po(gCellKW,muPo,err_muPo,err_Po)
863                                calc[selRow][%Po] = Po
864                                calc[selRow][%err_Po] = err_Po
865                                w[selRow][%Atomic_Pol] = Po             //for display
866                               
867                                // 5 calc Tmaj and error
868                                Tmaj = Calc_Tmaj(gCellKW,Po,err_Po,err_Tmaj)
869                                calc[selRow][%Tmaj] = Tmaj
870                                calc[selRow][%err_Tmaj] = err_Tmaj
871                                w[selRow][%T_major] = Tmaj
872                               
873                                // elapsed hours
874                                fname = FindFileFromRunNumber(w[selRow][%'Trans_He_In?'])
875                                t1str = getFileCreationDate(fname)
876                                w[selRow][%elapsed_hr] = ElapsedHours(t0Str,t1Str)
877                               
878                                // running average of muP and Po
879                                sum_muP += muPo
880                                sum_Po += Po
881                                err_avg_muP += err_muPo^2
882                                err_avg_Po += err_Po^2
883                               
884                        endfor          //loop over rows
885
886
887////// 26 APR 12 -- why was I getting a running average of these values??               not sure, so I commented them out...
888//                              they aren't returned or used anywhere...
889//                      // now get a running average of muP, Po, and the errors
890//                      avg_muP = sum_muP/numRows
891//                      avg_Po = sum_Po/numRows
892//                      err_avg_muP = sqrt(err_avg_muP) / numRows
893//                      err_avg_Po = sqrt(err_avg_Po) / numRows
894//     
895//
896//                      Printf "Average muP = %g +/- %g (%g%)\r",avg_muP,err_avg_muP,err_avg_muP/avg_muP*100
897//                      Printf "Average Po = %g +/- %g (%g%)\r",avg_Po,err_avg_Po,err_avg_Po/avg_Po*100
898//                     
899//              E  26 APR 12
900               
901//                      str = "muP=2,err_muP=0,P0=0.6,err_P0=0,T0=asdf,gamma=200,err_gamma=0,"
902
903                        // Don't put the average values into the wave note, but rather the results of the fit
904//                      noteStr = note(w)
905//                      noteStr = ReplaceNumberByKey("muP", noteStr, avg_muP ,"=", ",", 0)
906//                      noteStr = ReplaceNumberByKey("P0", noteStr, avg_Po ,"=", ",", 0)
907//                      noteStr = ReplaceNumberByKey("err_muP", noteStr, err_avg_muP ,"=", ",", 0)
908//                      noteStr = ReplaceNumberByKey("err_P0", noteStr, err_avg_Po ,"=", ",", 0)
909//                     
910//                      // replace the string
911//                      Note/K w
912//                      Note w, noteStr
913                                       
914
915                       
916                        //update the global values for display (not these, but after the fit)
917//                      Print " -- need to add the error to the display on the panel    "
918//                      NVAR gMuPo = root:Packages:NIST:Polarization:Cells:gMuPo
919//                      NVAR gPo  = root:Packages:NIST:Polarization:Cells:gPo
920//                      gMuPo = avg_muP
921//                      gPo = avg_Po
922                       
923                        break
924                case -1: // control being killed
925                        break
926        endswitch
927
928        return 0
929End
930
931
932// calculate Tmaj and its error
933Function Calc_Tmaj(cellStr,Po,err_Po,err_Tmaj)
934        String cellStr
935        Variable Po,err_Po,&err_Tmaj
936       
937        Variable Tmaj,arg
938        Variable Te,err_Te,mu,err_mu
939// cell constants       
940        Te = NumberByKey("Te", cellStr, "=", ",", 0)
941        err_Te = NumberByKey("err_Te", cellStr, "=", ",", 0)
942        mu = NumberByKey("mu", cellStr, "=", ",", 0)
943        err_mu = NumberByKey("err_mu", cellStr, "=", ",", 0)
944       
945        Tmaj = Te*exp(-mu*(1-Po))
946       
947        //the error
948        err_Tmaj = (Tmaj/Te)^2*err_Te^2 + (Tmaj*(1-Po))^2*err_mu^2 + (Tmaj*mu)^2*err_Po^2
949        err_Tmaj = sqrt(err_Tmaj)
950       
951        Printf "Tmaj = %g +/- %g (%g%)\r",Tmaj,err_Tmaj,err_Tmaj/Tmaj*100
952
953       
954        return(Tmaj)
955End
956
957
958// calculate Tmin and its error
959Function Calc_Tmin(cellStr,Po,err_Po,err_Tmin)
960        String cellStr
961        Variable Po,err_Po,&err_Tmin
962       
963        Variable Tmin,arg
964        Variable Te,err_Te,mu,err_mu
965// cell constants       
966        Te = NumberByKey("Te", cellStr, "=", ",", 0)
967        err_Te = NumberByKey("err_Te", cellStr, "=", ",", 0)
968        mu = NumberByKey("mu", cellStr, "=", ",", 0)
969        err_mu = NumberByKey("err_mu", cellStr, "=", ",", 0)
970       
971        Tmin = Te*exp(-mu*(1+Po))
972       
973        //the error
974        err_Tmin = (Tmin/Te)^2*err_Te^2 + (Tmin*(1+Po))^2*err_mu^2 + (Tmin*mu)^2*err_Po^2
975        err_Tmin = sqrt(err_Tmin)
976       
977        Printf "Tmin = %g +/- %g (%g%)\r",Tmin,err_Tmin,err_Tmin/Tmin*100
978
979       
980        return(Tmin)
981End
982
983
984
985// calculate PCell and its error
986//
987//
988Function Calc_PCell(muPo,err_muPo,err_PCell)
989        Variable muPo,err_muPo,&err_PCell
990       
991        Variable PCell,arg
992
993        PCell = tanh(muPo)
994       
995        // error (single term, sqrt already done)
996        err_Pcell = (1 - (tanh(muPo))^2) * err_muPo
997       
998        Printf "Pcell = %g +/- %g (%g%)\r",Pcell,err_Pcell,err_Pcell/PCell*100
999
1000        return(PCell)
1001End
1002
1003// calculate Po and its error
1004Function Calc_Po(cellStr,muPo,err_muPo,err_Po)
1005        String cellStr
1006        Variable muPo,err_muPo,&err_Po
1007       
1008        Variable Po,tmp
1009        Variable mu,err_mu
1010// cell constants       
1011        mu = NumberByKey("mu", cellStr, "=", ",", 0)
1012        err_mu = NumberByKey("err_mu", cellStr, "=", ",", 0)
1013       
1014        Po = muPo/mu
1015       
1016        tmp = (err_muPo/muPo)^2 + (err_mu/mu)^2
1017        err_Po = Po * sqrt(tmp)
1018//      tmp = 1/mu^2*err_muPo^2 + muPo^2/mu^4*err_mu^2
1019//      err_Po = sqrt(tmp)
1020       
1021        Printf "Po = %g +/- %g (%g%)\r",Po,err_Po,err_Po/Po*100
1022        return(Po)
1023End
1024
1025// calculate muPo and its error
1026Function Calc_muPo(calc,cellStr,selRow,err_muPo)
1027        Wave calc
1028        String cellStr
1029        Variable selRow,&err_muPo
1030       
1031        Variable muPo,arg
1032        Variable Te,err_Te,mu,err_mu
1033// cell constants       
1034        Te = NumberByKey("Te", cellStr, "=", ",", 0)
1035        err_Te = NumberByKey("err_Te", cellStr, "=", ",", 0)
1036        mu = NumberByKey("mu", cellStr, "=", ",", 0)
1037        err_mu = NumberByKey("err_mu", cellStr, "=", ",", 0)
1038       
1039        Variable cr1,cr2,cr3,err_cr1,err_cr2,err_cr3
1040        // cr1 is He in, 2 is He out, 3 is blocked
1041        cr1      =      calc[selRow][%CR_Trans_He_In]
1042        cr2 =   calc[selRow][%CR_Trans_He_Out]
1043        cr3 =   calc[selRow][%CR_Blocked]
1044        err_cr1 =       calc[selRow][%err_cr_Trans_He_In]
1045        err_cr2 =       calc[selRow][%err_cr_Trans_He_Out]
1046        err_cr3 =       calc[selRow][%err_cr_Blocked]
1047       
1048        muPo = acosh( (cr1 - cr3)/(cr2 - cr3) * (1/(Te*exp(-mu))) )
1049       
1050        Variable arg_err, tmp1, tmp2
1051        // the error is a big mess to calculate, since it's messy argument inside acosh
1052        arg = (cr1 - cr3)/(cr2 - cr3) * (1/(Te*exp(-mu)))
1053        tmp2 =  (1/sqrt(arg+1)/sqrt(arg-1))^2                                   // derivative of acosh(arg) (squared)
1054       
1055        // calculate the error of the argument first, then the error of acosh(arg)
1056        // there are 5 partial derivatives
1057        arg_err = tmp2 * ( arg/(cr1 - cr3) * err_cr1 )^2                //CR in
1058        arg_err += tmp2 * ( arg/(cr2 - cr3) * err_cr2 )^2       //CR out
1059        arg_err += tmp2 * ((-arg/(cr1 - cr3) +  arg/(cr2 - cr3) )* err_cr3 )^2//CR bkg
1060        arg_err += tmp2 * ( -arg/Te * err_Te )^2                                        //Te
1061        arg_err += tmp2 * ( arg * err_mu )^2                                            //mu  (probably the dominant relative error)
1062       
1063        err_muPo = sqrt(arg_err)
1064       
1065       
1066        return(muPo)
1067End
1068
1069
1070Function testCR(num)
1071        Variable num
1072        Variable err_cr
1073       
1074        Variable noNorm=0
1075        Variable cr = TotalCR_FromRun(num,err_cr,noNorm)
1076        printf "CR = %g +/- %g (%g%)\r",cr,err_cr,err_cr/cr*100
1077        return(0)
1078End
1079
1080// calculate the total detector CR and its error.
1081//
1082// the result is automatically normalized to 10^8 monitor counts, and to zero attenuators
1083//
1084// if noNorm = 1, then the normalization to attenuators is not done
1085//
1086Function TotalCR_FromRun(num,err_cr,noNorm)
1087        Variable num,&err_cr,noNorm
1088
1089        String fname="",instr="",tmpStr=""
1090        Variable cr,cts,err_cts,ctTime,monCts,attenNo,lambda,attenTrans,atten_err
1091       
1092        fname = FindFileFromRunNumber(num)
1093        cts = getDetCount(fname)
1094        err_cts = sqrt(cts)
1095       
1096        ctTime = getCountTime(fname)
1097        monCts = getMonitorCount(fname)
1098        attenNo = getAttenNumber(fname)
1099        instr = getAcctName(fname)              //this is 11 characters
1100        lambda = getWavelength(fname)
1101        attenTrans = AttenuationFactor(instr,lambda,AttenNo,atten_err)
1102       
1103        if(noNorm==1)                   //don't normalize to attenuation
1104                attenTrans=1
1105                atten_err=0
1106        endif
1107        cr = cts/ctTime*1e8/monCts/attenTrans
1108        err_cr = cr * sqrt(err_cts^2/cts^2 + atten_err^2/attenTrans^2)
1109       
1110        printf "CR = %g +/- %g (%g%)\r",cr,err_cr,err_cr/cr*100
1111
1112               
1113        return(cr)
1114end
1115
1116
1117// input is VAX date and time string, t1 later than t0
1118//
1119Function ElapsedHours(t0Str,t1Str)
1120        String t0Str,t1Str
1121       
1122        Variable t0,t1,elapsed
1123       
1124        t0 = ConvertVAXDateTime2Secs(t0Str)             //seconds
1125        t1 = ConvertVAXDateTime2Secs(t1Str)
1126       
1127        elapsed = t1-t0
1128        elapsed /= 3600                 //convert to hours
1129       
1130        return(elapsed)
1131End
1132
1133// bring up a table with the calculation results
1134Function ShowCalcRowButton(ba) : ButtonControl
1135        STRUCT WMButtonAction &ba
1136
1137        switch( ba.eventCode )
1138                case 2: // mouse up
1139                        // click code here
1140                        ControlInfo/W=DecayPanel popup_0
1141                        String cellStr = S_Value
1142                        WAVE calc=$("root:Packages:NIST:Polarization:Cells:DecayCalc_"+cellStr)         //the one that is displayed
1143                        edit calc.ld
1144                                               
1145                        break
1146                case -1: // control being killed
1147                        break
1148        endswitch
1149
1150        return 0
1151End
1152
1153
1154Function DecayFitButtonProc(ba) : ButtonControl
1155        STRUCT WMButtonAction &ba
1156
1157        String cellStr=""
1158        Variable num,plot_P
1159       
1160        plot_P = 1              //plot_Pol as Y, or muP if this == 0
1161
1162        switch( ba.eventCode )
1163                case 2: // mouse up
1164                        // click code here
1165
1166                        ControlInfo/W=DecayPanel popup_0
1167                        cellStr = S_Value
1168                       
1169                        SetDataFolder root:Packages:NIST:Polarization:Cells:
1170                       
1171                        WAVE decay=$("Decay_"+cellStr)          //the one that is displayed
1172                        WAVE calc=$("DecayCalc_"+cellStr)               //the one that is displayed
1173                       
1174//                      make temp copies for the fit and plot, extra for mask
1175                        num = DimSize(calc,0)
1176                        Make/O/D/N=(num)                tmp_Mask,tmp_hr,tmp_Y,tmp_err_Y,tmp_Y2
1177                       
1178                        tmp_Mask = decay[p][%'Include?']
1179                        tmp_hr = decay[p][%elapsed_hr]
1180                       
1181                        if(plot_P == 1)
1182                                tmp_Y = calc[p][%Po]
1183                                tmp_Y2 = tmp_Y
1184                                tmp_err_Y = calc[p][%err_Po]                   
1185                        else            //plot muP as the y-axis
1186                                tmp_Y = calc[p][%muPo]
1187                                tmp_Y2 = tmp_Y
1188                                tmp_err_Y = calc[p][%err_muPo]
1189                        endif
1190
1191                        tmp_Y2 = (tmp_Mask == 1) ? NaN : tmp_Y2                 //only excluded points will plot
1192                       
1193
1194
1195
1196                        // clear old data, and plot the new
1197                        //
1198                        CheckDisplayed/W=DecayPanel#G0 tmp_Y,tmp_Y2,fit_tmp_Y
1199                        // if both present, bit 0 + bit 1 = 3
1200                        if(V_flag & 2^0)                        //check bit 0
1201                                RemoveFromGraph/W=DecayPanel#G0 tmp_Y
1202                        endif
1203                        if(V_flag & 2^1)
1204                                RemoveFromGraph/W=DecayPanel#G0 tmp_Y2
1205                        endif
1206                        if(V_flag & 2^2)
1207                                RemoveFromGraph/W=DecayPanel#G0 fit_tmp_Y
1208                        endif
1209                       
1210                        AppendToGraph/W=DecayPanel#G0 tmp_Y vs tmp_hr
1211                        AppendToGraph/W=DecayPanel#G0 tmp_Y2 vs tmp_hr
1212
1213                        ModifyGraph/W=DecayPanel#G0 log(left)=1
1214                        ModifyGraph/W=DecayPanel#G0 frameStyle=2
1215                        ModifyGraph/W=DecayPanel#G0 mode=3
1216                        ModifyGraph/W=DecayPanel#G0 marker=19
1217                        ModifyGraph/W=DecayPanel#G0 rgb(tmp_Y)=(1,16019,65535),rgb(tmp_Y2)=(65535,0,0)
1218                        ModifyGraph/W=DecayPanel#G0 msize=3
1219                        ErrorBars/W=DecayPanel#G0 tmp_Y,Y wave=(tmp_err_Y,tmp_err_Y)
1220
1221                        if(plot_P == 1)
1222                                Label/W=DecayPanel#G0 left "Atomic Polarization, P"
1223                        else
1224                                Label/W=DecayPanel#G0 left "mu*P"
1225                        endif                   
1226                        Label/W=DecayPanel#G0 bottom "time (h)"
1227                       
1228// do the fit
1229//       as long as the constant X0 doesn't stray from zero, exp_XOffset is OK, otherwise I'll need to switch to the exp function
1230// -- use the /K={0} flag to set the constant to zero
1231
1232                        SetActiveSubwindow DecayPanel#G0                        //to get the automatic fit to show up on the graph
1233
1234                        Make/O/D/N=3 fitCoef={0,5,0.05}
1235                        CurveFit/H="100"/M=2/W=0/TBOX=(0x310)/K={0} exp_XOffset, kwCWave=fitCoef, tmp_Y /X=tmp_hr /D /I=1 /W=tmp_err_Y /M=tmp_Mask
1236// gives nice error on gamma, but it's wrong since it doesn't use the errors on muP
1237//                      CurveFit/H="100"/M=2/W=0/TBOX=(0x310)/K={0} exp_XOffset, kwCWave=fitCoef, tmp_Y /X=tmp_hr /D /M=tmp_Mask
1238
1239
1240//                      Make/O/D/N=3 fitCoef={0,5,0.05}
1241//                      CurveFit/H="100"/M=2/W=0/TBOX=(0x310) exp, kwCWave=fitCoef, tmp_Y /X=tmp_hr /D /I=1 /W=tmp_err_Y /M=tmp_Mask
1242                       
1243
1244                        SetActiveSubwindow ##
1245                       
1246                       
1247// then report and save the results
1248//                      the exp function => y = y0 + A*exp(-Bx)
1249//                      W_coef[0] = y0 should be close to zero (or fixed at zero)
1250//                      W_coef[1] = A should be close to the initial muP value
1251//                      W_coef[2] = B is 1/Gamma
1252//                      WAVE W_coef=W_coef
1253                        WAVE W_sigma=W_sigma
1254                        Variable gamma_val,err_gamma,muPo, err_muPo, Po, err_Po
1255                        String noteStr=""
1256       
1257                        SVAR gCellKW = $("root:Packages:NIST:Polarization:Cells:gCell_"+cellStr)       
1258                        SVAR gGamma  = root:Packages:NIST:Polarization:Cells:gGamma
1259                        SVAR gMuPo = root:Packages:NIST:Polarization:Cells:gMuPo
1260                        SVAR gPo  = root:Packages:NIST:Polarization:Cells:gPo
1261
1262                        Variable mu,err_mu
1263
1264                        if(plot_P == 1)
1265                                Po = fitCoef[1]
1266                                err_Po = W_sigma[1]
1267                        // calc muPo inline here, since the Calc_muP function uses a different method
1268                        // cell constants       
1269                                mu = NumberByKey("mu", gCellKW, "=", ",", 0)
1270                                err_mu = NumberByKey("err_mu", gCellKW, "=", ",", 0)
1271                               
1272                                muPo = Po*mu
1273                                err_muPo = muPo*sqrt( (err_Po/Po)^2 + (err_mu/mu)^2 )
1274                        else
1275                                muPo = fitCoef[1]
1276                                err_muPo = W_sigma[1]
1277                               
1278                                Po = Calc_Po(gCellKW,muPo,err_muPo,err_Po)
1279                        endif
1280                       
1281
1282
1283                        // if exp_XOffset used
1284                        gamma_val = fitCoef[2]
1285                        err_Gamma = W_sigma[2]
1286
1287                        // calculating the error using exp is the inverse of coef[2]:
1288//                      gamma_val  = 1/fitCoef[2]
1289//                      err_gamma = W_sigma[2]/(fitCoef[2])^2
1290               
1291                       
1292//              for the wave note
1293                        noteStr = note(decay)
1294                        noteStr = ReplaceNumberByKey("muP", noteStr, MuPo ,"=", ",", 0)
1295                        noteStr = ReplaceNumberByKey("P0", noteStr, Po ,"=", ",", 0)
1296                        noteStr = ReplaceNumberByKey("err_muP", noteStr, err_muPo ,"=", ",", 0)
1297                        noteStr = ReplaceNumberByKey("err_P0", noteStr, err_Po ,"=", ",", 0)
1298                        noteStr = ReplaceNumberByKey("gamma", noteStr, gamma_val ,"=", ",", 0)
1299                        noteStr = ReplaceNumberByKey("err_gamma", noteStr, err_gamma ,"=", ",", 0)
1300
1301                        // replace the string
1302                        Note/K decay
1303                        Note decay, noteStr
1304                       
1305                       
1306                        // for the panel display
1307                        sprintf gMuPo, "%g +/- %g",muPo,err_muPo
1308                        sprintf gPo, "%g +/- %g",Po,err_Po
1309                        sprintf gGamma, "%g +/- %g",gamma_val,err_gamma
1310
1311                       
1312                       
1313                        SetDataFolder root:
1314                       
1315                        break
1316                case -1: // control being killed
1317                        break
1318        endswitch
1319
1320        return 0
1321End
1322
1323
1324// clear just the row
1325//
1326Function ClearDecayWavesRowButton(ba) : ButtonControl
1327        STRUCT WMButtonAction &ba
1328
1329        String popStr=""
1330        Variable selRow
1331       
1332        switch( ba.eventCode )
1333                case 2: // mouse up
1334                        // click code here
1335                        DoAlert 1,"Clear the selected row?"
1336                        if(V_flag !=1)
1337                                return(0)
1338                        endif
1339                       
1340                        SetDataFolder root:Packages:NIST:Polarization:Cells
1341
1342                        ControlInfo/W=DecayPanel popup_0
1343                        popStr = S_Value
1344                       
1345                        Wave decay = $("Decay_"+popStr)
1346                        Wave calc = $("DecayCalc_"+popStr)
1347
1348                        // Delete just those points
1349                                               
1350                        GetSelection table, DecayPanel#T0, 1
1351                        selRow = V_startRow
1352                        DeletePoints selRow,1,decay,calc                       
1353                       
1354                        // clear the graph and the results                     
1355                        SVAR gMuPo = root:Packages:NIST:Polarization:Cells:gMuPo
1356                        SVAR gPo  = root:Packages:NIST:Polarization:Cells:gPo
1357                        SVAR gGamma  = root:Packages:NIST:Polarization:Cells:gGamma
1358                        SVAR gT0  = root:Packages:NIST:Polarization:Cells:gT0
1359                        gMuPo = "0"
1360                        gPo = "0"
1361                        gGamma = "0"
1362                        gT0 = "recalculate"
1363                       
1364                        SetDataFolder root:
1365                        break
1366                case -1: // control being killed
1367                        break
1368        endswitch
1369
1370        return 0
1371End
1372
1373
1374
1375// for this, do I want to clear everything, or just a selected row??
1376//
1377//
1378Function ClearDecayWavesButton(ba) : ButtonControl
1379        STRUCT WMButtonAction &ba
1380
1381        String popStr=""
1382       
1383        switch( ba.eventCode )
1384                case 2: // mouse up
1385                        // click code here
1386                        DoAlert 1,"Clear all of the decay waves for the selected cell?"
1387                        if(V_flag !=1)
1388                                return(0)
1389                        endif
1390                       
1391                        SetDataFolder root:Packages:NIST:Polarization:Cells
1392
1393                        ControlInfo/W=DecayPanel popup_0
1394                        popStr = S_Value
1395                       
1396                        Wave decay = $("Decay_"+popStr)
1397                        Wave calc = $("DecayCalc_"+popStr)
1398                       
1399//                      re-initialize the decay waves, so it appears as a blank, initialized table
1400
1401                        MakeDecayResultWaves(popStr)
1402                        decay = 0
1403                        calc = 0
1404       
1405                        // clear the graph and the results?     
1406                       
1407                       
1408                                       
1409                        SVAR gMuPo = root:Packages:NIST:Polarization:Cells:gMuPo
1410                        SVAR gPo  = root:Packages:NIST:Polarization:Cells:gPo
1411                        SVAR gGamma  = root:Packages:NIST:Polarization:Cells:gGamma
1412                        SVAR gT0  = root:Packages:NIST:Polarization:Cells:gT0
1413                        gMuPo = "0"
1414                        gPo = "0"
1415                        gGamma = "0"
1416                        gT0 = "recalculate"
1417                       
1418                       
1419                        SetDataFolder root:
1420                        break
1421                case -1: // control being killed
1422                        break
1423        endswitch
1424
1425        return 0
1426End
1427
1428
1429Function DecayHelpParButtonProc(ba) : ButtonControl
1430        STRUCT WMButtonAction &ba
1431
1432        switch( ba.eventCode )
1433                case 2: // mouse up
1434                        // click code here
1435                        DisplayHelpTopic/Z/K=1 "Cell Decay Constant Panel"
1436                        if(V_flag !=0)
1437                                DoAlert 0,"The Cell Decay Help file could not be found"
1438                        endif
1439                        break
1440                case -1: // control being killed
1441                        break
1442        endswitch
1443
1444        return 0
1445End
1446
1447// E=-5 is a PNG, =8 is PDF
1448// there are other options to do EPS, embed fonts, etc.
1449//
1450Function WindowSnapshotButton(ba) : ButtonControl
1451        STRUCT WMButtonAction &ba
1452
1453        switch( ba.eventCode )
1454                case 2: // mouse up
1455                        // click code here
1456                        SavePICT /E=-5/SNAP=1
1457                        break
1458                case -1: // control being killed
1459                        break
1460        endswitch
1461
1462        return 0
1463End
1464
1465Function SaveDecayPanelButton(ba) : ButtonControl
1466        STRUCT WMButtonAction &ba
1467
1468        switch( ba.eventCode )
1469                case 2: // mouse up
1470                        // click code here
1471                        SaveCellDecayTable()
1472                        break
1473                case -1: // control being killed
1474                        break
1475        endswitch
1476
1477        return 0
1478End
1479
1480Function RestoreDecayPanelButton(ba) : ButtonControl
1481        STRUCT WMButtonAction &ba
1482
1483        switch( ba.eventCode )
1484                case 2: // mouse up
1485                        // click code here
1486                        RestoreCellDecayTable()
1487                        break
1488                case -1: // control being killed
1489                        break
1490        endswitch
1491
1492        return 0
1493End
1494
1495// null condition is not right. if the loop fails, then the
1496// retStr will be ";;;;", not zero length. What's the proper test?
1497// Does it matter? the list of default gCell_sss should already be there.
1498//
1499Function/S D_CellNameList()
1500
1501        String retStr="",listStr,item
1502        Variable num,ii
1503       
1504        SetDataFolder root:Packages:NIST:Polarization:Cells
1505
1506        // get a list of the cell strings
1507        listStr=StringList("gCell_*",";")
1508        num=ItemsInList(listStr,";")
1509//      print listStr
1510       
1511        // parse the strings to fill the table
1512        for(ii=0;ii<num;ii+=1)
1513                item = StringFromList(ii, listStr,";")
1514                SVAR gStr = $item
1515                retStr += StringByKey("cell", gStr, "=", ",", 0) + ";"
1516        endfor
1517       
1518        if(strlen(retStr) == 0)
1519                retStr = "no cells defined;"
1520        endif
1521       
1522        SetDataFolder root:             
1523        return(retStr)
1524End
1525
1526
1527// parse the row to be sure that:
1528//
1529// - files are valid numbers
1530// - files are all at same SDD
1531// - files are all with same attenuation (just print a warning to cmd)
1532// - due to ICE FP values, I need to do a fuzzy comparison
1533//
1534//
1535Function ParseDecayRow(w,selRow)
1536        Wave w
1537        Variable selRow
1538       
1539        Variable err=0, atten1,atten2,atten3,sdd1,sdd2,sdd3,tol
1540        String fname=""
1541        tol = 0.01              //SDDs within 1%
1542       
1543        // are all file numbers valid?
1544        fname = FindFileFromRunNumber(w[selRow][%'Trans_He_In?'])
1545        if(cmpstr(fname,"")==0)
1546                DoAlert 0,"Trans_He_In run "+num2str(w[selRow][%'Trans_He_In?'])+" is not a valid run number"
1547                err = 1
1548        else
1549                atten1 = getAttenNumber(fname)
1550                sdd1 = getSDD(fname)
1551        endif
1552       
1553        fname = FindFileFromRunNumber(w[selRow][%'Trans_He_Out?'])
1554        if(cmpstr(fname,"")==0)
1555                DoAlert 0,"Trans_He_Out run "+num2str(w[selRow][%'Trans_He_Out?'])+" is not a valid run number"
1556                err = 1
1557        else
1558                atten2 = getAttenNumber(fname)
1559                sdd2 = getSDD(fname)
1560        endif
1561       
1562        fname = FindFileFromRunNumber(w[selRow][%'Blocked?'])
1563        if(cmpstr(fname,"")==0)
1564                DoAlert 0,"Blocked run "+num2str(w[selRow][%'Blocked?'])+" is not a valid run number"
1565                err = 1
1566        else
1567                atten3 = getAttenNumber(fname)
1568                sdd3 = getSDD(fname)
1569        endif
1570       
1571       
1572        if( (abs(sdd1 - sdd2) > tol) || (abs(sdd2 - sdd3) > tol) || (abs(sdd1 - sdd3) > tol) )
1573                DoAlert 0,"Files in row "+num2str(selRow)+" are not all at the same detector distance"
1574                err = 1
1575        endif
1576       
1577        if( (atten1 != atten2) || (atten2 != atten3) || (atten1 != atten3) )
1578                DoAlert 0,"Files in row "+num2str(selRow)+" are not all collected with the same attenuation. Just so you know."
1579                err = 0
1580        endif
1581       
1582        return(err)
1583end
1584
1585
1586////////////////////////////////////////////
1587
1588
1589//
1590// a simple little panel to calculate the flipping ratio.
1591// 3 input files, calculates the flipping ratio, then simply reports the result
1592//
1593
1594Proc ShowFlippingRatioPanel()
1595       
1596        // init folders
1597        // ASK before initializing cell constants
1598        // open the panel
1599        DoWindow/F FlipRatio
1600        if(V_flag == 0)
1601                FlippingRatioPanel()
1602        endif
1603
1604end
1605
1606Proc FlippingRatioPanel()
1607        PauseUpdate; Silent 1           // building window...
1608        NewPanel /W=(455,44,805,245)/N=FlipRatio/K=1 as "Flipping Ratio"
1609        ModifyPanel cbRGB=(65535,49157,16385)
1610//      ShowTools/A
1611        SetDrawLayer UserBack
1612        GroupBox group0,pos={12,9},size={307,123},title="Flipping Ratio"
1613        SetVariable setvar0,pos={23,35},size={150,15},title="UU or DD File"
1614        SetVariable setvar0,limits={-inf,inf,0},value= _NUM:0
1615        SetVariable setvar1,pos={23,58},size={150,15},title="UD or DU File"
1616        SetVariable setvar1,limits={-inf,inf,0},value= _NUM:0
1617        SetVariable setvar2,pos={23,82},size={150,15},title="Blocked beam"
1618        SetVariable setvar2,limits={-inf,inf,0},value= _NUM:0
1619        SetVariable setvar3,pos={23,104},size={240,16},title="Flipping Ratio",fSize=12
1620        SetVariable setvar3,fStyle=1,limits={-inf,inf,0},value= _STR:"enter the run numbers"
1621        Button button0,pos={214,55},size={90,20},proc=CalcFlippingRatioButtonProc,title="Calculate"
1622EndMacro
1623
1624
1625
1626Function CalcFlippingRatioButtonProc(ba) : ButtonControl
1627        STRUCT WMButtonAction &ba
1628
1629
1630        Variable num0,num1,num2,cr0,cr1,cr2,err_cr0,err_cr1,err_cr2
1631        Variable tmp0,tmp1,tmp2,flip,flip_err
1632        String str=""
1633       
1634        switch( ba.eventCode )
1635                case 2: // mouse up
1636                        // click code here
1637                       
1638                        ControlInfo setvar0
1639                        num0 = V_Value
1640                        ControlInfo setvar1
1641                        num1 = V_Value
1642                        ControlInfo setvar2
1643                        num2 = V_Value
1644                       
1645                        cr0 = TotalCR_FromRun(num0,err_cr0,0)           //last zero means yes, normalize everything to zero atten
1646                        cr1 = TotalCR_FromRun(num1,err_cr1,0)
1647                        cr2 = TotalCR_FromRun(num2,err_cr2,0)           // this one is the blocked beam
1648                       
1649                       
1650                        flip = (cr0-cr2)/(cr1-cr2)
1651                        tmp0 = 1/(cr1-cr2)
1652                        tmp1 = -1*flip/(cr1-cr2)
1653                        tmp2 = flip/(cr1-cr2) - 1/(cr1-cr2)
1654                        flip_err = tmp0^2*err_cr0^2 + tmp1^2*err_cr1^2 +tmp2^2*err_cr2^2
1655                        flip_err = sqrt(flip_err)
1656                       
1657                       
1658                       
1659                        Printf "Flipping ratio = %g +/- %g (%g%)\r",flip,flip_err,flip_err/flip*100
1660                        str = num2str(flip)+" +/- "+num2str(flip_err)
1661                        SetVariable setvar3,value=_STR:str
1662                       
1663                        break
1664                case -1: // control being killed
1665                        break
1666        endswitch
1667
1668        return 0
1669End
1670
1671
1672/////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.