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

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

Added Auto-Fit (Batch fitting) to the Macros menu as a beta item

Updated broken links in Model_Docs

Added Auto-Fit help to the Analysis Help file as a new package

Updated the current version to 7.20, a new release for the web site

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