source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/VSANS/V_EventModeProcessing.ipf @ 1045

Last change on this file since 1045 was 1045, checked in by srkline, 6 years ago

add a truncated version of the SANS event mode panel. The loader has been altered to load my best guess of the VSANS data file. The histogramming works, and this will be needed initially at VSANS for TOF calibration.

The binning to the 4 detector panels will be much different than for SANS, decimation, editing, etc. are hopefully not necessary for VSANS, and I do not have an XOP. So there is a lot to change here to get ready for VSANS, but it compiles.

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