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

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

Added the binning of QxQy? data to 1D as a menu option under SANSModels->2D utilities. Mostly as a consistency check for the 2D data.

Added a package loader for the Event Mode Processing to the NCNR package loader, so that it behaves like the real spaces modeling and the polarization.

Added routines that split large event files, and then allow the accumulation of the slices from each chunk as it is processed. Eliminates the need to add a large number of split files together during the reduction.

File size: 67.0 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma IgorVersion=6.22
3
4// vers 7.13e
5
6// TODO:
7//
8// -- search for TODO for unresolved issues not on this list
9//
10// -- add comments to the code as needed
11//
12// -- write the help file, and link the help buttons to the help docs
13//
14// -- examples?
15//
16// 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
98Menu "Macros"
99        "Split Large File",SplitBigFile()
100        "Accumulate First Slice",AccumulateSlices(0)
101        "Add Current Slice",AccumulateSlices(1)
102        "Display Accumulated Slices",AccumulateSlices(2)       
103End
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// Would TISANE or TOF need a different loader?
774//
775Function LoadEventLog_Button(ctrlName) : ButtonControl
776        String ctrlName
777
778        NVAR mode=root:Packages:NIST:gEvent_mode
779        Variable err=0
780       
781        if(mode == 0)
782                err = Stream_LoadEventLog("")
783                if(err == 1)
784                        return(0)               // user cancelled from file load
785                endif
786        endif
787       
788        if(mode == 1)
789                err = Osc_LoadEventLog("")
790                if(err == 1)
791                        return(0)               // user cancelled from file load
792                endif
793        endif
794
795        STRUCT WMButtonAction ba
796        ba.eventCode = 2
797        ShowEventDataButtonProc(ba)
798
799        return(0)
800End
801
802// for the mode of "one continuous exposure"
803//
804Function Stream_LoadEventLog(ctrlName)
805        String ctrlName
806       
807        Variable fileref
808
809        SVAR filename = root:Packages:NIST:gEvent_logfile
810        NVAR nslices = root:Packages:NIST:gEvent_nslices
811        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
812       
813        String fileFilters = "All Files:.*;Data Files (*.txt):.txt;"
814       
815        Open/R/D/F=fileFilters fileref
816        filename = S_filename
817        if(strlen(S_filename) == 0)
818                // user cancelled
819                DoAlert 0,"No file selected, no file loaded."
820                return(1)
821        endif
822
823#if (exists("EventLoadWave")==4)
824        LoadEvents_XOP()
825#else
826        LoadEvents()
827#endif 
828
829        SetDataFolder root:Packages:NIST:Event:
830
831tic()
832        Wave timePt=timePt
833        Wave xLoc=xLoc
834        Wave yLoc=yLoc
835        CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
836       
837toc()
838
839        Duplicate/O timePt rescaledTime
840        rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
841        t_longest = waveMax(rescaledTime)               //should be the last point
842
843        SetDataFolder root:
844
845        return(0)
846End
847
848// for the mode "oscillatory"
849//
850Function Osc_LoadEventLog(ctrlName)
851        String ctrlName
852       
853        Variable fileref
854
855        SVAR filename = root:Packages:NIST:gEvent_logfile
856        NVAR nslices = root:Packages:NIST:gEvent_nslices
857        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
858       
859        String fileFilters = "All Files:.*;Data Files (*.txt):.txt;"
860       
861        Open/R/D/F=fileFilters fileref
862        filename = S_filename
863                if(strlen(S_filename) == 0)
864                // user cancelled
865                DoAlert 0,"No file selected, no file loaded."
866                return(1)
867        endif
868       
869#if (exists("EventLoadWave")==4)
870        LoadEvents_XOP()
871#else
872        LoadEvents()
873#endif 
874       
875        SetDataFolder root:Packages:NIST:Event:
876
877        Wave timePt=timePt
878        Wave xLoc=xLoc
879        Wave yLoc=yLoc
880        CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
881       
882        Duplicate/O timePt rescaledTime
883        rescaledTime *= 1e-7                    //convert to seconds and that's all
884        t_longest = waveMax(rescaledTime)               //if oscillatory, won't be the last point, so get it this way
885
886        KillWaves/Z OscSortIndex                        //to make sure that there is no old index hanging around
887
888        SetDataFolder root:
889
890        return(0)
891End
892
893
894//
895// -- MUCH faster to count the number of lines to remove, then delete (N)
896// rather then delete them one-by-one in the do-loop
897Function CleanupTimes(xLoc,yLoc,timePt)
898        Wave xLoc,yLoc,timePt
899
900        // start at the back and remove zeros
901        Variable num=numpnts(xLoc),ii,numToRemove
902
903        numToRemove = 0
904        ii=num
905        do
906                ii -= 1
907                if(timePt[ii] == 0 && xLoc[ii] == 0 && yLoc[ii] == 0)
908                        numToRemove += 1
909                endif
910        while(timePt[ii-1] == 0 && xLoc[ii-1] == 0 && yLoc[ii-1] == 0)
911       
912        if(numToRemove != 0)
913                DeletePoints ii, numToRemove, xLoc,yLoc,timePt
914        endif
915       
916        return(0)
917End
918
919Function LogIntEvent_Proc(ctrlName,checked) : CheckBoxControl
920        String ctrlName
921        Variable checked
922               
923        SetDataFolder root:Packages:NIST:Event
924        if(checked)
925                Duplicate/O logslicedData dispsliceData
926        else
927                Duplicate/O slicedData dispsliceData
928        endif
929
930        NVAR selectedslice = root:Packages:NIST:gEvent_tsdisp
931
932        sliceSelectEvent_Proc("", selectedslice, "", "")
933
934        SetDataFolder root:
935
936End
937
938
939// TODO
940// this "fails" for data sets that have 3 or 4 slices, as the ModifyImage command
941// interprets the data as being RGB - and so does nothing.
942// need to find a way around this
943///
944// I could modify this procedure to use the log = 0|1 keyword for the log Z display
945// rather than creating a duplicate wave of log(data)
946//
947Function sliceSelectEvent_Proc(ctrlName, varNum, varStr, varName) : SetVariableControl
948        String ctrlName
949        Variable varNum
950        String varStr
951        String varName
952       
953        NVAR nslices = root:Packages:NIST:gEvent_nslices
954        NVAR selectedslice = root:Packages:NIST:gEvent_tsdisp
955       
956        if(varNum < 0)
957                selectedslice = 0
958                DoUpdate
959        elseif (varNum > nslices-1)
960                selectedslice = nslices-1
961                DoUpdate
962        else
963                ModifyImage/W=EventModePanel#Event_slicegraph ''#0 plane = varNum
964        endif
965
966End
967
968Function DifferentiatedTime()
969
970        Wave rescaledTime = root:Packages:NIST:Event:rescaledTime
971
972        SetDataFolder root:Packages:NIST:Event:
973               
974        Differentiate rescaledTime/D=rescaledTime_DIF
975//      Display rescaledTime,rescaledTime_DIF
976        DoWindow/F Differentiated_Time
977        if(V_flag == 0)
978                Display/N=Differentiated_Time/K=1 rescaledTime_DIF
979                Legend
980                Modifygraph gaps=0
981                ModifyGraph zero(left)=1
982                Label left "\\Z14Delta (dt/event)"
983                Label bottom "\\Z14Event number"
984        endif
985       
986        SetDataFolder root:
987       
988        return(0)
989End
990
991
992//
993// for the bit shifts, see the decimal-binary conversion
994// http://www.binaryconvert.com/convert_unsigned_int.html
995//
996//              K0 = 536870912
997//              Print (K0 & 0x08000000)/134217728       //bit 27 only, shift by 2^27
998//              Print (K0 & 0x10000000)/268435456               //bit 28 only, shift by 2^28
999//              Print (K0 & 0x20000000)/536870912               //bit 29 only, shift by 2^29
1000//
1001// This is duplicated by the XOP, but the Igor code allows quick access to print out
1002// all of the gorey details of the events and every little bit of them. the print
1003// statements and flags are kept for this reason, so the code is a bit messy.
1004//
1005Function LoadEvents()
1006       
1007        NVAR time_msw = root:Packages:NIST:gEvent_time_msw
1008        NVAR time_lsw = root:Packages:NIST:gEvent_time_lsw
1009        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
1010       
1011        SVAR filepathstr = root:Packages:NIST:gEvent_logfile
1012        SVAR dispStr = root:Packages:NIST:gEventDisplayString
1013       
1014        SetDataFolder root:Packages:NIST:Event
1015
1016        Variable fileref
1017        String buffer
1018        String fileStr,tmpStr
1019        Variable dataval,timeval,type,numLines,verbose,verbose3
1020        Variable xval,yval,rollBit,nRoll,roll_time,bit29,bit28,bit27
1021        Variable ii,flaggedEvent,rolloverHappened,numBad=0,tmpPP=0,tmpT0=0
1022        Variable Xmax, yMax
1023       
1024        xMax = 127              // number the detector from 0->127
1025        yMax = 127
1026       
1027        verbose3 = 0                    //prints out the rollover events (type==3)
1028        verbose = 0
1029        numLines = 0
1030
1031       
1032        // what I really need is the number of XY events
1033        Variable numXYevents,num1,num2,num3,num0,totBytes,numPP,numT0,numDL,numFF,numZero
1034        Variable numRemoved
1035        numXYevents = 0
1036        num0 = 0
1037        num1 = 0
1038        num2 = 0
1039        num3 = 0
1040        numPP = 0
1041        numT0 = 0
1042        numDL = 0
1043        numFF = 0
1044        numZero = 0
1045        numRemoved = 0
1046
1047//tic()
1048        Open/R fileref as filepathstr
1049                FStatus fileref
1050        Close fileref
1051
1052        totBytes = V_logEOF
1053        Print "total bytes = ", totBytes
1054       
1055//toc()
1056//
1057
1058
1059// do a "pre-scan to get some of the counts, so that I can allocate space. This does
1060// double the read time, but is still faster than adding points to waves as the file is read
1061//     
1062
1063        tic()
1064
1065        Open/R fileref as filepathstr
1066        do
1067                do
1068                        FReadLine fileref, buffer                       //skip the "blank" lines that have one character
1069                while(strlen(buffer) == 1)             
1070
1071                if (strlen(buffer) == 0)
1072                        break
1073                endif
1074               
1075                sscanf buffer,"%x",dataval
1076               
1077                // two most sig bits (31-30)
1078                type = (dataval & 0xC0000000)/1073741824                //right shift by 2^30
1079                               
1080                if(type == 0)
1081                        num0 += 1
1082                        numXYevents += 1
1083                endif
1084                if(type == 2)
1085                        num2 += 1
1086                        numXYevents += 1
1087                endif
1088                if(type == 1)
1089                        num1 += 1
1090                endif
1091                if(type == 3)
1092                        num3 += 1
1093                endif   
1094               
1095                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1096               
1097                if(type==0 || type==2)
1098                        numPP += round(bit29)
1099                endif
1100               
1101                if(type==1 || type==3)
1102                        numT0 += round(bit29)
1103                endif
1104               
1105                if(dataval == 0)
1106                        numZero += 1
1107                endif
1108               
1109        while(1)
1110        Close fileref
1111//              done counting the number of XY events
1112        printf("Igor pre-scan done in  ")
1113        toc()
1114       
1115
1116        Print "(Igor) numT0 = ",numT0   
1117        Print "num0 = ",num0   
1118        Print "num1 = ",num1   
1119        Print "num2 = ",num2   
1120        Print "num3 = ",num3   
1121       
1122//
1123//     
1124//      Printf "numXYevents = %d\r",numXYevents
1125//      Printf "XY = num0 = %d\r",num0
1126//      Printf "XY time = num2 = %d\r",num2
1127//      Printf "time MSW = num1 = %d\r",num1
1128//      Printf "Rollover = num3 = %d\r",num3
1129//      Printf "num0 + num2 = %d\r",num0+num2
1130
1131// dispStr will be displayed on the panel
1132        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
1133       
1134        sprintf tmpStr, "%s: %d total bytes\r",fileStr,totBytes
1135        dispStr = tmpStr
1136        sprintf tmpStr,"numXYevents = %d\r",numXYevents
1137        dispStr += tmpStr
1138        sprintf tmpStr,"PP = %d  :  ",numPP
1139        dispStr += tmpStr
1140        sprintf tmpStr,"ZeroData = %d\r",numZero
1141        dispStr += tmpStr
1142        sprintf tmpStr,"Rollover = %d",num3
1143        dispStr += tmpStr
1144
1145        // /I/U is unsigned 32-bit integer (for the time)
1146        // /B/U is unsigned 8-bit integer (max val=255) for the x and y values
1147       
1148        Make/O/U/N=(numXYevents) xLoc,yLoc
1149        Make/O/D/N=(numXYevents) timePt
1150//      Make/O/U/N=(totBytes/4) xLoc,yLoc               //too large, trim when done (bad idea)
1151//      Make/O/D/N=(totBytes/4) timePt
1152        Make/O/D/N=1000 badTimePt,badEventNum,PPTime,PPEventNum,T0Time,T0EventNum
1153        badTimePt=0
1154        badEventNum=0
1155        PPTime=0
1156        PPEventNum=0
1157        T0Time=0
1158        T0EventNum=0
1159        xLoc=0
1160        yLoc=0
1161        timePt=0
1162       
1163        nRoll = 0               //number of rollover events
1164        roll_time = 2^26                //units of 10-7 sec
1165       
1166        NVAR removeBadEvents = root:Packages:NIST:gRemoveBadEvents
1167       
1168        time_msw=0
1169       
1170        tic()
1171       
1172        ii = 0
1173       
1174        Open/R fileref as filepathstr
1175       
1176        // remove events at the beginning up to a type==2 so that the msw and lsw times are reset properly
1177        if(RemoveBadEvents == 1)
1178                do
1179                        do
1180                                FReadLine fileref, buffer                       //skip the "blank" lines that have one character
1181                        while(strlen(buffer) == 1)             
1182       
1183                        if (strlen(buffer) == 0)
1184                                break
1185                        endif
1186                       
1187                        sscanf buffer,"%x",dataval
1188                // two most sig bits (31-30)
1189                        type = (dataval & 0xC0000000)/1073741824                //right shift by 2^30
1190                       
1191                        if(type == 2)
1192                                // this is the first event with a proper time value, so process the XY-time event as ususal
1193                                // and then break to drop to the main loop, where the next event == type 1
1194                               
1195                                xval = xMax - (dataval & 255)                                           //last 8 bits (7-0)
1196                                yval = (dataval & 65280)/256                                            //bits 15-8, right shift by 2^8
1197               
1198                                time_lsw = (dataval & 536805376)/65536                  //13 bits, 28-16, right shift by 2^16
1199               
1200                                if(verbose)
1201                //                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1202                                        printf "%u : %u : %u : %u\r",dataval,timeval,xval,yval
1203                                endif
1204                               
1205                                // this is the first point, be sure that ii = 0
1206                                ii = 0
1207                                xLoc[ii] = xval
1208                                yLoc[ii] = yval
1209                               
1210                                Print "At beginning of file, numBad = ",numBad
1211                                break   // the next do loop processes the bulk of the file (** the next event == type 1 = MIR)
1212                        else
1213                                numBad += 1
1214                                numRemoved += 1
1215                        endif
1216                       
1217                        //ii+=1         don't increment the counter
1218                while(1)
1219        endif
1220       
1221        // now read the main portion of the file.
1222        do
1223                do
1224                        FReadLine fileref, buffer                       //skip the "blank" lines that have one character
1225                while(strlen(buffer) == 1)             
1226
1227                if (strlen(buffer) == 0)
1228                        break
1229                endif
1230               
1231                sscanf buffer,"%x",dataval
1232               
1233
1234//              type = (dataval & ~(2^32 - 2^30 -1))/2^30
1235
1236                // two most sig bits (31-30)
1237                type = (dataval & 0xC0000000)/1073741824                //right shift by 2^30
1238               
1239                //
1240                // The defintions of the event types
1241                //
1242                //Constant ATXY = 0
1243                //Constant ATXYM = 2
1244                //Constant ATMIR = 1
1245                //Constant ATMAR = 3
1246                //
1247                                               
1248                if(verbose > 0)
1249                        verbose -= 1
1250                endif
1251//             
1252                switch(type)
1253                        case ATXY:              // 0
1254                                if(verbose)             
1255                                        printf "XY : "         
1256                                endif
1257                               
1258                                // if the datavalue is == 0, just skip it now (it can only be interpreted as type 0, obviously)
1259                                if(dataval == 0 && RemoveBadEvents == 1)
1260                                        numRemoved += 1
1261                                        //Print "zero at ii= ",ii
1262                                        break           //don't increment ii
1263                                endif
1264                               
1265                                // if it's a pileup event, skip it now (this can be either type 0 or 2)
1266                                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1267                                if(bit29 == 1 && RemoveBadEvents == 1)
1268                                        PPTime[tmpPP] = timeval
1269                                        PPEventNum[tmpPP] = ii
1270                                        tmpPP += 1
1271                                        numRemoved += 1
1272                                        break           //don't increment ii
1273                                endif
1274                               
1275//                              xval = ~(dataval & ~(2^32 - 2^8)) & 127
1276//                              yval = ((dataval & ~(2^32 - 2^16 ))/2^8) & 127
1277//                              time_lsw = (dataval & ~(2^32 - 2^29))/2^16
1278
1279                                xval = xMax - (dataval & 255)                                           //last 8 bits (7-0)
1280                                yval = (dataval & 65280)/256                                            //bits 15-8, right shift by 2^8
1281                                time_lsw = (dataval & 536805376)/65536                  //13 bits, 28-16, right shift by 2^16
1282
1283                                timeval = trunc( nRoll*roll_time + (time_msw * (8192)) + time_lsw )             //left shift msw by 2^13, then add in lsw, as an integer
1284                                if (timeval > t_longest)
1285                                        t_longest = timeval
1286                                endif
1287                               
1288                               
1289                                // catch the "bad" events:
1290                                // if an XY event follows a rollover, time_msw is 0 by definition, but does not immediately get
1291                                // re-evalulated here. Throw out only the immediately following points where msw is still 8191
1292                                if(rolloverHappened && RemoveBadEvents == 1)
1293                                        // maybe a bad event
1294                                        if(time_msw == 8191)
1295                                                badTimePt[numBad] = timeVal
1296                                                badEventNum[numBad] = ii
1297                                                numBad +=1
1298                                                numRemoved += 1
1299                                        else
1300                                                // time_msw has been reset, points are good now, so keep this one
1301                                                xLoc[ii] = xval
1302                                                yLoc[ii] = yval
1303                                                timePt[ii] = timeval
1304                                               
1305//                                              if(xval == 127 && yval == 0)
1306//                                                      // check bit 29
1307//                                                      bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1308//                                                      Print "XY=127,0 : bit29 = ",bit29
1309//                                              endif
1310                                               
1311                                                ii+=1
1312                                                rolloverHappened = 0
1313                                        endif
1314                                else
1315                                        // normal processing of good point, keep it
1316                                        xLoc[ii] = xval
1317                                        yLoc[ii] = yval
1318                                        timePt[ii] = timeval
1319                               
1320//                                      if(xval == 127 && yval == 0)
1321//                                              // check bit 29
1322//                                              bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1323//                                              Printf "XY=127,0 : bit29 = %u : d=%u\r",bit29,dataval
1324//                                      endif
1325                                        ii+=1
1326                                endif
1327
1328
1329                                if(verbose)             
1330//                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1331                                        printf "d=%u : t=%u : msw=%u : lsw=%u : %u : %u \r",dataval,timeval,time_msw,time_lsw,xval,yval
1332                                endif                           
1333       
1334//                              verbose = 0
1335                                break
1336                        case ATXYM: // 2
1337                                if(verbose)
1338                                        printf "XYM : "
1339                                endif
1340                               
1341                                // if it's a pileup event, skip it now (this can be either type 0 or 2)
1342                                // - but can I do this if this is an XY-time event? This will lead to a wrong time, and a time
1343                                // assigned to an XY (0,0)...
1344//                              bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1345//                              if(bit29 == 1 && RemoveBadEvents == 1)
1346//                                      Print "*****Bit 29 (PP) event set for Type==2, but not handled, ii = ",ii
1347////                                    break           //don't increment ii
1348//                              endif
1349                               
1350//                              xval = ~(dataval & ~(2^32 - 2^8)) & 127
1351//                              yval = ((dataval & ~(2^32 - 2^16 ))/2^8) & 127
1352//                              time_lsw =  (dataval & ~(2^32 - 2^29 ))/2^16            //this method gives a FP result!! likely since the "^" operation gives FP result...
1353
1354                                xval = xMax - (dataval & 255)                                           //last 8 bits (7-0)
1355                                yval = (dataval & 65280)/256                                            //bits 15-8, right shift by 2^8
1356
1357                                time_lsw = (dataval & 536805376)/65536                  //13 bits, 28-16, right shift by 2^16 (result is integer)
1358
1359                                if(verbose)
1360//                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1361                                        printf "%u : %u : %u : %u\r",dataval,timeval,xval,yval
1362                                endif
1363                               
1364                                xLoc[ii] = xval
1365                                yLoc[ii] = yval
1366
1367                                // don't fill in the time yet, or increment the index ii
1368                                // the next event MUST be ATMIR with the MSW time bits
1369                                //
1370//                              verbose = 0
1371                                break
1372                        case ATMIR:  // 1
1373                                if(verbose)
1374                                        printf "MIR : "
1375                                endif
1376
1377                                time_msw =  (dataval & 536805376)/65536                 //13 bits, 28-16, right shift by 2^16
1378                                timeval = trunc( nRoll*roll_time + (time_msw * (8192)) + time_lsw )
1379                                if (timeval > t_longest)
1380                                        t_longest = timeval
1381                                endif
1382                                if(verbose)
1383//                                      printf "%u : %u : %u : %u\r",dataval,time_lsw,time_msw,timeval
1384                                        printf "d=%u : t=%u : msw=%u : lsw=%u : tlong=%u\r",dataval,timeval,time_msw,time_lsw,t_longest
1385                                endif
1386                               
1387                                // the XY position was in the previous event ATXYM
1388                                timePt[ii] = timeval
1389
1390                                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1391                                if(bit29 != 0)          // bit 29 set is a T0 event
1392                                        //Printf "bit29 = 1 at ii = %d : type = %d\r",ii,type
1393                                        T0Time[tmpT0] = timeval
1394                                        T0EventNum[tmpT0] = ii
1395                                        tmpT0 += 1
1396                                        // reset nRoll = 0 for calcluating the time
1397                                        nRoll = 0
1398                                endif
1399                                                               
1400                                ii+=1
1401//                              verbose = 0
1402                                break
1403                        case ATMAR:  // 3
1404                                if(verbose3)
1405//                                      verbose = 15
1406//                                      verbose = 2
1407                                        printf "MAR : "
1408                                endif
1409                               
1410                                // do something with the rollover event?
1411                               
1412                                // check bit 29
1413                                bit29 = (dataval & 0x20000000)/536870912                //bit 29 only , shift by 2^29
1414                                nRoll += 1
1415// not doing anything with these bits yet       
1416                                bit28 = (dataval & 0x10000000)/268435456                //bit 28 only, shift by 2^28   
1417                                bit27 = (dataval & 0x08000000)/134217728        //bit 27 only, shift by 2^27
1418
1419                                if(verbose3)
1420                                        printf "d=%u : b29=%u : b28=%u : b27=%u : #Roll=%u \r",dataval,bit29, bit28, bit27,nRoll
1421                                endif
1422                               
1423                                if(bit29 != 0)          // bit 29 set is a T0 event
1424                                        //Printf "bit29 = 1 at ii = %d : type = %d\r",ii,type
1425                                        T0Time[tmpT0] = timeval
1426                                        T0EventNum[tmpT0] = ii
1427                                        tmpT0 += 1
1428                                        // reset nRoll = 0 for calcluating the time
1429                                        nRoll = 0
1430                                endif
1431                               
1432                                rolloverHappened = 1
1433
1434                                break
1435                endswitch
1436               
1437//              if(ii<18)
1438//                      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
1439//              endif   
1440                       
1441        while(1)
1442       
1443        Close fileref
1444       
1445        printf("Igor full file read done in  ")
1446        toc()
1447       
1448        Print "Events removed (Igor) = ",numRemoved
1449       
1450        sPrintf tmpStr,"\rBad Rollover Events = %d (%g %% of events)",numBad,numBad/numXYevents*100
1451        dispStr += tmpStr
1452        sPrintf tmpStr,"\rTotal Events Removed = %d (%g %% of events)",numRemoved,numRemoved/numXYevents*100
1453        dispStr += tmpStr
1454        SetDataFolder root:
1455       
1456        return(0)
1457       
1458End
1459
1460//////////////
1461//
1462// This calls the XOP, as an operation to load the events
1463//
1464// -- it's about 35x faster than the Igor code, so I guess that's OK.
1465//
1466//
1467Function LoadEvents_XOP()
1468       
1469//      NVAR time_msw = root:Packages:NIST:gEvent_time_msw
1470//      NVAR time_lsw = root:Packages:NIST:gEvent_time_lsw
1471        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
1472       
1473        SVAR filepathstr = root:Packages:NIST:gEvent_logfile
1474        SVAR dispStr = root:Packages:NIST:gEventDisplayString
1475       
1476        SetDataFolder root:Packages:NIST:Event
1477
1478        Variable fileref
1479        String buffer
1480        String fileStr,tmpStr
1481        Variable dataval,timeval,type,numLines,verbose,verbose3
1482        Variable xval,yval,rollBit,nRoll,roll_time,bit29,bit28,bit27
1483        Variable ii,flaggedEvent,rolloverHappened,numBad=0,tmpPP=0,tmpT0=0
1484        Variable Xmax, yMax
1485       
1486        xMax = 127              // number the detector from 0->127
1487        yMax = 127
1488       
1489        numLines = 0
1490
1491       
1492        // what I really need is the number of XY events
1493        Variable numXYevents,num1,num2,num3,num0,totBytes,numPP,numT0,numDL,numFF,numZero
1494        Variable numRemoved
1495        numXYevents = 0
1496        num0 = 0
1497        num1 = 0
1498        num2 = 0
1499        num3 = 0
1500        numPP = 0
1501        numT0 = 0
1502        numDL = 0
1503        numFF = 0
1504        numZero = 0
1505        numRemoved = 0
1506
1507// get the total number of bytes in the file
1508        Open/R fileref as filepathstr
1509                FStatus fileref
1510        Close fileref
1511
1512        totBytes = V_logEOF
1513        Print "total bytes = ", totBytes
1514       
1515//
1516
1517////
1518//
1519//  use the XOP operation to load in the data
1520// -- this does everything - the pre-scan and creating the waves
1521//
1522// need to zero the waves before loading, just in case
1523//
1524
1525        NVAR removeBadEvents = root:Packages:NIST:gRemoveBadEvents
1526
1527tic()
1528
1529//      Wave/Z wave0=wave0
1530//      Wave/Z wave1=wave1
1531//      Wave/Z wave2=wave2
1532//
1533//      if(WaveExists(wave0))
1534//              MultiThread wave0=0
1535//      endif
1536//      if(WaveExists(wave1))
1537//              MultiThread wave1=0
1538//      endif
1539//      if(WaveExists(wave2))
1540//              MultiThread wave2=0
1541//      endif
1542
1543#if (exists("EventLoadWave")==4)
1544        if(removeBadEvents)
1545                EventLoadWave/R/N=EventWave filepathstr
1546        else
1547                EventLoadWave/N=EventWave  filepathstr
1548        endif
1549#endif
1550
1551        Print "XOP files loaded = ",S_waveNames
1552
1553////            -- copy the waves over to xLoc,yLoc,timePt
1554        Wave/Z EventWave0=EventWave0
1555        Wave/Z EventWave1=EventWave1
1556        Wave/Z EventWave2=EventWave2
1557       
1558       
1559        Duplicate/O EventWave0,xLoc
1560        KillWaves/Z EventWave0
1561
1562        Duplicate/O EventWave1,yLoc
1563        KillWaves/Z EventWave1
1564
1565        Duplicate/O EventWave2,timePt
1566        KillWaves/Z EventWave2
1567
1568// could do this, but rescaled time will neeed to be converted to SP (or DP)
1569// and Igor loader was written with Make generating SP/DP waves
1570        // /I/U is unsigned 32-bit integer (for the time)
1571        // /B/U is unsigned 8-bit integer (max val=255) for the x and y values
1572       
1573//      Redimension/B/U xLoc,yLoc
1574//      Redimension/I/U timePt
1575
1576        // access the variables from the XOP
1577        numT0 = V_numT0
1578        numPP = V_numPP
1579        num0 = V_num0
1580        num1 = V_num1
1581        num2 = V_num2
1582        num3 = V_num3
1583        numXYevents = V_nXYevents
1584        numZero = V_numZero
1585        numBad = V_numBad
1586        numRemoved = V_numRemoved
1587       
1588        Print "(XOP) numT0 = ",numT0   
1589        Print "num0 = ",num0   
1590        Print "num1 = ",num1   
1591        Print "num2 = ",num2   
1592        Print "num3 = ",num3   
1593       
1594
1595// dispStr will be displayed on the panel
1596        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
1597       
1598        sprintf tmpStr, "%s: %d total bytes\r",fileStr,totBytes
1599        dispStr = tmpStr
1600        sprintf tmpStr,"numXYevents = %d\r",numXYevents
1601        dispStr += tmpStr
1602        sprintf tmpStr,"PP = %d  :  ",numPP
1603        dispStr += tmpStr
1604        sprintf tmpStr,"ZeroData = %d\r",numZero
1605        dispStr += tmpStr
1606        sprintf tmpStr,"Rollover = %d",num3
1607        dispStr += tmpStr
1608
1609        toc()
1610       
1611        Print "Events removed (XOP) = ",numRemoved
1612       
1613        sPrintf tmpStr,"\rBad Rollover Events = %d (%g %% of events)",numBad,numBad/numXYevents*100
1614        dispStr += tmpStr
1615        sPrintf tmpStr,"\rTotal Events Removed = %d (%g %% of events)",numRemoved,numRemoved/numXYevents*100
1616        dispStr += tmpStr
1617
1618        SetDataFolder root:
1619       
1620        return(0)
1621       
1622End
1623
1624//////////////
1625
1626Proc BinEventBarGraph()
1627       
1628        DoWindow/F EventBarGraph
1629        if(V_flag == 0)
1630                PauseUpdate; Silent 1           // building window...
1631                String fldrSav0= GetDataFolder(1)
1632                SetDataFolder root:Packages:NIST:Event:
1633                Display /W=(110,705,610,1132)/N=EventBarGraph /K=1 binCount vs binEndTime
1634                SetDataFolder fldrSav0
1635                ModifyGraph mode=5
1636                ModifyGraph marker=19
1637                ModifyGraph lSize=2
1638                ModifyGraph rgb=(0,0,0)
1639                ModifyGraph msize=2
1640                ModifyGraph hbFill=2
1641                ModifyGraph gaps=0
1642                ModifyGraph usePlusRGB=1
1643                ModifyGraph toMode=1
1644                ModifyGraph useBarStrokeRGB=1
1645                ModifyGraph standoff=0
1646                SetAxis left 0,*
1647                Label bottom "\\Z14Time (seconds)"
1648                Label left "\\Z14Number of Events"
1649        endif
1650End
1651
1652
1653Proc ShowBinTable() : Table
1654
1655        DoWindow/F BinEventTable
1656        if(V_flag == 0)
1657                PauseUpdate; Silent 1           // building window...
1658                String fldrSav0= GetDataFolder(1)
1659                SetDataFolder root:Packages:NIST:Event:
1660                Edit/W=(498,699,1003,955) /K=1/N=BinEventTable binCount,binEndTime,timeWidth
1661                ModifyTable format(Point)=1,sigDigits(binEndTime)=8,width(binEndTime)=100
1662                SetDataFolder fldrSav0
1663        endif
1664EndMacro
1665
1666
1667// only show the first 1500 data points
1668//
1669Proc ShowRescaledTimeGraph() : Graph
1670
1671        DoWindow/F RescaledTimeGraph
1672        if(V_flag == 0)
1673                PauseUpdate; Silent 1           // building window...
1674                String fldrSav0= GetDataFolder(1)
1675                SetDataFolder root:Packages:NIST:Event:
1676                Display /W=(25,44,486,356)/K=1/N=RescaledTimeGraph rescaledTime
1677                SetDataFolder fldrSav0
1678                ModifyGraph mode=4
1679                ModifyGraph marker=19
1680                ModifyGraph rgb(rescaledTime)=(0,0,0)
1681                ModifyGraph msize=1
1682//              SetAxis/A=2 left                        //only autoscale the visible data (based on the bottom limits)
1683                SetAxis bottom 0,1500
1684                ErrorBars rescaledTime OFF
1685                Label left "\\Z14Time (seconds)"
1686                Label bottom "\\Z14Event number"
1687                ShowInfo
1688        endif
1689       
1690EndMacro
1691
1692
1693
1694Proc ExportSlicesAsVAX(firstNum,prefix)
1695        Variable firstNum=1
1696        String prefix="SAMPL"
1697
1698        SaveSlicesAsVAX(firstNum,prefix[0,4])           //make sure that the prefix is 5 chars
1699End
1700
1701//////// procedures to be able to export the slices as RAW VAX files.
1702//
1703// 1- load the raw data file to use the header (it must already be in RAW)
1704// 1.5- copy the raw data to the temp folder (STO)
1705// 1.7- ask for the prefix and starting run number (these are passed in)
1706// 2- copy the slice of data to the temp folder (STO)
1707// 3- touch up the time/counts in the slice header values in STO
1708// 4- write out the VAX file
1709// 5- repeat (2-4) for the number of slices
1710//
1711//
1712Function SaveSlicesAsVAX(firstNum,prefix)
1713        Variable firstNum
1714        String prefix
1715
1716        DoAlert 1,"Is the full data file loaded as a RAW data file? If not, load it and start over..."
1717        if(V_flag == 2)
1718                return (0)
1719        endif
1720       
1721// copy the contents of RAW to STO so I can work from there
1722        CopyWorkContents("RAW","STO")
1723
1724        // now declare all of the waves, now that they are sure to be there
1725
1726        WAVE slicedData=root:Packages:NIST:Event:slicedData
1727        Make/O/D/N=(128,128) curSlice
1728       
1729        NVAR nslices = root:Packages:NIST:gEvent_nslices
1730        WAVE binEndTime = root:Packages:NIST:Event:binEndTime
1731
1732        Wave rw=root:Packages:NIST:STO:realsRead
1733        Wave iw=root:Packages:NIST:STO:integersRead
1734        Wave/T tw=root:Packages:NIST:STO:textRead
1735        Wave data=root:Packages:NIST:STO:data
1736        Wave linear_data=root:Packages:NIST:STO:linear_data
1737       
1738       
1739        Wave rw_raw=root:Packages:NIST:RAW:realsRead
1740        Wave iw_raw=root:Packages:NIST:RAW:integersRead
1741        Wave/T tw_raw=root:Packages:NIST:RAW:textRead
1742
1743// for generating the alphanumeric
1744        String timeStr= secs2date(datetime,-1)
1745        String monthStr=StringFromList(1, timeStr  ,"/")
1746        String numStr="",labelStr
1747
1748        Variable ii,err,binFraction
1749       
1750        for(ii=0;ii<nslices;ii+=1)
1751
1752                //get the current slice and put it in the STO folder
1753                curSlice = slicedData[p][q][ii]
1754                data = curSlice
1755                linear_data = curSlice
1756               
1757                // touch up the header as needed
1758                // count time = iw[2]
1759                // monCt = rw[0]
1760                // detCt = rw[2]
1761                //tw[0] must now be the file name
1762                //
1763                // count time = fraction of total binning * total count time
1764                binFraction = (binEndTime[ii+1]-binEndTime[ii])/(binEndTime[nslices]-binEndTime[0])
1765               
1766                iw[2] = trunc(binFraction*iw_raw[2])
1767                rw[0] = trunc(binFraction*rw_raw[0])
1768                rw[2] = sum(curSlice,-inf,inf)          //total counts in slice
1769       
1770                if(firstNum<10)
1771                        numStr = "00"+num2str(firstNum)
1772                else
1773                        if(firstNum<100)
1774                                numStr = "0"+num2str(firstNum)
1775                        else
1776                                numStr = num2str(firstNum)
1777                        Endif
1778                Endif   
1779                tw[0] = prefix+numstr+".SA2_EVE_"+(num2char(str2num(monthStr)+64))+numStr
1780                labelStr = tw_raw[6]
1781               
1782                labelStr = PadString(labelStr,60,0x20)  //60 fortran-style spaces
1783                tw[6] = labelStr[0,59]
1784               
1785                //write out the file - this uses the tw[0] and home path
1786                Write_VAXRaw_Data("STO","",0)
1787
1788                //increment the run number, alpha
1789                firstNum += 1   
1790        endfor
1791
1792        return(0)
1793End
1794
1795
1796
1797
1798
1799/////////////
1800//The histogramming
1801//
1802// 6 AUG 2012
1803//
1804// from Igor Exchange, RGerkin
1805//  http://www.igorexchange.com/node/1373
1806// -- see the related thread on the mailing list
1807//
1808//Function Setup_JointHistogram()
1809//
1810////    tic()
1811//
1812//      make/D /o/n=1000000 data1=gnoise(1), data2=gnoise(1)
1813//      make/D /o/n=(25,25) myHist
1814//      setscale x,-3,3,myHist
1815//      setscale y,-3,3,myHist
1816//      IndexForHistogram(data1,data2,myhist)
1817//      Wave index=SavedIndex
1818//      JointHistogram(data1,data2,myHist,index)
1819//      NewImage myHist
1820//     
1821////    toc()
1822//     
1823//End
1824
1825
1826Function JointHistogram(w0,w1,hist,index)
1827        wave w0,w1,hist,index
1828 
1829        variable bins0=dimsize(hist,0)
1830        variable bins1=dimsize(hist,1)
1831        variable n=numpnts(w0)
1832        variable left0=dimoffset(hist,0)
1833        variable left1=dimoffset(hist,1)
1834        variable right0=left0+bins0*dimdelta(hist,0)
1835        variable right1=left1+bins1*dimdelta(hist,1)
1836       
1837        // Compute the histogram and redimension it. 
1838        histogram /b={0,1,bins0*bins1} index,hist
1839        redimension/D /n=(bins0,bins1) hist // Redimension to 2D. 
1840        setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
1841        setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
1842End
1843
1844
1845// histogram with a point range
1846//
1847// x- just need to send x2pnt or findLevel, or something similar to define the POINT
1848// values
1849//
1850// x- can also speed this up since the index only needs to be done once, so the
1851// histogram operation can be done separately, as the bins require
1852//
1853//
1854Function JointHistogramWithRange(w0,w1,hist,index,pt1,pt2)
1855        wave w0,w1,hist,index
1856        Variable pt1,pt2
1857 
1858        variable bins0=dimsize(hist,0)
1859        variable bins1=dimsize(hist,1)
1860        variable n=numpnts(w0)
1861        variable left0=dimoffset(hist,0)
1862        variable left1=dimoffset(hist,1)
1863        variable right0=left0+bins0*dimdelta(hist,0)
1864        variable right1=left1+bins1*dimdelta(hist,1)
1865
1866        // Compute the histogram and redimension it. 
1867        histogram /b={0,1,bins0*bins1}/R=[pt1,pt2] index,hist
1868        redimension/D /n=(bins0,bins1) hist // Redimension to 2D. 
1869        setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
1870        setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
1871End
1872
1873
1874// just does the indexing, creates wave SavedIndex in the current folder for the index
1875//
1876Function IndexForHistogram(w0,w1,hist)
1877        wave w0,w1,hist
1878 
1879        variable bins0=dimsize(hist,0)
1880        variable bins1=dimsize(hist,1)
1881        variable n=numpnts(w0)
1882        variable left0=dimoffset(hist,0)
1883        variable left1=dimoffset(hist,1)
1884        variable right0=left0+bins0*dimdelta(hist,0)
1885        variable right1=left1+bins1*dimdelta(hist,1)
1886 
1887        // Scale between 0 and the number of bins to create an index wave. 
1888        if(ThreadProcessorCount<4) // For older machines, matrixop is faster. 
1889                matrixop /free idx=round(bins0*(w0-left0)/(right0-left0))+bins0*round(bins1*(w1-left1)/(right1-left1))
1890        else // For newer machines with many cores, multithreading with make is faster. 
1891                make/free/n=(n) idx
1892                multithread idx=round(bins0*(w0-left0)/(right0-left0))+bins0*round(bins1*(w1-left1)/(right1-left1))
1893        endif
1894 
1895        KillWaves/Z SavedIndex
1896        MoveWave idx,SavedIndex
1897       
1898//      // Compute the histogram and redimension it. 
1899//      histogram /b={0,1,bins0*bins1} idx,hist
1900//      redimension /n=(bins0,bins1) hist // Redimension to 2D. 
1901//      setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
1902//      setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
1903End
1904
1905
1906
1907
1908
1909////////////// Post-processing of the event mode data
1910Proc ShowEventCorrectionPanel()
1911        DoWindow/F EventCorrectionPanel
1912        if(V_flag ==0)
1913                EventCorrectionPanel()
1914        EndIf
1915End
1916
1917Proc EventCorrectionPanel()
1918
1919        PauseUpdate; Silent 1           // building window...
1920        SetDataFolder root:Packages:NIST:Event:
1921       
1922        Display /W=(35,44,761,533)/K=2 rescaledTime
1923        DoWindow/C EventCorrectionPanel
1924        ModifyGraph mode=4
1925        ModifyGraph marker=19
1926        ModifyGraph rgb=(0,0,0)
1927        ModifyGraph msize=1
1928        ErrorBars rescaledTime OFF
1929        Label left "\\Z14Time (seconds)"
1930        Label bottom "\\Z14Event number"       
1931        SetAxis bottom 0,0.10*numpnts(rescaledTime)             //show 1st 10% of data for speed in displaying
1932       
1933        ControlBar 100
1934        Button button0,pos={18,12},size={70,20},proc=EC_AddCursorButtonProc,title="Cursors"
1935        Button button1,pos={153,11},size={80,20},proc=EC_AddTimeButtonProc,title="Add time"
1936        Button button2,pos={153,37},size={80,20},proc=EC_SubtractTimeButtonProc,title="Subtr time"
1937        Button button3,pos={153,64},size={90,20},proc=EC_TrimPointsButtonProc,title="Trim points"
1938        Button button4,pos={295,12},size={90,20},proc=EC_SaveWavesButtonProc,title="Save Waves"
1939        Button button5,pos={294,38},size={100,20},proc=EC_ImportWavesButtonProc,title="Import Waves"
1940        Button button6,pos={18,39},size={80,20},proc=EC_ShowAllButtonProc,title="All Data"
1941        Button button7,pos={683,9},size={30,20},proc=EC_HelpButtonProc,title="?"
1942        Button button8,pos={658,72},size={60,20},proc=EC_DoneButtonProc,title="Done"
1943       
1944        SetDataFolder root:
1945       
1946EndMacro
1947
1948Function EC_AddCursorButtonProc(ba) : ButtonControl
1949        STRUCT WMButtonAction &ba
1950
1951        switch( ba.eventCode )
1952                case 2: // mouse up
1953                        // click code here
1954                        SetDataFolder root:Packages:NIST:Event:
1955                       
1956                        Wave rescaledTime = rescaledTime
1957                        Cursor/P A rescaledTime 0
1958                        Cursor/P B rescaledTime numpnts(rescaledTime)-1
1959                        ShowInfo
1960                        SetDataFolder root:
1961                        break
1962                case -1: // control being killed
1963                        break
1964        endswitch
1965
1966        return 0
1967End
1968
1969Function EC_AddTimeButtonProc(ba) : ButtonControl
1970        STRUCT WMButtonAction &ba
1971
1972        switch( ba.eventCode )
1973                case 2: // mouse up
1974                        // click code here
1975                        SetDataFolder root:Packages:NIST:Event:
1976                       
1977                        Wave rescaledTime = rescaledTime
1978                        Wave timePt = timePt
1979                        Variable rollTime,rollTicks,ptA,ptB,lo,hi
1980                       
1981                        rollTicks = 2^26                                // in ticks
1982                        rollTime = 2^26*1e-7            // in seconds
1983                        ptA = pcsr(A)
1984                        ptB = pcsr(B)
1985                        lo=min(ptA,ptB)
1986                        hi=max(ptA,ptB)
1987
1988                        MultiThread timePt[lo,hi] += rollTicks
1989                        MultiThread rescaledTime[lo,hi] += rollTime
1990
1991                       
1992                        SetDataFolder root:
1993                        break
1994                case -1: // control being killed
1995                        break
1996        endswitch
1997
1998        return 0
1999End
2000
2001Function EC_SubtractTimeButtonProc(ba) : ButtonControl
2002        STRUCT WMButtonAction &ba
2003
2004        switch( ba.eventCode )
2005                case 2: // mouse up
2006                        // click code here
2007                        SetDataFolder root:Packages:NIST:Event:
2008                       
2009                        Wave rescaledTime = rescaledTime
2010                        Wave timePt = timePt
2011                        Variable rollTime,rollTicks,ptA,ptB,lo,hi
2012                       
2013                        rollTicks = 2^26                                // in ticks
2014                        rollTime = 2^26*1e-7            // in seconds
2015                        ptA = pcsr(A)
2016                        ptB = pcsr(B)
2017                        lo=min(ptA,ptB)
2018                        hi=max(ptA,ptB)
2019                       
2020                        MultiThread timePt[lo,hi] -= rollTicks
2021                        MultiThread rescaledTime[lo,hi] -= rollTime
2022
2023                        SetDataFolder root:
2024                       
2025                        break
2026                case -1: // control being killed
2027                        break
2028        endswitch
2029
2030        return 0
2031End
2032
2033// points removed are inclusive
2034//
2035// put both cursors on the same point to remove just that single point
2036//
2037Function EC_TrimPointsButtonProc(ba) : ButtonControl
2038        STRUCT WMButtonAction &ba
2039
2040        switch( ba.eventCode )
2041                case 2: // mouse up
2042                        // click code here
2043                        SetDataFolder root:Packages:NIST:Event:
2044                       
2045                        Wave rescaledTime = rescaledTime
2046                        Wave timePt = timePt
2047                        Wave xLoc = xLoc
2048                        Wave yLoc = yLoc
2049                        Variable rollTime,ptA,ptB,numElements,lo,hi
2050                       
2051                        rollTime = 2^26*1e-7            // in seconds
2052                        ptA = pcsr(A)
2053                        ptB = pcsr(B)
2054                        lo=min(ptA,ptB)
2055                        hi=max(ptA,ptB)                 
2056                        numElements = abs(ptA-ptB)+1                    //so points removed are inclusive
2057                        DeletePoints lo, numElements, rescaledTime,timePt,xLoc,yLoc
2058                       
2059                        printf "Points %g to %g have been deleted in rescaledTime, timePt, xLoc, and yLoc\r",ptA,ptB
2060                        SetDataFolder root:
2061                       
2062                        break
2063                case -1: // control being killed
2064                        break
2065        endswitch
2066
2067        return 0
2068End
2069
2070// un-sort the data first, then save it
2071Function EC_SaveWavesButtonProc(ba) : ButtonControl
2072        STRUCT WMButtonAction &ba
2073
2074        switch( ba.eventCode )
2075                case 2: // mouse up
2076                        // click code here
2077                       
2078//                      Execute "UndoTheSorting()"
2079                       
2080                        SetDataFolder root:Packages:NIST:Event:
2081                       
2082                        Wave rescaledTime = rescaledTime
2083                        Wave timePt = timePt
2084                        Wave xLoc = xLoc
2085                        Wave yLoc = yLoc
2086                        Save/T xLoc,yLoc,timePt                 //will ask for a name
2087                       
2088                        SetDataFolder root:
2089                        break
2090                case -1: // control being killed
2091                        break
2092        endswitch
2093
2094        return 0
2095End
2096
2097// this duplicates all of the bits that would be done if the "load" button was pressed
2098//
2099//
2100Function EC_ImportWavesButtonProc(ba) : ButtonControl
2101        STRUCT WMButtonAction &ba
2102
2103        switch( ba.eventCode )
2104                case 2: // mouse up
2105                        // click code here
2106                        SetDataFolder root:Packages:NIST:Event:
2107
2108                        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
2109                        SVAR dispStr = root:Packages:NIST:gEventDisplayString
2110                        String tmpStr="",fileStr,filePathStr
2111                       
2112                        // load in the waves, saved as Igor text to preserve the data type
2113                        LoadWave/T/O
2114                        filePathStr = S_fileName
2115                        if(strlen(S_fileName) == 0)
2116                                //user cancelled
2117                                DoAlert 0,"No file selected, nothing done."
2118                                return(0)
2119                        endif
2120                       
2121                        // clear out the old sort index, if present, since new data is being loaded
2122                        KillWaves/Z OscSortIndex
2123                        Wave timePt=timePt
2124
2125                        Duplicate/O timePt rescaledTime
2126                        rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
2127                        t_longest = waveMax(rescaledTime)               //should be the last point
2128       
2129                        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
2130                        sprintf tmpStr, "%s: a user-modified event file\r",fileStr
2131                        dispStr = tmpStr
2132       
2133                        break
2134                case -1: // control being killed
2135                        break
2136        endswitch
2137
2138        return 0
2139End
2140
2141
2142Function EC_ShowAllButtonProc(ba) : ButtonControl
2143        STRUCT WMButtonAction &ba
2144
2145        switch( ba.eventCode )
2146                case 2: // mouse up
2147                        // click code here
2148                        SetAxis/A
2149                        break
2150                case -1: // control being killed
2151                        break
2152        endswitch
2153
2154        return 0
2155End
2156
2157Function EC_HelpButtonProc(ba) : ButtonControl
2158        STRUCT WMButtonAction &ba
2159
2160        switch( ba.eventCode )
2161                case 2: // mouse up
2162                        // click code here
2163                        DoAlert 0,"The Event Correction help file has not been written yet"
2164                        break
2165                case -1: // control being killed
2166                        break
2167        endswitch
2168
2169        return 0
2170End
2171
2172Function EC_DoneButtonProc(ba) : ButtonControl
2173        STRUCT WMButtonAction &ba
2174
2175        switch( ba.eventCode )
2176                case 2: // mouse up
2177                        // click code here
2178                        DoWindow/K EventCorrectionPanel
2179                        break
2180                case -1: // control being killed
2181                        break
2182        endswitch
2183
2184        return 0
2185End
2186
2187
2188
2189
2190//////////////   Custom Bins  /////////////////////
2191//
2192//
2193//
2194// make sure that the bins are defined and the waves exist before
2195// trying to draw the panel
2196//
2197Proc Show_CustomBinPanel()
2198        DoWindow/F CustomBinPanel
2199        if(V_flag ==0)
2200                Init_CustomBins()
2201                CustomBinPanel()
2202        EndIf
2203End
2204
2205
2206Function Init_CustomBins()
2207
2208        NVAR nSlice = root:Packages:NIST:gEvent_nslices
2209        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
2210
2211        Variable/G root:Packages:NIST:gEvent_ForceTmaxBin=1             //==1 to enforce t_longest in user-defined custom bins
2212
2213        SetDataFolder root:Packages:NIST:Event:
2214               
2215        Make/O/D/N=(nSlice) timeWidth
2216        Make/O/D/N=(nSlice+1) binEndTime,binCount
2217       
2218        timeWidth = t_longest/nslice
2219        binEndTime = p
2220        binCount = p+1 
2221       
2222        SetDataFolder root:
2223       
2224        return(0)
2225End
2226
2227////////////////       
2228//
2229// Allow custom definitions of the bin widths
2230//
2231// Define by the number of bins, and the time width of each bin
2232//
2233// This shares the number of slices and the maximum time with the main panel
2234//
2235Proc CustomBinPanel()
2236        PauseUpdate; Silent 1           // building window...
2237        NewPanel /W=(130,44,851,455)/K=2 /N=CustomBinPanel
2238        DoWindow/C CustomBinPanel
2239        ModifyPanel fixedSize=1//,noEdit =1
2240        SetDrawLayer UserBack
2241       
2242        Button button0,pos={654,42}, size={50,20},title="Done",fSize=12
2243        Button button0,proc=CB_Done_Proc
2244        Button button1,pos={663,14},size={40,20},proc=CB_HelpButtonProc,title="?"
2245        Button button2,pos={216,42},size={80,20},title="Update",proc=CB_UpdateWavesButton       
2246        SetVariable setvar1,pos={23,13},size={160,20},title="Number of slices",fSize=12
2247        SetVariable setvar1,proc=CB_NumSlicesSetVarProc,value=root:Packages:NIST:gEvent_nslices
2248        SetVariable setvar2,pos={24,44},size={160,20},title="Max Time (s)",fSize=12
2249        SetVariable setvar2,value=root:Packages:NIST:gEvent_t_longest   
2250
2251        CheckBox chkbox1,pos={216,14},title="Enforce Max Time?"
2252        CheckBox chkbox1,variable = root:Packages:NIST:gEvent_ForceTmaxBin
2253        Button button3,pos={500,14},size={90,20},proc=CB_SaveBinsButtonProc,title="Save Bins"
2254        Button button4,pos={500,42},size={100,20},proc=CB_ImportBinsButtonProc,title="Import Bins"     
2255               
2256        SetDataFolder root:Packages:NIST:Event:
2257
2258        Display/W=(291,86,706,395)/HOST=CustomBinPanel/N=BarGraph binCount vs binEndTime
2259        ModifyGraph mode=5
2260        ModifyGraph marker=19
2261        ModifyGraph lSize=2
2262        ModifyGraph rgb=(0,0,0)
2263        ModifyGraph msize=2
2264        ModifyGraph hbFill=2
2265        ModifyGraph gaps=0
2266        ModifyGraph usePlusRGB=1
2267        ModifyGraph toMode=1
2268        ModifyGraph useBarStrokeRGB=1
2269        ModifyGraph standoff=0
2270        SetAxis left 0,*
2271        Label bottom "\\Z14Time (seconds)"
2272        Label left "\\Z14Number of Events"
2273        SetActiveSubwindow ##
2274       
2275        // and the table
2276        Edit/W=(13,87,280,394)/HOST=CustomBinPanel/N=T0
2277        AppendToTable/W=CustomBinPanel#T0 timeWidth,binEndTime
2278        ModifyTable width(Point)=40
2279        SetActiveSubwindow ##
2280       
2281        SetDataFolder root:
2282       
2283EndMacro
2284
2285// save the bins - use Igor Text format
2286//
2287Function CB_SaveBinsButtonProc(ba) : ButtonControl
2288        STRUCT WMButtonAction &ba
2289
2290        switch( ba.eventCode )
2291                case 2: // mouse up
2292                        // click code here
2293
2294                        SetDataFolder root:Packages:NIST:Event:
2295
2296                        Wave timeWidth = timeWidth
2297                        Wave binEndTime = binEndTime
2298                       
2299                        Save/T timeWidth,binEndTime                     //will ask for a name
2300
2301                        break
2302                case -1: // control being killed
2303                        break
2304        endswitch
2305
2306        SetDataFolder root:
2307       
2308        return 0
2309End
2310
2311// Import the bins - use Igor Text format
2312//
2313// -- be sure that the number of bins is reset
2314// -?- how about the t_longest? - this should be set by the load, not here
2315//
2316// -- loads in timeWidth and binEndTime
2317//
2318Function CB_ImportBinsButtonProc(ba) : ButtonControl
2319        STRUCT WMButtonAction &ba
2320
2321        switch( ba.eventCode )
2322                case 2: // mouse up
2323                        // click code here
2324                        NVAR nSlice = root:Packages:NIST:gEvent_nslices
2325
2326                        SetDataFolder root:Packages:NIST:Event:
2327
2328                        // prompt for the load of data
2329                        LoadWave/T/O
2330                        if(strlen(S_fileName) == 0)
2331                                //user cancelled
2332                                DoAlert 0,"No file selected, nothing done."
2333                                return(0)
2334                        endif
2335
2336                        Wave timeWidth = timeWidth
2337                        nSlice = numpnts(timeWidth)
2338                       
2339                        break
2340                case -1: // control being killed
2341                        break
2342        endswitch
2343
2344        SetDataFolder root:
2345       
2346        return 0
2347End
2348
2349
2350
2351//
2352// can either use the widths as stated -- then the end time may not
2353// match the actual end time of the data set
2354//
2355// -- or --
2356//
2357// enforce the end time of the data set to be the end time of the bins,
2358// then the last bin width must be reset to force the constraint
2359//
2360//
2361Function CB_UpdateWavesButton(ba) : ButtonControl
2362        STRUCT WMButtonAction &ba
2363
2364        switch( ba.eventCode )
2365                case 2: // mouse up
2366                        // click code here
2367                        NVAR nSlice = root:Packages:NIST:gEvent_nslices
2368                        NVAR t_longest = root:Packages:NIST:gEvent_t_longest
2369                        NVAR enforceTmax = root:Packages:NIST:gEvent_ForceTmaxBin
2370                       
2371                        // update the waves, and recalculate everything for the display
2372                        SetDataFolder root:Packages:NIST:Event:
2373
2374                        Wave timeWidth = timeWidth
2375                        Wave binEndTime = binEndTime
2376                        Wave binCount = binCount
2377                       
2378                        // use the widths as entered
2379                        binEndTime[0] = 0
2380                        binEndTime[1,] = binEndTime[p-1] + timeWidth[p-1]
2381                       
2382                        // enforce the longest time as the end bin time
2383                        // note that this changes the last time width
2384                        if(enforceTmax)
2385                                binEndTime[nSlice] = t_longest
2386                                timeWidth[nSlice-1] = t_longest - binEndTime[nSlice-1]
2387                        endif
2388                       
2389                        binCount = p+1
2390                        binCount[nSlice] = 0            // last point is zero, just for display
2391//                      binCount *= sign(timeWidth)             //to alert to negative time bins
2392                       
2393                        // make the timeWidth bold and red if the widths are negative
2394                        WaveStats/Q timeWidth
2395                        if(V_min < 0)
2396                                ModifyTable/W=CustomBinPanel#T0 style(timeWidth)=1,rgb(timeWidth)=(65535,0,0)                   
2397                        else
2398                                ModifyTable/W=CustomBinPanel#T0 style(timeWidth)=0,rgb(timeWidth)=(0,0,0)                       
2399                        endif
2400                       
2401                        break
2402                case -1: // control being killed
2403                        break
2404        endswitch
2405
2406        SetDataFolder root:
2407       
2408        return 0
2409End
2410
2411Function CB_HelpButtonProc(ba) : ButtonControl
2412        STRUCT WMButtonAction &ba
2413
2414        switch( ba.eventCode )
2415                case 2: // mouse up
2416                        // click code here
2417                        DoAlert 0,"The help file for the bin editor has not been written yet"
2418                        break
2419                case -1: // control being killed
2420                        break
2421        endswitch
2422
2423        return 0
2424End
2425
2426Function CB_Done_Proc(ba) : ButtonControl
2427        STRUCT WMButtonAction &ba
2428       
2429        String win = ba.win
2430        switch (ba.eventCode)
2431                case 2:
2432                        DoWindow/K CustomBinPanel
2433                        break
2434        endswitch
2435        return(0)
2436End
2437
2438
2439Function CB_NumSlicesSetVarProc(sva) : SetVariableControl
2440        STRUCT WMSetVariableAction &sva
2441
2442        switch( sva.eventCode )
2443                case 1: // mouse up
2444                case 2: // Enter key
2445                case 3: // Live update
2446                        Variable dval = sva.dval
2447                        String sval = sva.sval
2448                        SetDataFolder root:Packages:NIST:Event:
2449
2450                        Wave timeWidth = timeWidth
2451                        Wave binEndTime = binEndTime
2452                       
2453                        Redimension/N=(dval) timeWidth
2454                        Redimension/N=(dval+1) binEndTime,binCount
2455                       
2456                        SetDataFolder root:
2457                       
2458                        break
2459                case -1: // control being killed
2460                        break
2461        endswitch
2462
2463        return 0
2464End
2465
2466
2467///////////////////
2468//
2469// utility to split a large file
2470// 100 MB is the recommended size
2471// events can be clipped here, so be sure to trim the ends of the
2472// resulting files as needed.
2473//
2474// - works like the unix 'split' command
2475//
2476//
2477
2478Macro SplitBigFile(splitSize, baseStr)
2479        Variable splitSize = 100
2480        String baseStr="split"
2481        Prompt splitSize,"Target file size, in MB"
2482        Prompt baseStr,"File prefix, number will be appended"
2483       
2484        fSplitBigFile(splitSize, baseStr)
2485End
2486
2487Function fSplitBigFile(splitSize, baseStr)
2488        Variable splitSize
2489        String baseStr         
2490
2491
2492        String fileName=""              // File name, partial path, full path or "" for dialog.
2493        String pathName=""
2494        Variable refNum
2495        String str
2496
2497        Variable readSize=1e6           //1 MB
2498        Make/O/B/U/N=(readSize) aBlob                   //1MB worth
2499        Variable numSplit
2500        Variable num,ii,jj,outRef,frac
2501        String thePath
2502       
2503        Printf "SplitSize = %u MB\r",splitSize
2504        splitSize = trunc(splitSize) * 1e6              // now in bytes
2505       
2506       
2507        // Open file for read.
2508        Open/R/Z=2/F="????"/P=$pathName refNum as fileName
2509        thePath = ParseFilePath(1, fileName, ":", 1, 0)
2510       
2511        // Store results from Open in a safe place.
2512        Variable err = V_flag
2513        String fullPath = S_fileName
2514
2515        if (err == -1)
2516                Print "cancelled by user."
2517                return -1
2518        endif
2519
2520        FStatus refNum
2521       
2522        Printf "total # bytes = %u\r",V_logEOF
2523
2524        numSplit=0
2525        if(V_logEOF > splitSize)
2526                numSplit = trunc(V_logEOF/splitSize)
2527        endif
2528
2529        frac = V_logEOF - numSplit*splitSize
2530        Print "numSplit = ",numSplit
2531        Printf "frac = %u\r",frac
2532       
2533        num=0
2534        if(frac > readSize)
2535                num = trunc(frac/readSize)
2536        endif
2537
2538       
2539        frac = frac - num*readSize
2540
2541        Print "num = ",num
2542        Printf "frac = %u\r",frac
2543       
2544        baseStr = "split"
2545       
2546        for(ii=0;ii<numSplit;ii+=1)
2547                Open outRef as (thePath+baseStr+num2str(ii))
2548
2549                for(jj=0;jj<(splitSize/readSize);jj+=1)
2550                        FBinRead refNum,aBlob
2551                        FBinWrite outRef,aBlob
2552                endfor
2553
2554                Close outRef
2555        endfor
2556
2557        Make/O/B/U/N=(frac) leftover
2558        // ii was already incremented past the loop
2559        Open outRef as (thePath+baseStr+num2str(ii))
2560        for(jj=0;jj<num;jj+=1)
2561                FBinRead refNum,aBlob
2562                FBinWrite outRef,aBlob
2563        endfor
2564        FBinRead refNum,leftover
2565        FBinWrite outRef,leftover
2566
2567        Close outRef
2568
2569
2570        FSetPos refNum,V_logEOF
2571        Close refNum
2572       
2573       
2574        return 0
2575End
2576
2577
2578
2579//// save the sliced data, and accumulate slices
2580//
2581// need some way of ensuring that the slices match up since I' blindly adding them together.
2582//
2583//
2584//
2585//
2586// mode = 0             wipe out the old accumulated, copy slicedData to accumulatedData
2587// mode = 1             add current slicedData to accumulatedData
2588// mode = 2             copy accumulatedData to slicedData in preparation of export or display
2589// mode = 3             sing a song
2590//
2591Function AccumulateSlices(mode)
2592        Variable mode
2593       
2594        SetDataFolder root:Packages:NIST:Event:
2595
2596        switch(mode)   
2597                case 0:
2598                        KillWaves/Z accumulatedData
2599                        Duplicate/O slicedData accumulatedData         
2600                        break
2601                case 1:
2602                        Wave acc=accumulatedData
2603                        Wave cur=slicedData
2604                        acc += cur
2605                        break
2606                case 2:
2607                        Duplicate/O accumulatedData slicedData         
2608                        break
2609                default:                       
2610                               
2611        endswitch
2612
2613        SetDataFolder root:
2614        return(0)
2615end
Note: See TracBrowser for help on using the repository browser.