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

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

adding buttons on the Event Panel for adjusting events and making custom bins.

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