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

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

Modified QKK files to remove the calls to the ProgressWindow? XOP, which crashed my machine (OSX 10.8), Igor 6.3

Updated event processing to add new editing features to remove outliers

Updated help file for Event Mode.

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