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

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

Changes to:
Polarization - to correct naming errors when saving polarization panel states. Names were too long.

Event Mode - improved the re-loading of split oscillatory data sets. Also allows easier editing of the list of split files to re-load for decimation.

FFT/real space - Modified gizmo to automatically color the different SLDs present. Limitied to 5 different SLDs due to a limitation of the voxelgram. If more than 5 SLDs are present (solvent does not count), then the extra ones are not displayed. Also modified KR-3Cyl procedures to be able to save/import a table of coordinates.

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