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

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

Updated help files with information about FFT to USANS

Updated FFT routines and menu to include FFT to USANS routines and help

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