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

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

more additions to the R/W functions to access VSANS data files

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