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

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

few fixes to event mode for SANS

major changes to VSANS basic R/W routines to keep up-to-date with the latest data file definition. Still needs to be tested for correct paths, entries, etc.

File size: 102.5 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma IgorVersion=6.22
3
4// vers 7.13e
5
6// TODO:
7//
8// -- search for TODO for unresolved issues not on this list
9//
10// -- add comments to the code as needed
11//
12// -- write the help file, and link the help buttons to the help docs
13//
14// -- examples?
15//
16//
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/S 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                        PathInfo/S catPathName          //should set the next dialog to the proper path...
2466                        LoadWave/T/O/P=catPathName
2467                        filePathStr = S_fileName
2468                        if(strlen(S_fileName) == 0)
2469                                //user cancelled
2470                                DoAlert 0,"No file selected, nothing done."
2471                                return(0)
2472                        endif
2473                       
2474                        NVAR mode = root:Packages:NIST:Event:gEvent_Mode                                // ==0 for "stream", ==1 for Oscillatory
2475                        // clear out the old sort index, if present, since new data is being loaded
2476                        KillWaves/Z OscSortIndex
2477                        Wave timePt=timePt
2478                        Wave rescaledTime=rescaledTime
2479                       
2480                        t_longest = waveMax(rescaledTime)               //should be the last point
2481                       
2482       
2483                        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
2484                        sprintf tmpStr, "%s: a user-modified event file\r",fileStr
2485                        dispStr = tmpStr
2486       
2487                        SetDataFolder root:
2488                        break
2489                case -1: // control being killed
2490                        break
2491        endswitch
2492
2493        return 0
2494End
2495
2496
2497Function EC_ShowAllButtonProc(ba) : ButtonControl
2498        STRUCT WMButtonAction &ba
2499
2500        switch( ba.eventCode )
2501                case 2: // mouse up
2502                        // click code here
2503                        SetAxis/A
2504                        break
2505                case -1: // control being killed
2506                        break
2507        endswitch
2508
2509        return 0
2510End
2511
2512Function EC_HelpButtonProc(ba) : ButtonControl
2513        STRUCT WMButtonAction &ba
2514
2515        switch( ba.eventCode )
2516                case 2: // mouse up
2517                        // click code here
2518                        DisplayHelpTopic/Z "Event Mode Data[Correcting for things that go wrong]"
2519                        break
2520                case -1: // control being killed
2521                        break
2522        endswitch
2523
2524        return 0
2525End
2526
2527Function EC_DoneButtonProc(ba) : ButtonControl
2528        STRUCT WMButtonAction &ba
2529
2530        switch( ba.eventCode )
2531                case 2: // mouse up
2532                        // click code here
2533                        DoWindow/K EventCorrectionPanel
2534                        break
2535                case -1: // control being killed
2536                        break
2537        endswitch
2538
2539        return 0
2540End
2541
2542//upDown 5 or -5 looks for spikes +5 or -5 std deviations from mean
2543//
2544// will search from the leftmost cursor to the end. this allows skipping of oscillations
2545// that are not timing errors. It may introduce other issues, but we'll see what happens
2546//
2547Function PutCursorsAtStep(upDown)
2548        Variable upDown
2549       
2550        SetDataFolder root:Packages:NIST:Event:
2551
2552        Wave rescaledTime=rescaledTime
2553        Wave rescaledTime_DIF=rescaledTime_DIF
2554        Variable avg,pt,zoom
2555        Variable ptA,ptB,startPt
2556               
2557        zoom = 200              //points in each direction
2558       
2559        WaveStats/M=1/Q rescaledTime_DIF
2560        avg = V_avg
2561       
2562        ptA = pcsr(A)
2563        ptB = pcsr(B)
2564        startPt = min(ptA,ptB)
2565       
2566        FindLevel/P/Q/R=[startPt] rescaledTime_DIF avg*upDown
2567        if(V_flag==0)
2568                pt = V_levelX
2569                WaveStats/Q/R=[pt-zoom,pt+zoom] rescaledTime            // find the max/min y-values within the point range
2570        else
2571                Print "Level not found"
2572//              return(0)
2573        endif
2574       
2575        Variable loLeft,hiLeft, loBottom,hiBottom
2576        loLeft = V_min*0.98             //+/- 2%
2577        hiLeft = V_max*1.02
2578       
2579        SetAxis left loLeft,hiLeft
2580        SetAxis bottom pnt2x(rescaledTime,pt-zoom),pnt2x(rescaledTime,pt+zoom)
2581       
2582        Cursor/P A rescaledTime pt+2    //at the point
2583        Cursor/P B rescaledTime numpnts(rescaledTime)-1         //at the end
2584
2585        SetDataFolder root:
2586
2587        return(0)
2588End
2589
2590
2591// find the max (or min) of the rescaled time set
2592// and place both cursors there
2593Function fFindOutlier()
2594
2595        SetDataFolder root:Packages:NIST:Event:
2596
2597        Wave rescaledTime=rescaledTime
2598        Variable avg,pt,zoom,maxPt,minPt,maxVal,minVal
2599       
2600        zoom = 200              //points in each direction
2601       
2602        WaveStats/M=1/Q rescaledTime
2603        maxPt = V_maxLoc
2604        minPt = V_minLoc
2605        avg = V_avg
2606        maxVal = abs(V_max)
2607        minVal = abs(V_min)
2608
2609        pt = abs(maxVal - avg) > abs(minVal - avg) ? maxPt : minPt
2610       
2611//      Variable loLeft,hiLeft, loBottom,hiBottom
2612//      loLeft = V_min*0.98             //+/- 2%
2613//      hiLeft = V_max*1.02
2614       
2615//      SetAxis left loLeft,hiLeft
2616//      SetAxis bottom pnt2x(rescaledTime,pt-zoom),pnt2x(rescaledTime,pt+zoom)
2617       
2618        Cursor/P A rescaledTime pt              //at the point
2619        Cursor/P B rescaledTime pt              //at the same point
2620
2621        SetDataFolder root:
2622       
2623        return(0)
2624End
2625
2626Function EC_FindStepButton_down(ctrlName) : ButtonControl
2627        String ctrlName
2628       
2629//      Variable upDown = -5
2630        NVAR upDown = root:Packages:NIST:Event:gStepTolerance
2631       
2632        PutCursorsAtStep(-1*upDown)
2633
2634        return(0)
2635end
2636
2637
2638Function EC_FindStepButton_up(ctrlName) : ButtonControl
2639        String ctrlName
2640       
2641//      Variable upDown = 5
2642        NVAR upDown = root:Packages:NIST:Event:gStepTolerance
2643
2644        PutCursorsAtStep(upDown)
2645
2646        return(0)
2647end
2648
2649// if the Trim button section is uncommented, it's "Zap outlier"
2650//
2651Function EC_FindOutlierButton(ctrlName) : ButtonControl
2652        String ctrlName
2653       
2654        fFindOutlier()
2655//
2656//      STRUCT WMButtonAction ba
2657//      ba.eventCode = 2
2658//
2659//      EC_TrimPointsButtonProc(ba)
2660
2661        return(0)
2662end
2663
2664Function EC_DoDifferential(ctrlName) : ButtonControl
2665        String ctrlName
2666       
2667        DifferentiatedTime()
2668        DoWindow/F EventCorrectionPanel
2669       
2670        //if trace is not on graph, add it
2671        SetDataFolder root:Packages:NIST:Event:
2672
2673        String list = WaveList("*_DIF", ";", "WIN:EventCorrectionPanel")
2674        if(strlen(list) == 0)
2675                AppendToGraph/R rescaledTime_DIF
2676                ModifyGraph msize=1,rgb(rescaledTime_DIF)=(65535,0,0)
2677                ReorderTraces rescaledTime,{rescaledTime_DIF}           // put the differential behind the event data
2678        endif
2679        SetDataFolder root:
2680        return(0)
2681end
2682
2683//////////////   Custom Bins  /////////////////////
2684//
2685//
2686//
2687// make sure that the bins are defined and the waves exist before
2688// trying to draw the panel
2689//
2690Proc Show_CustomBinPanel()
2691        DoWindow/F CustomBinPanel
2692        if(V_flag ==0)
2693                Init_CustomBins()
2694                CustomBinPanel()
2695        EndIf
2696End
2697
2698
2699Function Init_CustomBins()
2700
2701        NVAR nSlice = root:Packages:NIST:Event:gEvent_nslices
2702        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
2703
2704        Variable/G root:Packages:NIST:Event:gEvent_ForceTmaxBin=1               //==1 to enforce t_longest in user-defined custom bins
2705
2706        SetDataFolder root:Packages:NIST:Event:
2707               
2708        Make/O/D/N=(nSlice) timeWidth
2709        Make/O/D/N=(nSlice+1) binEndTime,binCount
2710       
2711        timeWidth = t_longest/nslice
2712        binEndTime = p
2713        binCount = p+1 
2714       
2715        SetDataFolder root:
2716       
2717        return(0)
2718End
2719
2720////////////////       
2721//
2722// Allow custom definitions of the bin widths
2723//
2724// Define by the number of bins, and the time width of each bin
2725//
2726// This shares the number of slices and the maximum time with the main panel
2727//
2728Proc CustomBinPanel()
2729        PauseUpdate; Silent 1           // building window...
2730        NewPanel /W=(130,44,851,455)/K=2 /N=CustomBinPanel
2731        DoWindow/C CustomBinPanel
2732        ModifyPanel fixedSize=1//,noEdit =1
2733        SetDrawLayer UserBack
2734       
2735        Button button0,pos={654,42}, size={50,20},title="Done",fSize=12
2736        Button button0,proc=CB_Done_Proc
2737        Button button1,pos={663,14},size={40,20},proc=CB_HelpButtonProc,title="?"
2738        Button button2,pos={216,42},size={80,20},title="Update",proc=CB_UpdateWavesButton       
2739        SetVariable setvar1,pos={23,13},size={160,20},title="Number of slices",fSize=12
2740        SetVariable setvar1,proc=CB_NumSlicesSetVarProc,value=root:Packages:NIST:Event:gEvent_nslices
2741        SetVariable setvar2,pos={24,44},size={160,20},title="Max Time (s)",fSize=10
2742        SetVariable setvar2,value=root:Packages:NIST:Event:gEvent_t_longest     
2743
2744        CheckBox chkbox1,pos={216,14},title="Enforce Max Time?"
2745        CheckBox chkbox1,variable = root:Packages:NIST:Event:gEvent_ForceTmaxBin
2746        Button button3,pos={500,14},size={90,20},proc=CB_SaveBinsButtonProc,title="Save Bins"
2747        Button button4,pos={500,42},size={100,20},proc=CB_ImportBinsButtonProc,title="Import Bins"     
2748               
2749        SetDataFolder root:Packages:NIST:Event:
2750
2751        Display/W=(291,86,706,395)/HOST=CustomBinPanel/N=BarGraph binCount vs binEndTime
2752        ModifyGraph mode=5
2753        ModifyGraph marker=19
2754        ModifyGraph lSize=2
2755        ModifyGraph rgb=(0,0,0)
2756        ModifyGraph msize=2
2757        ModifyGraph hbFill=2
2758        ModifyGraph gaps=0
2759        ModifyGraph usePlusRGB=1
2760        ModifyGraph toMode=1
2761        ModifyGraph useBarStrokeRGB=1
2762        ModifyGraph standoff=0
2763        SetAxis left 0,*
2764        Label bottom "\\Z14Time (seconds)"
2765        Label left "\\Z14Number of Events"
2766        SetActiveSubwindow ##
2767       
2768        // and the table
2769        Edit/W=(13,87,280,394)/HOST=CustomBinPanel/N=T0
2770        AppendToTable/W=CustomBinPanel#T0 timeWidth,binEndTime
2771        ModifyTable width(Point)=40
2772        SetActiveSubwindow ##
2773       
2774        SetDataFolder root:
2775       
2776EndMacro
2777
2778// save the bins - use Igor Text format
2779//
2780Function CB_SaveBinsButtonProc(ba) : ButtonControl
2781        STRUCT WMButtonAction &ba
2782
2783        switch( ba.eventCode )
2784                case 2: // mouse up
2785                        // click code here
2786
2787                        SetDataFolder root:Packages:NIST:Event:
2788
2789                        Wave timeWidth = timeWidth
2790                        Wave binEndTime = binEndTime
2791                       
2792                        Save/T timeWidth,binEndTime                     //will ask for a name
2793
2794                        break
2795                case -1: // control being killed
2796                        break
2797        endswitch
2798
2799        SetDataFolder root:
2800       
2801        return 0
2802End
2803
2804// Import the bins - use Igor Text format
2805//
2806// -- be sure that the number of bins is reset
2807// -?- how about the t_longest? - this should be set by the load, not here
2808//
2809// -- loads in timeWidth and binEndTime
2810//
2811Function CB_ImportBinsButtonProc(ba) : ButtonControl
2812        STRUCT WMButtonAction &ba
2813
2814        switch( ba.eventCode )
2815                case 2: // mouse up
2816                        // click code here
2817                        NVAR nSlice = root:Packages:NIST:Event:gEvent_nslices
2818
2819                        SetDataFolder root:Packages:NIST:Event:
2820
2821                        // prompt for the load of data
2822                        LoadWave/T/O
2823                        if(strlen(S_fileName) == 0)
2824                                //user cancelled
2825                                DoAlert 0,"No file selected, nothing done."
2826                                return(0)
2827                        endif
2828
2829                        Wave timeWidth = timeWidth
2830                        nSlice = numpnts(timeWidth)
2831                       
2832                        break
2833                case -1: // control being killed
2834                        break
2835        endswitch
2836
2837        SetDataFolder root:
2838       
2839        return 0
2840End
2841
2842
2843
2844//
2845// can either use the widths as stated -- then the end time may not
2846// match the actual end time of the data set
2847//
2848// -- or --
2849//
2850// enforce the end time of the data set to be the end time of the bins,
2851// then the last bin width must be reset to force the constraint
2852//
2853//
2854Function CB_UpdateWavesButton(ba) : ButtonControl
2855        STRUCT WMButtonAction &ba
2856
2857        switch( ba.eventCode )
2858                case 2: // mouse up
2859                        // click code here
2860                        NVAR nSlice = root:Packages:NIST:Event:gEvent_nslices
2861                        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
2862                        NVAR enforceTmax = root:Packages:NIST:Event:gEvent_ForceTmaxBin
2863                       
2864                        // update the waves, and recalculate everything for the display
2865                        SetDataFolder root:Packages:NIST:Event:
2866
2867                        Wave timeWidth = timeWidth
2868                        Wave binEndTime = binEndTime
2869                        Wave binCount = binCount
2870                       
2871                        // use the widths as entered
2872                        binEndTime[0] = 0
2873                        binEndTime[1,] = binEndTime[p-1] + timeWidth[p-1]
2874                       
2875                        // enforce the longest time as the end bin time
2876                        // note that this changes the last time width
2877                        if(enforceTmax)
2878                                binEndTime[nSlice] = t_longest
2879                                timeWidth[nSlice-1] = t_longest - binEndTime[nSlice-1]
2880                        endif
2881                       
2882                        binCount = p+1
2883                        binCount[nSlice] = 0            // last point is zero, just for display
2884//                      binCount *= sign(timeWidth)             //to alert to negative time bins
2885                       
2886                        // make the timeWidth bold and red if the widths are negative
2887                        WaveStats/Q timeWidth
2888                        if(V_min < 0)
2889                                ModifyTable/W=CustomBinPanel#T0 style(timeWidth)=1,rgb(timeWidth)=(65535,0,0)                   
2890                        else
2891                                ModifyTable/W=CustomBinPanel#T0 style(timeWidth)=0,rgb(timeWidth)=(0,0,0)                       
2892                        endif
2893                       
2894                        break
2895                case -1: // control being killed
2896                        break
2897        endswitch
2898
2899        SetDataFolder root:
2900       
2901        return 0
2902End
2903
2904Function CB_HelpButtonProc(ba) : ButtonControl
2905        STRUCT WMButtonAction &ba
2906
2907        switch( ba.eventCode )
2908                case 2: // mouse up
2909                        // click code here
2910                        DisplayHelpTopic/Z "Event Mode Data[Setting up Custom Bin Widths]"
2911                        break
2912                case -1: // control being killed
2913                        break
2914        endswitch
2915
2916        return 0
2917End
2918
2919Function CB_Done_Proc(ba) : ButtonControl
2920        STRUCT WMButtonAction &ba
2921       
2922        String win = ba.win
2923        switch (ba.eventCode)
2924                case 2:
2925                        DoWindow/K CustomBinPanel
2926                        break
2927        endswitch
2928        return(0)
2929End
2930
2931
2932Function CB_NumSlicesSetVarProc(sva) : SetVariableControl
2933        STRUCT WMSetVariableAction &sva
2934
2935        switch( sva.eventCode )
2936                case 1: // mouse up
2937                case 2: // Enter key
2938                case 3: // Live update
2939                        Variable dval = sva.dval
2940                        String sval = sva.sval
2941                        SetDataFolder root:Packages:NIST:Event:
2942
2943                        Wave timeWidth = timeWidth
2944                        Wave binEndTime = binEndTime
2945                       
2946                        Redimension/N=(dval) timeWidth
2947                        Redimension/N=(dval+1) binEndTime,binCount
2948                       
2949                        SetDataFolder root:
2950                       
2951                        break
2952                case -1: // control being killed
2953                        break
2954        endswitch
2955
2956        return 0
2957End
2958
2959
2960///////////////////
2961//
2962// utility to split a large file
2963// 100 MB is the recommended size
2964// events can be clipped here, so be sure to trim the ends of the
2965// resulting files as needed.
2966//
2967// - works like the unix 'split' command
2968//
2969//
2970
2971Proc SplitBigFile(splitSize, baseStr)
2972        Variable splitSize = 100
2973        String baseStr="split"
2974        Prompt splitSize,"Target file size, in MB (< 150 MB!!)"
2975        Prompt baseStr,"File prefix, number will be appended"
2976       
2977        if(splitSize > root:Packages:NIST:Event:gEventFileTooLarge)
2978                Abort "File split must be less than 150 MB. Please try again"
2979        endif
2980       
2981        fSplitBigFile(splitSize, baseStr)
2982       
2983        ShowSplitFileTable()
2984End
2985
2986Function/S fSplitBigFile(splitSize, baseStr)
2987        Variable splitSize
2988        String baseStr         
2989
2990
2991        String fileName=""              // File name, partial path, full path or "" for dialog.
2992        Variable refNum
2993        String str
2994        SVAR listStr = root:Packages:NIST:Event:gSplitFileList
2995       
2996        listStr=""              //initialize output list
2997
2998        Variable readSize=1e6           //1 MB
2999        Make/O/B/U/N=(readSize) aBlob                   //1MB worth
3000        Variable numSplit
3001        Variable num,ii,jj,outRef,frac
3002        String thePath, outStr
3003       
3004        Printf "SplitSize = %u MB\r",splitSize
3005        splitSize = trunc(splitSize) * 1e6              // now in bytes
3006       
3007       
3008        // Open file for read.
3009        Open/R/Z=2/F="????"/P=catPathName refNum as fileName
3010        thePath = ParseFilePath(1, S_fileName, ":", 1, 0)
3011        Print "thePath = ",thePath
3012       
3013        // Store results from Open in a safe place.
3014        Variable err = V_flag
3015        String fullPath = S_fileName
3016
3017        if (err == -1)
3018                Print "cancelled by user."
3019                return ("")
3020        endif
3021
3022        FStatus refNum
3023       
3024        Printf "total # bytes = %u\r",V_logEOF
3025
3026        numSplit=0
3027        if(V_logEOF > splitSize)
3028                numSplit = trunc(V_logEOF/splitSize)
3029        endif
3030
3031        frac = V_logEOF - numSplit*splitSize
3032        Print "numSplit = ",numSplit
3033        Printf "frac = %u\r",frac
3034       
3035        num=0
3036        if(frac > readSize)
3037                num = trunc(frac/readSize)
3038        endif
3039
3040       
3041        frac = frac - num*readSize
3042
3043        Print "num = ",num
3044        Printf "frac = %u\r",frac
3045       
3046//      baseStr = "split"
3047       
3048        for(ii=0;ii<numSplit;ii+=1)
3049                outStr = (thePath+baseStr+num2str(ii))
3050//              Print "outStr = ",outStr
3051                Open outRef as outStr
3052
3053                for(jj=0;jj<(splitSize/readSize);jj+=1)
3054                        FBinRead refNum,aBlob
3055                        FBinWrite outRef,aBlob
3056                endfor
3057
3058                Close outRef
3059//              listStr += outStr+";"
3060                listStr += baseStr+num2str(ii)+";"
3061        endfor
3062
3063        Make/O/B/U/N=(frac) leftover
3064        // ii was already incremented past the loop
3065        outStr = (thePath+baseStr+num2str(ii))
3066        Open outRef as outStr
3067        for(jj=0;jj<num;jj+=1)
3068                FBinRead refNum,aBlob
3069                FBinWrite outRef,aBlob
3070        endfor
3071        FBinRead refNum,leftover
3072        FBinWrite outRef,leftover
3073
3074        Close outRef
3075//      listStr += outStr+";"
3076        listStr += baseStr+num2str(ii)+";"
3077
3078        FSetPos refNum,V_logEOF
3079        Close refNum
3080       
3081        KillWaves/Z aBlob,leftover
3082        return(listStr)
3083End
3084
3085// allows the list of loaded files to be edited
3086Function ShowSplitFileTable()
3087
3088        SVAR str = root:Packages:NIST:Event:gSplitFileList
3089       
3090        WAVE/T/Z tw = root:Packages:NIST:Event:SplitFileWave
3091        if(waveExists(tw) != 1)
3092                Make/O/T/N=1 root:Packages:NIST:Event:SplitFileWave
3093                WAVE/T/Z tw = root:Packages:NIST:Event:SplitFileWave
3094        endif
3095
3096        List2TextWave(str,tw)
3097        Edit tw
3098
3099        return(0)
3100End
3101
3102
3103//// save the sliced data, and accumulate slices
3104//  *** this works with sliced data -- that is data that has been PROCESSED
3105//
3106// need some way of ensuring that the slices match up since I'm blindly adding them together.
3107//
3108// mode = 0             wipe out the old accumulated, copy slicedData to accumulatedData
3109// mode = 1             add current slicedData to accumulatedData
3110// mode = 2             copy accumulatedData to slicedData in preparation of export or display
3111// mode = 3             unused...
3112//
3113//      "Split Large File",SplitBigFile()
3114//      "Accumulate First Slice",AccumulateSlices(0)
3115//      "Add Current Slice",AccumulateSlices(1)
3116//      "Display Accumulated Slices",AccumulateSlices(2)       
3117//
3118Function AccumulateSlicesButton(ctrlName) : ButtonControl
3119        String ctrlName
3120       
3121        Variable mode
3122        mode = str2num(ctrlName[strlen(ctrlName)-1])
3123//      Print "mode=",mode
3124        AccumulateSlices(mode)
3125       
3126        return(0)
3127End
3128
3129Function AccumulateSlices(mode)
3130        Variable mode
3131       
3132        SetDataFolder root:Packages:NIST:Event:
3133
3134        switch(mode)   
3135                case 0:
3136                        DoAlert 0,"The current data has been copied to the accumulated set. You are now ready to add more data."
3137                        KillWaves/Z accumulatedData
3138                        Duplicate/O slicedData accumulatedData         
3139                        break
3140                case 1:
3141                        DoAlert 0,"The current data has been added to the accumulated data. You can add more data."
3142                        Wave acc=accumulatedData
3143                        Wave cur=slicedData
3144                        acc += cur
3145                        break
3146                case 2:
3147                        DoAlert 0,"The accumulated data is now the display data and is ready for display or export."
3148                        Duplicate/O accumulatedData slicedData
3149                        // do something to "touch" the display to force it to update
3150                        NVAR gLog = root:Packages:NIST:Event:gEvent_logint
3151                        LogIntEvent_Proc("",gLog)
3152                        break
3153                default:                       
3154                               
3155        endswitch
3156
3157        SetDataFolder root:
3158        return(0)
3159end
3160
3161
3162////////////////////////////////////////////
3163//
3164// Panel and procedures for decimation
3165//
3166////////////////////////////////////////////
3167
3168//Function E_ShowDecimateButton(ctrlName) : ButtonControl
3169//      String ctrlName
3170//
3171//      DoWindow/F DecimatePanel
3172//      if(V_flag ==0)
3173//              Execute "DecimatePanel()"
3174//      endif
3175//End
3176//
3177//
3178//Proc DecimatePanel() //: Panel
3179//     
3180//      PauseUpdate; Silent 1           // building window...
3181//      NewPanel /W=(1602,44,1961,380)/K=1
3182////    ShowTools/A
3183//      Button button0,pos={29,15},size={100,20},proc=SplitFileButtonProc,title="Split Big File"
3184//      SetVariable setvar0,pos={182,55},size={150,15},title="Decimation factor",fsize=10
3185//      SetVariable setvar0,limits={1,inf,1},value= root:Packages:NIST:Event:gDecimation
3186//      Button button1,pos={26,245},size={150,20},proc=LoadDecimateButtonProc,title="Load and Decimate"
3187//      Button button2,pos={25,277},size={150,20},proc=ConcatenateButtonProc,title="Concatenate"
3188//      Button button3,pos={25,305},size={150,20},proc=DisplayConcatenatedButtonProc,title="Display Concatenated"
3189//      Button button4,pos={29,52},size={130,20},proc=Stream_LoadDecim,title="Load From List"
3190//     
3191//      GroupBox group0 title="Manual Controls",size={185,112},pos={14,220}
3192//EndMacro
3193
3194
3195Function SplitFileButtonProc(ctrlName) : ButtonControl
3196        String ctrlName
3197
3198        Execute "SplitBigFile()"
3199End
3200
3201
3202// show all of the data
3203//
3204Proc ShowDecimatedGraph()
3205
3206        DoWindow/F DecimatedGraph
3207        if(V_flag == 0)
3208                PauseUpdate; Silent 1           // building window...
3209                String fldrSav0= GetDataFolder(1)
3210                SetDataFolder root:Packages:NIST:Event:
3211                Display /W=(25,44,486,356)/K=1/N=DecimatedGraph rescaledTime_dec
3212                SetDataFolder fldrSav0
3213                ModifyGraph mode=4
3214                ModifyGraph marker=19
3215                ModifyGraph rgb(rescaledTime_dec)=(0,0,0)
3216                ModifyGraph msize=1
3217                ErrorBars rescaledTime_dec OFF
3218                Label left "\\Z14Time (seconds)"
3219                Label bottom "\\Z14Event number"
3220                ShowInfo
3221        endif
3222       
3223EndMacro
3224
3225// data has NOT been processed
3226//
3227// so work with x,y,t, and rescaled time
3228// variables -- t_longest
3229Function ConcatenateButtonProc(ctrlName) : ButtonControl
3230        String ctrlName
3231       
3232        DoAlert 1,"Is this the first file?"
3233        Variable first = V_flag
3234       
3235        fConcatenateButton(first)
3236       
3237        return(0)
3238End
3239
3240Function fConcatenateButton(first)
3241        Variable first
3242
3243
3244        SetDataFolder root:Packages:NIST:Event:
3245
3246        Wave timePt_dTmp=timePt_dTmp
3247        Wave xLoc_dTmp=xLoc_dTmp
3248        Wave yLoc_dTmp=yLoc_dTmp
3249        Wave rescaledTime_dTmp=rescaledTime_dTmp
3250       
3251        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3252        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
3253       
3254       
3255        if(first==1)            //1==yes, 2==no
3256                //then copy the files over, adjusting the time to start from zero
3257                // rescaledTime starts from zero (set by the loader)
3258
3259                timePt_dTmp -= timePt_dTmp[0]                   //subtract the first value
3260               
3261                Duplicate/O timePt_dTmp timePt_dec
3262                Duplicate/O xLoc_dTmp xLoc_dec
3263                Duplicate/O yLoc_dTmp yLoc_dec
3264                Duplicate/O rescaledTime_dTmp rescaledTime_dec
3265               
3266                t_longest_dec = t_longest
3267       
3268        else
3269                // concatenate the files + adjust the time
3270                Wave timePt_dec=timePt_dec
3271                Wave xLoc_dec=xLoc_dec
3272                Wave yLoc_dec=yLoc_dec
3273                Wave rescaledTime_dec=rescaledTime_dec
3274
3275                // adjust the times -- assuming they add
3276                // rescaledTime starts from zero (set by the loader)
3277                //
3278                //
3279                rescaledTime_dTmp += rescaledTime_dec[numpnts(rescaledTime_dec)-1]
3280                rescaledTime_dTmp += abs(rescaledTime_dec[numpnts(rescaledTime_dec)-1] - rescaledTime_dec[numpnts(rescaledTime_dec)-2])
3281               
3282                timePt_dTmp -= timePt_dTmp[0]                   //subtract the first value     
3283               
3284                timePt_dTmp += timePt_dec[numpnts(timePt_dec)-1]                // offset by the last point
3285                timePt_dTmp += abs(timePt_dec[numpnts(timePt_dec)-1] - timePt_dec[numpnts(timePt_dec)-2])               // plus delta so there's not a flat step
3286               
3287                Concatenate/NP/O {timePt_dec,timePt_dTmp}, tmp
3288                Duplicate/O tmp timePt_dec
3289               
3290                Concatenate/NP/O {xLoc_dec,xLoc_dTmp}, tmp
3291                Duplicate/O tmp xLoc_dec
3292               
3293                Concatenate/NP/O {yLoc_dec,yLoc_dTmp}, tmp
3294                Duplicate/O tmp yLoc_dec
3295               
3296                Concatenate/NP/O {rescaledTime_dec,rescaledTime_dTmp}, tmp
3297                Duplicate/O tmp rescaledTime_dec
3298               
3299
3300                KillWaves tmp
3301
3302                t_longest_dec = rescaledTime_dec[numpnts(rescaledTime_dec)-1]
3303
3304        endif
3305       
3306       
3307        SetDataFolder root:
3308       
3309        return(0)
3310
3311End
3312
3313Function DisplayConcatenatedButtonProc(ctrlName) : ButtonControl
3314        String ctrlName
3315
3316        //copy the files over to the display set for processing
3317        SetDataFolder root:Packages:NIST:Event:
3318
3319        Wave timePt_dec=timePt_dec
3320        Wave xLoc_dec=xLoc_dec
3321        Wave yLoc_dec=yLoc_dec
3322        Wave rescaledTime_dec=rescaledTime_dec
3323               
3324        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3325        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
3326       
3327        Duplicate/O timePt_dec timePt
3328        Duplicate/O xLoc_dec xLoc
3329        Duplicate/O yLoc_dec yLoc
3330        Duplicate/O rescaledTime_dec rescaledTime
3331       
3332        t_longest = t_longest_dec       
3333       
3334        SetDataFolder root:
3335       
3336        return(0)
3337
3338End
3339
3340
3341Macro DisplayForSlicing()
3342
3343        // plot the EventBarGraph?
3344                SetDataFolder root:Packages:NIST:Event:
3345                Display /W=(110,705,610,1132)/N=SliceGraph /K=1 binCount vs binEndTime
3346                ModifyGraph mode=5
3347                ModifyGraph marker=19
3348                ModifyGraph lSize=2
3349                ModifyGraph rgb=(0,0,0)
3350                ModifyGraph msize=2
3351                ModifyGraph hbFill=2
3352                ModifyGraph gaps=0
3353                ModifyGraph usePlusRGB=1
3354                ModifyGraph toMode=1
3355                ModifyGraph useBarStrokeRGB=1
3356                ModifyGraph standoff=0
3357
3358                SetDataFolder root:
3359
3360// append the differential
3361        AppendToGraph/R root:Packages:NIST:Event:rescaledTime_DIF vs root:Packages:NIST:Event:rescaledTime
3362        ModifyGraph rgb(rescaledTime_DIF)=(1,16019,65535)
3363
3364End
3365
3366
3367
3368// unused, old testing procedure
3369Function LoadDecimateButtonProc(ctrlName) : ButtonControl
3370        String ctrlName
3371
3372        LoadEventLog_Button("")
3373       
3374        // now decimate
3375        SetDataFolder root:Packages:NIST:Event:
3376
3377        Wave timePt=timePt
3378        Wave xLoc=xLoc
3379        Wave yLoc=yLoc
3380        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3381
3382        NVAR decimation = root:Packages:NIST:Event:gDecimation
3383
3384
3385        Duplicate/O timePt, timePt_dTmp
3386        Duplicate/O xLoc, xLoc_dTmp
3387        Duplicate/O yLoc, yLoc_dTmp
3388        Resample/DOWN=(decimation)/N=1 timePt_dTmp
3389        Resample/DOWN=(decimation)/N=1 xLoc_dTmp
3390        Resample/DOWN=(decimation)/N=1 yLoc_dTmp
3391
3392
3393        Duplicate/O timePt_dTmp rescaledTime_dTmp
3394        rescaledTime_dTmp = 1e-7*(timePt_dTmp - timePt_dTmp[0])         //convert to seconds and start from zero
3395        t_longest_dec = waveMax(rescaledTime_dTmp)              //should be the last point
3396
3397        SetDataFolder root:
3398
3399       
3400End
3401
3402
3403
3404
3405
3406
3407
3408//
3409// loads a list of files, decimating each chunk as it is read in
3410//
3411Function Stream_LoadDecim(ctrlName)
3412        String ctrlName
3413       
3414        Variable fileref
3415
3416        SVAR filename = root:Packages:NIST:Event:gEvent_logfile
3417        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
3418
3419        SVAR listStr = root:Packages:NIST:Event:gSplitFileList
3420        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3421        NVAR decimation = root:Packages:NIST:Event:gDecimation
3422
3423        String pathStr
3424        PathInfo catPathName
3425        pathStr = S_Path
3426
3427// if "stream" mode is not checked - abort
3428        NVAR gEventModeRadioVal= root:Packages:NIST:Event:gEvent_mode
3429        if(gEventModeRadioVal != MODE_STREAM)
3430                Abort "The mode must be 'Stream' to use this function"
3431                return(0)
3432        endif
3433
3434// if the list has been edited, turn it into a list
3435        WAVE/T/Z tw = root:Packages:NIST:Event:SplitFileWave
3436        if(WaveExists(tw))
3437                listStr = TextWave2SemiList(tw)
3438        else
3439                ShowSplitFileTable()
3440                DoAlert 0,"Enter the file names in the table, then click 'Load From List' again."
3441                return(0)
3442        endif
3443       
3444
3445        //loop through everything in the list
3446        Variable num,ii
3447        num = ItemsInList(listStr)
3448       
3449        for(ii=0;ii<num;ii+=1)
3450
3451// (1) load the file, prepending the path               
3452                filename = pathStr + StringFromList(ii, listStr  ,";")
3453               
3454
3455#if (exists("EventLoadWave")==4)
3456                LoadEvents_XOP()
3457#else
3458                LoadEvents()
3459#endif 
3460
3461                SetDataFolder root:Packages:NIST:Event:                 //LoadEvents sets back to root:
3462
3463                Wave timePt=timePt
3464                Wave xLoc=xLoc
3465                Wave yLoc=yLoc
3466                CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
3467
3468                Duplicate/O timePt rescaledTime
3469                rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
3470                t_longest = waveMax(rescaledTime)               //should be the last point
3471               
3472// (2) do the decimation, just on timePt. create rescaledTime from the decimated timePt
3473               
3474                Duplicate/O timePt, timePt_dTmp
3475                Duplicate/O xLoc, xLoc_dTmp
3476                Duplicate/O yLoc, yLoc_dTmp
3477                Resample/DOWN=(decimation)/N=1 timePt_dTmp
3478                Resample/DOWN=(decimation)/N=1 xLoc_dTmp
3479                Resample/DOWN=(decimation)/N=1 yLoc_dTmp
3480       
3481       
3482                Duplicate/O timePt_dTmp rescaledTime_dTmp
3483                rescaledTime_dTmp = 1e-7*(timePt_dTmp - timePt_dTmp[0])         //convert to seconds and start from zero
3484                t_longest_dec = waveMax(rescaledTime_dTmp)              //should be the last point
3485               
3486
3487// (3) concatenate the files + adjust the time
3488                fConcatenateButton(ii+1)                //passes 1 for the first time, >1 each other time
3489       
3490        endfor
3491
3492////            Now that everything is decimated and concatenated, create the rescaled time wave
3493//      SetDataFolder root:Packages:NIST:Event:                 //LoadEvents sets back to root:
3494//      Wave timePt_dec = timePt_dec
3495//      Duplicate/O timePt_dec rescaledTime_dec
3496//      rescaledTime_dec = 1e-7*(timePt_dec - timePt_dec[0])            //convert to seconds and start from zero
3497//      t_longest_dec = waveMax(rescaledTime_dec)               //should be the last point
3498       
3499        DisplayConcatenatedButtonProc("")
3500       
3501        SetDataFolder root:
3502
3503        return(0)
3504End
3505
3506Function ShowList_ToLoad(ctrlName)
3507        String ctrlName
3508       
3509        ShowSplitFileTable()
3510       
3511        return(0)
3512End
3513
3514
3515//
3516// loads a list of files that have been adjusted and saved
3517// -- does not decimate
3518//
3519Function Stream_LoadAdjustedList(ctrlName)
3520        String ctrlName
3521       
3522        Variable fileref
3523
3524        SVAR filename = root:Packages:NIST:Event:gEvent_logfile
3525        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
3526
3527        SVAR listStr = root:Packages:NIST:Event:gSplitFileList
3528        NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3529//      NVAR decimation = root:Packages:NIST:Event:gDecimation
3530
3531        String pathStr
3532        PathInfo catPathName
3533        pathStr = S_Path
3534
3535// if "stream" mode is not checked - abort
3536        NVAR gEventModeRadioVal= root:Packages:NIST:Event:gEvent_mode
3537        if(gEventModeRadioVal != MODE_STREAM)
3538                Abort "The mode must be 'Stream' to use this function"
3539                return(0)
3540        endif
3541
3542// if the list has been edited, turn it into a list
3543        WAVE/T/Z tw = root:Packages:NIST:Event:SplitFileWave
3544        if(WaveExists(tw))
3545                listStr = TextWave2SemiList(tw)
3546        else
3547                ShowSplitFileTable()
3548                DoAlert 0,"Enter the file names in the table, then click 'Load From List' again."
3549                return(0)
3550        endif
3551       
3552
3553        //loop through everything in the list
3554        Variable num,ii
3555        num = ItemsInList(listStr)
3556       
3557        for(ii=0;ii<num;ii+=1)
3558
3559// (1) load the file, prepending the path               
3560                filename = pathStr + StringFromList(ii, listStr  ,";")
3561               
3562                SetDataFolder root:Packages:NIST:Event:
3563                LoadWave/T/O fileName
3564
3565                SetDataFolder root:Packages:NIST:Event:                 //LoadEvents sets back to root: ??
3566
3567// this is what is loaded -- _dec extension is what is concatenated, and will be copied back later
3568                Wave timePt=timePt
3569                Wave xLoc=xLoc
3570                Wave yLoc=yLoc
3571                Wave rescaledTime=rescaledTime
3572
3573//              CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
3574
3575//              Duplicate/O timePt rescaledTime
3576//              rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
3577//              t_longest = waveMax(rescaledTime)               //should be the last point
3578               
3579// (2) No decimation
3580               
3581                Duplicate/O timePt, timePt_dTmp
3582                Duplicate/O xLoc, xLoc_dTmp
3583                Duplicate/O yLoc, yLoc_dTmp
3584                Duplicate/O rescaledTime, rescaledTime_dTmp
3585
3586
3587// (3) concatenate the files + adjust the time
3588                fConcatenateButton(ii+1)                //passes 1 for the first time, >1 each other time
3589       
3590        endfor
3591       
3592        DisplayConcatenatedButtonProc("")               // this resets the longest time, too
3593               
3594        SetDataFolder root:
3595
3596        return(0)
3597End
3598
3599//
3600// loads a list of files that have been adjusted and saved
3601// -- does not decimate
3602// -- bins as they are loaded
3603//
3604Function Stream_LoadAdjList_BinOnFly(ctrlName)
3605        String ctrlName
3606       
3607        Variable fileref
3608
3609        SVAR filename = root:Packages:NIST:Event:gEvent_logfile
3610        SVAR listStr = root:Packages:NIST:Event:gSplitFileList
3611
3612        String pathStr
3613        PathInfo catPathName
3614        pathStr = S_Path
3615
3616// if "stream" mode is not checked - abort
3617        NVAR gEventModeRadioVal= root:Packages:NIST:Event:gEvent_mode
3618        if(gEventModeRadioVal != MODE_STREAM)
3619                Abort "The mode must be 'Stream' to use this function"
3620                return(0)
3621        endif
3622
3623// if the list has been edited, turn it into a list
3624        WAVE/T/Z tw = root:Packages:NIST:Event:SplitFileWave
3625        if(WaveExists(tw))
3626                listStr = TextWave2SemiList(tw)
3627        else
3628                ShowSplitFileTable()
3629                DoAlert 0,"Enter the file names in the table, then click 'Load From List' again."
3630                return(0)
3631        endif
3632       
3633
3634        //loop through everything in the list
3635        Variable num,ii,jj
3636        num = ItemsInList(listStr)
3637
3638
3639////////////////
3640// declarations for the binning
3641// for the first pass, do all of this
3642        Make/O/D/N=(128,128) root:Packages:NIST:Event:binnedData
3643       
3644        Wave binnedData = root:Packages:NIST:Event:binnedData
3645        Wave xLoc = root:Packages:NIST:Event:xLoc
3646        Wave yLoc = root:Packages:NIST:Event:yLoc
3647
3648// now with the number of slices and max time, process the events
3649
3650        NVAR yesSortStream = root:Packages:NIST:Event:gSortStreamEvents         //do I sort the events?
3651        NVAR t_longest = root:Packages:NIST:Event:gEvent_t_longest
3652        NVAR nslices = root:Packages:NIST:Event:gEvent_nslices
3653//      NVAR t_longest_dec = root:Packages:NIST:Event:gEvent_t_longest_decimated
3654        NVAR t_segment_start = root:Packages:NIST:Event:gEvent_t_segment_start
3655        NVAR t_segment_end = root:Packages:NIST:Event:gEvent_t_segment_end
3656               
3657        SetDataFolder root:Packages:NIST:Event          //don't count on the folder remaining here
3658       
3659        Make/D/O/N=(128,128,nslices) slicedData
3660       
3661        Wave slicedData = slicedData
3662        Wave rescaledTime = rescaledTime
3663        Make/O/D/N=(128,128) tmpData
3664        Make/O/D/N=(nslices+1) binEndTime,binCount//,binStartTime
3665        Make/O/D/N=(nslices) timeWidth
3666        Wave binEndTime = binEndTime
3667        Wave timeWidth = timeWidth
3668        Wave binCount = binCount
3669
3670        slicedData = 0
3671        binCount = 0
3672
3673        variable p1,p2,t1,t2
3674
3675        t_segment_start = 0
3676// start w/file 1??     
3677        for(jj=0;jj<num;jj+=1)
3678
3679// (1) load the file, prepending the path               
3680                filename = pathStr + StringFromList(jj, listStr  ,";")
3681               
3682                SetDataFolder root:Packages:NIST:Event:
3683                LoadWave/T/O fileName
3684
3685                SetDataFolder root:Packages:NIST:Event:                 //LoadEvents sets back to root: ??
3686
3687// this is what is loaded --
3688                Wave timePt=timePt
3689                Wave xLoc=xLoc
3690                Wave yLoc=yLoc
3691                Wave rescaledTime=rescaledTime
3692
3693                if(jj==0)
3694                        timePt -= timePt[0]                     //make sure the first point is zero
3695                        t_segment_start = 0
3696                        t_segment_end = rescaledTime[numpnts(rescaledTime)-1]
3697                else
3698                        t_segment_start = t_segment_end
3699                        t_segment_end += rescaledTime[numpnts(rescaledTime)-1]
3700                       
3701                        rescaledTime += t_segment_start         
3702                endif
3703               
3704                Printf "jj=%g\t\tt_segment_start=%g\tt_segment_end=%g\r",jj,t_segment_start,t_segment_end
3705               
3706// this is the binning--
3707
3708//              del = t_longest/nslices
3709       
3710        // TODO
3711        // the global exists for this switch, but it is not implemented - not sure whether
3712        // it's correct to implement this at all --
3713        //
3714                if(yesSortStream == 1)
3715                        SortTimeData()
3716                endif
3717               
3718        // index the events before binning
3719        // if there is a sort of these events, I need to re-index the events for the histogram
3720        //      SetDataFolder root:Packages:NIST:Event
3721                IndexForHistogram(xLoc,yLoc,binnedData)
3722        //      SetDataFolder root:
3723                Wave index = root:Packages:NIST:Event:SavedIndex                //the index for the histogram
3724               
3725                for(ii=0;ii<nslices;ii+=1)
3726                        if(ii==0)
3727        //                      t1 = ii*del
3728        //                      t2 = (ii+1)*del
3729                                p1 = BinarySearch(rescaledTime,0)
3730                                p2 = BinarySearch(rescaledTime,binEndTime[ii+1])
3731                        else
3732        //                      t2 = (ii+1)*del
3733                                p1 = p2+1               //one more than the old one
3734                                p2 = BinarySearch(rescaledTime,binEndTime[ii+1])               
3735                        endif
3736       
3737                        if(p1 == -1)
3738                                Printf "p1 = -1 Binary search off the end %15.10g <?? %15.10g\r", 0, rescaledTime[0]
3739                                p1 = 0          //set to the first point if it's off the end
3740                        Endif
3741                        if(p2 == -2)
3742                                Printf "p2 = -2 Binary search off the end %15.10g >?? %15.10g\r", binEndTime[ii+1], rescaledTime[numpnts(rescaledTime)-1]
3743                                p2 = numpnts(rescaledTime)-1            //set to the last point if it's off the end
3744                        Endif
3745        //              Print p1,p2
3746       
3747                        tmpData=0
3748                        JointHistogramWithRange(xLoc,yLoc,tmpData,index,p1,p2)
3749        //              slicedData[][][ii] = tmpData[p][q]
3750                        slicedData[][][ii] += tmpData[p][q]
3751                       
3752//                      Duplicate/O tmpData,$("tmpData_"+num2str(ii)+"_"+num2str(jj))
3753                       
3754        //              binEndTime[ii+1] = t2
3755        //              binCount[ii] = sum(tmpData,-inf,inf)
3756                        binCount[ii] += sum(tmpData,-inf,inf)
3757                endfor
3758       
3759        endfor  //end loop over the file list
3760
3761// after all of the files have been loaded
3762        t_longest = t_segment_end               //this is the total time
3763
3764        Duplicate/O slicedData,root:Packages:NIST:Event:dispsliceData,root:Packages:NIST:Event:logSlicedData
3765        Wave logSlicedData = root:Packages:NIST:Event:logSlicedData
3766        logslicedData = log(slicedData)
3767       
3768               
3769        SetDataFolder root:
3770
3771        return(0)
3772End
3773
3774
3775/////////////////////////////////////
3776
3777// dd-mon-yyyy hh:mm:ss -> Event file name
3778// the VAX uses 24 hr time for hh
3779//
3780// scans as string elements since I'm reconstructing a string name
3781Function/S DateAndTime2HSTName(dateandtime)
3782        string dateAndTime
3783       
3784        String day,yr,hh,mm,ss,time_secs
3785        Variable mon
3786        string str,monStr,fileStr
3787       
3788        str=dateandtime
3789        sscanf str,"%2s-%3s-%4s %2s:%2s:%2s",day,monStr,yr,hh,mm,ss
3790        mon = monStr2num(monStr)
3791
3792        fileStr = "Event"+yr+num2str(mon)+day+hh+mm+ss+".hst"
3793        Print fileStr
3794
3795        return(fileStr)
3796end
3797
3798// dd-mon-yyyy hh:mm:ss -> Event file name
3799// the VAX uses 24 hr time for hh
3800//
3801// scans as string elements since I'm reconstructing a string name
3802Function DateAndTime2HSTNumber(dateandtime)
3803        string dateAndTime
3804       
3805        String day,yr,hh,mm,ss,time_secs
3806        Variable mon,num
3807        string str,monStr,fileStr
3808       
3809        str=dateandtime
3810        sscanf str,"%2s-%3s-%4s %2s:%2s:%2s",day,monStr,yr,hh,mm,ss
3811        mon = monStr2num(monStr)
3812
3813        fileStr = yr+num2str(mon)+day+hh+mm+ss
3814        num = str2num(fileStr)
3815
3816        return(num)
3817end
3818
3819Function HSTName2Num(str)
3820        String str
3821       
3822        Variable num
3823        sscanf str,"Event%d.hst",num
3824        return(num)
3825end
3826/////////////////////////////
Note: See TracBrowser for help on using the repository browser.