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

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

Cleaning up the code a bit, adding comments. Making constant declarations in the Event.ipf and Tisane.ipf static so that they are not entangled.

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