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

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

Lots of changes to the Event Mode reading/processing. Added panels to allow correction of the event data, and a panel to create custom bins.

Added conditional compile to look for the EventLoadWave? operation from the EventLoadWave? XOP. The XOP is likely to be distributed with releases 7.13e and higher, pending testing.

Updated the FilesToRemove? and the installer to look for the EventLoader? XOP and remove it if it's present when updating.

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