source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/EventModeProcessing.ipf @ 941

Last change on this file since 941 was 941, checked in by srkline, 9 years ago

Moved rescaling panel from Wrapper.ipf to PlotUtils?.ipf, a more natural location.

Added "Manual Optimization" utility to the SANS Models/1D operations menu. this is a simple panel that allows users to "optimize" the fit in 1 or 2 directions. Very instructive to see whether you're near a minimum, and what the chi2 surface looks like around the minimum.

Did a similar Manual Optimization for the Real-space MultiClyinder? calculations from Ken Rubinson. simpler interface here.

All of the "CGB" fixes are present here, including the calculation of the number of guides.

File size: 93.9 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma IgorVersion=6.22
3
4// vers 7.13e
5
6// TODO:
7//
8// -- search for TODO for unresolved issues not on this list
9//
10// -- add comments to the code as needed
11//
12// -- write the help file, and link the help buttons to the help docs
13//
14// -- examples?
15//
16// -- ?? need way to get correspondence between .hst files and VAX files? Names are all different. See
17//    DateAndTime2HSTName() functions and similar @ bottom of this file
18//
19// x- add the XOP to the distribution package
20//
21// x- Need to make sure that the rescaledTime and the differentiated time graphs are
22//     being properly updated when the data is processed, modified, etc.
23//
24// -- I need better nomenclature other than "stream" for the "continuous" data set.
25//     It's all a stream, just sometimes it's not oscillatory
26//
27//
28// X- the slice display "fails" for data sets that have 3 or 4 slices, as the ModifyImage command
29//     interprets the data as being RGB - and so does nothing.
30//     need to find a way around this. This was fixed by displaying the data using the G=1 flag on AppendImage
31//     to prevent the "atuo-detection" of data as RGB
32//
33// -- Do something with the PP events. Currently, only the PP events that are XY (just the
34//    type 0 events (since I still need to find out what they realy mean)
35//
36// -- Add a switch to allow Sorting of the Stream data to remove the "time-reversed" data
37//     points. Maybe not kosher, but would clean things up.
38//
39///////////////////////////////
40//
41// NOTE -- to be able to show the T0 and PP event locations/times, force the loader to use the Igor code rather than
42// the XOP. Then there will be waves generated with their locations: T0Time and T0EventNum, PPTime and PPEventNum. Edit these waves
43// and (1) delete the zero points at the end of the waves and (2) multiply the Time wave * 1e-7 to convert to seconds.
44// Then the waves can be plotted on top of the event data, so it can be seen where these events were identified.
45//
46///////////////   SWITCHES     /////////////////
47//
48// for the "File Too Big" limit:
49//      Variable/G root:Packages:NIST:Event:gEventFileTooLarge = 150            // 150 MB considered too large
50//
51// for the tolerance of "step" detection
52//      Variable/G root:Packages:NIST:Event:gStepTolerance = 5          // 5 = # of standard deviations from mean. See PutCursorsAtStep()
53//
54//
55///////// DONE //////////
56//
57// X- memory issues:
58//              -- in LoadEvents -- should I change the MAKE to:
59//                              /I/U is unsigned 32-bit integer (for the time)
60//                              /B/U is unsigned 8-bit integer (max val=255) for the x and y values
61//                      -- then how does this affect downstream processing - such as rescaledTime, differentiation, etc.
62//                      x- and can I re-write the XOP to create these types of data waves, and properly fill them...
63//
64//  **- any integer waves must be translated by Igor into FP to be able to be displayed or for any
65//    type of analysis. so it's largely a waste of time to use integers. so simply force the XOP to
66//    generate only SP waves. this will at least save some space.
67//
68//
69//
70// x- Is there any way to improve the speed of the loader? How could an XOP be structured
71//     for maximum flexibility? Leave the post processing to Igor, but how much for the XOP
72//     to do? And can it handle such large amounts of data to pass back and forth, or
73//     does it need to be written as an operation, rather than a function??? I'd really
74//     rather that Igor handles the memory management, not me, if I write the XOP.
75//
76// **- as of 11/27, the OSX version of the XOP event loader is about 35x faster for the load!
77//    and is taking approx 1.8s/28MB, or about 6.5s/100MB of file. quite reasonable now, and
78//    probably a bit faster yet on the PC.
79//
80//
81// X- fix the log/lin display - it's not working correctly
82//                      I could use ModifyImage and log = 0|1 keyword for the log Z display
83//                      rather than creating a duplicate wave of log(data)
84//                      -- it's in the Function sliceSelectEvent_Proc()
85//
86// X- add controls to show the bar graph
87// x- add popup for selecting the binning type
88// x- add ability to save the slices to RAW VAX files
89// X- add control to show the bin counts and bin end times
90// x- ADD buttons, switches, etc for the oscillatory mode - so that this can be accessed
91//
92// x- How are the headers filled for the VAX files from Teabag???
93// -- I currently read the events 2x. Once to count the events to make the waves the proper
94//     size, then a second time to actualy process the events. Would it be faster to insert points
95//     as needed, or to estimate the size, and make it too large, then trim at the end...
96// ((( NO -- I have no good way of getting a proper estimate of how many XY events there are for a file))
97//
98//
99//
100
101
102//
103// These are also defined in the TISANE procedure file. In both files they are declared
104// as Static, so they are local to each procedure
105//
106Static Constant ATXY = 0
107Static Constant ATXYM = 2
108Static Constant ATMIR = 1
109Static Constant ATMAR = 3
110
111Static Constant USECSPERTICK=0.1 // microseconds
112Static Constant TICKSPERUSEC=10
113Static Constant XBINS=128
114Static Constant YBINS=128
115//
116
117Static Constant MODE_STREAM = 0
118Static Constant MODE_OSCILL = 1
119Static Constant MODE_TISANE = 2
120Static Constant MODE_TOF = 3
121
122//Menu "Macros"
123//      "Split Large File",SplitBigFile()
124//      "Accumulate First Slice",AccumulateSlices(0)
125//      "Add Current Slice",AccumulateSlices(1)
126//      "Display Accumulated Slices",AccumulateSlices(2)       
127//End
128
129
130
131Proc Show_Event_Panel()
132        DoWindow/F EventModePanel
133        if(V_flag ==0)
134                Init_Event()
135                EventModePanel()
136        EndIf
137End
138
139
140Function Init_Event()
141
142        NewDataFolder/O/S root:Packages:NIST:Event
143
144        String/G        root:Packages:NIST:Event:gEvent_logfile
145        String/G        root:Packages:NIST:Event:gEventDisplayString="Details of the file load"
146       
147        Variable/G      root:Packages:NIST:Event:AIMTYPE_XY=0 // XY Event
148        Variable/G      root:Packages:NIST:Event:AIMTYPE_XYM=2 // XY Minor event
149        Variable/G      root:Packages:NIST:Event:AIMTYPE_MIR=1 // Minor rollover event
150        Variable/G      root:Packages:NIST:Event:AIMTYPE_MAR=3 // Major rollover event
151
152        Variable/G root:Packages:NIST:Event:gEvent_time_msw = 0
153        Variable/G root:Packages:NIST:Event:gEvent_time_lsw = 0
154        Variable/G root:Packages:NIST:Event:gEvent_t_longest = 0
155
156        Variable/G root:Packages:NIST:Event:gEvent_tsdisp //Displayed slice
157        Variable/G root:Packages:NIST:Event:gEvent_nslices = 10  //Number of time slices
158       
159        Variable/G root:Packages:NIST:Event:gEvent_logint = 1
160
161        Variable/G root:Packages:NIST:Event:gEvent_Mode = MODE_OSCILL                           // ==0 for "stream", ==1 for Oscillatory
162        Variable/G root:Packages:NIST:Event:gRemoveBadEvents = 1                // ==1 to remove "bad" events, ==0 to read "as-is"
163        Variable/G root:Packages:NIST:Event:gSortStreamEvents = 0               // ==1 to sort the event stream, a last resort for a stream of data
164       
165        Variable/G root:Packages:NIST:Event:gEvent_ForceTmaxBin=1               //==1 to enforce t_longest in user-defined custom bins
166
167        NVAR nslices = root:Packages:NIST:Event:gEvent_nslices
168       
169               
170        Make/D/O/N=(XBINS,YBINS,nslices) slicedData
171        Duplicate/O slicedData logslicedData
172        Duplicate/O slicedData dispsliceData
173
174
175// for decimation
176        Variable/G root:Packages:NIST:Event:gEventFileTooLarge = 150            // 150 MB considered too large
177        Variable/G root:Packages:NIST:Event:gDecimation = 100
178        Variable/G root:Packages:NIST:Event:gEvent_t_longest_decimated = 0
179
180// for large file splitting
181        String/G root:Packages:NIST:Event:gSplitFileList = ""           // a list of the file names as split
182       
183// for editing
184        Variable/G root:Packages:NIST:Event:gStepTolerance = 5          // 5 = # of standard deviations from mean. See PutCursorsAtStep()
185       
186        SetDataFolder root:
187End
188
189//
190// -- extra bits of buttons... not used
191//
192//      Button button9 title="Decimation",size={100,20},pos={490,400},proc=E_ShowDecimateButton
193//
194//      Button button11,pos={490,245},size={150,20},proc=LoadDecimateButtonProc,title="Load and Decimate"
195//      Button button12,pos={490,277},size={150,20},proc=ConcatenateButtonProc,title="Concatenate"
196//      Button button13,pos={490,305},size={150,20},proc=DisplayConcatenatedButtonProc,title="Display Concatenated"
197//     
198//      GroupBox group0 title="Manual Controls",size={185,112},pos={490,220}
199//
200//      NewPanel /W=(82,44,854,664)/N=EventModePanel/K=2
201//      DoWindow/C EventModePanel
202//      ModifyPanel fixedSize=1,noEdit =1
203Proc EventModePanel()
204        PauseUpdate; Silent 1           // building window...
205        NewPanel /W=(82,44,854,664)/N=EventModePanel/K=2
206        DoWindow/C EventModePanel
207        ModifyPanel fixedSize=1,noEdit =1
208
209        SetDrawLayer UserBack
210        DrawText 479,345,"Stream Data"
211        DrawLine 563,338,731,338
212        DrawText 479,419,"Oscillatory Data"
213        DrawLine 578,411,731,411
214
215//      ShowTools/A
216        Button button0,pos={14,87},size={150,20},proc=LoadEventLog_Button,title="Load Event Log File"
217        Button button0,fSize=12
218        TitleBox tb1,pos={475,500},size={135,24},fSize=10
219        TitleBox tb1,variable= root:Packages:NIST:Event:gEventDisplayString
220
221        CheckBox chkbox2,pos={376,151},size={81,14},proc=LogIntEvent_Proc,title="Log Intensity"
222        CheckBox chkbox2,fSize=10,variable= root:Packages:NIST:Event:gEvent_logint
223        CheckBox chkbox3,pos={14,125},size={119,14},title="Remove Bad Events?",fSize=10
224        CheckBox chkbox3,variable= root:Packages:NIST:Event:gRemoveBadEvents
225       
226        Button doneButton,pos={708,36},size={50,20},proc=EventDone_Proc,title="Done"
227        Button doneButton,fSize=12
228        Button button2,pos={419,28},size={140,20},proc=ShowEventDataButtonProc,title="Show Event Data"
229        Button button3,pos={419,56},size={140,20},proc=ShowBinDetailsButtonProc,title="Show Bin Details"
230        Button button5,pos={419,85},size={140,20},proc=ExportSlicesButtonProc,title="Export Slices as VAX"
231        Button button6,pos={718,9},size={40,20},proc=EventModeHelpButtonProc,title="?"
232       
233       
234        Button button7,pos={487,197},size={120,20},proc=AdjustEventDataButtonProc,title="Adjust Events"
235        Button button8,pos={619,197},size={120,20},proc=CustomBinButtonProc,title="Custom Bins"
236        Button button4,pos={487,227},size={120,20},proc=UndoTimeSortButtonProc,title="Undo Time Sort"
237        Button button18,pos={619,227},size={120,20},proc=EC_ImportWavesButtonProc,title="Import Edited"
238
239       
240        SetVariable setvar0,pos={208,149},size={160,16},proc=sliceSelectEvent_Proc,title="Display Time Slice"
241        SetVariable setvar0,fSize=10
242        SetVariable setvar0,limits={0,1000,1},value= root:Packages:NIST:Event:gEvent_tsdisp     
243        SetVariable setvar1,pos={206,26},size={160,16},title="Number of slices",fSize=10
244        SetVariable setvar1,limits={1,1000,1},value= root:Packages:NIST:Event:gEvent_nslices
245        SetVariable setvar2,pos={206,51},size={160,16},title="Max Time (s)",fSize=10
246        SetVariable setvar2,value= root:Packages:NIST:Event:gEvent_t_longest
247       
248        PopupMenu popup0,pos={206,74},size={119,20},proc=BinTypePopMenuProc,title="Bin Spacing"
249        PopupMenu popup0,fSize=10
250        PopupMenu popup0,mode=1,popvalue="Equal",value= #"\"Equal;Fibonacci;Custom;\""
251        Button button1,pos={206,100},size={120,20},fSize=12,proc=ProcessEventLog_Button,title="Bin Event Data"
252
253        Button button10,pos={488,305},size={100,20},proc=SplitFileButtonProc,title="Split Big File"
254        Button button14,pos={488,350},size={120,20},proc=Stream_LoadDecim,title="Load Split List"
255        Button button19,pos={619,350},size={120,20},proc=Stream_LoadAdjustedList,title="Load Edited List"
256        Button button20,pos={650,376},size={90,20},proc=ShowList_ToLoad,title="Show List"
257        SetVariable setvar3,pos={487,378},size={150,16},title="Decimation factor"
258        SetVariable setvar3,fSize=10
259        SetVariable setvar3,limits={1,inf,1},value= root:Packages:NIST:Event:gDecimation
260
261        Button button15_0,pos={488,425},size={110,20},proc=AccumulateSlicesButton,title="Add First Slice"
262        Button button16_1,pos={488,450},size={110,20},proc=AccumulateSlicesButton,title="Add Next Slice"
263        Button button17_2,pos={620,425},size={110,20},proc=AccumulateSlicesButton,title="Display Total"
264
265
266        CheckBox chkbox1_0,pos={25,34},size={69,14},title="Oscillatory",fSize=10
267        CheckBox chkbox1_0,mode=1,proc=EventModeRadioProc,value=1
268        CheckBox chkbox1_1,pos={25,59},size={53,14},title="Stream",fSize=10
269        CheckBox chkbox1_1,proc=EventModeRadioProc,value=0,mode=1
270        CheckBox chkbox1_2,pos={104,59},size={53,14},title="TISANE",fSize=10
271        CheckBox chkbox1_2,proc=EventModeRadioProc,value=0,mode=1
272        CheckBox chkbox1_3,pos={104,34},size={37,14},title="TOF",fSize=10
273        CheckBox chkbox1_3,proc=EventModeRadioProc,value=0,mode=1
274       
275        GroupBox group0_0,pos={5,5},size={174,112},title="Mode",fSize=12,fStyle=1
276        GroupBox group0_1,pos={192,5},size={192,123},title="Binning",fSize=12,fStyle=1
277        GroupBox group0_2,pos={403,5},size={173,109},title="Viewing",fSize=12,fStyle=1
278        GroupBox group0_3,pos={476,169},size={277,92},title="Editing",fSize=12,fStyle=1
279        GroupBox group0_4,pos={474,278},size={279,200},title="Big Files",fSize=12
280        GroupBox group0_4,fStyle=1
281       
282        Display/W=(10,170,460,610)/HOST=#
283        AppendImage/T/G=1 :Packages:NIST:Event:dispsliceData            //  /G=1 flag prevents interpretation as RGB so 3, 4 slices display correctly
284        ModifyImage dispsliceData ctab= {*,*,ColdWarm,0}
285        ModifyImage dispsliceData ctabAutoscale=3
286        ModifyGraph margin(left)=14,margin(bottom)=14,margin(top)=14,margin(right)=14
287        ModifyGraph mirror=2
288        ModifyGraph nticks=4
289        ModifyGraph minor=1
290        ModifyGraph fSize=9
291        ModifyGraph standoff=0
292        ModifyGraph tkLblRot(left)=90
293        ModifyGraph btLen=3
294        ModifyGraph tlOffset=-2
295        RenameWindow #,Event_slicegraph
296        SetActiveSubwindow ##
297EndMacro
298
299
300
301
302// mode selector
303//Static Constant MODE_STREAM = 0
304//Static Constant MODE_OSCILL = 1
305//Static Constant MODE_TISANE = 2
306//Static Constant MODE_TOF = 3
307//
308Function EventModeRadioProc(name,value)
309        String name
310        Variable value
311       
312        NVAR gEventModeRadioVal= root:Packages:NIST:Event:gEvent_mode
313       
314        strswitch (name)
315                case "chkbox1_0":
316                        gEventModeRadioVal= MODE_OSCILL
317                        break
318                case "chkbox1_1":
319                        gEventModeRadioVal= MODE_STREAM
320                        break
321                case "chkbox1_2":
322                        gEventModeRadioVal= MODE_TISANE
323                        break
324                case "chkbox1_3":
325                        gEventModeRadioVal= MODE_TOF
326                        break
327        endswitch
328        CheckBox chkbox1_0,value= gEventModeRadioVal==MODE_OSCILL
329        CheckBox chkbox1_1,value= gEventModeRadioVal==MODE_STREAM
330        CheckBox chkbox1_2,value= gEventModeRadioVal==MODE_TISANE
331        CheckBox chkbox1_3,value= gEventModeRadioVal==MODE_TOF
332
333        return(0)
334End
335
336Function AdjustEventDataButtonProc(ba) : ButtonControl
337        STRUCT WMButtonAction &ba
338
339        switch( ba.eventCode )
340                case 2: // mouse up
341                        // click code here
342                        Execute "ShowEventCorrectionPanel()"
343                        //
344                        break
345                case -1: // control being killed
346                        break
347        endswitch
348
349        return 0
350End
351
352Function CustomBinButtonProc(ba) : ButtonControl
353        STRUCT WMButtonAction &ba
354
355        switch( ba.eventCode )
356                case 2: // mouse up
357                        // click code here
358                        Execute "Show_CustomBinPanel()"
359                        //
360                        break
361                case -1: // control being killed
362                        break
363        endswitch
364
365        return 0
366End
367
368
369Function ShowEventDataButtonProc(ba) : ButtonControl
370        STRUCT WMButtonAction &ba
371
372        switch( ba.eventCode )
373                case 2: // mouse up
374                        // click code here
375                        Execute "ShowRescaledTimeGraph()"
376                        //
377                        DifferentiatedTime()
378                        //
379                        break
380                case -1: // control being killed
381                        break
382        endswitch
383
384        return 0
385End
386
387Function BinTypePopMenuProc(pa) : PopupMenuControl
388        STRUCT WMPopupAction &pa
389
390        switch( pa.eventCode )
391                case 2: // mouse up
392                        Variable popNum = pa.popNum
393                        String popStr = pa.popStr
394                        if(cmpstr(popStr,"Custom")==0)
395                                Execute "Show_CustomBinPanel()"
396                        endif
397                        break
398                case -1: // control being killed
399                        break
400        endswitch
401
402        return 0
403End
404
405Function ShowBinDetailsButtonProc(ba) : ButtonControl
406        STRUCT WMButtonAction &ba
407
408        switch( ba.eventCode )
409                case 2: // mouse up
410                        // click code here
411                        Execute "ShowBinTable()"
412                        Execute "BinEventBarGraph()"
413                        break
414                case -1: // control being killed
415                        break
416        endswitch
417
418        return 0
419End
420
421Function UndoTimeSortButtonProc(ba) : ButtonControl
422        STRUCT WMButtonAction &ba
423
424        switch( ba.eventCode )
425                case 2: // mouse up
426                        // click code here
427                        Execute "UndoTheSorting()"
428                        break
429                case -1: // control being killed
430                        break
431        endswitch
432
433        return 0
434End
435
436Function ExportSlicesButtonProc(ba) : ButtonControl
437        STRUCT WMButtonAction &ba
438
439        switch( ba.eventCode )
440                case 2: // mouse up
441                        // click code here
442                        Execute "ExportSlicesAsVAX()"           //will invoke the dialog
443                        break
444                case -1: // control being killed
445                        break
446        endswitch
447
448        return 0
449End
450
451Function EventModeHelpButtonProc(ba) : ButtonControl
452        STRUCT WMButtonAction &ba
453
454        switch( ba.eventCode )
455                case 2: // mouse up
456                        // click code here
457                        DisplayHelpTopic/Z "Event Mode Data"
458                        break
459                case -1: // control being killed
460                        break
461        endswitch
462
463        return 0
464End
465
466
467Function EventDone_Proc(ba) : ButtonControl
468        STRUCT WMButtonAction &ba
469       
470        String win = ba.win
471        switch (ba.eventCode)
472                case 2:
473                        DoWindow/K EventModePanel
474                        break
475        endswitch
476        return(0)
477End
478
479
480
481Function ProcessEventLog_Button(ctrlName) : ButtonControl
482        String ctrlName
483       
484        NVAR mode=root:Packages:NIST:Event:gEvent_Mode
485       
486        if(mode == MODE_STREAM)
487                Stream_ProcessEventLog("")
488        endif
489       
490        if(mode == MODE_OSCILL)
491                Osc_ProcessEventLog("")
492        endif
493       
494        // If TOF mode, process as Oscillatory -- that is, take the times as is
495        if(mode == MODE_TOF)
496                Osc_ProcessEventLog("")
497        endif
498       
499        // toggle the checkbox for log display to force the display to be correct
500        NVAR gLog = root:Packages:NIST:Event:gEvent_logint
501        LogIntEvent_Proc("",gLog)
502       
503        return(0)
504end
505
506// for oscillatory mode
507//
508Function Osc_ProcessEventLog(ctrlName)
509        String ctrlName
510
511        Make/O/D/N=(128,128) root:Packages:NIST:Event:binnedData
512       
513        Wave binnedData = root:Packages:NIST:Event:binnedData
514        Wave xLoc = root:Packages:NIST:Event:xLoc
515        Wave yLoc = root:Packages:NIST:Event:yLoc
516
517// now with the number of slices and max time, process the events
518
519        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
520        NVAR nslices = root:Packages:NIST:Event:gEvent_nslices
521
522        SetDataFolder root:Packages:NIST:Event          //don't count on the folder remaining here
523       
524        Make/D/O/N=(XBINS,YBINS,nslices) slicedData
525               
526        Wave slicedData = slicedData
527        Wave rescaledTime = rescaledTime
528        Wave timePt = timePt
529        Make/O/D/N=(128,128) tmpData
530        Make/O/D/N=(nslices+1) binEndTime,binCount
531        Make/O/D/N=(nslices) timeWidth
532        Wave timeWidth = timeWidth
533        Wave binEndTime = binEndTime
534        Wave binCount = binCount
535
536        variable ii,del,p1,p2,t1,t2
537        del = t_longest/nslices
538
539        slicedData = 0
540        binEndTime[0]=0
541        BinCount[nslices]=0
542
543
544        String binTypeStr=""
545        ControlInfo /W=EventModePanel popup0
546        binTypeStr = S_value
547       
548        strswitch(binTypeStr)   // string switch
549                case "Equal":           // execute if case matches expression
550                        SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
551                        break                                           // exit from switch
552                case "Fibonacci":               // execute if case matches expression
553                        SetFibonacciBins(binEndTime,timeWidth,nslices,t_longest)
554                        break
555                case "Log":             // execute if case matches expression
556                        SetLogBins(binEndTime,timeWidth,nslices,t_longest)
557                        break
558                case "Custom":          // execute if case matches expression
559                        //bins are set by the user on the panel - assume it's good to go
560                        break
561                default:                                                        // optional default expression executed
562                        DoAlert 0,"No match for bin type, Equal bins used"
563                        SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
564        endswitch
565
566
567// now before binning, sort the data
568
569        //this is slow - undoing the sorting and starting over, but if you don't,
570        // you'll never be able to undo the sort
571        //
572        SetDataFolder root:Packages:NIST:Event:
573
574        if(WaveExists($"root:Packages:NIST:Event:OscSortIndex") == 0 )
575                Duplicate/O rescaledTime OscSortIndex
576                MakeIndex rescaledTime OscSortIndex
577                IndexSort OscSortIndex, yLoc,xLoc,timePt,rescaledTime   
578                //SetDataFolder root:Packages:NIST:Event
579                IndexForHistogram(xLoc,yLoc,binnedData)                 // index the events AFTER sorting
580                //SetDataFolder root:
581        Endif
582       
583        Wave index = root:Packages:NIST:Event:SavedIndex                //this is the histogram index
584
585        for(ii=0;ii<nslices;ii+=1)
586                if(ii==0)
587//                      t1 = ii*del
588//                      t2 = (ii+1)*del
589                        p1 = BinarySearch(rescaledTime,0)
590                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])
591                else
592//                      t2 = (ii+1)*del
593                        p1 = p2+1               //one more than the old one
594                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])               
595                endif
596
597        // typically zero will never be a valid time value in oscillatory mode. in "stream" mode, the first is normalized to == 0
598        // but not here - times are what they are.
599                if(p1 == -1)
600                        Printf "p1 = -1 Binary search off the end %15.10g <?? %15.10g\r", 0, rescaledTime[0]
601                        p1 = 0          //set to the first point if it's off the end
602                Endif
603               
604                if(p2 == -2)
605                        Printf "p2 = -2 Binary search off the end %15.10g >?? %15.10g\r", binEndTime[ii+1], rescaledTime[numpnts(rescaledTime)-1]
606                        p2 = numpnts(rescaledTime)-1            //set to the last point if it's off the end
607                Endif
608//              Print p1,p2
609
610
611                tmpData=0
612                JointHistogramWithRange(xLoc,yLoc,tmpData,index,p1,p2)
613                slicedData[][][ii] = tmpData[p][q]
614               
615//              binEndTime[ii+1] = t2
616                binCount[ii] = sum(tmpData,-inf,inf)
617        endfor
618
619        Duplicate/O slicedData,root:Packages:NIST:Event:dispsliceData,root:Packages:NIST:Event:logSlicedData
620        Wave logSlicedData = root:Packages:NIST:Event:logSlicedData
621        logslicedData = log(slicedData)
622
623        SetDataFolder root:
624        return(0)
625End
626
627// for a "continuous exposure"
628//
629// if there is a sort of these events, I need to re-index the events for the histogram
630// - see the oscillatory mode  - and sort the events here, then immediately re-index for the histogram
631// - but with the added complication that I need to always remember to index for the histogram, every time
632// - since I don't know if I've sorted or un-sorted. Osc mode always forces a re-sort and a re-index
633//
634Function Stream_ProcessEventLog(ctrlName)
635        String ctrlName
636
637//      NVAR slicewidth = root:Packages:NIST:gTISANE_slicewidth
638
639       
640        Make/O/D/N=(128,128) root:Packages:NIST:Event:binnedData
641       
642        Wave binnedData = root:Packages:NIST:Event:binnedData
643        Wave xLoc = root:Packages:NIST:Event:xLoc
644        Wave yLoc = root:Packages:NIST:Event:yLoc
645
646// now with the number of slices and max time, process the events
647
648        NVAR yesSortStream = root:Packages:NIST:Event:gSortStreamEvents         //do I sort the events?
649        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
650        NVAR nslices = root:Packages:NIST:Event:gEvent_nslices
651
652        SetDataFolder root:Packages:NIST:Event          //don't count on the folder remaining here
653       
654        Make/D/O/N=(XBINS,YBINS,nslices) slicedData
655               
656        Wave slicedData = slicedData
657        Wave rescaledTime = rescaledTime
658        Make/O/D/N=(128,128) tmpData
659        Make/O/D/N=(nslices+1) binEndTime,binCount//,binStartTime
660        Make/O/D/N=(nslices) timeWidth
661        Wave binEndTime = binEndTime
662        Wave timeWidth = timeWidth
663        Wave binCount = binCount
664
665        variable ii,del,p1,p2,t1,t2
666        del = t_longest/nslices
667
668        slicedData = 0
669        binEndTime[0]=0
670        BinCount[nslices]=0
671       
672        String binTypeStr=""
673        ControlInfo /W=EventModePanel popup0
674        binTypeStr = S_value
675       
676        strswitch(binTypeStr)   // string switch
677                case "Equal":           // execute if case matches expression
678                        SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
679                        break                                           // exit from switch
680                case "Fibonacci":               // execute if case matches expression
681                        SetFibonacciBins(binEndTime,timeWidth,nslices,t_longest)
682                        break
683                case "Log":             // execute if case matches expression
684                        SetLogBins(binEndTime,timeWidth,nslices,t_longest)
685                        break
686                case "Custom":          // execute if case matches expression
687                        //bins are set by the user on the panel - assume it's good to go
688                        break
689                default:                                                        // optional default expression executed
690                        DoAlert 0,"No match for bin type, Equal bins used"
691                        SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
692        endswitch
693
694// TODO
695// the global exists for this switch, but it is not implemented - not sure whether
696// it's correct to implement this at all --
697//
698        if(yesSortStream == 1)
699                SortTimeData()
700        endif
701       
702// index the events before binning
703// if there is a sort of these events, I need to re-index the events for the histogram
704//      SetDataFolder root:Packages:NIST:Event
705        IndexForHistogram(xLoc,yLoc,binnedData)
706//      SetDataFolder root:
707        Wave index = root:Packages:NIST:Event:SavedIndex                //the index for the histogram
708       
709       
710        for(ii=0;ii<nslices;ii+=1)
711                if(ii==0)
712//                      t1 = ii*del
713//                      t2 = (ii+1)*del
714                        p1 = BinarySearch(rescaledTime,0)
715                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])
716                else
717//                      t2 = (ii+1)*del
718                        p1 = p2+1               //one more than the old one
719                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])               
720                endif
721
722                if(p1 == -1)
723                        Printf "p1 = -1 Binary search off the end %15.10g <?? %15.10g\r", 0, rescaledTime[0]
724                        p1 = 0          //set to the first point if it's off the end
725                Endif
726                if(p2 == -2)
727                        Printf "p2 = -2 Binary search off the end %15.10g >?? %15.10g\r", binEndTime[ii+1], rescaledTime[numpnts(rescaledTime)-1]
728                        p2 = numpnts(rescaledTime)-1            //set to the last point if it's off the end
729                Endif
730//              Print p1,p2
731
732
733                tmpData=0
734                JointHistogramWithRange(xLoc,yLoc,tmpData,index,p1,p2)
735                slicedData[][][ii] = tmpData[p][q]
736               
737//              binEndTime[ii+1] = t2
738                binCount[ii] = sum(tmpData,-inf,inf)
739        endfor
740
741        Duplicate/O slicedData,root:Packages:NIST:Event:dispsliceData,root:Packages:NIST:Event:logSlicedData
742        Wave logSlicedData = root:Packages:NIST:Event:logSlicedData
743        logslicedData = log(slicedData)
744
745        SetDataFolder root:
746        return(0)
747End
748
749
750Proc    UndoTheSorting()
751        Osc_UndoSort()
752End
753
754// for oscillatory mode
755//
756// -- this takes the previously generated index, and un-sorts the data to restore to the
757// "as-collected" state
758//
759Function Osc_UndoSort()
760
761        SetDataFolder root:Packages:NIST:Event          //don't count on the folder remaining here
762        Wave rescaledTime = rescaledTime
763        Wave OscSortIndex = OscSortIndex
764        Wave yLoc = yLoc
765        Wave xLoc = xLoc
766        Wave timePt = timePt
767
768        Sort OscSortIndex OscSortIndex,yLoc,xLoc,timePt,rescaledTime
769
770        KillWaves/Z OscSortIndex
771       
772        SetDataFolder root:
773        return(0)
774End
775
776
777// now before binning, sort the data
778//
779//this is slow - undoing the sorting and starting over, but if you don't,
780// you'll never be able to undo the sort
781//
782Function SortTimeData()
783
784
785        SetDataFolder root:Packages:NIST:Event:
786
787        KillWaves/Z OscSortIndex
788       
789        if(WaveExists($"root:Packages:NIST:Event:OscSortIndex") == 0 )
790                Duplicate/O rescaledTime OscSortIndex
791                MakeIndex rescaledTime OscSortIndex
792                IndexSort OscSortIndex, yLoc,xLoc,timePt,rescaledTime   
793        Endif
794       
795        SetDataFolder root:
796        return(0)
797End
798
799
800
801Function SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
802        Wave binEndTime,timeWidth
803        Variable nslices,t_longest
804
805        Variable del,ii,t2
806        binEndTime[0]=0         //so the bar graph plots right...
807        del = t_longest/nslices
808       
809        for(ii=0;ii<nslices;ii+=1)
810                t2 = (ii+1)*del
811                binEndTime[ii+1] = t2
812        endfor
813        binEndTime[ii+1] = t_longest*(1-1e-6)           //otherwise floating point errors such that the last time point is off the end of the Binary search
814
815        timeWidth = binEndTime[p+1]-binEndTime[p]
816
817        return(0)       
818End
819
820// TODO
821// either get this to work, or scrap it entirely. it currently isn't on the popup
822// so it can't be accessed
823Function SetLogBins(binEndTime,timeWidth,nslices,t_longest)
824        Wave binEndTime,timeWidth
825        Variable nslices,t_longest
826
827        Variable tMin,ii
828
829        Wave rescaledTime = root:Packages:NIST:Event:rescaledTime
830       
831        binEndTime[0]=0         //so the bar graph plots right...
832
833        // just like the log-scaled q-points
834        tMin = rescaledTime[1]/1                        //just a guess... can't use tMin=0, and rescaledTime[0] == 0 by definition
835        Print rescaledTime[1], tMin
836        for(ii=0;ii<nslices;ii+=1)
837                binEndTime[ii+1] =alog(log(tMin) + (ii+1)*((log(t_longest)-log(tMin))/nslices))
838        endfor
839        binEndTime[ii+1] = t_longest            //otherwise floating point errors such that the last time point is off the end of the Binary search
840       
841        timeWidth = binEndTime[p+1]-binEndTime[p]
842
843        return(0)
844End
845
846Function MakeFibonacciWave(w,num)
847        Wave w
848        Variable num
849
850        //skip the initial zero
851        Variable f1,f2,ii
852        f1=1
853        f2=1
854        w[0] = f1
855        w[1] = f2
856        for(ii=2;ii<num;ii+=1)
857                w[ii] = f1+f2
858                f1=f2
859                f2=w[ii]
860        endfor
861               
862        return(0)
863end
864
865Function SetFibonacciBins(binEndTime,timeWidth,nslices,t_longest)
866        Wave binEndTime,timeWidth
867        Variable nslices,t_longest
868
869        Variable tMin,ii,total,t2,tmp
870        Make/O/D/N=(nslices) fibo
871        fibo=0
872        MakeFibonacciWave(fibo,nslices)
873       
874//      Make/O/D tmpFib={1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946}
875
876        binEndTime[0]=0         //so the bar graph plots right...
877        total = sum(fibo,0,nslices-1)           //total number of "pieces"
878       
879        tmp=0
880        for(ii=0;ii<nslices;ii+=1)
881                t2 = sum(fibo,0,ii)/total*t_longest
882                binEndTime[ii+1] = t2
883        endfor
884        binEndTime[ii+1] = t_longest            //otherwise floating point errors such that the last time point is off the end of the Binary search
885       
886        timeWidth = binEndTime[p+1]-binEndTime[p]
887       
888        return(0)
889End
890
891
892
893// TODO:
894//
895// ** currently, the "stream" loader uses the first data point as time=0
896//    and rescales everything to that time. "Osc" loading uses the times "as-is"
897//    from the file, trusting the times to be correct.
898//
899// Would TISANE or TOF need a different loader?
900//     
901Function LoadEventLog_Button(ctrlName) : ButtonControl
902        String ctrlName
903
904        NVAR mode=root:Packages:NIST:Event:gEvent_mode
905        Variable err=0
906        Variable fileref,totBytes
907        NVAR fileTooLarge = root:Packages:NIST:Event:gEventFileTooLarge         //limit load to 150MB
908
909        SVAR filename = root:Packages:NIST:Event:gEvent_logfile
910        NVAR nslices = root:Packages:NIST:Event:gEvent_nslices
911        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
912       
913        String fileFilters = "All Files:.*;Data Files (*.txt):.txt;"
914        String abortStr
915       
916        PathInfo catPathName
917        if(V_flag==0)
918                DoAlert 0,"Please 'Pick Path' to the data from the Main (yellow) Panel."
919                return(0)
920        endif
921       
922       
923        Open/R/D/P=catPathName/F=fileFilters fileref
924        filename = S_filename
925        if(strlen(S_filename) == 0)
926                // user cancelled
927                DoAlert 0,"No file selected, no file loaded."
928                return(1)
929        endif
930       
931/// Abort if the files are too large
932        Open/R fileref as fileName
933                FStatus fileref
934        Close fileref
935
936        totBytes = V_logEOF/1e6         //in MB
937        if(totBytes > fileTooLarge)
938                sprintf abortStr,"File is %g MB, larger than the limit of %g MB. Split and Decimate.",totBytes,fileTooLarge
939                Abort abortStr
940        endif
941       
942
943#if (exists("EventLoadWave")==4)
944        LoadEvents_XOP()
945#else
946        LoadEvents()
947#endif 
948
949        SetDataFolder root:Packages:NIST:Event:
950
951//tic()
952        Wave timePt=timePt
953        Wave xLoc=xLoc
954        Wave yLoc=yLoc
955        CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
956//toc()
957       
958       
959/////
960// now do a little processing of the times based on the type of data
961//     
962        if(mode == MODE_STREAM)         // continuous "Stream" mode - start from zero
963                Duplicate/O timePt rescaledTime
964                rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
965                t_longest = waveMax(rescaledTime)               //should be the last point     
966        endif
967       
968        if(mode == MODE_OSCILL)         // oscillatory mode - don't adjust the times, we get periodic t0 to reset t=0
969                Duplicate/O timePt rescaledTime
970                rescaledTime *= 1e-7                    //convert to seconds and that's all
971                t_longest = waveMax(rescaledTime)               //if oscillatory, won't be the last point, so get it this way
972       
973                KillWaves/Z OscSortIndex                        //to make sure that there is no old index hanging around
974        endif
975
976// MODE_TISANE
977
978// MODE_TOF
979        if(mode == MODE_TOF)            // TOF mode - don't adjust the times, we get periodic t0 to reset t=0
980                Duplicate/O timePt rescaledTime
981                rescaledTime *= 1e-7                    //convert to seconds and that's all
982                t_longest = waveMax(rescaledTime)               //if oscillatory, won't be the last point, so get it this way
983       
984                KillWaves/Z OscSortIndex                        //to make sure that there is no old index hanging around
985        endif
986
987        SetDataFolder root:
988
989        STRUCT WMButtonAction ba
990        ba.eventCode = 2
991        ShowEventDataButtonProc(ba)
992
993        return(0)
994End
995
996//// for the mode of "one continuous exposure"
997////
998//Function Stream_LoadEventLog(ctrlName)
999//      String ctrlName
1000//     
1001//      Variable fileref
1002//
1003//      SVAR filename = root:Packages:NIST:Event:gEvent_logfile
1004//      NVAR nslices = root:Packages:NIST:Event:gEvent_nslices
1005//      NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
1006//     
1007//      String fileFilters = "All Files:.*;Data Files (*.txt):.txt;"
1008//     
1009//      Open/R/D/F=fileFilters fileref
1010//      filename = S_filename
1011//      if(strlen(S_filename) == 0)
1012//              // user cancelled
1013//              DoAlert 0,"No file selected, no file loaded."
1014//              return(1)
1015//      endif
1016//
1017//#if (exists("EventLoadWave")==4)
1018//      LoadEvents_XOP()
1019//#else
1020//      LoadEvents()
1021//#endif       
1022//
1023//      SetDataFolder root:Packages:NIST:Event:
1024//
1025////tic()
1026//      Wave timePt=timePt
1027//      Wave xLoc=xLoc
1028//      Wave yLoc=yLoc
1029//      CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
1030//     
1031////toc()
1032//
1033//      Duplicate/O timePt rescaledTime
1034//      rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
1035//      t_longest = waveMax(rescaledTime)               //should be the last point
1036//
1037//      SetDataFolder root:
1038//
1039//      return(0)
1040//End
1041//
1042//// for the mode "oscillatory"
1043////
1044//Function Osc_LoadEventLog(ctrlName)
1045//      String ctrlName
1046//     
1047//      Variable fileref
1048//
1049//      SVAR filename = root:Packages:NIST:Event:gEvent_logfile
1050//      NVAR nslices = root:Packages:NIST:Event:gEvent_nslices
1051//      NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
1052//     
1053//      String fileFilters = "All Files:.*;Data Files (*.txt):.txt;"
1054//     
1055//      Open/R/D/F=fileFilters fileref
1056//      filename = S_filename
1057//              if(strlen(S_filename) == 0)
1058//              // user cancelled
1059//              DoAlert 0,"No file selected, no file loaded."
1060//              return(1)
1061//      endif
1062//     
1063//#if (exists("EventLoadWave")==4)
1064//      LoadEvents_XOP()
1065//#else
1066//      LoadEvents()
1067//#endif       
1068//     
1069//      SetDataFolder root:Packages:NIST:Event:
1070//
1071//      Wave timePt=timePt
1072//      Wave xLoc=xLoc
1073//      Wave yLoc=yLoc
1074//      CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
1075//     
1076//      Duplicate/O timePt rescaledTime
1077//      rescaledTime *= 1e-7                    //convert to seconds and that's all
1078//      t_longest = waveMax(rescaledTime)               //if oscillatory, won't be the last point, so get it this way
1079//
1080//      KillWaves/Z OscSortIndex                        //to make sure that there is no old index hanging around
1081//
1082//      SetDataFolder root:
1083//
1084//      return(0)
1085//End
1086
1087
1088//
1089// -- MUCH faster to count the number of lines to remove, then delete (N)
1090// rather then delete them one-by-one in the do-loop
1091Function CleanupTimes(xLoc,yLoc,timePt)
1092        Wave xLoc,yLoc,timePt
1093
1094        // start at the back and remove zeros
1095        Variable num=numpnts(xLoc),ii,numToRemove
1096
1097        numToRemove = 0
1098        ii=num
1099        do
1100                ii -= 1
1101                if(timePt[ii] == 0 && xLoc[ii] == 0 && yLoc[ii] == 0)
1102                        numToRemove += 1
1103                endif
1104        while(timePt[ii-1] == 0 && xLoc[ii-1] == 0 && yLoc[ii-1] == 0)
1105       
1106        if(numToRemove != 0)
1107                DeletePoints ii, numToRemove, xLoc,yLoc,timePt
1108        endif
1109       
1110        return(0)
1111End
1112
1113Function LogIntEvent_Proc(ctrlName,checked) : CheckBoxControl
1114        String ctrlName
1115        Variable checked
1116               
1117        SetDataFolder root:Packages:NIST:Event
1118       
1119        Wave slicedData = slicedData
1120        Wave logSlicedData = logSlicedData
1121        Wave dispSliceData = dispSliceData
1122       
1123        if(checked)
1124                logslicedData = log(slicedData)
1125                Duplicate/O logslicedData dispsliceData
1126        else
1127                Duplicate/O slicedData dispsliceData
1128        endif
1129
1130        NVAR selectedslice = root:Packages:NIST:Event:gEvent_tsdisp
1131
1132        sliceSelectEvent_Proc("", selectedslice, "", "")
1133
1134        SetDataFolder root:
1135
1136End
1137
1138
1139// TODO (DONE)
1140// this "fails" for data sets that have 3 or 4 slices, as the ModifyImage command
1141// interprets the data as being RGB - and so does nothing.
1142// need to find a way around this
1143//
1144////  When first plotted, AppendImage/G=1 flag prevents interpretation as RGB so 3, 4 slices display correctly
1145///
1146// I could modify this procedure to use the log = 0|1 keyword for the log Z display
1147// rather than creating a duplicate wave of log(data)
1148//
1149Function sliceSelectEvent_Proc(ctrlName, varNum, varStr, varName) : SetVariableControl
1150        String ctrlName
1151        Variable varNum
1152        String varStr
1153        String varName
1154       
1155        NVAR nslices = root:Packages:NIST:Event:gEvent_nslices
1156        NVAR selectedslice = root:Packages:NIST:Event:gEvent_tsdisp
1157       
1158        if(varNum < 0)
1159                selectedslice = 0
1160                DoUpdate
1161        elseif (varNum > nslices-1)
1162                selectedslice = nslices-1
1163                DoUpdate
1164        else
1165                ModifyImage/W=EventModePanel#Event_slicegraph ''#0 plane = varNum
1166        endif
1167
1168End
1169
1170Function DifferentiatedTime()
1171
1172        Wave rescaledTime = root:Packages:NIST:Event:rescaledTime
1173
1174        SetDataFolder root:Packages:NIST:Event:
1175               
1176        Differentiate rescaledTime/D=rescaledTime_DIF
1177//      Display rescaledTime,rescaledTime_DIF
1178        DoWindow/F Differentiated_Time
1179        if(V_flag == 0)
1180                Display/N=Differentiated_Time/K=1 rescaledTime_DIF
1181                Legend
1182                Modifygraph gaps=0
1183                ModifyGraph zero(left)=1
1184                Label left "\\Z14Delta (dt/event)"
1185                Label bottom "\\Z14Event number"
1186        endif
1187       
1188        SetDataFolder root:
1189       
1190        return(0)
1191End
1192
1193
1194//
1195// for the bit shifts, see the decimal-binary conversion
1196// http://www.binaryconvert.com/convert_unsigned_int.html
1197//
1198//              K0 = 536870912
1199//              Print (K0 & 0x08000000)/134217728       //bit 27 only, shift by 2^27
1200//              Print (K0 & 0x10000000)/268435456               //bit 28 only, shift by 2^28
1201//              Print (K0 & 0x20000000)/536870912               //bit 29 only, shift by 2^29
1202//
1203// This is duplicated by the XOP, but the Igor code allows quick access to print out
1204// all of the gorey details of the events and every little bit of them. the print
1205// statements and flags are kept for this reason, so the code is a bit messy.
1206//
1207Function LoadEvents()
1208       
1209        NVAR time_msw = root:Packages:NIST:Event:gEvent_time_msw
1210        NVAR time_lsw = root:Packages:NIST:Event:gEvent_time_lsw
1211        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
1212       
1213        SVAR filepathstr = root:Packages:NIST:Event:gEvent_logfile
1214        SVAR dispStr = root:Packages:NIST:Event:gEventDisplayString
1215       
1216       
1217////    Variable decFac = 10                    //decimation factor
1218////    Variable jj,keep
1219       
1220        SetDataFolder root:Packages:NIST:Event
1221
1222        Variable fileref
1223        String buffer
1224        String fileStr,tmpStr
1225        Variable dataval,timeval,type,numLines,verbose,verbose3
1226        Variable xval,yval,rollBit,nRoll,roll_time,bit29,bit28,bit27
1227        Variable ii,flaggedEvent,rolloverHappened,numBad=0,tmpPP=0,tmpT0=0
1228        Variable Xmax, yMax
1229       
1230        xMax = 127              // number the detector from 0->127
1231        yMax = 127
1232       
1233        verbose3 = 0                    //prints out the rollover events (type==3)
1234        verbose = 0
1235        numLines = 0
1236
1237       
1238        // what I really need is the number of XY events
1239        Variable numXYevents,num1,num2,num3,num0,totBytes,numPP,numT0,numDL,numFF,numZero
1240        Variable numRemoved
1241        numXYevents = 0
1242        num0 = 0
1243        num1 = 0
1244        num2 = 0
1245        num3 = 0
1246        numPP = 0
1247        numT0 = 0
1248        numDL = 0
1249        numFF = 0
1250        numZero = 0
1251        numRemoved = 0
1252
1253//tic()
1254        Open/R fileref as filepathstr
1255                FStatus fileref
1256        Close fileref
1257
1258        totBytes = V_logEOF
1259        Print "total bytes = ", totBytes
1260       
1261//toc()
1262//
1263
1264
1265// do a "pre-scan to get some of the counts, so that I can allocate space. This does
1266// double the read time, but is still faster than adding points to waves as the file is read
1267//     
1268
1269        tic()
1270
1271        Open/R fileref as filepathstr
1272        do
1273                do
1274                        FReadLine fileref, buffer                       //skip the "blank" lines that have one character
1275                while(strlen(buffer) == 1)             
1276
1277                if (strlen(buffer) == 0)
1278                        break
1279                endif
1280               
1281                sscanf buffer,"%x",dataval
1282               
1283                // two most sig bits (31-30)
1284                type = (dataval & 0xC0000000)/1073741824                //right shift by 2^30
1285                               
1286                if(type == 0)
1287                        num0 += 1
1288                        numXYevents += 1
1289                endif
1290                if(type == 2)
1291                        num2 += 1
1292                        numXYevents += 1
1293                endif
1294                if(type == 1)
1295                        num1 += 1
1296                endif
1297                if(type == 3)
1298                        num3 += 1
1299                endif   
1300               
1301                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1302               
1303                if(type==0 || type==2)
1304                        numPP += round(bit29)
1305                endif
1306               
1307                if(type==1 || type==3)
1308                        numT0 += round(bit29)
1309                endif
1310               
1311                if(dataval == 0)
1312                        numZero += 1
1313                endif
1314               
1315        while(1)
1316        Close fileref
1317//              done counting the number of XY events
1318        printf("Igor pre-scan done in  ")
1319        toc()
1320       
1321
1322        Print "(Igor) numT0 = ",numT0   
1323        Print "num0 = ",num0   
1324        Print "num1 = ",num1   
1325        Print "num2 = ",num2   
1326        Print "num3 = ",num3   
1327
1328//
1329//     
1330//      Printf "numXYevents = %d\r",numXYevents
1331//      Printf "XY = num0 = %d\r",num0
1332//      Printf "XY time = num2 = %d\r",num2
1333//      Printf "time MSW = num1 = %d\r",num1
1334//      Printf "Rollover = num3 = %d\r",num3
1335//      Printf "num0 + num2 = %d\r",num0+num2
1336
1337// dispStr will be displayed on the panel
1338        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
1339       
1340        sprintf tmpStr, "%s: %d total bytes\r",fileStr,totBytes
1341        dispStr = tmpStr
1342        sprintf tmpStr,"numXYevents = %d\r",numXYevents
1343        dispStr += tmpStr
1344        sprintf tmpStr,"PP = %d  :  ",numPP
1345        dispStr += tmpStr
1346        sprintf tmpStr,"ZeroData = %d\r",numZero
1347        dispStr += tmpStr
1348        sprintf tmpStr,"Rollover = %d",num3
1349        dispStr += tmpStr
1350
1351        // /I/U is unsigned 32-bit integer (for the time)
1352        // /B/U is unsigned 8-bit integer (max val=255) for the x and y values
1353       
1354        Make/O/U/N=(numXYevents) xLoc,yLoc
1355        Make/O/D/N=(numXYevents) timePt
1356////    Make/O/U/N=(numXYevents/decFac) xLoc,yLoc
1357////    Make/O/D/N=(numXYevents/decFac) timePt
1358//      Make/O/U/N=(totBytes/4) xLoc,yLoc               //too large, trim when done (bad idea)
1359//      Make/O/D/N=(totBytes/4) timePt
1360        Make/O/D/N=1000 badTimePt,badEventNum,PPTime,PPEventNum,T0Time,T0EventNum
1361        badTimePt=0
1362        badEventNum=0
1363        PPTime=0
1364        PPEventNum=0
1365        T0Time=0
1366        T0EventNum=0
1367        xLoc=0
1368        yLoc=0
1369        timePt=0
1370       
1371        nRoll = 0               //number of rollover events
1372        roll_time = 2^26                //units of 10-7 sec
1373       
1374        NVAR removeBadEvents = root:Packages:NIST:Event:gRemoveBadEvents
1375       
1376        time_msw=0
1377       
1378        tic()
1379       
1380        ii = 0          //indexes the points in xLoc,yLoc,timePt
1381////    keep = decFac           //keep the first point
1382       
1383       
1384        Open/R fileref as filepathstr
1385       
1386        // remove events at the beginning up to a type==2 so that the msw and lsw times are reset properly
1387        if(RemoveBadEvents == 1)
1388                do
1389                        do
1390                                FReadLine fileref, buffer                       //skip the "blank" lines that have one character
1391                        while(strlen(buffer) == 1)             
1392       
1393                        if (strlen(buffer) == 0)
1394                                break
1395                        endif
1396                       
1397                        sscanf buffer,"%x",dataval
1398                // two most sig bits (31-30)
1399                        type = (dataval & 0xC0000000)/1073741824                //right shift by 2^30
1400                       
1401                        if(type == 2)
1402                                // this is the first event with a proper time value, so process the XY-time event as ususal
1403                                // and then break to drop to the main loop, where the next event == type 1
1404                               
1405                                xval = xMax - (dataval & 255)                                           //last 8 bits (7-0)
1406                                yval = (dataval & 65280)/256                                            //bits 15-8, right shift by 2^8
1407               
1408                                time_lsw = (dataval & 536805376)/65536                  //13 bits, 28-16, right shift by 2^16
1409               
1410                                if(verbose)
1411                //                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1412                                        printf "%u : %u : %u : %u\r",dataval,timeval,xval,yval
1413                                endif
1414                               
1415                                // this is the first point, be sure that ii = 0, and always keep this point
1416////                            if(keep==decFac)
1417                                        ii = 0
1418                                        xLoc[ii] = xval
1419                                        yLoc[ii] = yval
1420////                                    keep = 0
1421////                            endif
1422                                Print "At beginning of file, numBad = ",numBad
1423                                break   // the next do loop processes the bulk of the file (** the next event == type 1 = MIR)
1424                        else
1425                                numBad += 1
1426                                numRemoved += 1
1427                        endif
1428                       
1429                        //ii+=1         don't increment the counter
1430                while(1)
1431        endif
1432       
1433        // now read the main portion of the file.
1434////    // keep is = 0 if bad points were removed, or is decFac is I need to keep the first point
1435        do
1436                do
1437                        FReadLine fileref, buffer                       //skip the "blank" lines that have one character
1438                while(strlen(buffer) == 1)             
1439
1440                if (strlen(buffer) == 0)                                // this marks the end of the file and is our only way out
1441                        break
1442                endif
1443               
1444                sscanf buffer,"%x",dataval
1445               
1446
1447//              type = (dataval & ~(2^32 - 2^30 -1))/2^30
1448
1449                // two most sig bits (31-30)
1450                type = (dataval & 0xC0000000)/1073741824                //right shift by 2^30
1451               
1452                //
1453                // The defintions of the event types
1454                //
1455                //Constant ATXY = 0
1456                //Constant ATXYM = 2
1457                //Constant ATMIR = 1
1458                //Constant ATMAR = 3
1459                //
1460                                               
1461                if(verbose > 0)
1462                        verbose -= 1
1463                endif
1464//             
1465                switch(type)
1466                        case ATXY:              // 0
1467                                if(verbose)             
1468                                        printf "XY : "         
1469                                endif
1470                               
1471                                // if the datavalue is == 0, just skip it now (it can only be interpreted as type 0, obviously)
1472                                if(dataval == 0 && RemoveBadEvents == 1)
1473                                        numRemoved += 1
1474                                        //Print "zero at ii= ",ii
1475                                        break           //don't increment ii
1476                                endif
1477                               
1478                                // if it's a pileup event, skip it now (this can be either type 0 or 2)
1479                                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1480                                if(bit29 == 1 && RemoveBadEvents == 1)
1481                                        PPTime[tmpPP] = timeval
1482                                        PPEventNum[tmpPP] = ii
1483                                        tmpPP += 1
1484                                        numRemoved += 1
1485                                        break           //don't increment ii
1486                                endif
1487                               
1488//                              xval = ~(dataval & ~(2^32 - 2^8)) & 127
1489//                              yval = ((dataval & ~(2^32 - 2^16 ))/2^8) & 127
1490//                              time_lsw = (dataval & ~(2^32 - 2^29))/2^16
1491
1492                                xval = xMax - (dataval & 255)                                           //last 8 bits (7-0)
1493                                yval = (dataval & 65280)/256                                            //bits 15-8, right shift by 2^8
1494                                time_lsw = (dataval & 536805376)/65536                  //13 bits, 28-16, right shift by 2^16
1495
1496                                timeval = trunc( nRoll*roll_time + (time_msw * (8192)) + time_lsw )             //left shift msw by 2^13, then add in lsw, as an integer
1497                                if (timeval > t_longest)
1498                                        t_longest = timeval
1499                                endif
1500                               
1501                               
1502                                // catch the "bad" events:
1503                                // if an XY event follows a rollover, time_msw is 0 by definition, but does not immediately get
1504                                // re-evalulated here. Throw out only the immediately following points where msw is still 8191
1505                                if(rolloverHappened && RemoveBadEvents == 1)
1506                                        // maybe a bad event
1507                                        if(time_msw == 8191)
1508                                                badTimePt[numBad] = timeVal
1509                                                badEventNum[numBad] = ii
1510                                                numBad +=1
1511                                                numRemoved += 1
1512                                        else
1513                                                // time_msw has been reset, points are good now, so keep this one
1514////                                            if(keep==decFac)
1515                                                        xLoc[ii] = xval
1516                                                        yLoc[ii] = yval
1517                                                        timePt[ii] = timeval
1518                                                       
1519        //                                              if(xval == 127 && yval == 0)
1520        //                                                      // check bit 29
1521        //                                                      bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1522        //                                                      Print "XY=127,0 : bit29 = ",bit29
1523        //                                              endif
1524                                                       
1525                                                        ii+=1
1526                                                        rolloverHappened = 0
1527////                                                    keep = 0
1528////                                            else
1529////                                                    keep += 1
1530////                                            endif
1531                                        endif
1532                                else
1533                                        // normal processing of good point, keep it
1534////                                    if(keep==decFac)
1535                                                xLoc[ii] = xval
1536                                                yLoc[ii] = yval
1537                                                timePt[ii] = timeval
1538                                       
1539        //                                      if(xval == 127 && yval == 0)
1540        //                                              // check bit 29
1541        //                                              bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1542        //                                              Printf "XY=127,0 : bit29 = %u : d=%u\r",bit29,dataval
1543        //                                      endif
1544                                                ii+=1
1545////                                            keep = 0
1546////                                    else
1547////                                            keep += 1
1548////                                    endif
1549                                endif
1550
1551
1552                                if(verbose)             
1553//                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1554                                        printf "d=%u : t=%u : msw=%u : lsw=%u : %u : %u \r",dataval,timeval,time_msw,time_lsw,xval,yval
1555                                endif                           
1556       
1557//                              verbose = 0
1558                                break
1559                        case ATXYM: // 2
1560                                if(verbose)
1561                                        printf "XYM : "
1562                                endif
1563                               
1564                                // if it's a pileup event, skip it now (this can be either type 0 or 2)
1565                                // - but can I do this if this is an XY-time event? This will lead to a wrong time, and a time
1566                                // assigned to an XY (0,0)...
1567//                              bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1568//                              if(bit29 == 1 && RemoveBadEvents == 1)
1569//                                      Print "*****Bit 29 (PP) event set for Type==2, but not handled, ii = ",ii
1570////                                    break           //don't increment ii
1571//                              endif
1572                               
1573//                              xval = ~(dataval & ~(2^32 - 2^8)) & 127
1574//                              yval = ((dataval & ~(2^32 - 2^16 ))/2^8) & 127
1575//                              time_lsw =  (dataval & ~(2^32 - 2^29 ))/2^16            //this method gives a FP result!! likely since the "^" operation gives FP result...
1576
1577                                xval = xMax - (dataval & 255)                                           //last 8 bits (7-0)
1578                                yval = (dataval & 65280)/256                                            //bits 15-8, right shift by 2^8
1579
1580                                time_lsw = (dataval & 536805376)/65536                  //13 bits, 28-16, right shift by 2^16 (result is integer)
1581
1582                                if(verbose)
1583//                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1584                                        printf "%u : %u : %u : %u\r",dataval,timeval,xval,yval
1585                                endif
1586                               
1587////                            if(keep==decFac)                        //don't reset keep yet, do this only when ii increments
1588                                        xLoc[ii] = xval
1589                                        yLoc[ii] = yval
1590////                            endif
1591                               
1592                                // don't fill in the time yet, or increment the index ii
1593                                // the next event MUST be ATMIR with the MSW time bits
1594                                //
1595//                              verbose = 0
1596                                break
1597                        case ATMIR:  // 1
1598                                if(verbose)
1599                                        printf "MIR : "
1600                                endif
1601
1602                                time_msw =  (dataval & 536805376)/65536                 //13 bits, 28-16, right shift by 2^16
1603                                timeval = trunc( nRoll*roll_time + (time_msw * (8192)) + time_lsw )
1604                                if (timeval > t_longest)
1605                                        t_longest = timeval
1606                                endif
1607                                if(verbose)
1608//                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1609                                        printf "d=%u : t=%u : msw=%u : lsw=%u : tlong=%u\r",dataval,timeval,time_msw,time_lsw,t_longest
1610                                endif
1611                               
1612                                // the XY position was in the previous event ATXYM
1613////                            if(keep == decFac)
1614                                        timePt[ii] = timeval
1615////                            endif
1616
1617                                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1618                                if(bit29 != 0)          // bit 29 set is a T0 event
1619                                        //Printf "bit29 = 1 at ii = %d : type = %d\r",ii,type
1620                                        T0Time[tmpT0] = timeval
1621                                        T0EventNum[tmpT0] = ii
1622                                        tmpT0 += 1
1623                                        // reset nRoll = 0 for calcluating the time
1624                                        nRoll = 0
1625                                endif
1626                               
1627////                            if(keep == decFac)                     
1628                                        ii+=1
1629////                                    keep = 0
1630////                            endif
1631//                              verbose = 0
1632                                break
1633                        case ATMAR:  // 3
1634                                if(verbose3)
1635//                                      verbose = 15
1636//                                      verbose = 2
1637                                        printf "MAR : "
1638                                endif
1639                               
1640                                // do something with the rollover event?
1641                               
1642                                // check bit 29
1643                                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1644                                nRoll += 1
1645// not doing anything with these bits yet       
1646                                bit28 = (dataval & 0x10000000)/268435456                //bit 28 only, shift by 2^28   
1647                                bit27 = (dataval & 0x08000000)/134217728        //bit 27 only, shift by 2^27
1648
1649                                if(verbose3)
1650                                        printf "d=%u : b29=%u : b28=%u : b27=%u : #Roll=%u \r",dataval,bit29, bit28, bit27,nRoll
1651                                endif
1652                               
1653                                if(bit29 != 0)          // bit 29 set is a T0 event
1654                                        //Printf "bit29 = 1 at ii = %d : type = %d\r",ii,type
1655                                        T0Time[tmpT0] = timeval
1656                                        T0EventNum[tmpT0] = ii
1657                                        tmpT0 += 1
1658                                        // reset nRoll = 0 for calcluating the time
1659                                        nRoll = 0
1660                                endif
1661                               
1662                                rolloverHappened = 1
1663
1664                                break
1665                endswitch
1666               
1667//              if(ii<18)
1668//                      printf "TYPE=%d : ii=%d : d=%u : t=%u : msw=%u : lsw=%u : %u : %u \r",type,ii,dataval,timeval,time_msw,time_lsw,xval,yval
1669//              endif   
1670                       
1671        while(1)
1672       
1673        Close fileref
1674       
1675        printf("Igor full file read done in  ")
1676        toc()
1677       
1678        Print "Events removed (Igor) = ",numRemoved
1679       
1680        sPrintf tmpStr,"\rBad Rollover Events = %d (%4.4g %% of events)",numBad,numBad/numXYevents*100
1681        dispStr += tmpStr
1682        sPrintf tmpStr,"\rTotal Events Removed = %d (%4.4g %% of events)",numRemoved,numRemoved/numXYevents*100
1683        dispStr += tmpStr
1684        SetDataFolder root:
1685       
1686        return(0)
1687       
1688End
1689
1690//////////////
1691//
1692// This calls the XOP, as an operation to load the events
1693//
1694// -- it's about 35x faster than the Igor code, so I guess that's OK.
1695//
1696// conditional compile the whole inner workings in case XOP is not present
1697Function LoadEvents_XOP()
1698#if (exists("EventLoadWave")==4)
1699       
1700//      NVAR time_msw = root:Packages:NIST:Event:gEvent_time_msw
1701//      NVAR time_lsw = root:Packages:NIST:Event:gEvent_time_lsw
1702        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
1703       
1704        SVAR filepathstr = root:Packages:NIST:Event:gEvent_logfile
1705        SVAR dispStr = root:Packages:NIST:Event:gEventDisplayString
1706       
1707        SetDataFolder root:Packages:NIST:Event
1708
1709
1710
1711        Variable fileref
1712        String buffer
1713        String fileStr,tmpStr
1714        Variable dataval,timeval,type,numLines,verbose,verbose3
1715        Variable xval,yval,rollBit,nRoll,roll_time,bit29,bit28,bit27
1716        Variable ii,flaggedEvent,rolloverHappened,numBad=0,tmpPP=0,tmpT0=0
1717        Variable Xmax, yMax
1718       
1719        xMax = 127              // number the detector from 0->127
1720        yMax = 127
1721       
1722        numLines = 0
1723
1724        //Have to declare local variables for Loadwave so that this compiles without XOP.
1725        String S_waveNames
1726        //  and those for the XOP
1727        Variable V_nXYevents,V_num1,V_num2,V_num3,V_num0,V_totBytes,V_numPP,V_numT0,V_numDL,V_numFF,V_numZero
1728        Variable V_numBad,V_numRemoved
1729       
1730        // what I really need is the number of XY events
1731        Variable numXYevents,num1,num2,num3,num0,totBytes,numPP,numT0,numDL,numFF,numZero
1732        Variable numRemoved
1733        numXYevents = 0
1734        num0 = 0
1735        num1 = 0
1736        num2 = 0
1737        num3 = 0
1738        numPP = 0
1739        numT0 = 0
1740        numDL = 0
1741        numFF = 0
1742        numZero = 0
1743        numRemoved = 0
1744
1745// get the total number of bytes in the file
1746        Open/R fileref as filepathstr
1747                FStatus fileref
1748        Close fileref
1749
1750        totBytes = V_logEOF
1751        Print "total bytes = ", totBytes
1752       
1753//
1754//      Print "scan only"
1755//      tic()
1756//              EventLoadWave/R/N=EventWave/W filepathstr
1757//      toc()
1758
1759////
1760//
1761//  use the XOP operation to load in the data
1762// -- this does everything - the pre-scan and creating the waves
1763//
1764// need to zero the waves before loading, just in case
1765//
1766
1767        NVAR removeBadEvents = root:Packages:NIST:Event:gRemoveBadEvents
1768
1769tic()
1770
1771//      Wave/Z wave0=wave0
1772//      Wave/Z wave1=wave1
1773//      Wave/Z wave2=wave2
1774//
1775//      if(WaveExists(wave0))
1776//              MultiThread wave0=0
1777//      endif
1778//      if(WaveExists(wave1))
1779//              MultiThread wave1=0
1780//      endif
1781//      if(WaveExists(wave2))
1782//              MultiThread wave2=0
1783//      endif
1784
1785        if(removeBadEvents)
1786                EventLoadWave/R/N=EventWave filepathstr
1787        else
1788                EventLoadWave/N=EventWave  filepathstr
1789        endif
1790
1791
1792        Print "XOP files loaded = ",S_waveNames
1793
1794////            -- copy the waves over to xLoc,yLoc,timePt
1795        Wave/Z EventWave0=EventWave0
1796        Wave/Z EventWave1=EventWave1
1797        Wave/Z EventWave2=EventWave2
1798       
1799       
1800        Duplicate/O EventWave0,xLoc
1801        KillWaves/Z EventWave0
1802
1803        Duplicate/O EventWave1,yLoc
1804        KillWaves/Z EventWave1
1805
1806        Duplicate/O EventWave2,timePt
1807        KillWaves/Z EventWave2
1808
1809// could do this, but rescaled time will neeed to be converted to SP (or DP)
1810// and Igor loader was written with Make generating SP/DP waves
1811        // /I/U is unsigned 32-bit integer (for the time)
1812        // /B/U is unsigned 8-bit integer (max val=255) for the x and y values
1813       
1814//      Redimension/B/U xLoc,yLoc
1815//      Redimension/I/U timePt
1816
1817        // access the variables from the XOP
1818        numT0 = V_numT0
1819        numPP = V_numPP
1820        num0 = V_num0
1821        num1 = V_num1
1822        num2 = V_num2
1823        num3 = V_num3
1824        numXYevents = V_nXYevents
1825        numZero = V_numZero
1826        numBad = V_numBad
1827        numRemoved = V_numRemoved
1828       
1829        Print "(XOP) numT0 = ",numT0   
1830        Print "num0 = ",num0   
1831        Print "num1 = ",num1   
1832        Print "num2 = ",num2   
1833        Print "num3 = ",num3   
1834       
1835
1836// dispStr will be displayed on the panel
1837        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
1838       
1839        sprintf tmpStr, "%s: %d total bytes\r",fileStr,totBytes
1840        dispStr = tmpStr
1841        sprintf tmpStr,"numXYevents = %d\r",numXYevents
1842        dispStr += tmpStr
1843        sprintf tmpStr,"PP = %d  :  ",numPP
1844        dispStr += tmpStr
1845        sprintf tmpStr,"ZeroData = %d\r",numZero
1846        dispStr += tmpStr
1847        sprintf tmpStr,"Rollover = %d",num3
1848        dispStr += tmpStr
1849
1850        toc()
1851       
1852        Print "Events removed (XOP) = ",numRemoved
1853       
1854        sPrintf tmpStr,"\rBad Rollover Events = %d (%4.4g %% of events)",numBad,numBad/numXYevents*100
1855        dispStr += tmpStr
1856        sPrintf tmpStr,"\rTotal Events Removed = %d (%4.4g %% of events)",numRemoved,numRemoved/numXYevents*100
1857        dispStr += tmpStr
1858
1859
1860// simply to compile a table of # XY vs # bytes
1861//      Wave/Z nxy = root:numberXY
1862//      Wave/Z nBytes = root:numberBytes
1863//      if(WaveExists(nxy) && WaveExists(nBytes))
1864//              InsertPoints 0, 1, nxy,nBytes
1865//              nxy[0] = numXYevents
1866//              nBytes[0] = totBytes
1867//      endif
1868
1869        SetDataFolder root:
1870
1871#endif 
1872        return(0)
1873       
1874End
1875
1876//////////////
1877
1878Proc BinEventBarGraph()
1879       
1880        DoWindow/F EventBarGraph
1881        if(V_flag == 0)
1882                PauseUpdate; Silent 1           // building window...
1883                String fldrSav0= GetDataFolder(1)
1884                SetDataFolder root:Packages:NIST:Event:
1885                Display /W=(110,705,610,1132)/N=EventBarGraph /K=1 binCount vs binEndTime
1886                SetDataFolder fldrSav0
1887                ModifyGraph mode=5
1888                ModifyGraph marker=19
1889                ModifyGraph lSize=2
1890                ModifyGraph rgb=(0,0,0)
1891                ModifyGraph msize=2
1892                ModifyGraph hbFill=2
1893                ModifyGraph gaps=0
1894                ModifyGraph usePlusRGB=1
1895                ModifyGraph toMode=1
1896                ModifyGraph useBarStrokeRGB=1
1897                ModifyGraph standoff=0
1898                SetAxis left 0,*
1899                Label bottom "\\Z14Time (seconds)"
1900                Label left "\\Z14Number of Events"
1901        endif
1902End
1903
1904
1905Proc ShowBinTable()
1906
1907        DoWindow/F BinEventTable
1908        if(V_flag == 0)
1909                PauseUpdate; Silent 1           // building window...
1910                String fldrSav0= GetDataFolder(1)
1911                SetDataFolder root:Packages:NIST:Event:
1912                Edit/W=(498,699,1003,955) /K=1/N=BinEventTable binCount,binEndTime,timeWidth
1913                ModifyTable format(Point)=1,sigDigits(binEndTime)=8,width(binEndTime)=100
1914                SetDataFolder fldrSav0
1915        endif
1916EndMacro
1917
1918
1919// only show the first 1500 data points
1920//
1921Proc ShowRescaledTimeGraph()
1922
1923        DoWindow/F RescaledTimeGraph
1924        if(V_flag == 0)
1925                PauseUpdate; Silent 1           // building window...
1926                String fldrSav0= GetDataFolder(1)
1927                SetDataFolder root:Packages:NIST:Event:
1928                Display /W=(25,44,486,356)/K=1/N=RescaledTimeGraph rescaledTime
1929                SetDataFolder fldrSav0
1930                ModifyGraph mode=4
1931                ModifyGraph marker=19
1932                ModifyGraph rgb(rescaledTime)=(0,0,0)
1933                ModifyGraph msize=1
1934//              SetAxis/A=2 left                        //only autoscale the visible data (based on the bottom limits)
1935                SetAxis bottom 0,1500
1936                ErrorBars rescaledTime OFF
1937                Label left "\\Z14Time (seconds)"
1938                Label bottom "\\Z14Event number"
1939                ShowInfo
1940        endif
1941       
1942EndMacro
1943
1944
1945
1946Proc ExportSlicesAsVAX(firstNum,prefix)
1947        Variable firstNum=1
1948        String prefix="SAMPL"
1949
1950        SaveSlicesAsVAX(firstNum,prefix[0,4])           //make sure that the prefix is 5 chars
1951End
1952
1953//////// procedures to be able to export the slices as RAW VAX files.
1954//
1955// 1- load the raw data file to use the header (it must already be in RAW)
1956// 1.5- copy the raw data to the temp folder (STO)
1957// 1.7- ask for the prefix and starting run number (these are passed in)
1958// 2- copy the slice of data to the temp folder (STO)
1959// 3- touch up the time/counts in the slice header values in STO
1960// 4- write out the VAX file
1961// 5- repeat (2-4) for the number of slices
1962//
1963//
1964Function SaveSlicesAsVAX(firstNum,prefix)
1965        Variable firstNum
1966        String prefix
1967
1968        DoAlert 1,"Is the full data file loaded as a RAW data file? If not, load it and start over..."
1969        if(V_flag == 2)
1970                return (0)
1971        endif
1972       
1973// copy the contents of RAW to STO so I can work from there
1974        CopyWorkContents("RAW","STO")
1975
1976        // now declare all of the waves, now that they are sure to be there
1977
1978        WAVE slicedData=root:Packages:NIST:Event:slicedData
1979        Make/O/D/N=(128,128) curSlice
1980       
1981        NVAR nslices = root:Packages:NIST:Event:gEvent_nslices
1982        WAVE binEndTime = root:Packages:NIST:Event:binEndTime
1983
1984        Wave rw=root:Packages:NIST:STO:realsRead
1985        Wave iw=root:Packages:NIST:STO:integersRead
1986        Wave/T tw=root:Packages:NIST:STO:textRead
1987        Wave data=root:Packages:NIST:STO:data
1988        Wave linear_data=root:Packages:NIST:STO:linear_data
1989       
1990       
1991        Wave rw_raw=root:Packages:NIST:RAW:realsRead
1992        Wave iw_raw=root:Packages:NIST:RAW:integersRead
1993        Wave/T tw_raw=root:Packages:NIST:RAW:textRead
1994
1995// for generating the alphanumeric
1996        String timeStr= secs2date(datetime,-1)
1997        String monthStr=StringFromList(1, timeStr  ,"/")
1998        String numStr="",labelStr
1999
2000        Variable ii,err,binFraction
2001       
2002        for(ii=0;ii<nslices;ii+=1)
2003
2004                //get the current slice and put it in the STO folder
2005                curSlice = slicedData[p][q][ii]
2006                data = curSlice
2007                linear_data = curSlice
2008               
2009                // touch up the header as needed
2010                // count time = iw[2]
2011                // monCt = rw[0]
2012                // detCt = rw[2]
2013                //tw[0] must now be the file name
2014                //
2015                // count time = fraction of total binning * total count time
2016                binFraction = (binEndTime[ii+1]-binEndTime[ii])/(binEndTime[nslices]-binEndTime[0])
2017               
2018                iw[2] = trunc(binFraction*iw_raw[2])
2019                rw[0] = trunc(binFraction*rw_raw[0])
2020                rw[2] = sum(curSlice,-inf,inf)          //total counts in slice
2021       
2022                if(firstNum<10)
2023                        numStr = "00"+num2str(firstNum)
2024                else
2025                        if(firstNum<100)
2026                                numStr = "0"+num2str(firstNum)
2027                        else
2028                                numStr = num2str(firstNum)
2029                        Endif
2030                Endif   
2031                tw[0] = prefix+numstr+".SA2_EVE_"+(num2char(str2num(monthStr)+64))+numStr
2032                labelStr = tw_raw[6]
2033               
2034                labelStr = PadString(labelStr,60,0x20)  //60 fortran-style spaces
2035                tw[6] = labelStr[0,59]
2036               
2037                //write out the file - this uses the tw[0] and home path
2038                Write_VAXRaw_Data("STO","",0)
2039
2040                //increment the run number, alpha
2041                firstNum += 1   
2042        endfor
2043
2044        return(0)
2045End
2046
2047
2048
2049
2050
2051/////////////
2052//The histogramming
2053//
2054// 6 AUG 2012
2055//
2056// from Igor Exchange, RGerkin
2057//  http://www.igorexchange.com/node/1373
2058// -- see the related thread on the mailing list
2059//
2060//Function Setup_JointHistogram()
2061//
2062////    tic()
2063//
2064//      make/D /o/n=1000000 data1=gnoise(1), data2=gnoise(1)
2065//      make/D /o/n=(25,25) myHist
2066//      setscale x,-3,3,myHist
2067//      setscale y,-3,3,myHist
2068//      IndexForHistogram(data1,data2,myhist)
2069//      Wave index=SavedIndex
2070//      JointHistogram(data1,data2,myHist,index)
2071//      NewImage myHist
2072//     
2073////    toc()
2074//     
2075//End
2076
2077
2078Function JointHistogram(w0,w1,hist,index)
2079        wave w0,w1,hist,index
2080 
2081        variable bins0=dimsize(hist,0)
2082        variable bins1=dimsize(hist,1)
2083        variable n=numpnts(w0)
2084        variable left0=dimoffset(hist,0)
2085        variable left1=dimoffset(hist,1)
2086        variable right0=left0+bins0*dimdelta(hist,0)
2087        variable right1=left1+bins1*dimdelta(hist,1)
2088       
2089        // Compute the histogram and redimension it. 
2090        histogram /b={0,1,bins0*bins1} index,hist
2091        redimension/D /n=(bins0,bins1) hist // Redimension to 2D. 
2092        setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
2093        setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
2094End
2095
2096
2097// histogram with a point range
2098//
2099// x- just need to send x2pnt or findLevel, or something similar to define the POINT
2100// values
2101//
2102// x- can also speed this up since the index only needs to be done once, so the
2103// histogram operation can be done separately, as the bins require
2104//
2105//
2106Function JointHistogramWithRange(w0,w1,hist,index,pt1,pt2)
2107        wave w0,w1,hist,index
2108        Variable pt1,pt2
2109 
2110        variable bins0=dimsize(hist,0)
2111        variable bins1=dimsize(hist,1)
2112        variable n=numpnts(w0)
2113        variable left0=dimoffset(hist,0)
2114        variable left1=dimoffset(hist,1)
2115        variable right0=left0+bins0*dimdelta(hist,0)
2116        variable right1=left1+bins1*dimdelta(hist,1)
2117
2118        // Compute the histogram and redimension it. 
2119        histogram /b={0,1,bins0*bins1}/R=[pt1,pt2] index,hist
2120        redimension/D /n=(bins0,bins1) hist // Redimension to 2D. 
2121        setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
2122        setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
2123End
2124
2125
2126// just does the indexing, creates wave SavedIndex in the current folder for the index
2127//
2128Function IndexForHistogram(w0,w1,hist)
2129        wave w0,w1,hist
2130 
2131        variable bins0=dimsize(hist,0)
2132        variable bins1=dimsize(hist,1)
2133        variable n=numpnts(w0)
2134        variable left0=dimoffset(hist,0)
2135        variable left1=dimoffset(hist,1)
2136        variable right0=left0+bins0*dimdelta(hist,0)
2137        variable right1=left1+bins1*dimdelta(hist,1)
2138 
2139        // Scale between 0 and the number of bins to create an index wave. 
2140        if(ThreadProcessorCount<4) // For older machines, matrixop is faster. 
2141                matrixop /free idx=round(bins0*(w0-left0)/(right0-left0))+bins0*round(bins1*(w1-left1)/(right1-left1))
2142        else // For newer machines with many cores, multithreading with make is faster. 
2143                make/free/n=(n) idx
2144                multithread idx=round(bins0*(w0-left0)/(right0-left0))+bins0*round(bins1*(w1-left1)/(right1-left1))
2145        endif
2146 
2147        KillWaves/Z SavedIndex
2148        MoveWave idx,SavedIndex
2149       
2150//      // Compute the histogram and redimension it. 
2151//      histogram /b={0,1,bins0*bins1} idx,hist
2152//      redimension /n=(bins0,bins1) hist // Redimension to 2D. 
2153//      setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
2154//      setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
2155End
2156
2157
2158
2159
2160
2161////////////// Post-processing of the event mode data
2162Proc ShowEventCorrectionPanel()
2163        DoWindow/F EventCorrectionPanel
2164        if(V_flag ==0)
2165                EventCorrectionPanel()
2166        EndIf
2167End
2168
2169Proc EventCorrectionPanel()
2170
2171        PauseUpdate; Silent 1           // building window...
2172        SetDataFolder root:Packages:NIST:Event:
2173       
2174        if(exists("rescaledTime") == 1)
2175                Display /W=(35,44,761,533)/K=2 rescaledTime
2176                DoWindow/C EventCorrectionPanel
2177                ModifyGraph mode=4
2178                ModifyGraph marker=19
2179                ModifyGraph rgb=(0,0,0)
2180                ModifyGraph msize=1
2181                ErrorBars rescaledTime OFF
2182                Label left "\\Z14Time (seconds)"
2183                Label bottom "\\Z14Event number"       
2184                SetAxis bottom 0,0.10*numpnts(rescaledTime)             //show 1st 10% of data for speed in displaying
2185               
2186                ControlBar 100
2187                Button button0,pos={18,12},size={70,20},proc=EC_AddCursorButtonProc,title="Cursors"
2188                Button button1,pos={153,12},size={80,20},proc=EC_AddTimeButtonProc,title="Add time"
2189                Button button2,pos={153,38},size={80,20},proc=EC_SubtractTimeButtonProc,title="Subtr time"
2190                Button button3,pos={153,64},size={90,20},proc=EC_TrimPointsButtonProc,title="Trim points"
2191                Button button4,pos={295+150,12},size={90,20},proc=EC_SaveWavesButtonProc,title="Save Waves"
2192                Button button5,pos={295,64},size={100,20},proc=EC_FindOutlierButton,title="Find Outlier"
2193                Button button6,pos={18,38},size={80,20},proc=EC_ShowAllButtonProc,title="All Data"
2194                Button button7,pos={683,12},size={30,20},proc=EC_HelpButtonProc,title="?"
2195                Button button8,pos={658,72},size={60,20},proc=EC_DoneButtonProc,title="Done"
2196       
2197                Button button9,pos={295,12},size={110,20},proc=EC_FindStepButton_down,title="Find Step Down"
2198                Button button10,pos={295,38},size={110,20},proc=EC_FindStepButton_up,title="Find Step Up"
2199                Button button11,pos={295+150,38},size={110,20},proc=EC_DoDifferential,title="Differential"
2200               
2201               
2202        else
2203                DoAlert 0, "Please load some event data, then you'll have something to edit."
2204        endif
2205       
2206        SetDataFolder root:
2207       
2208EndMacro
2209
2210Function EC_AddCursorButtonProc(ba) : ButtonControl
2211        STRUCT WMButtonAction &ba
2212
2213        switch( ba.eventCode )
2214                case 2: // mouse up
2215                        // click code here
2216                        SetDataFolder root:Packages:NIST:Event:
2217                       
2218                        Wave rescaledTime = rescaledTime
2219                        Cursor/P A rescaledTime 0
2220                        Cursor/P B rescaledTime numpnts(rescaledTime)-1
2221                        ShowInfo
2222                        SetDataFolder root:
2223                        break
2224                case -1: // control being killed
2225                        break
2226        endswitch
2227
2228        return 0
2229End
2230
2231// updates the longest time (as does every operation of adjusting the data)
2232//
2233Function EC_AddTimeButtonProc(ba) : ButtonControl
2234        STRUCT WMButtonAction &ba
2235
2236        switch( ba.eventCode )
2237                case 2: // mouse up
2238                        // click code here
2239                        SetDataFolder root:Packages:NIST:Event:
2240                       
2241                        Wave rescaledTime = rescaledTime
2242                        Wave timePt = timePt
2243                        Variable rollTime,rollTicks,ptA,ptB,lo,hi
2244                       
2245                        rollTicks = 2^26                                // in ticks
2246                        rollTime = 2^26*1e-7            // in seconds
2247                        ptA = pcsr(A)
2248                        ptB = pcsr(B)
2249                        lo=min(ptA,ptB)
2250                        hi=max(ptA,ptB)
2251
2252                        MultiThread timePt[lo,hi] += rollTicks
2253                        MultiThread rescaledTime[lo,hi] += rollTime
2254
2255                        // updates the longest time (as does every operation of adjusting the data)
2256                        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
2257                        t_longest = waveMax(rescaledTime)
2258                       
2259                        SetDataFolder root:
2260                        break
2261                case -1: // control being killed
2262                        break
2263        endswitch
2264
2265        return 0
2266End
2267
2268Function EC_SubtractTimeButtonProc(ba) : ButtonControl
2269        STRUCT WMButtonAction &ba
2270
2271        switch( ba.eventCode )
2272                case 2: // mouse up
2273                        // click code here
2274                        SetDataFolder root:Packages:NIST:Event:
2275                       
2276                        Wave rescaledTime = rescaledTime
2277                        Wave timePt = timePt
2278                        Variable rollTime,rollTicks,ptA,ptB,lo,hi
2279                       
2280                        rollTicks = 2^26                                // in ticks
2281                        rollTime = 2^26*1e-7            // in seconds
2282                        ptA = pcsr(A)
2283                        ptB = pcsr(B)
2284                        lo=min(ptA,ptB)
2285                        hi=max(ptA,ptB)
2286                       
2287                        MultiThread timePt[lo,hi] -= rollTicks
2288                        MultiThread rescaledTime[lo,hi] -= rollTime
2289
2290                        // updates the longest time (as does every operation of adjusting the data)
2291                        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
2292                        t_longest = waveMax(rescaledTime)
2293                       
2294                        SetDataFolder root:
2295                       
2296                        break
2297                case -1: // control being killed
2298                        break
2299        endswitch
2300
2301        return 0
2302End
2303
2304// points removed are inclusive
2305//
2306// put both cursors on the same point to remove just that single point
2307//
2308Function EC_TrimPointsButtonProc(ba) : ButtonControl
2309        STRUCT WMButtonAction &ba
2310
2311        switch( ba.eventCode )
2312                case 2: // mouse up
2313                        // click code here
2314                        SetDataFolder root:Packages:NIST:Event:
2315                       
2316                        Wave rescaledTime = rescaledTime
2317                        Wave timePt = timePt
2318                        Wave xLoc = xLoc
2319                        Wave yLoc = yLoc
2320                        Variable rollTime,ptA,ptB,numElements,lo,hi
2321                       
2322                        rollTime = 2^26*1e-7            // in seconds
2323                        ptA = pcsr(A)
2324                        ptB = pcsr(B)
2325                        lo=min(ptA,ptB)
2326                        hi=max(ptA,ptB)                 
2327                        numElements = abs(ptA-ptB)+1                    //so points removed are inclusive
2328                        DeletePoints lo, numElements, rescaledTime,timePt,xLoc,yLoc
2329                       
2330                        printf "Points %g to %g have been deleted in rescaledTime, timePt, xLoc, and yLoc\r",ptA,ptB
2331                       
2332                        // updates the longest time (as does every operation of adjusting the data)
2333                        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
2334                        t_longest = waveMax(rescaledTime)
2335                       
2336                        SetDataFolder root:
2337                       
2338                        break
2339                case -1: // control being killed
2340                        break
2341        endswitch
2342
2343        return 0
2344End
2345
2346// un-sort the data first, then save it
2347Function EC_SaveWavesButtonProc(ba) : ButtonControl
2348        STRUCT WMButtonAction &ba
2349
2350        switch( ba.eventCode )
2351                case 2: // mouse up
2352                        // click code here
2353                       
2354//                      Execute "UndoTheSorting()"
2355                       
2356                        SetDataFolder root:Packages:NIST:Event:
2357                       
2358                        Wave rescaledTime = rescaledTime
2359                        Wave timePt = timePt
2360                        Wave xLoc = xLoc
2361                        Wave yLoc = yLoc
2362                        Save/T xLoc,yLoc,timePt ,rescaledTime           //will ask for a name
2363                       
2364                        SetDataFolder root:
2365                        break
2366                case -1: // control being killed
2367                        break
2368        endswitch
2369
2370        return 0
2371End
2372
2373//
2374// this duplicates all of the bits that would be done if the "load" button was pressed
2375//
2376Function EC_ImportWavesButtonProc(ba) : ButtonControl
2377        STRUCT WMButtonAction &ba
2378
2379        switch( ba.eventCode )
2380                case 2: // mouse up
2381                        // click code here
2382                        SetDataFolder root:Packages:NIST:Event:
2383
2384                        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
2385                        SVAR dispStr = root:Packages:NIST:Event:gEventDisplayString
2386                        String tmpStr="",fileStr,filePathStr
2387                       
2388                        // load in the waves, saved as Igor text to preserve the data type
2389                        LoadWave/T/O/P=catPathName
2390                        filePathStr = S_fileName
2391                        if(strlen(S_fileName) == 0)
2392                                //user cancelled
2393                                DoAlert 0,"No file selected, nothing done."
2394                                return(0)
2395                        endif
2396                       
2397                        NVAR mode = root:Packages:NIST:Event:gEvent_Mode                                // ==0 for "stream", ==1 for Oscillatory
2398                        // clear out the old sort index, if present, since new data is being loaded
2399                        KillWaves/Z OscSortIndex
2400                        Wave timePt=timePt
2401                        Wave rescaledTime=rescaledTime
2402                       
2403                        t_longest = waveMax(rescaledTime)               //should be the last point
2404                       
2405       
2406                        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
2407                        sprintf tmpStr, "%s: a user-modified event file\r",fileStr
2408                        dispStr = tmpStr
2409       
2410                        SetDataFolder root:
2411                        break
2412                case -1: // control being killed
2413                        break
2414        endswitch
2415
2416        return 0
2417End
2418
2419
2420Function EC_ShowAllButtonProc(ba) : ButtonControl
2421        STRUCT WMButtonAction &ba
2422
2423        switch( ba.eventCode )
2424                case 2: // mouse up
2425                        // click code here
2426                        SetAxis/A
2427                        break
2428                case -1: // control being killed
2429                        break
2430        endswitch
2431
2432        return 0
2433End
2434
2435Function EC_HelpButtonProc(ba) : ButtonControl
2436        STRUCT WMButtonAction &ba
2437
2438        switch( ba.eventCode )
2439                case 2: // mouse up
2440                        // click code here
2441                        DisplayHelpTopic/Z "Event Mode Data[Correcting for things that go wrong]"
2442                        break
2443                case -1: // control being killed
2444                        break
2445        endswitch
2446
2447        return 0
2448End
2449
2450Function EC_DoneButtonProc(ba) : ButtonControl
2451        STRUCT WMButtonAction &ba
2452
2453        switch( ba.eventCode )
2454                case 2: // mouse up
2455                        // click code here
2456                        DoWindow/K EventCorrectionPanel
2457                        break
2458                case -1: // control being killed
2459                        break
2460        endswitch
2461
2462        return 0
2463End
2464
2465//upDown 5 or -5 looks for spikes +5 or -5 std deviations from mean
2466Function PutCursorsAtStep(upDown)
2467        Variable upDown
2468       
2469        SetDataFolder root:Packages:NIST:Event:
2470
2471        Wave rescaledTime=rescaledTime
2472        Wave rescaledTime_DIF=rescaledTime_DIF
2473        Variable avg,pt,zoom
2474       
2475        zoom = 200              //points in each direction
2476       
2477        WaveStats/M=1/Q rescaledTime_DIF
2478        avg = V_avg
2479               
2480        FindLevel/P/Q rescaledTime_DIF avg*upDown
2481        if(V_flag==0)
2482                pt = V_levelX
2483                WaveStats/Q/R=[pt-zoom,pt+zoom] rescaledTime            // find the max/min y-vallues within the point range
2484        else
2485                Print "Level not found"
2486                return(0)
2487        endif
2488       
2489        Variable loLeft,hiLeft, loBottom,hiBottom
2490        loLeft = V_min*0.98             //+/- 2%
2491        hiLeft = V_max*1.02
2492       
2493        SetAxis left loLeft,hiLeft
2494        SetAxis bottom pnt2x(rescaledTime,pt-zoom),pnt2x(rescaledTime,pt+zoom)
2495       
2496        Cursor/P A rescaledTime pt+2    //at the point
2497        Cursor/P B rescaledTime numpnts(rescaledTime)-1         //at the end
2498
2499        SetDataFolder root:
2500
2501        return(0)
2502End
2503
2504
2505// find the max (or min) of the rescaled time set
2506// and place both cursors there
2507Function fFindOutlier()
2508
2509        SetDataFolder root:Packages:NIST:Event:
2510
2511        Wave rescaledTime=rescaledTime
2512        Variable avg,pt,zoom,maxPt,minPt,maxVal,minVal
2513       
2514        zoom = 200              //points in each direction
2515       
2516        WaveStats/M=1/Q rescaledTime
2517        maxPt = V_maxLoc
2518        minPt = V_minLoc
2519        avg = V_avg
2520        maxVal = abs(V_max)
2521        minVal = abs(V_min)
2522
2523        pt = abs(maxVal - avg) > abs(minVal - avg) ? maxPt : minPt
2524       
2525//      Variable loLeft,hiLeft, loBottom,hiBottom
2526//      loLeft = V_min*0.98             //+/- 2%
2527//      hiLeft = V_max*1.02
2528       
2529//      SetAxis left loLeft,hiLeft
2530//      SetAxis bottom pnt2x(rescaledTime,pt-zoom),pnt2x(rescaledTime,pt+zoom)
2531       
2532        Cursor/P A rescaledTime pt              //at the point
2533        Cursor/P B rescaledTime pt              //at the same point
2534
2535        SetDataFolder root:
2536       
2537        return(0)
2538End
2539
2540Function EC_FindStepButton_down(ctrlName) : ButtonControl
2541        String ctrlName
2542       
2543//      Variable upDown = -5
2544        NVAR upDown = root:Packages:NIST:Event:gStepTolerance
2545       
2546        PutCursorsAtStep(-1*upDown)
2547
2548        return(0)
2549end
2550
2551
2552Function EC_FindStepButton_up(ctrlName) : ButtonControl
2553        String ctrlName
2554       
2555//      Variable upDown = 5
2556        NVAR upDown = root:Packages:NIST:Event:gStepTolerance
2557
2558        PutCursorsAtStep(upDown)
2559
2560        return(0)
2561end
2562
2563// if the Trim button section is uncommented, it's "Zap outlier"
2564//
2565Function EC_FindOutlierButton(ctrlName) : ButtonControl
2566        String ctrlName
2567       
2568        fFindOutlier()
2569//
2570//      STRUCT WMButtonAction ba
2571//      ba.eventCode = 2
2572//
2573//      EC_TrimPointsButtonProc(ba)
2574
2575        return(0)
2576end
2577
2578Function EC_DoDifferential(ctrlName) : ButtonControl
2579        String ctrlName
2580       
2581        DifferentiatedTime()
2582        DoWindow/F EventCorrectionPanel
2583       
2584        //if trace is not on graph, add it
2585        SetDataFolder root:Packages:NIST:Event:
2586
2587        String list = WaveList("*_DIF", ";", "WIN:EventCorrectionPanel")
2588        if(strlen(list) == 0)
2589                AppendToGraph/R rescaledTime_DIF
2590                ModifyGraph msize=1,rgb(rescaledTime_DIF)=(65535,0,0)
2591                ReorderTraces rescaledTime,{rescaledTime_DIF}           // put the differential behind the event data
2592        endif
2593        SetDataFolder root:
2594        return(0)
2595end
2596
2597//////////////   Custom Bins  /////////////////////
2598//
2599//
2600//
2601// make sure that the bins are defined and the waves exist before
2602// trying to draw the panel
2603//
2604Proc Show_CustomBinPanel()
2605        DoWindow/F CustomBinPanel
2606        if(V_flag ==0)
2607                Init_CustomBins()
2608                CustomBinPanel()
2609        EndIf
2610End
2611
2612
2613Function Init_CustomBins()
2614
2615        NVAR nSlice = root:Packages:NIST:Event:gEvent_nslices
2616        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
2617
2618        Variable/G root:Packages:NIST:Event:gEvent_ForceTmaxBin=1               //==1 to enforce t_longest in user-defined custom bins
2619
2620        SetDataFolder root:Packages:NIST:Event:
2621               
2622        Make/O/D/N=(nSlice) timeWidth
2623        Make/O/D/N=(nSlice+1) binEndTime,binCount
2624       
2625        timeWidth = t_longest/nslice
2626        binEndTime = p
2627        binCount = p+1 
2628       
2629        SetDataFolder root:
2630       
2631        return(0)
2632End
2633
2634////////////////       
2635//
2636// Allow custom definitions of the bin widths
2637//
2638// Define by the number of bins, and the time width of each bin
2639//
2640// This shares the number of slices and the maximum time with the main panel
2641//
2642Proc CustomBinPanel()
2643        PauseUpdate; Silent 1           // building window...
2644        NewPanel /W=(130,44,851,455)/K=2 /N=CustomBinPanel
2645        DoWindow/C CustomBinPanel
2646        ModifyPanel fixedSize=1//,noEdit =1
2647        SetDrawLayer UserBack
2648       
2649        Button button0,pos={654,42}, size={50,20},title="Done",fSize=12
2650        Button button0,proc=CB_Done_Proc
2651        Button button1,pos={663,14},size={40,20},proc=CB_HelpButtonProc,title="?"
2652        Button button2,pos={216,42},size={80,20},title="Update",proc=CB_UpdateWavesButton       
2653        SetVariable setvar1,pos={23,13},size={160,20},title="Number of slices",fSize=12
2654        SetVariable setvar1,proc=CB_NumSlicesSetVarProc,value=root:Packages:NIST:Event:gEvent_nslices
2655        SetVariable setvar2,pos={24,44},size={160,20},title="Max Time (s)",fSize=10
2656        SetVariable setvar2,value=root:Packages:NIST:Event:gEvent_t_longest     
2657
2658        CheckBox chkbox1,pos={216,14},title="Enforce Max Time?"
2659        CheckBox chkbox1,variable = root:Packages:NIST:Event:gEvent_ForceTmaxBin
2660        Button button3,pos={500,14},size={90,20},proc=CB_SaveBinsButtonProc,title="Save Bins"
2661        Button button4,pos={500,42},size={100,20},proc=CB_ImportBinsButtonProc,title="Import Bins"     
2662               
2663        SetDataFolder root:Packages:NIST:Event:
2664
2665        Display/W=(291,86,706,395)/HOST=CustomBinPanel/N=BarGraph binCount vs binEndTime
2666        ModifyGraph mode=5
2667        ModifyGraph marker=19
2668        ModifyGraph lSize=2
2669        ModifyGraph rgb=(0,0,0)
2670        ModifyGraph msize=2
2671        ModifyGraph hbFill=2
2672        ModifyGraph gaps=0
2673        ModifyGraph usePlusRGB=1
2674        ModifyGraph toMode=1
2675        ModifyGraph useBarStrokeRGB=1
2676        ModifyGraph standoff=0
2677        SetAxis left 0,*
2678        Label bottom "\\Z14Time (seconds)"
2679        Label left "\\Z14Number of Events"
2680        SetActiveSubwindow ##
2681       
2682        // and the table
2683        Edit/W=(13,87,280,394)/HOST=CustomBinPanel/N=T0
2684        AppendToTable/W=CustomBinPanel#T0 timeWidth,binEndTime
2685        ModifyTable width(Point)=40
2686        SetActiveSubwindow ##
2687       
2688        SetDataFolder root:
2689       
2690EndMacro
2691
2692// save the bins - use Igor Text format
2693//
2694Function CB_SaveBinsButtonProc(ba) : ButtonControl
2695        STRUCT WMButtonAction &ba
2696
2697        switch( ba.eventCode )
2698                case 2: // mouse up
2699                        // click code here
2700
2701                        SetDataFolder root:Packages:NIST:Event:
2702
2703                        Wave timeWidth = timeWidth
2704                        Wave binEndTime = binEndTime
2705                       
2706                        Save/T timeWidth,binEndTime                     //will ask for a name
2707
2708                        break
2709                case -1: // control being killed
2710                        break
2711        endswitch
2712
2713        SetDataFolder root:
2714       
2715        return 0
2716End
2717
2718// Import the bins - use Igor Text format
2719//
2720// -- be sure that the number of bins is reset
2721// -?- how about the t_longest? - this should be set by the load, not here
2722//
2723// -- loads in timeWidth and binEndTime
2724//
2725Function CB_ImportBinsButtonProc(ba) : ButtonControl
2726        STRUCT WMButtonAction &ba
2727
2728        switch( ba.eventCode )
2729                case 2: // mouse up
2730                        // click code here
2731                        NVAR nSlice = root:Packages:NIST:Event:gEvent_nslices
2732
2733                        SetDataFolder root:Packages:NIST:Event:
2734
2735                        // prompt for the load of data
2736                        LoadWave/T/O
2737                        if(strlen(S_fileName) == 0)
2738                                //user cancelled
2739                                DoAlert 0,"No file selected, nothing done."
2740                                return(0)
2741                        endif
2742
2743                        Wave timeWidth = timeWidth
2744                        nSlice = numpnts(timeWidth)
2745                       
2746                        break
2747                case -1: // control being killed
2748                        break
2749        endswitch
2750
2751        SetDataFolder root:
2752       
2753        return 0
2754End
2755
2756
2757
2758//
2759// can either use the widths as stated -- then the end time may not
2760// match the actual end time of the data set
2761//
2762// -- or --
2763//
2764// enforce the end time of the data set to be the end time of the bins,
2765// then the last bin width must be reset to force the constraint
2766//
2767//
2768Function CB_UpdateWavesButton(ba) : ButtonControl
2769        STRUCT WMButtonAction &ba
2770
2771        switch( ba.eventCode )
2772                case 2: // mouse up
2773                        // click code here
2774                        NVAR nSlice = root:Packages:NIST:Event:gEvent_nslices
2775                        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
2776                        NVAR enforceTmax = root:Packages:NIST:Event:gEvent_ForceTmaxBin
2777                       
2778                        // update the waves, and recalculate everything for the display
2779                        SetDataFolder root:Packages:NIST:Event:
2780
2781                        Wave timeWidth = timeWidth
2782                        Wave binEndTime = binEndTime
2783                        Wave binCount = binCount
2784                       
2785                        // use the widths as entered
2786                        binEndTime[0] = 0
2787                        binEndTime[1,] = binEndTime[p-1] + timeWidth[p-1]
2788                       
2789                        // enforce the longest time as the end bin time
2790                        // note that this changes the last time width
2791                        if(enforceTmax)
2792                                binEndTime[nSlice] = t_longest
2793                                timeWidth[nSlice-1] = t_longest - binEndTime[nSlice-1]
2794                        endif
2795                       
2796                        binCount = p+1
2797                        binCount[nSlice] = 0            // last point is zero, just for display
2798//                      binCount *= sign(timeWidth)             //to alert to negative time bins
2799                       
2800                        // make the timeWidth bold and red if the widths are negative
2801                        WaveStats/Q timeWidth
2802                        if(V_min < 0)
2803                                ModifyTable/W=CustomBinPanel#T0 style(timeWidth)=1,rgb(timeWidth)=(65535,0,0)                   
2804                        else
2805                                ModifyTable/W=CustomBinPanel#T0 style(timeWidth)=0,rgb(timeWidth)=(0,0,0)                       
2806                        endif
2807                       
2808                        break
2809                case -1: // control being killed
2810                        break
2811        endswitch
2812
2813        SetDataFolder root:
2814       
2815        return 0
2816End
2817
2818Function CB_HelpButtonProc(ba) : ButtonControl
2819        STRUCT WMButtonAction &ba
2820
2821        switch( ba.eventCode )
2822                case 2: // mouse up
2823                        // click code here
2824                        DisplayHelpTopic/Z "Event Mode Data[Setting up Custom Bin Widths]"
2825                        break
2826                case -1: // control being killed
2827                        break
2828        endswitch
2829
2830        return 0
2831End
2832
2833Function CB_Done_Proc(ba) : ButtonControl
2834        STRUCT WMButtonAction &ba
2835       
2836        String win = ba.win
2837        switch (ba.eventCode)
2838                case 2:
2839                        DoWindow/K CustomBinPanel
2840                        break
2841        endswitch
2842        return(0)
2843End
2844
2845
2846Function CB_NumSlicesSetVarProc(sva) : SetVariableControl
2847        STRUCT WMSetVariableAction &sva
2848
2849        switch( sva.eventCode )
2850                case 1: // mouse up
2851                case 2: // Enter key
2852                case 3: // Live update
2853                        Variable dval = sva.dval
2854                        String sval = sva.sval
2855                        SetDataFolder root:Packages:NIST:Event:
2856
2857                        Wave timeWidth = timeWidth
2858                        Wave binEndTime = binEndTime
2859                       
2860                        Redimension/N=(dval) timeWidth
2861                        Redimension/N=(dval+1) binEndTime,binCount
2862                       
2863                        SetDataFolder root:
2864                       
2865                        break
2866                case -1: // control being killed
2867                        break
2868        endswitch
2869
2870        return 0
2871End
2872
2873
2874///////////////////
2875//
2876// utility to split a large file
2877// 100 MB is the recommended size
2878// events can be clipped here, so be sure to trim the ends of the
2879// resulting files as needed.
2880//
2881// - works like the unix 'split' command
2882//
2883//
2884
2885Proc SplitBigFile(splitSize, baseStr)
2886        Variable splitSize = 100
2887        String baseStr="split"
2888        Prompt splitSize,"Target file size, in MB"
2889        Prompt baseStr,"File prefix, number will be appended"
2890       
2891       
2892        fSplitBigFile(splitSize, baseStr)
2893       
2894        ShowSplitFileTable()
2895End
2896
2897Function/S fSplitBigFile(splitSize, baseStr)
2898        Variable splitSize
2899        String baseStr         
2900
2901
2902        String fileName=""              // File name, partial path, full path or "" for dialog.
2903        Variable refNum
2904        String str
2905        SVAR listStr = root:Packages:NIST:Event:gSplitFileList
2906       
2907        listStr=""              //initialize output list
2908
2909        Variable readSize=1e6           //1 MB
2910        Make/O/B/U/N=(readSize) aBlob                   //1MB worth
2911        Variable numSplit
2912        Variable num,ii,jj,outRef,frac
2913        String thePath, outStr
2914       
2915        Printf "SplitSize = %u MB\r",splitSize
2916        splitSize = trunc(splitSize) * 1e6              // now in bytes
2917       
2918       
2919        // Open file for read.
2920        Open/R/Z=2/F="????"/P=catPathName refNum as fileName
2921        thePath = ParseFilePath(1, S_fileName, ":", 1, 0)
2922        Print "thePath = ",thePath
2923       
2924        // Store results from Open in a safe place.
2925        Variable err = V_flag
2926        String fullPath = S_fileName
2927
2928        if (err == -1)
2929                Print "cancelled by user."
2930                return ("")
2931        endif
2932
2933        FStatus refNum
2934       
2935        Printf "total # bytes = %u\r",V_logEOF
2936
2937        numSplit=0
2938        if(V_logEOF > splitSize)
2939                numSplit = trunc(V_logEOF/splitSize)
2940        endif
2941
2942        frac = V_logEOF - numSplit*splitSize
2943        Print "numSplit = ",numSplit
2944        Printf "frac = %u\r",frac
2945       
2946        num=0
2947        if(frac > readSize)
2948                num = trunc(frac/readSize)
2949        endif
2950
2951       
2952        frac = frac - num*readSize
2953
2954        Print "num = ",num
2955        Printf "frac = %u\r",frac
2956       
2957//      baseStr = "split"
2958       
2959        for(ii=0;ii<numSplit;ii+=1)
2960                outStr = (thePath+baseStr+num2str(ii))
2961//              Print "outStr = ",outStr
2962                Open outRef as outStr
2963
2964                for(jj=0;jj<(splitSize/readSize);jj+=1)
2965                        FBinRead refNum,aBlob
2966                        FBinWrite outRef,aBlob
2967                endfor
2968
2969                Close outRef
2970//              listStr += outStr+";"
2971                listStr += baseStr+num2str(ii)+";"
2972        endfor
2973
2974        Make/O/B/U/N=(frac) leftover
2975        // ii was already incremented past the loop
2976        outStr = (thePath+baseStr+num2str(ii))
2977        Open outRef as outStr
2978        for(jj=0;jj<num;jj+=1)
2979                FBinRead refNum,aBlob
2980                FBinWrite outRef,aBlob
2981        endfor
2982        FBinRead refNum,leftover
2983        FBinWrite outRef,leftover
2984
2985        Close outRef
2986//      listStr += outStr+";"
2987        listStr += baseStr+num2str(ii)+";"
2988
2989        FSetPos refNum,V_logEOF
2990        Close refNum
2991       
2992        KillWaves/Z aBlob,leftover
2993        return(listStr)
2994End
2995
2996// allows the list of loaded files to be edited
2997Function ShowSplitFileTable()
2998
2999        SVAR str = root:Packages:NIST:Event:gSplitFileList
3000       
3001        WAVE/T/Z tw = root:Packages:NIST:Event:SplitFileWave
3002        if(waveExists(tw) != 1)
3003                Make/O/T/N=1 root:Packages:NIST:Event:SplitFileWave
3004                WAVE/T/Z tw = root:Packages:NIST:Event:SplitFileWave
3005        endif
3006
3007        List2TextWave(str,tw)
3008        Edit tw
3009
3010        return(0)
3011End
3012
3013
3014//// save the sliced data, and accumulate slices
3015//  *** this works with sliced data -- that is data that has been PROCESSED
3016//
3017// need some way of ensuring that the slices match up since I'm blindly adding them together.
3018//
3019// mode = 0             wipe out the old accumulated, copy slicedData to accumulatedData
3020// mode = 1             add current slicedData to accumulatedData
3021// mode = 2             copy accumulatedData to slicedData in preparation of export or display
3022// mode = 3             unused...
3023//
3024//      "Split Large File",SplitBigFile()
3025//      "Accumulate First Slice",AccumulateSlices(0)
3026//      "Add Current Slice",AccumulateSlices(1)
3027//      "Display Accumulated Slices",AccumulateSlices(2)       
3028//
3029Function AccumulateSlicesButton(ctrlName) : ButtonControl
3030        String ctrlName
3031       
3032        Variable mode
3033        mode = str2num(ctrlName[strlen(ctrlName)-1])
3034//      Print "mode=",mode
3035        AccumulateSlices(mode)
3036       
3037        return(0)
3038End
3039
3040Function AccumulateSlices(mode)
3041        Variable mode
3042       
3043        SetDataFolder root:Packages:NIST:Event:
3044
3045        switch(mode)   
3046                case 0:
3047                        DoAlert 0,"The current data has been copied to the accumulated set. You are now ready to add more data."
3048                        KillWaves/Z accumulatedData
3049                        Duplicate/O slicedData accumulatedData         
3050                        break
3051                case 1:
3052                        DoAlert 0,"The current data has been added to the accumulated data. You can add more data."
3053                        Wave acc=accumulatedData
3054                        Wave cur=slicedData
3055                        acc += cur
3056                        break
3057                case 2:
3058                        DoAlert 0,"The accumulated data is now the display data and is ready for display or export."
3059                        Duplicate/O accumulatedData slicedData
3060                        // do something to "touch" the display to force it to update
3061                        NVAR gLog = root:Packages:NIST:Event:gEvent_logint
3062                        LogIntEvent_Proc("",gLog)
3063                        break
3064                default:                       
3065                               
3066        endswitch
3067
3068        SetDataFolder root:
3069        return(0)
3070end
3071
3072
3073////////////////////////////////////////////
3074//
3075// Panel and procedures for decimation
3076//
3077////////////////////////////////////////////
3078
3079//Function E_ShowDecimateButton(ctrlName) : ButtonControl
3080//      String ctrlName
3081//
3082//      DoWindow/F DecimatePanel
3083//      if(V_flag ==0)
3084//              Execute "DecimatePanel()"
3085//      endif
3086//End
3087//
3088//
3089//Proc DecimatePanel() //: Panel
3090//     
3091//      PauseUpdate; Silent 1           // building window...
3092//      NewPanel /W=(1602,44,1961,380)/K=1
3093////    ShowTools/A
3094//      Button button0,pos={29,15},size={100,20},proc=SplitFileButtonProc,title="Split Big File"
3095//      SetVariable setvar0,pos={182,55},size={150,15},title="Decimation factor",fsize=10
3096//      SetVariable setvar0,limits={1,inf,1},value= root:Packages:NIST:Event:gDecimation
3097//      Button button1,pos={26,245},size={150,20},proc=LoadDecimateButtonProc,title="Load and Decimate"
3098//      Button button2,pos={25,277},size={150,20},proc=ConcatenateButtonProc,title="Concatenate"
3099//      Button button3,pos={25,305},size={150,20},proc=DisplayConcatenatedButtonProc,title="Display Concatenated"
3100//      Button button4,pos={29,52},size={130,20},proc=Stream_LoadDecim,title="Load From List"
3101//     
3102//      GroupBox group0 title="Manual Controls",size={185,112},pos={14,220}
3103//EndMacro
3104
3105
3106Function SplitFileButtonProc(ctrlName) : ButtonControl
3107        String ctrlName
3108
3109        Execute "SplitBigFile()"
3110End
3111
3112
3113// show all of the data
3114//
3115Proc ShowDecimatedGraph()
3116
3117        DoWindow/F DecimatedGraph
3118        if(V_flag == 0)
3119                PauseUpdate; Silent 1           // building window...
3120                String fldrSav0= GetDataFolder(1)
3121                SetDataFolder root:Packages:NIST:Event:
3122                Display /W=(25,44,486,356)/K=1/N=DecimatedGraph rescaledTime_dec
3123                SetDataFolder fldrSav0
3124                ModifyGraph mode=4
3125                ModifyGraph marker=19
3126                ModifyGraph rgb(rescaledTime_dec)=(0,0,0)
3127                ModifyGraph msize=1
3128                ErrorBars rescaledTime_dec OFF
3129                Label left "\\Z14Time (seconds)"
3130                Label bottom "\\Z14Event number"
3131                ShowInfo
3132        endif
3133       
3134EndMacro
3135
3136// data has NOT been processed
3137//
3138// so work with x,y,t, and rescaled time
3139// variables -- t_longest
3140Function ConcatenateButtonProc(ctrlName) : ButtonControl
3141        String ctrlName
3142       
3143        DoAlert 1,"Is this the first file?"
3144        Variable first = V_flag
3145       
3146        fConcatenateButton(first)
3147       
3148        return(0)
3149End
3150
3151Function fConcatenateButton(first)
3152        Variable first
3153
3154
3155        SetDataFolder root:Packages:NIST:Event:
3156
3157        Wave timePt_dTmp=timePt_dTmp
3158        Wave xLoc_dTmp=xLoc_dTmp
3159        Wave yLoc_dTmp=yLoc_dTmp
3160        Wave rescaledTime_dTmp=rescaledTime_dTmp
3161       
3162        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3163        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
3164       
3165       
3166        if(first==1)            //1==yes, 2==no
3167                //then copy the files over, adjusting the time to start from zero
3168                // rescaledTime starts from zero (set by the loader)
3169
3170                timePt_dTmp -= timePt_dTmp[0]                   //subtract the first value
3171               
3172                Duplicate/O timePt_dTmp timePt_dec
3173                Duplicate/O xLoc_dTmp xLoc_dec
3174                Duplicate/O yLoc_dTmp yLoc_dec
3175                Duplicate/O rescaledTime_dTmp rescaledTime_dec
3176               
3177                t_longest_dec = t_longest
3178       
3179        else
3180                // concatenate the files + adjust the time
3181                Wave timePt_dec=timePt_dec
3182                Wave xLoc_dec=xLoc_dec
3183                Wave yLoc_dec=yLoc_dec
3184                Wave rescaledTime_dec=rescaledTime_dec
3185
3186                // adjust the times -- assuming they add
3187                // rescaledTime starts from zero (set by the loader)
3188                //
3189                //
3190                rescaledTime_dTmp += rescaledTime_dec[numpnts(rescaledTime_dec)-1]
3191                rescaledTime_dTmp += abs(rescaledTime_dec[numpnts(rescaledTime_dec)-1] - rescaledTime_dec[numpnts(rescaledTime_dec)-2])
3192               
3193                timePt_dTmp -= timePt_dTmp[0]                   //subtract the first value     
3194               
3195                timePt_dTmp += timePt_dec[numpnts(timePt_dec)-1]                // offset by the last point
3196                timePt_dTmp += abs(timePt_dec[numpnts(timePt_dec)-1] - timePt_dec[numpnts(timePt_dec)-2])               // plus delta so there's not a flat step
3197               
3198                Concatenate/NP/O {timePt_dec,timePt_dTmp}, tmp
3199                Duplicate/O tmp timePt_dec
3200               
3201                Concatenate/NP/O {xLoc_dec,xLoc_dTmp}, tmp
3202                Duplicate/O tmp xLoc_dec
3203               
3204                Concatenate/NP/O {yLoc_dec,yLoc_dTmp}, tmp
3205                Duplicate/O tmp yLoc_dec
3206               
3207                Concatenate/NP/O {rescaledTime_dec,rescaledTime_dTmp}, tmp
3208                Duplicate/O tmp rescaledTime_dec
3209               
3210
3211                KillWaves tmp
3212
3213                t_longest_dec = rescaledTime_dec[numpnts(rescaledTime_dec)-1]
3214
3215        endif
3216       
3217       
3218        SetDataFolder root:
3219       
3220        return(0)
3221
3222End
3223
3224Function DisplayConcatenatedButtonProc(ctrlName) : ButtonControl
3225        String ctrlName
3226
3227        //copy the files over to the display set for processing
3228        SetDataFolder root:Packages:NIST:Event:
3229
3230        Wave timePt_dec=timePt_dec
3231        Wave xLoc_dec=xLoc_dec
3232        Wave yLoc_dec=yLoc_dec
3233        Wave rescaledTime_dec=rescaledTime_dec
3234               
3235        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3236        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
3237       
3238        Duplicate/O timePt_dec timePt
3239        Duplicate/O xLoc_dec xLoc
3240        Duplicate/O yLoc_dec yLoc
3241        Duplicate/O rescaledTime_dec rescaledTime
3242       
3243        t_longest = t_longest_dec       
3244       
3245        SetDataFolder root:
3246       
3247        return(0)
3248
3249End
3250
3251
3252
3253// unused, old testing procedure
3254Function LoadDecimateButtonProc(ctrlName) : ButtonControl
3255        String ctrlName
3256
3257        LoadEventLog_Button("")
3258       
3259        // now decimate
3260        SetDataFolder root:Packages:NIST:Event:
3261
3262        Wave timePt=timePt
3263        Wave xLoc=xLoc
3264        Wave yLoc=yLoc
3265        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3266
3267        NVAR decimation = root:Packages:NIST:Event:gDecimation
3268
3269
3270        Duplicate/O timePt, timePt_dTmp
3271        Duplicate/O xLoc, xLoc_dTmp
3272        Duplicate/O yLoc, yLoc_dTmp
3273        Resample/DOWN=(decimation)/N=1 timePt_dTmp
3274        Resample/DOWN=(decimation)/N=1 xLoc_dTmp
3275        Resample/DOWN=(decimation)/N=1 yLoc_dTmp
3276
3277
3278        Duplicate/O timePt_dTmp rescaledTime_dTmp
3279        rescaledTime_dTmp = 1e-7*(timePt_dTmp - timePt_dTmp[0])         //convert to seconds and start from zero
3280        t_longest_dec = waveMax(rescaledTime_dTmp)              //should be the last point
3281
3282        SetDataFolder root:
3283
3284       
3285End
3286
3287
3288
3289
3290
3291
3292
3293//
3294// loads a list of files, decimating each chunk as it is read in
3295//
3296Function Stream_LoadDecim(ctrlName)
3297        String ctrlName
3298       
3299        Variable fileref
3300
3301        SVAR filename = root:Packages:NIST:Event:gEvent_logfile
3302        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
3303
3304        SVAR listStr = root:Packages:NIST:Event:gSplitFileList
3305        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3306        NVAR decimation = root:Packages:NIST:Event:gDecimation
3307
3308        String pathStr
3309        PathInfo catPathName
3310        pathStr = S_Path
3311
3312// if "stream" mode is not checked - abort
3313        NVAR gEventModeRadioVal= root:Packages:NIST:Event:gEvent_mode
3314        if(gEventModeRadioVal != MODE_STREAM)
3315                Abort "The mode must be 'Stream' to use this function"
3316                return(0)
3317        endif
3318
3319// if the list has been edited, turn it into a list
3320        WAVE/T/Z tw = root:Packages:NIST:Event:SplitFileWave
3321        if(WaveExists(tw))
3322                listStr = TextWave2SemiList(tw)
3323        else
3324                ShowSplitFileTable()
3325                DoAlert 0,"Enter the file names in the table, then click 'Load From List' again."
3326                return(0)
3327        endif
3328       
3329
3330        //loop through everything in the list
3331        Variable num,ii
3332        num = ItemsInList(listStr)
3333       
3334        for(ii=0;ii<num;ii+=1)
3335
3336// (1) load the file, prepending the path               
3337                filename = pathStr + StringFromList(ii, listStr  ,";")
3338               
3339
3340#if (exists("EventLoadWave")==4)
3341                LoadEvents_XOP()
3342#else
3343                LoadEvents()
3344#endif 
3345
3346                SetDataFolder root:Packages:NIST:Event:                 //LoadEvents sets back to root:
3347
3348                Wave timePt=timePt
3349                Wave xLoc=xLoc
3350                Wave yLoc=yLoc
3351                CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
3352
3353                Duplicate/O timePt rescaledTime
3354                rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
3355                t_longest = waveMax(rescaledTime)               //should be the last point
3356               
3357// (2) do the decimation, just on timePt. create rescaledTime from the decimated timePt
3358               
3359                Duplicate/O timePt, timePt_dTmp
3360                Duplicate/O xLoc, xLoc_dTmp
3361                Duplicate/O yLoc, yLoc_dTmp
3362                Resample/DOWN=(decimation)/N=1 timePt_dTmp
3363                Resample/DOWN=(decimation)/N=1 xLoc_dTmp
3364                Resample/DOWN=(decimation)/N=1 yLoc_dTmp
3365       
3366       
3367                Duplicate/O timePt_dTmp rescaledTime_dTmp
3368                rescaledTime_dTmp = 1e-7*(timePt_dTmp - timePt_dTmp[0])         //convert to seconds and start from zero
3369                t_longest_dec = waveMax(rescaledTime_dTmp)              //should be the last point
3370               
3371
3372// (3) concatenate
3373                fConcatenateButton(ii+1)                //passes 1 for the first time, >1 each other time
3374       
3375        endfor
3376
3377////            Now that everything is decimated and concatenated, create the rescaled time wave
3378//      SetDataFolder root:Packages:NIST:Event:                 //LoadEvents sets back to root:
3379//      Wave timePt_dec = timePt_dec
3380//      Duplicate/O timePt_dec rescaledTime_dec
3381//      rescaledTime_dec = 1e-7*(timePt_dec - timePt_dec[0])            //convert to seconds and start from zero
3382//      t_longest_dec = waveMax(rescaledTime_dec)               //should be the last point
3383       
3384        DisplayConcatenatedButtonProc("")
3385       
3386        SetDataFolder root:
3387
3388        return(0)
3389End
3390
3391Function ShowList_ToLoad(ctrlName)
3392        String ctrlName
3393       
3394        ShowSplitFileTable()
3395       
3396        return(0)
3397End
3398
3399
3400//
3401// loads a list of files that have been adjusted and saved
3402// -- does not decimate
3403//
3404Function Stream_LoadAdjustedList(ctrlName)
3405        String ctrlName
3406       
3407        Variable fileref
3408
3409        SVAR filename = root:Packages:NIST:Event:gEvent_logfile
3410        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
3411
3412        SVAR listStr = root:Packages:NIST:Event:gSplitFileList
3413        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3414//      NVAR decimation = root:Packages:NIST:Event:gDecimation
3415
3416        String pathStr
3417        PathInfo catPathName
3418        pathStr = S_Path
3419
3420// if "stream" mode is not checked - abort
3421        NVAR gEventModeRadioVal= root:Packages:NIST:Event:gEvent_mode
3422        if(gEventModeRadioVal != MODE_STREAM)
3423                Abort "The mode must be 'Stream' to use this function"
3424                return(0)
3425        endif
3426
3427// if the list has been edited, turn it into a list
3428        WAVE/T/Z tw = root:Packages:NIST:Event:SplitFileWave
3429        if(WaveExists(tw))
3430                listStr = TextWave2SemiList(tw)
3431        else
3432                ShowSplitFileTable()
3433                DoAlert 0,"Enter the file names in the table, then click 'Load From List' again."
3434                return(0)
3435        endif
3436       
3437
3438        //loop through everything in the list
3439        Variable num,ii
3440        num = ItemsInList(listStr)
3441       
3442        for(ii=0;ii<num;ii+=1)
3443
3444// (1) load the file, prepending the path               
3445                filename = pathStr + StringFromList(ii, listStr  ,";")
3446               
3447                SetDataFolder root:Packages:NIST:Event:
3448                LoadWave/T/O fileName
3449
3450                SetDataFolder root:Packages:NIST:Event:                 //LoadEvents sets back to root: ??
3451
3452// this is what is loaded -- _dec extension is what is concatenated, and will be copied back later
3453                Wave timePt=timePt
3454                Wave xLoc=xLoc
3455                Wave yLoc=yLoc
3456                Wave rescaledTime=rescaledTime
3457
3458//              CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
3459
3460//              Duplicate/O timePt rescaledTime
3461//              rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
3462//              t_longest = waveMax(rescaledTime)               //should be the last point
3463               
3464// (2) No decimation
3465               
3466                Duplicate/O timePt, timePt_dTmp
3467                Duplicate/O xLoc, xLoc_dTmp
3468                Duplicate/O yLoc, yLoc_dTmp
3469                Duplicate/O rescaledTime, rescaledTime_dTmp
3470
3471
3472// (3) concatenate
3473                fConcatenateButton(ii+1)                //passes 1 for the first time, >1 each other time
3474       
3475        endfor
3476       
3477        DisplayConcatenatedButtonProc("")               // this resets the longest time, too
3478               
3479        SetDataFolder root:
3480
3481        return(0)
3482End
3483
3484/////////////////////////////////////
3485
3486// dd-mon-yyyy hh:mm:ss -> Event file name
3487// the VAX uses 24 hr time for hh
3488//
3489// scans as string elements since I'm reconstructing a string name
3490Function/S DateAndTime2HSTName(dateandtime)
3491        string dateAndTime
3492       
3493        String day,yr,hh,mm,ss,time_secs
3494        Variable mon
3495        string str,monStr,fileStr
3496       
3497        str=dateandtime
3498        sscanf str,"%2s-%3s-%4s %2s:%2s:%2s",day,monStr,yr,hh,mm,ss
3499        mon = monStr2num(monStr)
3500
3501        fileStr = "Event"+yr+num2str(mon)+day+hh+mm+ss+".hst"
3502        Print fileStr
3503
3504        return(fileStr)
3505end
3506
3507// dd-mon-yyyy hh:mm:ss -> Event file name
3508// the VAX uses 24 hr time for hh
3509//
3510// scans as string elements since I'm reconstructing a string name
3511Function DateAndTime2HSTNumber(dateandtime)
3512        string dateAndTime
3513       
3514        String day,yr,hh,mm,ss,time_secs
3515        Variable mon,num
3516        string str,monStr,fileStr
3517       
3518        str=dateandtime
3519        sscanf str,"%2s-%3s-%4s %2s:%2s:%2s",day,monStr,yr,hh,mm,ss
3520        mon = monStr2num(monStr)
3521
3522        fileStr = yr+num2str(mon)+day+hh+mm+ss
3523        num = str2num(fileStr)
3524
3525        return(num)
3526end
3527
3528Function HSTName2Num(str)
3529        String str
3530       
3531        Variable num
3532        sscanf str,"Event%d.hst",num
3533        return(num)
3534end
3535/////////////////////////////
Note: See TracBrowser for help on using the repository browser.