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

Last change on this file since 989 was 989, checked in by srkline, 7 years ago

more additions to HDF reader to work with the Nexus definition

Additions to SANS event mode processing to allow proper processing of large data streams. Data was inproperly saved after decimation without correcting for the decimation. Instead, use decimation for screening, and bin the full data (splits) on the fly.

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