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

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

Changed the TISANE button on the main panel to be "Event Data"

Added commands to the SANS menu for event mode data, inlcluding opening the panels and splitting large files.

fixed a bug in the reloading of previously adjusted data where oscillatory data would be rescaled to the first event time. Now there is no rescaling of the time.

File size: 67.7 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
98//Menu "Macros"
99//      "Split Large File",SplitBigFile()
100//      "Accumulate First Slice",AccumulateSlices(0)
101//      "Add Current Slice",AccumulateSlices(1)
102//      "Display Accumulated Slices",AccumulateSlices(2)       
103//End
104
105
106
107Proc Show_Event_Panel()
108        DoWindow/F EventModePanel
109        if(V_flag ==0)
110                Init_Event()
111                EventModePanel()
112        EndIf
113End
114
115
116Function Init_Event()
117        String/G        root:Packages:NIST:gEvent_logfile
118        String/G        root:Packages:NIST:gEventDisplayString="Details of the file load"
119       
120        Variable/G      root:Packages:NIST:AIMTYPE_XY=0 // XY Event
121        Variable/G      root:Packages:NIST:AIMTYPE_XYM=2 // XY Minor event
122        Variable/G      root:Packages:NIST:AIMTYPE_MIR=1 // Minor rollover event
123        Variable/G      root:Packages:NIST:AIMTYPE_MAR=3 // Major rollover event
124
125        Variable/G root:Packages:NIST:gEvent_time_msw = 0
126        Variable/G root:Packages:NIST:gEvent_time_lsw = 0
127        Variable/G root:Packages:NIST:gEvent_t_longest = 0
128
129        Variable/G root:Packages:NIST:gEvent_tsdisp //Displayed slice
130        Variable/G root:Packages:NIST:gEvent_nslices = 10  //Number of time slices
131       
132        Variable/G root:Packages:NIST:gEvent_logint = 1
133
134        Variable/G root:Packages:NIST:gEvent_Mode = 0                           // ==0 for "stream", ==1 for Oscillatory
135        Variable/G root:Packages:NIST:gRemoveBadEvents = 1              // ==1 to remove "bad" events, ==0 to read "as-is"
136        Variable/G root:Packages:NIST:gSortStreamEvents = 0             // ==1 to sort the event stream, a last resort for a stream of data
137       
138        Variable/G root:Packages:NIST:gEvent_ForceTmaxBin=1             //==1 to enforce t_longest in user-defined custom bins
139
140        NVAR nslices = root:Packages:NIST:gEvent_nslices
141       
142        SetDataFolder root:
143        NewDataFolder/O/S root:Packages:NIST:Event
144       
145        Make/D/O/N=(XBINS,YBINS,nslices) slicedData
146        Duplicate/O slicedData logslicedData
147        Duplicate/O slicedData dispsliceData
148       
149        SetDataFolder root:
150End
151
152Proc EventModePanel()
153        PauseUpdate; Silent 1           // building window...
154        NewPanel /W=(100,50,600,840)/N=EventModePanel/K=2
155        DoWindow/C EventModePanel
156        ModifyPanel fixedSize=1,noEdit =1
157        //ShowTools/A
158        SetDrawLayer UserBack
159        Button button0,pos={10,10}, size={150,20},title="Load Event Log File",fSize=12
160        Button button0,proc=LoadEventLog_Button
161       
162        TitleBox tb1,pos={20,650},size={460,80},fSize=12
163        TitleBox tb1,variable=root:Packages:NIST:gEventDisplayString
164       
165        CheckBox chkbox1,pos={170,8},title="Oscillatory Mode?"
166        CheckBox chkbox1,variable = root:Packages:NIST:gEvent_mode
167        CheckBox chkbox3,pos={170,27},title="Remove Bad Events?"
168        CheckBox chkbox3,variable = root:Packages:NIST:gRemoveBadEvents
169       
170        Button doneButton,pos={435,12}, size={50,20},title="Done",fSize=12
171        Button doneButton,proc=EventDone_Proc
172
173        Button button2,pos={20,122},size={140,20},proc=ShowEventDataButtonProc,title="Show Event Data"
174        Button button3,pos={20,147},size={140,20},proc=ShowBinDetailsButtonProc,title="Show Bin Details"
175        Button button4,pos={175,122},size={140,20},proc=UndoTimeSortButtonProc,title="Undo Time Sort"
176        Button button5,pos={175,147},size={140,20},proc=ExportSlicesButtonProc,title="Export Slices as VAX"
177        Button button6,pos={378,13},size={40,20},proc=EventModeHelpButtonProc,title="?"
178
179        Button button7,pos={175+155,122},size={140,20},proc=AdjustEventDataButtonProc,title="Adjust Events"
180        Button button8,pos={175+155,147},size={140,20},proc=CustomBinButtonProc,title="Custom Bins"
181       
182        Button button1,pos = {10,50}, size={150,20},title="Process Data",fSize=12
183        Button button1,proc=ProcessEventLog_Button
184        SetVariable setvar1,pos={170,50},size={160,20},title="Number of slices",fSize=12,limits={1,1000,1}
185        SetVariable setvar1,value=root:Packages:NIST:gEvent_nslices
186        SetVariable setvar2,pos={330,50},size={160,20},title="Max Time (s)",fSize=12
187        SetVariable setvar2,value=root:Packages:NIST:gEvent_t_longest
188       
189        PopupMenu popup0 title="Bin Spacing",pos={150,90},value="Equal;Fibonacci;Custom;"
190        PopupMenu popup0 proc=BinTypePopMenuProc
191       
192        CheckBox chkbox2,pos={20,95},title="Log Intensity",value=1
193        CheckBox chkbox2,variable=root:Packages:NIST:gEvent_logint,proc=LogIntEvent_Proc
194        SetVariable setvar0,pos={320,90},size={160,20},title="Display Time Slice",fSize=12
195        SetVariable setvar0,limits={0,1000,1},value= root:Packages:NIST:gEvent_tsdisp
196        SetVariable setvar0,proc=sliceSelectEvent_Proc
197        Display/W=(20,180,480,640)/HOST=EventModePanel/N=Event_slicegraph
198        AppendImage/W=EventModePanel#Event_slicegraph/T root:Packages:NIST:Event:dispsliceData
199        ModifyImage/W=EventModePanel#Event_slicegraph  ''#0 ctab= {*,*,ColdWarm,0}
200        ModifyImage/W=EventModePanel#Event_slicegraph ''#0 ctabAutoscale=3
201        ModifyGraph margin(left)=14,margin(bottom)=14,margin(top)=14,margin(right)=14
202        ModifyGraph mirror=2
203        ModifyGraph nticks=4
204        ModifyGraph minor=1
205        ModifyGraph fSize=9
206        ModifyGraph standoff=0
207        ModifyGraph tkLblRot(left)=90
208        ModifyGraph btLen=3
209        ModifyGraph tlOffset=-2
210        SetAxis/A left
211        SetActiveSubwindow ##
212EndMacro
213
214
215Function AdjustEventDataButtonProc(ba) : ButtonControl
216        STRUCT WMButtonAction &ba
217
218        switch( ba.eventCode )
219                case 2: // mouse up
220                        // click code here
221                        Execute "ShowEventCorrectionPanel()"
222                        //
223                        break
224                case -1: // control being killed
225                        break
226        endswitch
227
228        return 0
229End
230
231Function CustomBinButtonProc(ba) : ButtonControl
232        STRUCT WMButtonAction &ba
233
234        switch( ba.eventCode )
235                case 2: // mouse up
236                        // click code here
237                        Execute "Show_CustomBinPanel()"
238                        //
239                        break
240                case -1: // control being killed
241                        break
242        endswitch
243
244        return 0
245End
246
247
248Function ShowEventDataButtonProc(ba) : ButtonControl
249        STRUCT WMButtonAction &ba
250
251        switch( ba.eventCode )
252                case 2: // mouse up
253                        // click code here
254                        Execute "ShowRescaledTimeGraph()"
255                        //
256                        DifferentiatedTime()
257                        //
258                        break
259                case -1: // control being killed
260                        break
261        endswitch
262
263        return 0
264End
265
266Function BinTypePopMenuProc(pa) : PopupMenuControl
267        STRUCT WMPopupAction &pa
268
269        switch( pa.eventCode )
270                case 2: // mouse up
271                        Variable popNum = pa.popNum
272                        String popStr = pa.popStr
273                        if(cmpstr(popStr,"Custom")==0)
274                                Execute "Show_CustomBinPanel()"
275                        endif
276                        break
277                case -1: // control being killed
278                        break
279        endswitch
280
281        return 0
282End
283
284Function ShowBinDetailsButtonProc(ba) : ButtonControl
285        STRUCT WMButtonAction &ba
286
287        switch( ba.eventCode )
288                case 2: // mouse up
289                        // click code here
290                        Execute "ShowBinTable()"
291                        Execute "BinEventBarGraph()"
292                        break
293                case -1: // control being killed
294                        break
295        endswitch
296
297        return 0
298End
299
300Function UndoTimeSortButtonProc(ba) : ButtonControl
301        STRUCT WMButtonAction &ba
302
303        switch( ba.eventCode )
304                case 2: // mouse up
305                        // click code here
306                        Execute "UndoTheSorting()"
307                        break
308                case -1: // control being killed
309                        break
310        endswitch
311
312        return 0
313End
314
315Function ExportSlicesButtonProc(ba) : ButtonControl
316        STRUCT WMButtonAction &ba
317
318        switch( ba.eventCode )
319                case 2: // mouse up
320                        // click code here
321                        Execute "ExportSlicesAsVAX()"           //will invoke the dialog
322                        break
323                case -1: // control being killed
324                        break
325        endswitch
326
327        return 0
328End
329
330Function EventModeHelpButtonProc(ba) : ButtonControl
331        STRUCT WMButtonAction &ba
332
333        switch( ba.eventCode )
334                case 2: // mouse up
335                        // click code here
336                        DoAlert 0,"The help file has not been written yet"
337                        break
338                case -1: // control being killed
339                        break
340        endswitch
341
342        return 0
343End
344
345
346Function EventDone_Proc(ba) : ButtonControl
347        STRUCT WMButtonAction &ba
348       
349        String win = ba.win
350        switch (ba.eventCode)
351                case 2:
352                        DoWindow/K EventModePanel
353                        break
354        endswitch
355        return(0)
356End
357
358
359
360Function ProcessEventLog_Button(ctrlName) : ButtonControl
361        String ctrlName
362       
363        NVAR mode=root:Packages:NIST:gEvent_Mode
364       
365        if(mode == 0)
366                Stream_ProcessEventLog("")
367        endif
368       
369        if(mode == 1)
370                Osc_ProcessEventLog("")
371        endif
372       
373        // toggle the checkbox for log display to force the display to be correct
374        NVAR gLog = root:Packages:NIST:gEvent_logint
375        LogIntEvent_Proc("",gLog)
376       
377        return(0)
378end
379
380// for oscillatory mode
381//
382Function Osc_ProcessEventLog(ctrlName)
383        String ctrlName
384
385        Make/O/D/N=(128,128) root:Packages:NIST:Event:binnedData
386       
387        Wave binnedData = root:Packages:NIST:Event:binnedData
388        Wave xLoc = root:Packages:NIST:Event:xLoc
389        Wave yLoc = root:Packages:NIST:Event:yLoc
390
391// now with the number of slices and max time, process the events
392
393        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
394        NVAR nslices = root:Packages:NIST:gEvent_nslices
395
396        SetDataFolder root:Packages:NIST:Event          //don't count on the folder remaining here
397       
398        Make/D/O/N=(XBINS,YBINS,nslices) slicedData
399               
400        Wave slicedData = slicedData
401        Wave rescaledTime = rescaledTime
402        Wave timePt = timePt
403        Make/O/D/N=(128,128) tmpData
404        Make/O/D/N=(nslices+1) binEndTime,binCount
405        Make/O/D/N=(nslices) timeWidth
406        Wave timeWidth = timeWidth
407        Wave binEndTime = binEndTime
408        Wave binCount = binCount
409
410        variable ii,del,p1,p2,t1,t2
411        del = t_longest/nslices
412
413        slicedData = 0
414        binEndTime[0]=0
415        BinCount[nslices]=0
416
417
418        String binTypeStr=""
419        ControlInfo /W=EventModePanel popup0
420        binTypeStr = S_value
421       
422        strswitch(binTypeStr)   // string switch
423                case "Equal":           // execute if case matches expression
424                        SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
425                        break                                           // exit from switch
426                case "Fibonacci":               // execute if case matches expression
427                        SetFibonacciBins(binEndTime,timeWidth,nslices,t_longest)
428                        break
429                case "Log":             // execute if case matches expression
430                        SetLogBins(binEndTime,timeWidth,nslices,t_longest)
431                        break
432                case "Custom":          // execute if case matches expression
433                        //bins are set by the user on the panel - assume it's good to go
434                        break
435                default:                                                        // optional default expression executed
436                        DoAlert 0,"No match for bin type, Equal bins used"
437                        SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
438        endswitch
439
440
441// now before binning, sort the data
442
443        //this is slow - undoing the sorting and starting over, but if you don't,
444        // you'll never be able to undo the sort
445        //
446        SetDataFolder root:Packages:NIST:Event:
447
448        if(WaveExists($"root:Packages:NIST:Event:OscSortIndex") == 0 )
449                Duplicate/O rescaledTime OscSortIndex
450                MakeIndex rescaledTime OscSortIndex
451                IndexSort OscSortIndex, yLoc,xLoc,timePt,rescaledTime   
452                //SetDataFolder root:Packages:NIST:Event
453                IndexForHistogram(xLoc,yLoc,binnedData)                 // index the events AFTER sorting
454                //SetDataFolder root:
455        Endif
456       
457        Wave index = root:Packages:NIST:Event:SavedIndex                //this is the histogram index
458
459        for(ii=0;ii<nslices;ii+=1)
460                if(ii==0)
461//                      t1 = ii*del
462//                      t2 = (ii+1)*del
463                        p1 = BinarySearch(rescaledTime,0)
464                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])
465                else
466//                      t2 = (ii+1)*del
467                        p1 = p2+1               //one more than the old one
468                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])               
469                endif
470
471        // typically zero will never be a valid time value in oscillatory mode. in "stream" mode, the first is normalized to == 0
472        // but not here - times are what they are.
473                if(p1 == -1)
474                        Printf "p1 = -1 Binary search off the end %15.10g <?? %15.10g\r", 0, rescaledTime[0]
475                        p1 = 0          //set to the first point if it's off the end
476                Endif
477               
478                if(p2 == -2)
479                        Printf "p2 = -2 Binary search off the end %15.10g >?? %15.10g\r", binEndTime[ii+1], rescaledTime[numpnts(rescaledTime)-1]
480                        p2 = numpnts(rescaledTime)-1            //set to the last point if it's off the end
481                Endif
482//              Print p1,p2
483
484
485                tmpData=0
486                JointHistogramWithRange(xLoc,yLoc,tmpData,index,p1,p2)
487                slicedData[][][ii] = tmpData[p][q]
488               
489//              binEndTime[ii+1] = t2
490                binCount[ii] = sum(tmpData,-inf,inf)
491        endfor
492
493        Duplicate/O slicedData,root:Packages:NIST:Event:dispsliceData,root:Packages:NIST:Event:logSlicedData
494        Wave logSlicedData = root:Packages:NIST:Event:logSlicedData
495        logslicedData = log(slicedData)
496
497        SetDataFolder root:
498        return(0)
499End
500
501// for a "continuous exposure"
502//
503// if there is a sort of these events, I need to re-index the events for the histogram
504// - see the oscillatory mode  - and sort the events here, then immediately re-index for the histogram
505// - but with the added complication that I need to always remember to index for the histogram, every time
506// - since I don't know if I've sorted or un-sorted. Osc mode always forces a re-sort and a re-index
507//
508Function Stream_ProcessEventLog(ctrlName)
509        String ctrlName
510
511//      NVAR slicewidth = root:Packages:NIST:gTISANE_slicewidth
512
513       
514        Make/O/D/N=(128,128) root:Packages:NIST:Event:binnedData
515       
516        Wave binnedData = root:Packages:NIST:Event:binnedData
517        Wave xLoc = root:Packages:NIST:Event:xLoc
518        Wave yLoc = root:Packages:NIST:Event:yLoc
519
520// now with the number of slices and max time, process the events
521
522        NVAR yesSortStream = root:Packages:NIST:gSortStreamEvents               //do I sort the events?
523        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
524        NVAR nslices = root:Packages:NIST:gEvent_nslices
525
526        SetDataFolder root:Packages:NIST:Event          //don't count on the folder remaining here
527       
528        Make/D/O/N=(XBINS,YBINS,nslices) slicedData
529               
530        Wave slicedData = slicedData
531        Wave rescaledTime = rescaledTime
532        Make/O/D/N=(128,128) tmpData
533        Make/O/D/N=(nslices+1) binEndTime,binCount//,binStartTime
534        Make/O/D/N=(nslices) timeWidth
535        Wave binEndTime = binEndTime
536        Wave timeWidth = timeWidth
537        Wave binCount = binCount
538
539        variable ii,del,p1,p2,t1,t2
540        del = t_longest/nslices
541
542        slicedData = 0
543        binEndTime[0]=0
544        BinCount[nslices]=0
545       
546        String binTypeStr=""
547        ControlInfo /W=EventModePanel popup0
548        binTypeStr = S_value
549       
550        strswitch(binTypeStr)   // string switch
551                case "Equal":           // execute if case matches expression
552                        SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
553                        break                                           // exit from switch
554                case "Fibonacci":               // execute if case matches expression
555                        SetFibonacciBins(binEndTime,timeWidth,nslices,t_longest)
556                        break
557                case "Log":             // execute if case matches expression
558                        SetLogBins(binEndTime,timeWidth,nslices,t_longest)
559                        break
560                case "Custom":          // execute if case matches expression
561                        //bins are set by the user on the panel - assume it's good to go
562                        break
563                default:                                                        // optional default expression executed
564                        DoAlert 0,"No match for bin type, Equal bins used"
565                        SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
566        endswitch
567
568// TODO
569// the global exists for this switch, but it is not implemented - not sure whether
570// it's correct to implement this at all --
571//
572        if(yesSortStream == 1)
573                SortTimeData()
574        endif
575       
576// index the events before binning
577// if there is a sort of these events, I need to re-index the events for the histogram
578//      SetDataFolder root:Packages:NIST:Event
579        IndexForHistogram(xLoc,yLoc,binnedData)
580//      SetDataFolder root:
581        Wave index = root:Packages:NIST:Event:SavedIndex                //the index for the histogram
582       
583       
584        for(ii=0;ii<nslices;ii+=1)
585                if(ii==0)
586//                      t1 = ii*del
587//                      t2 = (ii+1)*del
588                        p1 = BinarySearch(rescaledTime,0)
589                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])
590                else
591//                      t2 = (ii+1)*del
592                        p1 = p2+1               //one more than the old one
593                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])               
594                endif
595
596                if(p1 == -1)
597                        Printf "p1 = -1 Binary search off the end %15.10g <?? %15.10g\r", 0, rescaledTime[0]
598                        p1 = 0          //set to the first point if it's off the end
599                Endif
600                if(p2 == -2)
601                        Printf "p2 = -2 Binary search off the end %15.10g >?? %15.10g\r", binEndTime[ii+1], rescaledTime[numpnts(rescaledTime)-1]
602                        p2 = numpnts(rescaledTime)-1            //set to the last point if it's off the end
603                Endif
604//              Print p1,p2
605
606
607                tmpData=0
608                JointHistogramWithRange(xLoc,yLoc,tmpData,index,p1,p2)
609                slicedData[][][ii] = tmpData[p][q]
610               
611//              binEndTime[ii+1] = t2
612                binCount[ii] = sum(tmpData,-inf,inf)
613        endfor
614
615        Duplicate/O slicedData,root:Packages:NIST:Event:dispsliceData,root:Packages:NIST:Event:logSlicedData
616        Wave logSlicedData = root:Packages:NIST:Event:logSlicedData
617        logslicedData = log(slicedData)
618
619        SetDataFolder root:
620        return(0)
621End
622
623
624Proc    UndoTheSorting()
625        Osc_UndoSort()
626End
627
628// for oscillatory mode
629//
630// -- this takes the previously generated index, and un-sorts the data to restore to the
631// "as-collected" state
632//
633Function Osc_UndoSort()
634
635        SetDataFolder root:Packages:NIST:Event          //don't count on the folder remaining here
636        Wave rescaledTime = rescaledTime
637        Wave OscSortIndex = OscSortIndex
638        Wave yLoc = yLoc
639        Wave xLoc = xLoc
640        Wave timePt = timePt
641
642        Sort OscSortIndex OscSortIndex,yLoc,xLoc,timePt,rescaledTime
643
644        KillWaves/Z OscSortIndex
645       
646        SetDataFolder root:
647        return(0)
648End
649
650
651// now before binning, sort the data
652//
653//this is slow - undoing the sorting and starting over, but if you don't,
654// you'll never be able to undo the sort
655//
656Function SortTimeData()
657
658
659        SetDataFolder root:Packages:NIST:Event:
660
661        KillWaves/Z OscSortIndex
662       
663        if(WaveExists($"root:Packages:NIST:Event:OscSortIndex") == 0 )
664                Duplicate/O rescaledTime OscSortIndex
665                MakeIndex rescaledTime OscSortIndex
666                IndexSort OscSortIndex, yLoc,xLoc,timePt,rescaledTime   
667        Endif
668       
669        SetDataFolder root:
670        return(0)
671End
672
673
674
675Function SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
676        Wave binEndTime,timeWidth
677        Variable nslices,t_longest
678
679        Variable del,ii,t2
680        binEndTime[0]=0         //so the bar graph plots right...
681        del = t_longest/nslices
682       
683        for(ii=0;ii<nslices;ii+=1)
684                t2 = (ii+1)*del
685                binEndTime[ii+1] = t2
686        endfor
687        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
688
689        timeWidth = binEndTime[p+1]-binEndTime[p]
690
691        return(0)       
692End
693
694// TODO
695// either get this to work, or scrap it entirely. it currently isn't on the popup
696// so it can't be accessed
697Function SetLogBins(binEndTime,timeWidth,nslices,t_longest)
698        Wave binEndTime,timeWidth
699        Variable nslices,t_longest
700
701        Variable tMin,ii
702
703        Wave rescaledTime = root:Packages:NIST:Event:rescaledTime
704       
705        binEndTime[0]=0         //so the bar graph plots right...
706
707        // just like the log-scaled q-points
708        tMin = rescaledTime[1]/1                        //just a guess... can't use tMin=0, and rescaledTime[0] == 0 by definition
709        Print rescaledTime[1], tMin
710        for(ii=0;ii<nslices;ii+=1)
711                binEndTime[ii+1] =alog(log(tMin) + (ii+1)*((log(t_longest)-log(tMin))/nslices))
712        endfor
713        binEndTime[ii+1] = t_longest            //otherwise floating point errors such that the last time point is off the end of the Binary search
714       
715        timeWidth = binEndTime[p+1]-binEndTime[p]
716
717        return(0)
718End
719
720Function MakeFibonacciWave(w,num)
721        Wave w
722        Variable num
723
724        //skip the initial zero
725        Variable f1,f2,ii
726        f1=1
727        f2=1
728        w[0] = f1
729        w[1] = f2
730        for(ii=2;ii<num;ii+=1)
731                w[ii] = f1+f2
732                f1=f2
733                f2=w[ii]
734        endfor
735               
736        return(0)
737end
738
739Function SetFibonacciBins(binEndTime,timeWidth,nslices,t_longest)
740        Wave binEndTime,timeWidth
741        Variable nslices,t_longest
742
743        Variable tMin,ii,total,t2,tmp
744        Make/O/D/N=(nslices) fibo
745        fibo=0
746        MakeFibonacciWave(fibo,nslices)
747       
748//      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}
749
750        binEndTime[0]=0         //so the bar graph plots right...
751        total = sum(fibo,0,nslices-1)           //total number of "pieces"
752       
753        tmp=0
754        for(ii=0;ii<nslices;ii+=1)
755                t2 = sum(fibo,0,ii)/total*t_longest
756                binEndTime[ii+1] = t2
757        endfor
758        binEndTime[ii+1] = t_longest            //otherwise floating point errors such that the last time point is off the end of the Binary search
759       
760        timeWidth = binEndTime[p+1]-binEndTime[p]
761       
762        return(0)
763End
764
765
766
767// TODO:
768//
769// What, if anything is different about the OSC or STREAM load?
770// I think that only the processing is different. so this could be
771// consolidated into a single loader.
772//
773// ** currently, the "stream" loader uses the first data point as time=0
774//    and rescales everything to that time. "Osc" loading uses the times "as-is"
775//    from the file, trusting the times to be correct.
776//
777// Would TISANE or TOF need a different loader?
778//
779Function LoadEventLog_Button(ctrlName) : ButtonControl
780        String ctrlName
781
782        NVAR mode=root:Packages:NIST:gEvent_mode
783        Variable err=0
784       
785        if(mode == 0)
786                err = Stream_LoadEventLog("")
787                if(err == 1)
788                        return(0)               // user cancelled from file load
789                endif
790        endif
791       
792        if(mode == 1)
793                err = Osc_LoadEventLog("")
794                if(err == 1)
795                        return(0)               // user cancelled from file load
796                endif
797        endif
798
799        STRUCT WMButtonAction ba
800        ba.eventCode = 2
801        ShowEventDataButtonProc(ba)
802
803        return(0)
804End
805
806// for the mode of "one continuous exposure"
807//
808Function Stream_LoadEventLog(ctrlName)
809        String ctrlName
810       
811        Variable fileref
812
813        SVAR filename = root:Packages:NIST:gEvent_logfile
814        NVAR nslices = root:Packages:NIST:gEvent_nslices
815        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
816       
817        String fileFilters = "All Files:.*;Data Files (*.txt):.txt;"
818       
819        Open/R/D/F=fileFilters fileref
820        filename = S_filename
821        if(strlen(S_filename) == 0)
822                // user cancelled
823                DoAlert 0,"No file selected, no file loaded."
824                return(1)
825        endif
826
827#if (exists("EventLoadWave")==4)
828        LoadEvents_XOP()
829#else
830        LoadEvents()
831#endif 
832
833        SetDataFolder root:Packages:NIST:Event:
834
835tic()
836        Wave timePt=timePt
837        Wave xLoc=xLoc
838        Wave yLoc=yLoc
839        CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
840       
841toc()
842
843        Duplicate/O timePt rescaledTime
844        rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
845        t_longest = waveMax(rescaledTime)               //should be the last point
846
847        SetDataFolder root:
848
849        return(0)
850End
851
852// for the mode "oscillatory"
853//
854Function Osc_LoadEventLog(ctrlName)
855        String ctrlName
856       
857        Variable fileref
858
859        SVAR filename = root:Packages:NIST:gEvent_logfile
860        NVAR nslices = root:Packages:NIST:gEvent_nslices
861        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
862       
863        String fileFilters = "All Files:.*;Data Files (*.txt):.txt;"
864       
865        Open/R/D/F=fileFilters fileref
866        filename = S_filename
867                if(strlen(S_filename) == 0)
868                // user cancelled
869                DoAlert 0,"No file selected, no file loaded."
870                return(1)
871        endif
872       
873#if (exists("EventLoadWave")==4)
874        LoadEvents_XOP()
875#else
876        LoadEvents()
877#endif 
878       
879        SetDataFolder root:Packages:NIST:Event:
880
881        Wave timePt=timePt
882        Wave xLoc=xLoc
883        Wave yLoc=yLoc
884        CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
885       
886        Duplicate/O timePt rescaledTime
887        rescaledTime *= 1e-7                    //convert to seconds and that's all
888        t_longest = waveMax(rescaledTime)               //if oscillatory, won't be the last point, so get it this way
889
890        KillWaves/Z OscSortIndex                        //to make sure that there is no old index hanging around
891
892        SetDataFolder root:
893
894        return(0)
895End
896
897
898//
899// -- MUCH faster to count the number of lines to remove, then delete (N)
900// rather then delete them one-by-one in the do-loop
901Function CleanupTimes(xLoc,yLoc,timePt)
902        Wave xLoc,yLoc,timePt
903
904        // start at the back and remove zeros
905        Variable num=numpnts(xLoc),ii,numToRemove
906
907        numToRemove = 0
908        ii=num
909        do
910                ii -= 1
911                if(timePt[ii] == 0 && xLoc[ii] == 0 && yLoc[ii] == 0)
912                        numToRemove += 1
913                endif
914        while(timePt[ii-1] == 0 && xLoc[ii-1] == 0 && yLoc[ii-1] == 0)
915       
916        if(numToRemove != 0)
917                DeletePoints ii, numToRemove, xLoc,yLoc,timePt
918        endif
919       
920        return(0)
921End
922
923Function LogIntEvent_Proc(ctrlName,checked) : CheckBoxControl
924        String ctrlName
925        Variable checked
926               
927        SetDataFolder root:Packages:NIST:Event
928        if(checked)
929                Duplicate/O logslicedData dispsliceData
930        else
931                Duplicate/O slicedData dispsliceData
932        endif
933
934        NVAR selectedslice = root:Packages:NIST:gEvent_tsdisp
935
936        sliceSelectEvent_Proc("", selectedslice, "", "")
937
938        SetDataFolder root:
939
940End
941
942
943// TODO
944// this "fails" for data sets that have 3 or 4 slices, as the ModifyImage command
945// interprets the data as being RGB - and so does nothing.
946// need to find a way around this
947///
948// I could modify this procedure to use the log = 0|1 keyword for the log Z display
949// rather than creating a duplicate wave of log(data)
950//
951Function sliceSelectEvent_Proc(ctrlName, varNum, varStr, varName) : SetVariableControl
952        String ctrlName
953        Variable varNum
954        String varStr
955        String varName
956       
957        NVAR nslices = root:Packages:NIST:gEvent_nslices
958        NVAR selectedslice = root:Packages:NIST:gEvent_tsdisp
959       
960        if(varNum < 0)
961                selectedslice = 0
962                DoUpdate
963        elseif (varNum > nslices-1)
964                selectedslice = nslices-1
965                DoUpdate
966        else
967                ModifyImage/W=EventModePanel#Event_slicegraph ''#0 plane = varNum
968        endif
969
970End
971
972Function DifferentiatedTime()
973
974        Wave rescaledTime = root:Packages:NIST:Event:rescaledTime
975
976        SetDataFolder root:Packages:NIST:Event:
977               
978        Differentiate rescaledTime/D=rescaledTime_DIF
979//      Display rescaledTime,rescaledTime_DIF
980        DoWindow/F Differentiated_Time
981        if(V_flag == 0)
982                Display/N=Differentiated_Time/K=1 rescaledTime_DIF
983                Legend
984                Modifygraph gaps=0
985                ModifyGraph zero(left)=1
986                Label left "\\Z14Delta (dt/event)"
987                Label bottom "\\Z14Event number"
988        endif
989       
990        SetDataFolder root:
991       
992        return(0)
993End
994
995
996//
997// for the bit shifts, see the decimal-binary conversion
998// http://www.binaryconvert.com/convert_unsigned_int.html
999//
1000//              K0 = 536870912
1001//              Print (K0 & 0x08000000)/134217728       //bit 27 only, shift by 2^27
1002//              Print (K0 & 0x10000000)/268435456               //bit 28 only, shift by 2^28
1003//              Print (K0 & 0x20000000)/536870912               //bit 29 only, shift by 2^29
1004//
1005// This is duplicated by the XOP, but the Igor code allows quick access to print out
1006// all of the gorey details of the events and every little bit of them. the print
1007// statements and flags are kept for this reason, so the code is a bit messy.
1008//
1009Function LoadEvents()
1010       
1011        NVAR time_msw = root:Packages:NIST:gEvent_time_msw
1012        NVAR time_lsw = root:Packages:NIST:gEvent_time_lsw
1013        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
1014       
1015        SVAR filepathstr = root:Packages:NIST:gEvent_logfile
1016        SVAR dispStr = root:Packages:NIST:gEventDisplayString
1017       
1018        SetDataFolder root:Packages:NIST:Event
1019
1020        Variable fileref
1021        String buffer
1022        String fileStr,tmpStr
1023        Variable dataval,timeval,type,numLines,verbose,verbose3
1024        Variable xval,yval,rollBit,nRoll,roll_time,bit29,bit28,bit27
1025        Variable ii,flaggedEvent,rolloverHappened,numBad=0,tmpPP=0,tmpT0=0
1026        Variable Xmax, yMax
1027       
1028        xMax = 127              // number the detector from 0->127
1029        yMax = 127
1030       
1031        verbose3 = 0                    //prints out the rollover events (type==3)
1032        verbose = 0
1033        numLines = 0
1034
1035       
1036        // what I really need is the number of XY events
1037        Variable numXYevents,num1,num2,num3,num0,totBytes,numPP,numT0,numDL,numFF,numZero
1038        Variable numRemoved
1039        numXYevents = 0
1040        num0 = 0
1041        num1 = 0
1042        num2 = 0
1043        num3 = 0
1044        numPP = 0
1045        numT0 = 0
1046        numDL = 0
1047        numFF = 0
1048        numZero = 0
1049        numRemoved = 0
1050
1051//tic()
1052        Open/R fileref as filepathstr
1053                FStatus fileref
1054        Close fileref
1055
1056        totBytes = V_logEOF
1057        Print "total bytes = ", totBytes
1058       
1059//toc()
1060//
1061
1062
1063// do a "pre-scan to get some of the counts, so that I can allocate space. This does
1064// double the read time, but is still faster than adding points to waves as the file is read
1065//     
1066
1067        tic()
1068
1069        Open/R fileref as filepathstr
1070        do
1071                do
1072                        FReadLine fileref, buffer                       //skip the "blank" lines that have one character
1073                while(strlen(buffer) == 1)             
1074
1075                if (strlen(buffer) == 0)
1076                        break
1077                endif
1078               
1079                sscanf buffer,"%x",dataval
1080               
1081                // two most sig bits (31-30)
1082                type = (dataval & 0xC0000000)/1073741824                //right shift by 2^30
1083                               
1084                if(type == 0)
1085                        num0 += 1
1086                        numXYevents += 1
1087                endif
1088                if(type == 2)
1089                        num2 += 1
1090                        numXYevents += 1
1091                endif
1092                if(type == 1)
1093                        num1 += 1
1094                endif
1095                if(type == 3)
1096                        num3 += 1
1097                endif   
1098               
1099                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1100               
1101                if(type==0 || type==2)
1102                        numPP += round(bit29)
1103                endif
1104               
1105                if(type==1 || type==3)
1106                        numT0 += round(bit29)
1107                endif
1108               
1109                if(dataval == 0)
1110                        numZero += 1
1111                endif
1112               
1113        while(1)
1114        Close fileref
1115//              done counting the number of XY events
1116        printf("Igor pre-scan done in  ")
1117        toc()
1118       
1119
1120        Print "(Igor) numT0 = ",numT0   
1121        Print "num0 = ",num0   
1122        Print "num1 = ",num1   
1123        Print "num2 = ",num2   
1124        Print "num3 = ",num3   
1125       
1126//
1127//     
1128//      Printf "numXYevents = %d\r",numXYevents
1129//      Printf "XY = num0 = %d\r",num0
1130//      Printf "XY time = num2 = %d\r",num2
1131//      Printf "time MSW = num1 = %d\r",num1
1132//      Printf "Rollover = num3 = %d\r",num3
1133//      Printf "num0 + num2 = %d\r",num0+num2
1134
1135// dispStr will be displayed on the panel
1136        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
1137       
1138        sprintf tmpStr, "%s: %d total bytes\r",fileStr,totBytes
1139        dispStr = tmpStr
1140        sprintf tmpStr,"numXYevents = %d\r",numXYevents
1141        dispStr += tmpStr
1142        sprintf tmpStr,"PP = %d  :  ",numPP
1143        dispStr += tmpStr
1144        sprintf tmpStr,"ZeroData = %d\r",numZero
1145        dispStr += tmpStr
1146        sprintf tmpStr,"Rollover = %d",num3
1147        dispStr += tmpStr
1148
1149        // /I/U is unsigned 32-bit integer (for the time)
1150        // /B/U is unsigned 8-bit integer (max val=255) for the x and y values
1151       
1152        Make/O/U/N=(numXYevents) xLoc,yLoc
1153        Make/O/D/N=(numXYevents) timePt
1154//      Make/O/U/N=(totBytes/4) xLoc,yLoc               //too large, trim when done (bad idea)
1155//      Make/O/D/N=(totBytes/4) timePt
1156        Make/O/D/N=1000 badTimePt,badEventNum,PPTime,PPEventNum,T0Time,T0EventNum
1157        badTimePt=0
1158        badEventNum=0
1159        PPTime=0
1160        PPEventNum=0
1161        T0Time=0
1162        T0EventNum=0
1163        xLoc=0
1164        yLoc=0
1165        timePt=0
1166       
1167        nRoll = 0               //number of rollover events
1168        roll_time = 2^26                //units of 10-7 sec
1169       
1170        NVAR removeBadEvents = root:Packages:NIST:gRemoveBadEvents
1171       
1172        time_msw=0
1173       
1174        tic()
1175       
1176        ii = 0
1177       
1178        Open/R fileref as filepathstr
1179       
1180        // remove events at the beginning up to a type==2 so that the msw and lsw times are reset properly
1181        if(RemoveBadEvents == 1)
1182                do
1183                        do
1184                                FReadLine fileref, buffer                       //skip the "blank" lines that have one character
1185                        while(strlen(buffer) == 1)             
1186       
1187                        if (strlen(buffer) == 0)
1188                                break
1189                        endif
1190                       
1191                        sscanf buffer,"%x",dataval
1192                // two most sig bits (31-30)
1193                        type = (dataval & 0xC0000000)/1073741824                //right shift by 2^30
1194                       
1195                        if(type == 2)
1196                                // this is the first event with a proper time value, so process the XY-time event as ususal
1197                                // and then break to drop to the main loop, where the next event == type 1
1198                               
1199                                xval = xMax - (dataval & 255)                                           //last 8 bits (7-0)
1200                                yval = (dataval & 65280)/256                                            //bits 15-8, right shift by 2^8
1201               
1202                                time_lsw = (dataval & 536805376)/65536                  //13 bits, 28-16, right shift by 2^16
1203               
1204                                if(verbose)
1205                //                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1206                                        printf "%u : %u : %u : %u\r",dataval,timeval,xval,yval
1207                                endif
1208                               
1209                                // this is the first point, be sure that ii = 0
1210                                ii = 0
1211                                xLoc[ii] = xval
1212                                yLoc[ii] = yval
1213                               
1214                                Print "At beginning of file, numBad = ",numBad
1215                                break   // the next do loop processes the bulk of the file (** the next event == type 1 = MIR)
1216                        else
1217                                numBad += 1
1218                                numRemoved += 1
1219                        endif
1220                       
1221                        //ii+=1         don't increment the counter
1222                while(1)
1223        endif
1224       
1225        // now read the main portion of the file.
1226        do
1227                do
1228                        FReadLine fileref, buffer                       //skip the "blank" lines that have one character
1229                while(strlen(buffer) == 1)             
1230
1231                if (strlen(buffer) == 0)
1232                        break
1233                endif
1234               
1235                sscanf buffer,"%x",dataval
1236               
1237
1238//              type = (dataval & ~(2^32 - 2^30 -1))/2^30
1239
1240                // two most sig bits (31-30)
1241                type = (dataval & 0xC0000000)/1073741824                //right shift by 2^30
1242               
1243                //
1244                // The defintions of the event types
1245                //
1246                //Constant ATXY = 0
1247                //Constant ATXYM = 2
1248                //Constant ATMIR = 1
1249                //Constant ATMAR = 3
1250                //
1251                                               
1252                if(verbose > 0)
1253                        verbose -= 1
1254                endif
1255//             
1256                switch(type)
1257                        case ATXY:              // 0
1258                                if(verbose)             
1259                                        printf "XY : "         
1260                                endif
1261                               
1262                                // if the datavalue is == 0, just skip it now (it can only be interpreted as type 0, obviously)
1263                                if(dataval == 0 && RemoveBadEvents == 1)
1264                                        numRemoved += 1
1265                                        //Print "zero at ii= ",ii
1266                                        break           //don't increment ii
1267                                endif
1268                               
1269                                // if it's a pileup event, skip it now (this can be either type 0 or 2)
1270                                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1271                                if(bit29 == 1 && RemoveBadEvents == 1)
1272                                        PPTime[tmpPP] = timeval
1273                                        PPEventNum[tmpPP] = ii
1274                                        tmpPP += 1
1275                                        numRemoved += 1
1276                                        break           //don't increment ii
1277                                endif
1278                               
1279//                              xval = ~(dataval & ~(2^32 - 2^8)) & 127
1280//                              yval = ((dataval & ~(2^32 - 2^16 ))/2^8) & 127
1281//                              time_lsw = (dataval & ~(2^32 - 2^29))/2^16
1282
1283                                xval = xMax - (dataval & 255)                                           //last 8 bits (7-0)
1284                                yval = (dataval & 65280)/256                                            //bits 15-8, right shift by 2^8
1285                                time_lsw = (dataval & 536805376)/65536                  //13 bits, 28-16, right shift by 2^16
1286
1287                                timeval = trunc( nRoll*roll_time + (time_msw * (8192)) + time_lsw )             //left shift msw by 2^13, then add in lsw, as an integer
1288                                if (timeval > t_longest)
1289                                        t_longest = timeval
1290                                endif
1291                               
1292                               
1293                                // catch the "bad" events:
1294                                // if an XY event follows a rollover, time_msw is 0 by definition, but does not immediately get
1295                                // re-evalulated here. Throw out only the immediately following points where msw is still 8191
1296                                if(rolloverHappened && RemoveBadEvents == 1)
1297                                        // maybe a bad event
1298                                        if(time_msw == 8191)
1299                                                badTimePt[numBad] = timeVal
1300                                                badEventNum[numBad] = ii
1301                                                numBad +=1
1302                                                numRemoved += 1
1303                                        else
1304                                                // time_msw has been reset, points are good now, so keep this one
1305                                                xLoc[ii] = xval
1306                                                yLoc[ii] = yval
1307                                                timePt[ii] = timeval
1308                                               
1309//                                              if(xval == 127 && yval == 0)
1310//                                                      // check bit 29
1311//                                                      bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1312//                                                      Print "XY=127,0 : bit29 = ",bit29
1313//                                              endif
1314                                               
1315                                                ii+=1
1316                                                rolloverHappened = 0
1317                                        endif
1318                                else
1319                                        // normal processing of good point, keep it
1320                                        xLoc[ii] = xval
1321                                        yLoc[ii] = yval
1322                                        timePt[ii] = timeval
1323                               
1324//                                      if(xval == 127 && yval == 0)
1325//                                              // check bit 29
1326//                                              bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1327//                                              Printf "XY=127,0 : bit29 = %u : d=%u\r",bit29,dataval
1328//                                      endif
1329                                        ii+=1
1330                                endif
1331
1332
1333                                if(verbose)             
1334//                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1335                                        printf "d=%u : t=%u : msw=%u : lsw=%u : %u : %u \r",dataval,timeval,time_msw,time_lsw,xval,yval
1336                                endif                           
1337       
1338//                              verbose = 0
1339                                break
1340                        case ATXYM: // 2
1341                                if(verbose)
1342                                        printf "XYM : "
1343                                endif
1344                               
1345                                // if it's a pileup event, skip it now (this can be either type 0 or 2)
1346                                // - but can I do this if this is an XY-time event? This will lead to a wrong time, and a time
1347                                // assigned to an XY (0,0)...
1348//                              bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1349//                              if(bit29 == 1 && RemoveBadEvents == 1)
1350//                                      Print "*****Bit 29 (PP) event set for Type==2, but not handled, ii = ",ii
1351////                                    break           //don't increment ii
1352//                              endif
1353                               
1354//                              xval = ~(dataval & ~(2^32 - 2^8)) & 127
1355//                              yval = ((dataval & ~(2^32 - 2^16 ))/2^8) & 127
1356//                              time_lsw =  (dataval & ~(2^32 - 2^29 ))/2^16            //this method gives a FP result!! likely since the "^" operation gives FP result...
1357
1358                                xval = xMax - (dataval & 255)                                           //last 8 bits (7-0)
1359                                yval = (dataval & 65280)/256                                            //bits 15-8, right shift by 2^8
1360
1361                                time_lsw = (dataval & 536805376)/65536                  //13 bits, 28-16, right shift by 2^16 (result is integer)
1362
1363                                if(verbose)
1364//                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1365                                        printf "%u : %u : %u : %u\r",dataval,timeval,xval,yval
1366                                endif
1367                               
1368                                xLoc[ii] = xval
1369                                yLoc[ii] = yval
1370
1371                                // don't fill in the time yet, or increment the index ii
1372                                // the next event MUST be ATMIR with the MSW time bits
1373                                //
1374//                              verbose = 0
1375                                break
1376                        case ATMIR:  // 1
1377                                if(verbose)
1378                                        printf "MIR : "
1379                                endif
1380
1381                                time_msw =  (dataval & 536805376)/65536                 //13 bits, 28-16, right shift by 2^16
1382                                timeval = trunc( nRoll*roll_time + (time_msw * (8192)) + time_lsw )
1383                                if (timeval > t_longest)
1384                                        t_longest = timeval
1385                                endif
1386                                if(verbose)
1387//                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1388                                        printf "d=%u : t=%u : msw=%u : lsw=%u : tlong=%u\r",dataval,timeval,time_msw,time_lsw,t_longest
1389                                endif
1390                               
1391                                // the XY position was in the previous event ATXYM
1392                                timePt[ii] = timeval
1393
1394                                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1395                                if(bit29 != 0)          // bit 29 set is a T0 event
1396                                        //Printf "bit29 = 1 at ii = %d : type = %d\r",ii,type
1397                                        T0Time[tmpT0] = timeval
1398                                        T0EventNum[tmpT0] = ii
1399                                        tmpT0 += 1
1400                                        // reset nRoll = 0 for calcluating the time
1401                                        nRoll = 0
1402                                endif
1403                                                               
1404                                ii+=1
1405//                              verbose = 0
1406                                break
1407                        case ATMAR:  // 3
1408                                if(verbose3)
1409//                                      verbose = 15
1410//                                      verbose = 2
1411                                        printf "MAR : "
1412                                endif
1413                               
1414                                // do something with the rollover event?
1415                               
1416                                // check bit 29
1417                                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1418                                nRoll += 1
1419// not doing anything with these bits yet       
1420                                bit28 = (dataval & 0x10000000)/268435456                //bit 28 only, shift by 2^28   
1421                                bit27 = (dataval & 0x08000000)/134217728        //bit 27 only, shift by 2^27
1422
1423                                if(verbose3)
1424                                        printf "d=%u : b29=%u : b28=%u : b27=%u : #Roll=%u \r",dataval,bit29, bit28, bit27,nRoll
1425                                endif
1426                               
1427                                if(bit29 != 0)          // bit 29 set is a T0 event
1428                                        //Printf "bit29 = 1 at ii = %d : type = %d\r",ii,type
1429                                        T0Time[tmpT0] = timeval
1430                                        T0EventNum[tmpT0] = ii
1431                                        tmpT0 += 1
1432                                        // reset nRoll = 0 for calcluating the time
1433                                        nRoll = 0
1434                                endif
1435                               
1436                                rolloverHappened = 1
1437
1438                                break
1439                endswitch
1440               
1441//              if(ii<18)
1442//                      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
1443//              endif   
1444                       
1445        while(1)
1446       
1447        Close fileref
1448       
1449        printf("Igor full file read done in  ")
1450        toc()
1451       
1452        Print "Events removed (Igor) = ",numRemoved
1453       
1454        sPrintf tmpStr,"\rBad Rollover Events = %d (%g %% of events)",numBad,numBad/numXYevents*100
1455        dispStr += tmpStr
1456        sPrintf tmpStr,"\rTotal Events Removed = %d (%g %% of events)",numRemoved,numRemoved/numXYevents*100
1457        dispStr += tmpStr
1458        SetDataFolder root:
1459       
1460        return(0)
1461       
1462End
1463
1464//////////////
1465//
1466// This calls the XOP, as an operation to load the events
1467//
1468// -- it's about 35x faster than the Igor code, so I guess that's OK.
1469//
1470//
1471Function LoadEvents_XOP()
1472       
1473//      NVAR time_msw = root:Packages:NIST:gEvent_time_msw
1474//      NVAR time_lsw = root:Packages:NIST:gEvent_time_lsw
1475        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
1476       
1477        SVAR filepathstr = root:Packages:NIST:gEvent_logfile
1478        SVAR dispStr = root:Packages:NIST:gEventDisplayString
1479       
1480        SetDataFolder root:Packages:NIST:Event
1481
1482        Variable fileref
1483        String buffer
1484        String fileStr,tmpStr
1485        Variable dataval,timeval,type,numLines,verbose,verbose3
1486        Variable xval,yval,rollBit,nRoll,roll_time,bit29,bit28,bit27
1487        Variable ii,flaggedEvent,rolloverHappened,numBad=0,tmpPP=0,tmpT0=0
1488        Variable Xmax, yMax
1489       
1490        xMax = 127              // number the detector from 0->127
1491        yMax = 127
1492       
1493        numLines = 0
1494
1495       
1496        // what I really need is the number of XY events
1497        Variable numXYevents,num1,num2,num3,num0,totBytes,numPP,numT0,numDL,numFF,numZero
1498        Variable numRemoved
1499        numXYevents = 0
1500        num0 = 0
1501        num1 = 0
1502        num2 = 0
1503        num3 = 0
1504        numPP = 0
1505        numT0 = 0
1506        numDL = 0
1507        numFF = 0
1508        numZero = 0
1509        numRemoved = 0
1510
1511// get the total number of bytes in the file
1512        Open/R fileref as filepathstr
1513                FStatus fileref
1514        Close fileref
1515
1516        totBytes = V_logEOF
1517        Print "total bytes = ", totBytes
1518       
1519//
1520
1521////
1522//
1523//  use the XOP operation to load in the data
1524// -- this does everything - the pre-scan and creating the waves
1525//
1526// need to zero the waves before loading, just in case
1527//
1528
1529        NVAR removeBadEvents = root:Packages:NIST:gRemoveBadEvents
1530
1531tic()
1532
1533//      Wave/Z wave0=wave0
1534//      Wave/Z wave1=wave1
1535//      Wave/Z wave2=wave2
1536//
1537//      if(WaveExists(wave0))
1538//              MultiThread wave0=0
1539//      endif
1540//      if(WaveExists(wave1))
1541//              MultiThread wave1=0
1542//      endif
1543//      if(WaveExists(wave2))
1544//              MultiThread wave2=0
1545//      endif
1546
1547#if (exists("EventLoadWave")==4)
1548        if(removeBadEvents)
1549                EventLoadWave/R/N=EventWave filepathstr
1550        else
1551                EventLoadWave/N=EventWave  filepathstr
1552        endif
1553#endif
1554
1555        Print "XOP files loaded = ",S_waveNames
1556
1557////            -- copy the waves over to xLoc,yLoc,timePt
1558        Wave/Z EventWave0=EventWave0
1559        Wave/Z EventWave1=EventWave1
1560        Wave/Z EventWave2=EventWave2
1561       
1562       
1563        Duplicate/O EventWave0,xLoc
1564        KillWaves/Z EventWave0
1565
1566        Duplicate/O EventWave1,yLoc
1567        KillWaves/Z EventWave1
1568
1569        Duplicate/O EventWave2,timePt
1570        KillWaves/Z EventWave2
1571
1572// could do this, but rescaled time will neeed to be converted to SP (or DP)
1573// and Igor loader was written with Make generating SP/DP waves
1574        // /I/U is unsigned 32-bit integer (for the time)
1575        // /B/U is unsigned 8-bit integer (max val=255) for the x and y values
1576       
1577//      Redimension/B/U xLoc,yLoc
1578//      Redimension/I/U timePt
1579
1580        // access the variables from the XOP
1581        numT0 = V_numT0
1582        numPP = V_numPP
1583        num0 = V_num0
1584        num1 = V_num1
1585        num2 = V_num2
1586        num3 = V_num3
1587        numXYevents = V_nXYevents
1588        numZero = V_numZero
1589        numBad = V_numBad
1590        numRemoved = V_numRemoved
1591       
1592        Print "(XOP) numT0 = ",numT0   
1593        Print "num0 = ",num0   
1594        Print "num1 = ",num1   
1595        Print "num2 = ",num2   
1596        Print "num3 = ",num3   
1597       
1598
1599// dispStr will be displayed on the panel
1600        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
1601       
1602        sprintf tmpStr, "%s: %d total bytes\r",fileStr,totBytes
1603        dispStr = tmpStr
1604        sprintf tmpStr,"numXYevents = %d\r",numXYevents
1605        dispStr += tmpStr
1606        sprintf tmpStr,"PP = %d  :  ",numPP
1607        dispStr += tmpStr
1608        sprintf tmpStr,"ZeroData = %d\r",numZero
1609        dispStr += tmpStr
1610        sprintf tmpStr,"Rollover = %d",num3
1611        dispStr += tmpStr
1612
1613        toc()
1614       
1615        Print "Events removed (XOP) = ",numRemoved
1616       
1617        sPrintf tmpStr,"\rBad Rollover Events = %d (%g %% of events)",numBad,numBad/numXYevents*100
1618        dispStr += tmpStr
1619        sPrintf tmpStr,"\rTotal Events Removed = %d (%g %% of events)",numRemoved,numRemoved/numXYevents*100
1620        dispStr += tmpStr
1621
1622        SetDataFolder root:
1623       
1624        return(0)
1625       
1626End
1627
1628//////////////
1629
1630Proc BinEventBarGraph()
1631       
1632        DoWindow/F EventBarGraph
1633        if(V_flag == 0)
1634                PauseUpdate; Silent 1           // building window...
1635                String fldrSav0= GetDataFolder(1)
1636                SetDataFolder root:Packages:NIST:Event:
1637                Display /W=(110,705,610,1132)/N=EventBarGraph /K=1 binCount vs binEndTime
1638                SetDataFolder fldrSav0
1639                ModifyGraph mode=5
1640                ModifyGraph marker=19
1641                ModifyGraph lSize=2
1642                ModifyGraph rgb=(0,0,0)
1643                ModifyGraph msize=2
1644                ModifyGraph hbFill=2
1645                ModifyGraph gaps=0
1646                ModifyGraph usePlusRGB=1
1647                ModifyGraph toMode=1
1648                ModifyGraph useBarStrokeRGB=1
1649                ModifyGraph standoff=0
1650                SetAxis left 0,*
1651                Label bottom "\\Z14Time (seconds)"
1652                Label left "\\Z14Number of Events"
1653        endif
1654End
1655
1656
1657Proc ShowBinTable() : Table
1658
1659        DoWindow/F BinEventTable
1660        if(V_flag == 0)
1661                PauseUpdate; Silent 1           // building window...
1662                String fldrSav0= GetDataFolder(1)
1663                SetDataFolder root:Packages:NIST:Event:
1664                Edit/W=(498,699,1003,955) /K=1/N=BinEventTable binCount,binEndTime,timeWidth
1665                ModifyTable format(Point)=1,sigDigits(binEndTime)=8,width(binEndTime)=100
1666                SetDataFolder fldrSav0
1667        endif
1668EndMacro
1669
1670
1671// only show the first 1500 data points
1672//
1673Proc ShowRescaledTimeGraph() : Graph
1674
1675        DoWindow/F RescaledTimeGraph
1676        if(V_flag == 0)
1677                PauseUpdate; Silent 1           // building window...
1678                String fldrSav0= GetDataFolder(1)
1679                SetDataFolder root:Packages:NIST:Event:
1680                Display /W=(25,44,486,356)/K=1/N=RescaledTimeGraph rescaledTime
1681                SetDataFolder fldrSav0
1682                ModifyGraph mode=4
1683                ModifyGraph marker=19
1684                ModifyGraph rgb(rescaledTime)=(0,0,0)
1685                ModifyGraph msize=1
1686//              SetAxis/A=2 left                        //only autoscale the visible data (based on the bottom limits)
1687                SetAxis bottom 0,1500
1688                ErrorBars rescaledTime OFF
1689                Label left "\\Z14Time (seconds)"
1690                Label bottom "\\Z14Event number"
1691                ShowInfo
1692        endif
1693       
1694EndMacro
1695
1696
1697
1698Proc ExportSlicesAsVAX(firstNum,prefix)
1699        Variable firstNum=1
1700        String prefix="SAMPL"
1701
1702        SaveSlicesAsVAX(firstNum,prefix[0,4])           //make sure that the prefix is 5 chars
1703End
1704
1705//////// procedures to be able to export the slices as RAW VAX files.
1706//
1707// 1- load the raw data file to use the header (it must already be in RAW)
1708// 1.5- copy the raw data to the temp folder (STO)
1709// 1.7- ask for the prefix and starting run number (these are passed in)
1710// 2- copy the slice of data to the temp folder (STO)
1711// 3- touch up the time/counts in the slice header values in STO
1712// 4- write out the VAX file
1713// 5- repeat (2-4) for the number of slices
1714//
1715//
1716Function SaveSlicesAsVAX(firstNum,prefix)
1717        Variable firstNum
1718        String prefix
1719
1720        DoAlert 1,"Is the full data file loaded as a RAW data file? If not, load it and start over..."
1721        if(V_flag == 2)
1722                return (0)
1723        endif
1724       
1725// copy the contents of RAW to STO so I can work from there
1726        CopyWorkContents("RAW","STO")
1727
1728        // now declare all of the waves, now that they are sure to be there
1729
1730        WAVE slicedData=root:Packages:NIST:Event:slicedData
1731        Make/O/D/N=(128,128) curSlice
1732       
1733        NVAR nslices = root:Packages:NIST:gEvent_nslices
1734        WAVE binEndTime = root:Packages:NIST:Event:binEndTime
1735
1736        Wave rw=root:Packages:NIST:STO:realsRead
1737        Wave iw=root:Packages:NIST:STO:integersRead
1738        Wave/T tw=root:Packages:NIST:STO:textRead
1739        Wave data=root:Packages:NIST:STO:data
1740        Wave linear_data=root:Packages:NIST:STO:linear_data
1741       
1742       
1743        Wave rw_raw=root:Packages:NIST:RAW:realsRead
1744        Wave iw_raw=root:Packages:NIST:RAW:integersRead
1745        Wave/T tw_raw=root:Packages:NIST:RAW:textRead
1746
1747// for generating the alphanumeric
1748        String timeStr= secs2date(datetime,-1)
1749        String monthStr=StringFromList(1, timeStr  ,"/")
1750        String numStr="",labelStr
1751
1752        Variable ii,err,binFraction
1753       
1754        for(ii=0;ii<nslices;ii+=1)
1755
1756                //get the current slice and put it in the STO folder
1757                curSlice = slicedData[p][q][ii]
1758                data = curSlice
1759                linear_data = curSlice
1760               
1761                // touch up the header as needed
1762                // count time = iw[2]
1763                // monCt = rw[0]
1764                // detCt = rw[2]
1765                //tw[0] must now be the file name
1766                //
1767                // count time = fraction of total binning * total count time
1768                binFraction = (binEndTime[ii+1]-binEndTime[ii])/(binEndTime[nslices]-binEndTime[0])
1769               
1770                iw[2] = trunc(binFraction*iw_raw[2])
1771                rw[0] = trunc(binFraction*rw_raw[0])
1772                rw[2] = sum(curSlice,-inf,inf)          //total counts in slice
1773       
1774                if(firstNum<10)
1775                        numStr = "00"+num2str(firstNum)
1776                else
1777                        if(firstNum<100)
1778                                numStr = "0"+num2str(firstNum)
1779                        else
1780                                numStr = num2str(firstNum)
1781                        Endif
1782                Endif   
1783                tw[0] = prefix+numstr+".SA2_EVE_"+(num2char(str2num(monthStr)+64))+numStr
1784                labelStr = tw_raw[6]
1785               
1786                labelStr = PadString(labelStr,60,0x20)  //60 fortran-style spaces
1787                tw[6] = labelStr[0,59]
1788               
1789                //write out the file - this uses the tw[0] and home path
1790                Write_VAXRaw_Data("STO","",0)
1791
1792                //increment the run number, alpha
1793                firstNum += 1   
1794        endfor
1795
1796        return(0)
1797End
1798
1799
1800
1801
1802
1803/////////////
1804//The histogramming
1805//
1806// 6 AUG 2012
1807//
1808// from Igor Exchange, RGerkin
1809//  http://www.igorexchange.com/node/1373
1810// -- see the related thread on the mailing list
1811//
1812//Function Setup_JointHistogram()
1813//
1814////    tic()
1815//
1816//      make/D /o/n=1000000 data1=gnoise(1), data2=gnoise(1)
1817//      make/D /o/n=(25,25) myHist
1818//      setscale x,-3,3,myHist
1819//      setscale y,-3,3,myHist
1820//      IndexForHistogram(data1,data2,myhist)
1821//      Wave index=SavedIndex
1822//      JointHistogram(data1,data2,myHist,index)
1823//      NewImage myHist
1824//     
1825////    toc()
1826//     
1827//End
1828
1829
1830Function JointHistogram(w0,w1,hist,index)
1831        wave w0,w1,hist,index
1832 
1833        variable bins0=dimsize(hist,0)
1834        variable bins1=dimsize(hist,1)
1835        variable n=numpnts(w0)
1836        variable left0=dimoffset(hist,0)
1837        variable left1=dimoffset(hist,1)
1838        variable right0=left0+bins0*dimdelta(hist,0)
1839        variable right1=left1+bins1*dimdelta(hist,1)
1840       
1841        // Compute the histogram and redimension it. 
1842        histogram /b={0,1,bins0*bins1} index,hist
1843        redimension/D /n=(bins0,bins1) hist // Redimension to 2D. 
1844        setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
1845        setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
1846End
1847
1848
1849// histogram with a point range
1850//
1851// x- just need to send x2pnt or findLevel, or something similar to define the POINT
1852// values
1853//
1854// x- can also speed this up since the index only needs to be done once, so the
1855// histogram operation can be done separately, as the bins require
1856//
1857//
1858Function JointHistogramWithRange(w0,w1,hist,index,pt1,pt2)
1859        wave w0,w1,hist,index
1860        Variable pt1,pt2
1861 
1862        variable bins0=dimsize(hist,0)
1863        variable bins1=dimsize(hist,1)
1864        variable n=numpnts(w0)
1865        variable left0=dimoffset(hist,0)
1866        variable left1=dimoffset(hist,1)
1867        variable right0=left0+bins0*dimdelta(hist,0)
1868        variable right1=left1+bins1*dimdelta(hist,1)
1869
1870        // Compute the histogram and redimension it. 
1871        histogram /b={0,1,bins0*bins1}/R=[pt1,pt2] index,hist
1872        redimension/D /n=(bins0,bins1) hist // Redimension to 2D. 
1873        setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
1874        setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
1875End
1876
1877
1878// just does the indexing, creates wave SavedIndex in the current folder for the index
1879//
1880Function IndexForHistogram(w0,w1,hist)
1881        wave w0,w1,hist
1882 
1883        variable bins0=dimsize(hist,0)
1884        variable bins1=dimsize(hist,1)
1885        variable n=numpnts(w0)
1886        variable left0=dimoffset(hist,0)
1887        variable left1=dimoffset(hist,1)
1888        variable right0=left0+bins0*dimdelta(hist,0)
1889        variable right1=left1+bins1*dimdelta(hist,1)
1890 
1891        // Scale between 0 and the number of bins to create an index wave. 
1892        if(ThreadProcessorCount<4) // For older machines, matrixop is faster. 
1893                matrixop /free idx=round(bins0*(w0-left0)/(right0-left0))+bins0*round(bins1*(w1-left1)/(right1-left1))
1894        else // For newer machines with many cores, multithreading with make is faster. 
1895                make/free/n=(n) idx
1896                multithread idx=round(bins0*(w0-left0)/(right0-left0))+bins0*round(bins1*(w1-left1)/(right1-left1))
1897        endif
1898 
1899        KillWaves/Z SavedIndex
1900        MoveWave idx,SavedIndex
1901       
1902//      // Compute the histogram and redimension it. 
1903//      histogram /b={0,1,bins0*bins1} idx,hist
1904//      redimension /n=(bins0,bins1) hist // Redimension to 2D. 
1905//      setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
1906//      setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
1907End
1908
1909
1910
1911
1912
1913////////////// Post-processing of the event mode data
1914Proc ShowEventCorrectionPanel()
1915        DoWindow/F EventCorrectionPanel
1916        if(V_flag ==0)
1917                EventCorrectionPanel()
1918        EndIf
1919End
1920
1921Proc EventCorrectionPanel()
1922
1923        PauseUpdate; Silent 1           // building window...
1924        SetDataFolder root:Packages:NIST:Event:
1925       
1926        Display /W=(35,44,761,533)/K=2 rescaledTime
1927        DoWindow/C EventCorrectionPanel
1928        ModifyGraph mode=4
1929        ModifyGraph marker=19
1930        ModifyGraph rgb=(0,0,0)
1931        ModifyGraph msize=1
1932        ErrorBars rescaledTime OFF
1933        Label left "\\Z14Time (seconds)"
1934        Label bottom "\\Z14Event number"       
1935        SetAxis bottom 0,0.10*numpnts(rescaledTime)             //show 1st 10% of data for speed in displaying
1936       
1937        ControlBar 100
1938        Button button0,pos={18,12},size={70,20},proc=EC_AddCursorButtonProc,title="Cursors"
1939        Button button1,pos={153,11},size={80,20},proc=EC_AddTimeButtonProc,title="Add time"
1940        Button button2,pos={153,37},size={80,20},proc=EC_SubtractTimeButtonProc,title="Subtr time"
1941        Button button3,pos={153,64},size={90,20},proc=EC_TrimPointsButtonProc,title="Trim points"
1942        Button button4,pos={295,12},size={90,20},proc=EC_SaveWavesButtonProc,title="Save Waves"
1943        Button button5,pos={294,38},size={100,20},proc=EC_ImportWavesButtonProc,title="Import Waves"
1944        Button button6,pos={18,39},size={80,20},proc=EC_ShowAllButtonProc,title="All Data"
1945        Button button7,pos={683,9},size={30,20},proc=EC_HelpButtonProc,title="?"
1946        Button button8,pos={658,72},size={60,20},proc=EC_DoneButtonProc,title="Done"
1947       
1948        SetDataFolder root:
1949       
1950EndMacro
1951
1952Function EC_AddCursorButtonProc(ba) : ButtonControl
1953        STRUCT WMButtonAction &ba
1954
1955        switch( ba.eventCode )
1956                case 2: // mouse up
1957                        // click code here
1958                        SetDataFolder root:Packages:NIST:Event:
1959                       
1960                        Wave rescaledTime = rescaledTime
1961                        Cursor/P A rescaledTime 0
1962                        Cursor/P B rescaledTime numpnts(rescaledTime)-1
1963                        ShowInfo
1964                        SetDataFolder root:
1965                        break
1966                case -1: // control being killed
1967                        break
1968        endswitch
1969
1970        return 0
1971End
1972
1973Function EC_AddTimeButtonProc(ba) : ButtonControl
1974        STRUCT WMButtonAction &ba
1975
1976        switch( ba.eventCode )
1977                case 2: // mouse up
1978                        // click code here
1979                        SetDataFolder root:Packages:NIST:Event:
1980                       
1981                        Wave rescaledTime = rescaledTime
1982                        Wave timePt = timePt
1983                        Variable rollTime,rollTicks,ptA,ptB,lo,hi
1984                       
1985                        rollTicks = 2^26                                // in ticks
1986                        rollTime = 2^26*1e-7            // in seconds
1987                        ptA = pcsr(A)
1988                        ptB = pcsr(B)
1989                        lo=min(ptA,ptB)
1990                        hi=max(ptA,ptB)
1991
1992                        MultiThread timePt[lo,hi] += rollTicks
1993                        MultiThread rescaledTime[lo,hi] += rollTime
1994
1995                       
1996                        SetDataFolder root:
1997                        break
1998                case -1: // control being killed
1999                        break
2000        endswitch
2001
2002        return 0
2003End
2004
2005Function EC_SubtractTimeButtonProc(ba) : ButtonControl
2006        STRUCT WMButtonAction &ba
2007
2008        switch( ba.eventCode )
2009                case 2: // mouse up
2010                        // click code here
2011                        SetDataFolder root:Packages:NIST:Event:
2012                       
2013                        Wave rescaledTime = rescaledTime
2014                        Wave timePt = timePt
2015                        Variable rollTime,rollTicks,ptA,ptB,lo,hi
2016                       
2017                        rollTicks = 2^26                                // in ticks
2018                        rollTime = 2^26*1e-7            // in seconds
2019                        ptA = pcsr(A)
2020                        ptB = pcsr(B)
2021                        lo=min(ptA,ptB)
2022                        hi=max(ptA,ptB)
2023                       
2024                        MultiThread timePt[lo,hi] -= rollTicks
2025                        MultiThread rescaledTime[lo,hi] -= rollTime
2026
2027                        SetDataFolder root:
2028                       
2029                        break
2030                case -1: // control being killed
2031                        break
2032        endswitch
2033
2034        return 0
2035End
2036
2037// points removed are inclusive
2038//
2039// put both cursors on the same point to remove just that single point
2040//
2041Function EC_TrimPointsButtonProc(ba) : ButtonControl
2042        STRUCT WMButtonAction &ba
2043
2044        switch( ba.eventCode )
2045                case 2: // mouse up
2046                        // click code here
2047                        SetDataFolder root:Packages:NIST:Event:
2048                       
2049                        Wave rescaledTime = rescaledTime
2050                        Wave timePt = timePt
2051                        Wave xLoc = xLoc
2052                        Wave yLoc = yLoc
2053                        Variable rollTime,ptA,ptB,numElements,lo,hi
2054                       
2055                        rollTime = 2^26*1e-7            // in seconds
2056                        ptA = pcsr(A)
2057                        ptB = pcsr(B)
2058                        lo=min(ptA,ptB)
2059                        hi=max(ptA,ptB)                 
2060                        numElements = abs(ptA-ptB)+1                    //so points removed are inclusive
2061                        DeletePoints lo, numElements, rescaledTime,timePt,xLoc,yLoc
2062                       
2063                        printf "Points %g to %g have been deleted in rescaledTime, timePt, xLoc, and yLoc\r",ptA,ptB
2064                        SetDataFolder root:
2065                       
2066                        break
2067                case -1: // control being killed
2068                        break
2069        endswitch
2070
2071        return 0
2072End
2073
2074// un-sort the data first, then save it
2075Function EC_SaveWavesButtonProc(ba) : ButtonControl
2076        STRUCT WMButtonAction &ba
2077
2078        switch( ba.eventCode )
2079                case 2: // mouse up
2080                        // click code here
2081                       
2082//                      Execute "UndoTheSorting()"
2083                       
2084                        SetDataFolder root:Packages:NIST:Event:
2085                       
2086                        Wave rescaledTime = rescaledTime
2087                        Wave timePt = timePt
2088                        Wave xLoc = xLoc
2089                        Wave yLoc = yLoc
2090                        Save/T xLoc,yLoc,timePt                 //will ask for a name
2091                       
2092                        SetDataFolder root:
2093                        break
2094                case -1: // control being killed
2095                        break
2096        endswitch
2097
2098        return 0
2099End
2100
2101// this duplicates all of the bits that would be done if the "load" button was pressed
2102//
2103//
2104Function EC_ImportWavesButtonProc(ba) : ButtonControl
2105        STRUCT WMButtonAction &ba
2106
2107        switch( ba.eventCode )
2108                case 2: // mouse up
2109                        // click code here
2110                        SetDataFolder root:Packages:NIST:Event:
2111
2112                        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
2113                        SVAR dispStr = root:Packages:NIST:gEventDisplayString
2114                        String tmpStr="",fileStr,filePathStr
2115                       
2116                        // load in the waves, saved as Igor text to preserve the data type
2117                        LoadWave/T/O
2118                        filePathStr = S_fileName
2119                        if(strlen(S_fileName) == 0)
2120                                //user cancelled
2121                                DoAlert 0,"No file selected, nothing done."
2122                                return(0)
2123                        endif
2124                       
2125                        NVAR mode = root:Packages:NIST:gEvent_Mode                              // ==0 for "stream", ==1 for Oscillatory
2126                        // clear out the old sort index, if present, since new data is being loaded
2127                        KillWaves/Z OscSortIndex
2128                        Wave timePt=timePt
2129
2130                        Duplicate/O timePt rescaledTime
2131                        if(mode==0)
2132                                rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
2133                        else
2134                                rescaledTime = timePt*1e-7                                              //just take the times as-is
2135                        endif
2136                       
2137                        t_longest = waveMax(rescaledTime)               //should be the last point
2138                       
2139       
2140                        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
2141                        sprintf tmpStr, "%s: a user-modified event file\r",fileStr
2142                        dispStr = tmpStr
2143       
2144                        break
2145                case -1: // control being killed
2146                        break
2147        endswitch
2148
2149        return 0
2150End
2151
2152
2153Function EC_ShowAllButtonProc(ba) : ButtonControl
2154        STRUCT WMButtonAction &ba
2155
2156        switch( ba.eventCode )
2157                case 2: // mouse up
2158                        // click code here
2159                        SetAxis/A
2160                        break
2161                case -1: // control being killed
2162                        break
2163        endswitch
2164
2165        return 0
2166End
2167
2168Function EC_HelpButtonProc(ba) : ButtonControl
2169        STRUCT WMButtonAction &ba
2170
2171        switch( ba.eventCode )
2172                case 2: // mouse up
2173                        // click code here
2174                        DoAlert 0,"The Event Correction help file has not been written yet"
2175                        break
2176                case -1: // control being killed
2177                        break
2178        endswitch
2179
2180        return 0
2181End
2182
2183Function EC_DoneButtonProc(ba) : ButtonControl
2184        STRUCT WMButtonAction &ba
2185
2186        switch( ba.eventCode )
2187                case 2: // mouse up
2188                        // click code here
2189                        DoWindow/K EventCorrectionPanel
2190                        break
2191                case -1: // control being killed
2192                        break
2193        endswitch
2194
2195        return 0
2196End
2197
2198
2199
2200
2201//////////////   Custom Bins  /////////////////////
2202//
2203//
2204//
2205// make sure that the bins are defined and the waves exist before
2206// trying to draw the panel
2207//
2208Proc Show_CustomBinPanel()
2209        DoWindow/F CustomBinPanel
2210        if(V_flag ==0)
2211                Init_CustomBins()
2212                CustomBinPanel()
2213        EndIf
2214End
2215
2216
2217Function Init_CustomBins()
2218
2219        NVAR nSlice = root:Packages:NIST:gEvent_nslices
2220        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
2221
2222        Variable/G root:Packages:NIST:gEvent_ForceTmaxBin=1             //==1 to enforce t_longest in user-defined custom bins
2223
2224        SetDataFolder root:Packages:NIST:Event:
2225               
2226        Make/O/D/N=(nSlice) timeWidth
2227        Make/O/D/N=(nSlice+1) binEndTime,binCount
2228       
2229        timeWidth = t_longest/nslice
2230        binEndTime = p
2231        binCount = p+1 
2232       
2233        SetDataFolder root:
2234       
2235        return(0)
2236End
2237
2238////////////////       
2239//
2240// Allow custom definitions of the bin widths
2241//
2242// Define by the number of bins, and the time width of each bin
2243//
2244// This shares the number of slices and the maximum time with the main panel
2245//
2246Proc CustomBinPanel()
2247        PauseUpdate; Silent 1           // building window...
2248        NewPanel /W=(130,44,851,455)/K=2 /N=CustomBinPanel
2249        DoWindow/C CustomBinPanel
2250        ModifyPanel fixedSize=1//,noEdit =1
2251        SetDrawLayer UserBack
2252       
2253        Button button0,pos={654,42}, size={50,20},title="Done",fSize=12
2254        Button button0,proc=CB_Done_Proc
2255        Button button1,pos={663,14},size={40,20},proc=CB_HelpButtonProc,title="?"
2256        Button button2,pos={216,42},size={80,20},title="Update",proc=CB_UpdateWavesButton       
2257        SetVariable setvar1,pos={23,13},size={160,20},title="Number of slices",fSize=12
2258        SetVariable setvar1,proc=CB_NumSlicesSetVarProc,value=root:Packages:NIST:gEvent_nslices
2259        SetVariable setvar2,pos={24,44},size={160,20},title="Max Time (s)",fSize=12
2260        SetVariable setvar2,value=root:Packages:NIST:gEvent_t_longest   
2261
2262        CheckBox chkbox1,pos={216,14},title="Enforce Max Time?"
2263        CheckBox chkbox1,variable = root:Packages:NIST:gEvent_ForceTmaxBin
2264        Button button3,pos={500,14},size={90,20},proc=CB_SaveBinsButtonProc,title="Save Bins"
2265        Button button4,pos={500,42},size={100,20},proc=CB_ImportBinsButtonProc,title="Import Bins"     
2266               
2267        SetDataFolder root:Packages:NIST:Event:
2268
2269        Display/W=(291,86,706,395)/HOST=CustomBinPanel/N=BarGraph binCount vs binEndTime
2270        ModifyGraph mode=5
2271        ModifyGraph marker=19
2272        ModifyGraph lSize=2
2273        ModifyGraph rgb=(0,0,0)
2274        ModifyGraph msize=2
2275        ModifyGraph hbFill=2
2276        ModifyGraph gaps=0
2277        ModifyGraph usePlusRGB=1
2278        ModifyGraph toMode=1
2279        ModifyGraph useBarStrokeRGB=1
2280        ModifyGraph standoff=0
2281        SetAxis left 0,*
2282        Label bottom "\\Z14Time (seconds)"
2283        Label left "\\Z14Number of Events"
2284        SetActiveSubwindow ##
2285       
2286        // and the table
2287        Edit/W=(13,87,280,394)/HOST=CustomBinPanel/N=T0
2288        AppendToTable/W=CustomBinPanel#T0 timeWidth,binEndTime
2289        ModifyTable width(Point)=40
2290        SetActiveSubwindow ##
2291       
2292        SetDataFolder root:
2293       
2294EndMacro
2295
2296// save the bins - use Igor Text format
2297//
2298Function CB_SaveBinsButtonProc(ba) : ButtonControl
2299        STRUCT WMButtonAction &ba
2300
2301        switch( ba.eventCode )
2302                case 2: // mouse up
2303                        // click code here
2304
2305                        SetDataFolder root:Packages:NIST:Event:
2306
2307                        Wave timeWidth = timeWidth
2308                        Wave binEndTime = binEndTime
2309                       
2310                        Save/T timeWidth,binEndTime                     //will ask for a name
2311
2312                        break
2313                case -1: // control being killed
2314                        break
2315        endswitch
2316
2317        SetDataFolder root:
2318       
2319        return 0
2320End
2321
2322// Import the bins - use Igor Text format
2323//
2324// -- be sure that the number of bins is reset
2325// -?- how about the t_longest? - this should be set by the load, not here
2326//
2327// -- loads in timeWidth and binEndTime
2328//
2329Function CB_ImportBinsButtonProc(ba) : ButtonControl
2330        STRUCT WMButtonAction &ba
2331
2332        switch( ba.eventCode )
2333                case 2: // mouse up
2334                        // click code here
2335                        NVAR nSlice = root:Packages:NIST:gEvent_nslices
2336
2337                        SetDataFolder root:Packages:NIST:Event:
2338
2339                        // prompt for the load of data
2340                        LoadWave/T/O
2341                        if(strlen(S_fileName) == 0)
2342                                //user cancelled
2343                                DoAlert 0,"No file selected, nothing done."
2344                                return(0)
2345                        endif
2346
2347                        Wave timeWidth = timeWidth
2348                        nSlice = numpnts(timeWidth)
2349                       
2350                        break
2351                case -1: // control being killed
2352                        break
2353        endswitch
2354
2355        SetDataFolder root:
2356       
2357        return 0
2358End
2359
2360
2361
2362//
2363// can either use the widths as stated -- then the end time may not
2364// match the actual end time of the data set
2365//
2366// -- or --
2367//
2368// enforce the end time of the data set to be the end time of the bins,
2369// then the last bin width must be reset to force the constraint
2370//
2371//
2372Function CB_UpdateWavesButton(ba) : ButtonControl
2373        STRUCT WMButtonAction &ba
2374
2375        switch( ba.eventCode )
2376                case 2: // mouse up
2377                        // click code here
2378                        NVAR nSlice = root:Packages:NIST:gEvent_nslices
2379                        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
2380                        NVAR enforceTmax = root:Packages:NIST:gEvent_ForceTmaxBin
2381                       
2382                        // update the waves, and recalculate everything for the display
2383                        SetDataFolder root:Packages:NIST:Event:
2384
2385                        Wave timeWidth = timeWidth
2386                        Wave binEndTime = binEndTime
2387                        Wave binCount = binCount
2388                       
2389                        // use the widths as entered
2390                        binEndTime[0] = 0
2391                        binEndTime[1,] = binEndTime[p-1] + timeWidth[p-1]
2392                       
2393                        // enforce the longest time as the end bin time
2394                        // note that this changes the last time width
2395                        if(enforceTmax)
2396                                binEndTime[nSlice] = t_longest
2397                                timeWidth[nSlice-1] = t_longest - binEndTime[nSlice-1]
2398                        endif
2399                       
2400                        binCount = p+1
2401                        binCount[nSlice] = 0            // last point is zero, just for display
2402//                      binCount *= sign(timeWidth)             //to alert to negative time bins
2403                       
2404                        // make the timeWidth bold and red if the widths are negative
2405                        WaveStats/Q timeWidth
2406                        if(V_min < 0)
2407                                ModifyTable/W=CustomBinPanel#T0 style(timeWidth)=1,rgb(timeWidth)=(65535,0,0)                   
2408                        else
2409                                ModifyTable/W=CustomBinPanel#T0 style(timeWidth)=0,rgb(timeWidth)=(0,0,0)                       
2410                        endif
2411                       
2412                        break
2413                case -1: // control being killed
2414                        break
2415        endswitch
2416
2417        SetDataFolder root:
2418       
2419        return 0
2420End
2421
2422Function CB_HelpButtonProc(ba) : ButtonControl
2423        STRUCT WMButtonAction &ba
2424
2425        switch( ba.eventCode )
2426                case 2: // mouse up
2427                        // click code here
2428                        DoAlert 0,"The help file for the bin editor has not been written yet"
2429                        break
2430                case -1: // control being killed
2431                        break
2432        endswitch
2433
2434        return 0
2435End
2436
2437Function CB_Done_Proc(ba) : ButtonControl
2438        STRUCT WMButtonAction &ba
2439       
2440        String win = ba.win
2441        switch (ba.eventCode)
2442                case 2:
2443                        DoWindow/K CustomBinPanel
2444                        break
2445        endswitch
2446        return(0)
2447End
2448
2449
2450Function CB_NumSlicesSetVarProc(sva) : SetVariableControl
2451        STRUCT WMSetVariableAction &sva
2452
2453        switch( sva.eventCode )
2454                case 1: // mouse up
2455                case 2: // Enter key
2456                case 3: // Live update
2457                        Variable dval = sva.dval
2458                        String sval = sva.sval
2459                        SetDataFolder root:Packages:NIST:Event:
2460
2461                        Wave timeWidth = timeWidth
2462                        Wave binEndTime = binEndTime
2463                       
2464                        Redimension/N=(dval) timeWidth
2465                        Redimension/N=(dval+1) binEndTime,binCount
2466                       
2467                        SetDataFolder root:
2468                       
2469                        break
2470                case -1: // control being killed
2471                        break
2472        endswitch
2473
2474        return 0
2475End
2476
2477
2478///////////////////
2479//
2480// utility to split a large file
2481// 100 MB is the recommended size
2482// events can be clipped here, so be sure to trim the ends of the
2483// resulting files as needed.
2484//
2485// - works like the unix 'split' command
2486//
2487//
2488
2489Proc SplitBigFile(splitSize, baseStr)
2490        Variable splitSize = 100
2491        String baseStr="split"
2492        Prompt splitSize,"Target file size, in MB"
2493        Prompt baseStr,"File prefix, number will be appended"
2494       
2495        fSplitBigFile(splitSize, baseStr)
2496End
2497
2498Function fSplitBigFile(splitSize, baseStr)
2499        Variable splitSize
2500        String baseStr         
2501
2502
2503        String fileName=""              // File name, partial path, full path or "" for dialog.
2504        String pathName=""
2505        Variable refNum
2506        String str
2507
2508        Variable readSize=1e6           //1 MB
2509        Make/O/B/U/N=(readSize) aBlob                   //1MB worth
2510        Variable numSplit
2511        Variable num,ii,jj,outRef,frac
2512        String thePath
2513       
2514        Printf "SplitSize = %u MB\r",splitSize
2515        splitSize = trunc(splitSize) * 1e6              // now in bytes
2516       
2517       
2518        // Open file for read.
2519        Open/R/Z=2/F="????"/P=$pathName refNum as fileName
2520        thePath = ParseFilePath(1, fileName, ":", 1, 0)
2521       
2522        // Store results from Open in a safe place.
2523        Variable err = V_flag
2524        String fullPath = S_fileName
2525
2526        if (err == -1)
2527                Print "cancelled by user."
2528                return -1
2529        endif
2530
2531        FStatus refNum
2532       
2533        Printf "total # bytes = %u\r",V_logEOF
2534
2535        numSplit=0
2536        if(V_logEOF > splitSize)
2537                numSplit = trunc(V_logEOF/splitSize)
2538        endif
2539
2540        frac = V_logEOF - numSplit*splitSize
2541        Print "numSplit = ",numSplit
2542        Printf "frac = %u\r",frac
2543       
2544        num=0
2545        if(frac > readSize)
2546                num = trunc(frac/readSize)
2547        endif
2548
2549       
2550        frac = frac - num*readSize
2551
2552        Print "num = ",num
2553        Printf "frac = %u\r",frac
2554       
2555        baseStr = "split"
2556       
2557        for(ii=0;ii<numSplit;ii+=1)
2558                Open outRef as (thePath+baseStr+num2str(ii))
2559
2560                for(jj=0;jj<(splitSize/readSize);jj+=1)
2561                        FBinRead refNum,aBlob
2562                        FBinWrite outRef,aBlob
2563                endfor
2564
2565                Close outRef
2566        endfor
2567
2568        Make/O/B/U/N=(frac) leftover
2569        // ii was already incremented past the loop
2570        Open outRef as (thePath+baseStr+num2str(ii))
2571        for(jj=0;jj<num;jj+=1)
2572                FBinRead refNum,aBlob
2573                FBinWrite outRef,aBlob
2574        endfor
2575        FBinRead refNum,leftover
2576        FBinWrite outRef,leftover
2577
2578        Close outRef
2579
2580
2581        FSetPos refNum,V_logEOF
2582        Close refNum
2583       
2584       
2585        return 0
2586End
2587
2588
2589
2590//// save the sliced data, and accumulate slices
2591//
2592// need some way of ensuring that the slices match up since I' blindly adding them together.
2593//
2594//
2595//
2596//
2597// mode = 0             wipe out the old accumulated, copy slicedData to accumulatedData
2598// mode = 1             add current slicedData to accumulatedData
2599// mode = 2             copy accumulatedData to slicedData in preparation of export or display
2600// mode = 3             sing a song, dance a dance
2601//
2602Function AccumulateSlices(mode)
2603        Variable mode
2604       
2605        SetDataFolder root:Packages:NIST:Event:
2606
2607        switch(mode)   
2608                case 0:
2609                        DoAlert 0,"The current data has been copied to the accumulated set. You are now ready to add more data."
2610                        KillWaves/Z accumulatedData
2611                        Duplicate/O slicedData accumulatedData         
2612                        break
2613                case 1:
2614                        DoAlert 0,"The current data has been added to the accumulated data. You can add more data."
2615                        Wave acc=accumulatedData
2616                        Wave cur=slicedData
2617                        acc += cur
2618                        break
2619                case 2:
2620                        DoAlert 0,"The accumulated data is now the display data and is ready for display or export."
2621                        Duplicate/O accumulatedData slicedData         
2622                        break
2623                default:                       
2624                               
2625        endswitch
2626
2627        SetDataFolder root:
2628        return(0)
2629end
Note: See TracBrowser for help on using the repository browser.