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

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

Updates to the Event Mode handling to better deal with big files - splitting, modifying, and re-loading.

Updated the help file for Event Mode to reflect the new panel and button options.

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