source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/VSANS/V_EventModeProcessing.ipf @ 1047

Last change on this file since 1047 was 1047, checked in by srkline, 6 years ago

event mode processing - splitting the binned data into 4 panels, speedup of binning, display of split panels.

fitting routines for fitting 5 peaks for nonlinear corrections.

all needs to documented, then expanded

File size: 84.7 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma IgorVersion=6.22
3
4//
5// Event mode prcessing for VSANS
6//
7// First pass, getting the basics to work
8//
9// -- need TOF processing for wavelength calibration
10//  -- document this so it can be done quickly and easily.
11//
12
13
14
15
16// TODO:
17//
18// -- Can any of this be multithreaded?
19//  -- the histogram operation, the Indexing for the histogram, all are candidates
20//  -- can the decoding be multithreaded as a wave assignment speedup?
21//
22//
23// -- search for TODO for unresolved issues not on this list
24//
25// -- add comments to the code as needed
26//
27// -- write the help file, and link the help buttons to the help docs
28//
29// -- examples?
30//
31//
32// X- the slice display "fails" for data sets that have 3 or 4 slices, as the ModifyImage command
33//     interprets the data as being RGB - and so does nothing.
34//     need to find a way around this. This was fixed by displaying the data using the G=1 flag on AppendImage
35//     to prevent the "atuo-detection" of data as RGB
36//
37//
38///////////////   SWITCHES     /////////////////
39//
40// for the "File Too Big" limit:
41//      Variable/G root:Packages:NIST:VSANS:Event:gEventFileTooLarge = 150              // 150 MB considered too large
42//
43// for the tolerance of "step" detection
44//      Variable/G root:Packages:NIST:VSANS:Event:gStepTolerance = 5            // 5 = # of standard deviations from mean. See PutCursorsAtStep()
45//
46//
47//
48//
49
50
51// TODO
52// x- these dimensions are hard-wired (OK)
53//
54Constant XBINS=48
55Constant NTUBES=192
56Constant YBINS=128
57
58Static Constant MODE_STREAM = 0
59Static Constant MODE_OSCILL = 1
60Static Constant MODE_TISANE = 2
61Static Constant MODE_TOF = 3
62
63
64
65Proc V_Show_Event_Panel()
66        DoWindow/F VSANS_EventModePanel
67        if(V_flag ==0)
68                V_Init_Event()
69                VSANS_EventModePanel()
70        EndIf
71End
72
73// TODO:
74//  x- need an index table with the tube <-> panel correspondence
75//    NO, per Phil, the tube numbering is sequential:
76//
77// Based on the numbering 0-191:
78// group 1 = R (0,47)                   MatrixOp out = ReverseRows(in)
79// group 2 = T (48,95)          output = slices_T[q][p][r]
80// group 3 = B (96,143)                 output = slices_B[XBINS-q-1][YBINS-p-1][r]              (reverses rows and columns)
81// group 4 = L (144,191)        MatrixOp out = ReverseCols(in)
82//
83// There is a separate function that does the proper flipping to get the panels into the correct orientation
84//
85Function V_Init_Event()
86
87        NewDataFolder/O/S root:Packages:NIST:VSANS:Event
88
89        String/G        root:Packages:NIST:VSANS:Event:gEvent_logfile
90        String/G        root:Packages:NIST:VSANS:Event:gEventDisplayString="Details of the file load"
91
92
93// globals that are the header of the VSANS event file
94        String/G root:Packages:NIST:VSANS:Event:gVsansStr=""
95        Variable/G root:Packages:NIST:VSANS:Event:gRevision = 0
96        Variable/G root:Packages:NIST:VSANS:Event:gOffset=0             // = 22 bytes if no disabled tubes
97        Variable/G root:Packages:NIST:VSANS:Event:gTime1=0
98        Variable/G root:Packages:NIST:VSANS:Event:gTime2=0
99        Variable/G root:Packages:NIST:VSANS:Event:gTime3=0
100        Variable/G root:Packages:NIST:VSANS:Event:gTime4=0      // these 4 time pieces are supposed to be 8 bytes total
101        Variable/G root:Packages:NIST:VSANS:Event:gTime5=0      // these 5 time pieces are supposed to be 10 bytes total
102        String/G root:Packages:NIST:VSANS:Event:gDetStr=""
103        Variable/G root:Packages:NIST:VSANS:Event:gVolt=0
104        Variable/G root:Packages:NIST:VSANS:Event:gResol=0              //time resolution in nanoseconds
105// TODO -- need a wave? for the list of disabled tubes
106// don't know how many there might be, or why I would need to know
107
108        Variable/G root:Packages:NIST:VSANS:Event:gEvent_t_longest = 0
109
110        Variable/G root:Packages:NIST:VSANS:Event:gEvent_tsdisp //Displayed slice
111        Variable/G root:Packages:NIST:VSANS:Event:gEvent_nslices = 10  //Number of time slices
112       
113        Variable/G root:Packages:NIST:VSANS:Event:gEvent_logint = 1
114
115        Variable/G root:Packages:NIST:VSANS:Event:gEvent_Mode = 3                               // ==0 for "stream", ==1 for Oscillatory
116        Variable/G root:Packages:NIST:VSANS:Event:gRemoveBadEvents = 1          // ==1 to remove "bad" events, ==0 to read "as-is"
117        Variable/G root:Packages:NIST:VSANS:Event:gSortStreamEvents = 0         // ==1 to sort the event stream, a last resort for a stream of data
118       
119        Variable/G root:Packages:NIST:VSANS:Event:gEvent_ForceTmaxBin=1         //==1 to enforce t_longest in user-defined custom bins
120
121        NVAR nslices = root:Packages:NIST:VSANS:Event:gEvent_nslices
122       
123               
124        Make/D/O/N=(XBINS,YBINS,nslices) slicedData
125        Duplicate/O slicedData logslicedData
126        Duplicate/O slicedData dispsliceData
127
128
129// for decimation
130        Variable/G root:Packages:NIST:VSANS:Event:gEventFileTooLarge = 150              // 150 MB considered too large
131        Variable/G root:Packages:NIST:VSANS:Event:gDecimation = 100
132        Variable/G root:Packages:NIST:VSANS:Event:gEvent_t_longest_decimated = 0
133
134// for large file splitting
135        String/G root:Packages:NIST:VSANS:Event:gSplitFileList = ""             // a list of the file names as split
136       
137// for editing
138        Variable/G root:Packages:NIST:VSANS:Event:gStepTolerance = 5            // 5 = # of standard deviations from mean. See PutCursorsAtStep()
139       
140        SetDataFolder root:
141End
142
143
144
145Proc VSANS_EventModePanel()
146        PauseUpdate; Silent 1           // building window...
147        NewPanel /W=(82,44,884,664)/N=VSANS_EventModePanel/K=2
148        DoWindow/C VSANS_EventModePanel
149        ModifyPanel fixedSize=1,noEdit =1
150
151        SetDrawLayer UserBack
152        DrawText 479,345,"Stream Data"
153        DrawLine 563,338,775,338
154        DrawText 479,419,"Oscillatory or Stream Data"
155        DrawLine 647,411,775,411
156
157//      ShowTools/A
158        Button button0,pos={14,87},size={150,20},proc=V_LoadEventLog_Button,title="Load Event Log File"
159        Button button0,fSize=12
160        TitleBox tb1,pos={475,500},size={266,86},fSize=10
161        TitleBox tb1,variable= root:Packages:NIST:VSANS:Event:gEventDisplayString
162
163        CheckBox chkbox2,pos={376,151},size={81,15},proc=V_LogIntEvent_Proc,title="Log Intensity"
164        CheckBox chkbox2,fSize=10,variable= root:Packages:NIST:VSANS:Event:gEvent_logint
165        CheckBox chkbox3,pos={14,125},size={119,15},title="Remove Bad Events?",fSize=10
166        CheckBox chkbox3,variable= root:Packages:NIST:VSANS:Event:gRemoveBadEvents
167       
168        Button doneButton,pos={738,36},size={50,20},proc=V_EventDone_Proc,title="Done"
169        Button doneButton,fSize=12
170        Button button2,pos={486,200},size={140,20},proc=V_ShowEventDataButtonProc,title="Show Event Data"
171        Button button3,pos={486,228},size={140,20},proc=V_ShowBinDetailsButtonProc,title="Show Bin Details"
172        Button button5,pos={633,228},size={140,20},proc=V_ExportSlicesButtonProc,title="Export Slices as VAX",disable=2
173        Button button6,pos={748,9},size={40,20},proc=V_EventModeHelpButtonProc,title="?"
174               
175        Button button7,pos={211,33},size={120,20},proc=V_AdjustEventDataButtonProc,title="Adjust Events"
176        Button button8,pos={653,201},size={120,20},proc=V_CustomBinButtonProc,title="Custom Bins"
177        Button button4,pos={211,63},size={120,20},proc=V_UndoTimeSortButtonProc,title="Undo Time Sort"
178        Button button18,pos={211,90},size={120,20},proc=V_EC_ImportWavesButtonProc,title="Import Edited"
179       
180        SetVariable setvar0,pos={208,149},size={160,16},proc=V_sliceSelectEvent_Proc,title="Display Time Slice"
181        SetVariable setvar0,fSize=10
182        SetVariable setvar0,limits={0,1000,1},value= root:Packages:NIST:VSANS:Event:gEvent_tsdisp       
183        SetVariable setvar1,pos={389,29},size={160,16},title="Number of slices",fSize=10
184        SetVariable setvar1,limits={1,1000,1},value= root:Packages:NIST:VSANS:Event:gEvent_nslices
185        SetVariable setvar2,pos={389,54},size={160,16},title="Max Time (s)",fSize=10
186        SetVariable setvar2,value= root:Packages:NIST:VSANS:Event:gEvent_t_longest
187       
188        PopupMenu popup0,pos={389,77},size={119,20},proc=V_BinTypePopMenuProc,title="Bin Spacing"
189        PopupMenu popup0,fSize=10
190        PopupMenu popup0,mode=1,popvalue="Equal",value= #"\"Equal;Fibonacci;Custom;\""
191        Button button1,pos={389,103},size={120,20},fSize=12,proc=V_ProcessEventLog_Button,title="Bin Event Data"
192
193
194        Button button21,pos={580,70},size={120,20},proc=V_SplitToPanels_Button,title="Split to Panels"
195        Button button22,pos={580,90},size={120,20},proc=V_GraphPanels_Button,title="Show Panels"
196
197        Button button10,pos={488,305},size={100,20},proc=V_SplitFileButtonProc,title="Split Big File",disable=2
198        Button button14,pos={488,350},size={120,20},proc=V_Stream_LoadDecim,title="Load Split List",disable=2
199        Button button19,pos={649,350},size={120,20},proc=V_Stream_LoadAdjustedList,title="Load Edited List",disable=2
200        Button button20,pos={680,376},size={90,20},proc=V_ShowList_ToLoad,title="Show List",disable=2
201        SetVariable setvar3,pos={487,378},size={150,16},title="Decimation factor",disable=2
202        SetVariable setvar3,fSize=10
203        SetVariable setvar3,limits={1,inf,1},value= root:Packages:NIST:VSANS:Event:gDecimation
204
205        Button button15_0,pos={488,425},size={110,20},proc=V_AccumulateSlicesButton,title="Add First Slice",disable=2
206        Button button16_1,pos={488,450},size={110,20},proc=V_AccumulateSlicesButton,title="Add Next Slice",disable=2
207        Button button17_2,pos={620,425},size={110,20},proc=V_AccumulateSlicesButton,title="Display Total",disable=2
208
209        CheckBox chkbox1_0,pos={25,34},size={69,14},title="Oscillatory",fSize=10
210        CheckBox chkbox1_0,mode=1,proc=V_EventModeRadioProc,value=0
211        CheckBox chkbox1_1,pos={25,59},size={53,14},title="Stream",fSize=10
212        CheckBox chkbox1_1,proc=V_EventModeRadioProc,value=0,mode=1
213        CheckBox chkbox1_2,pos={104,59},size={53,14},title="TISANE",fSize=10
214        CheckBox chkbox1_2,proc=V_EventModeRadioProc,value=0,mode=1
215        CheckBox chkbox1_3,pos={104,34},size={37,14},title="TOF",fSize=10
216        CheckBox chkbox1_3,proc=V_EventModeRadioProc,value=1,mode=1
217       
218        GroupBox group0_0,pos={5,5},size={174,112},title="(1) Loading Mode",fSize=12,fStyle=1
219        GroupBox group0_1,pos={372,5},size={192,127},title="(3) Bin Events",fSize=12,fStyle=1
220        GroupBox group0_2,pos={477,169},size={310,92},title="(4) View / Export",fSize=12,fStyle=1
221        GroupBox group0_3,pos={191,5},size={165,117},title="(2) Edit Events",fSize=12,fStyle=1
222        GroupBox group0_4,pos={474,278},size={312,200},title="Split / Accumulate Files",fSize=12
223        GroupBox group0_4,fStyle=1
224       
225        Display/W=(10,170,460,610)/HOST=#
226        AppendImage/T/G=1 :Packages:NIST:VSANS:Event:dispsliceData              //  /G=1 flag prevents interpretation as RGB so 3, 4 slices display correctly
227        ModifyImage dispsliceData ctab= {*,*,ColdWarm,0}
228        ModifyImage dispsliceData ctabAutoscale=3
229        ModifyGraph margin(left)=14,margin(bottom)=14,margin(top)=14,margin(right)=14
230        ModifyGraph mirror=2
231        ModifyGraph nticks=4
232        ModifyGraph minor=1
233        ModifyGraph fSize=9
234        ModifyGraph standoff=0
235        ModifyGraph tkLblRot(left)=90
236        ModifyGraph btLen=3
237        ModifyGraph tlOffset=-2
238        RenameWindow #,Event_slicegraph
239        SetActiveSubwindow ##
240EndMacro
241
242
243Function V_SplitToPanels_Button(ba) : ButtonControl
244        STRUCT WMButtonAction &ba
245
246        switch( ba.eventCode )
247                case 2: // mouse up
248                        // click code here
249                        V_SplitBinnedToPanels()
250                        //
251                        break
252                case -1: // control being killed
253                        break
254        endswitch
255
256        return 0
257End
258
259Function V_GraphPanels_Button(ba) : ButtonControl
260        STRUCT WMButtonAction &ba
261
262        switch( ba.eventCode )
263                case 2: // mouse up
264                        // click code here
265                        Execute "VSANS_EventPanels()"
266                        //
267                        break
268                case -1: // control being killed
269                        break
270        endswitch
271
272        return 0
273End
274
275// mode selector
276//Static Constant MODE_STREAM = 0
277//Static Constant MODE_OSCILL = 1
278//Static Constant MODE_TISANE = 2
279//Static Constant MODE_TOF = 3
280//
281Function V_EventModeRadioProc(name,value)
282        String name
283        Variable value
284       
285        NVAR gEventModeRadioVal= root:Packages:NIST:VSANS:Event:gEvent_mode
286       
287        strswitch (name)
288                case "chkbox1_0":
289                        gEventModeRadioVal= MODE_OSCILL
290                        break
291                case "chkbox1_1":
292                        gEventModeRadioVal= MODE_STREAM
293                        break
294                case "chkbox1_2":
295                        gEventModeRadioVal= MODE_TISANE
296                        break
297                case "chkbox1_3":
298                        gEventModeRadioVal= MODE_TOF
299                        break
300        endswitch
301        CheckBox chkbox1_0,value= gEventModeRadioVal==MODE_OSCILL
302        CheckBox chkbox1_1,value= gEventModeRadioVal==MODE_STREAM
303        CheckBox chkbox1_2,value= gEventModeRadioVal==MODE_TISANE
304        CheckBox chkbox1_3,value= gEventModeRadioVal==MODE_TOF
305
306        return(0)
307End
308
309Function V_AdjustEventDataButtonProc(ba) : ButtonControl
310        STRUCT WMButtonAction &ba
311
312        switch( ba.eventCode )
313                case 2: // mouse up
314                        // click code here
315                        Execute "V_ShowEventCorrectionPanel()"
316                        //
317                        break
318                case -1: // control being killed
319                        break
320        endswitch
321
322        return 0
323End
324
325Function V_CustomBinButtonProc(ba) : ButtonControl
326        STRUCT WMButtonAction &ba
327
328        switch( ba.eventCode )
329                case 2: // mouse up
330                        // click code here
331                        Execute "V_Show_CustomBinPanel()"
332                        //
333                        break
334                case -1: // control being killed
335                        break
336        endswitch
337
338        return 0
339End
340
341
342Function V_ShowEventDataButtonProc(ba) : ButtonControl
343        STRUCT WMButtonAction &ba
344
345        switch( ba.eventCode )
346                case 2: // mouse up
347                        // click code here
348                        Execute "V_ShowRescaledTimeGraph()"
349                        //
350                        V_DifferentiatedTime()
351                        //
352                        break
353                case -1: // control being killed
354                        break
355        endswitch
356
357        return 0
358End
359
360Function V_BinTypePopMenuProc(pa) : PopupMenuControl
361        STRUCT WMPopupAction &pa
362
363        switch( pa.eventCode )
364                case 2: // mouse up
365                        Variable popNum = pa.popNum
366                        String popStr = pa.popStr
367                        if(cmpstr(popStr,"Custom")==0)
368                                Execute "V_Show_CustomBinPanel()"
369                        endif
370                        break
371                case -1: // control being killed
372                        break
373        endswitch
374
375        return 0
376End
377
378Function V_ShowBinDetailsButtonProc(ba) : ButtonControl
379        STRUCT WMButtonAction &ba
380
381        switch( ba.eventCode )
382                case 2: // mouse up
383                        // click code here
384                        Execute "V_ShowBinTable()"
385                        Execute "V_BinEventBarGraph()"
386                        break
387                case -1: // control being killed
388                        break
389        endswitch
390
391        return 0
392End
393
394Function V_UndoTimeSortButtonProc(ba) : ButtonControl
395        STRUCT WMButtonAction &ba
396
397        switch( ba.eventCode )
398                case 2: // mouse up
399                        // click code here
400                        Execute "V_UndoTheSorting()"
401                        break
402                case -1: // control being killed
403                        break
404        endswitch
405
406        return 0
407End
408
409Function V_ExportSlicesButtonProc(ba) : ButtonControl
410        STRUCT WMButtonAction &ba
411
412        switch( ba.eventCode )
413                case 2: // mouse up
414                        // click code here
415                        Execute "V_ExportSlicesAsVAX()"         //will invoke the dialog
416                        break
417                case -1: // control being killed
418                        break
419        endswitch
420
421        return 0
422End
423
424Function V_EventModeHelpButtonProc(ba) : ButtonControl
425        STRUCT WMButtonAction &ba
426
427        switch( ba.eventCode )
428                case 2: // mouse up
429                        // click code here
430                        DisplayHelpTopic/Z "Event Mode Data"
431                        break
432                case -1: // control being killed
433                        break
434        endswitch
435
436        return 0
437End
438
439
440Function V_EventDone_Proc(ba) : ButtonControl
441        STRUCT WMButtonAction &ba
442       
443        String win = ba.win
444        switch (ba.eventCode)
445                case 2:
446                        DoWindow/K VSANS_EventModePanel
447                        break
448        endswitch
449        return(0)
450End
451
452
453
454Function V_ProcessEventLog_Button(ctrlName) : ButtonControl
455        String ctrlName
456       
457        NVAR mode=root:Packages:NIST:VSANS:Event:gEvent_Mode
458       
459        if(mode == MODE_STREAM)
460                V_Stream_ProcessEventLog("")
461        endif
462       
463        if(mode == MODE_OSCILL)
464                V_Osc_ProcessEventLog("")
465        endif
466       
467        // If TOF mode, process as Oscillatory -- that is, take the times as is
468        if(mode == MODE_TOF)
469                V_Osc_ProcessEventLog("")
470        endif
471       
472        // toggle the checkbox for log display to force the display to be correct
473        NVAR gLog = root:Packages:NIST:VSANS:Event:gEvent_logint
474        V_LogIntEvent_Proc("",gLog)
475       
476        return(0)
477end
478
479// for oscillatory mode
480//
481Function V_Osc_ProcessEventLog(ctrlName)
482        String ctrlName
483
484//      Make/O/D/N=(XBINS,YBINS) root:Packages:NIST:VSANS:Event:binnedData
485        Make/O/D/N=(NTUBES,YBINS) root:Packages:NIST:VSANS:Event:binnedData
486       
487        Wave binnedData = root:Packages:NIST:VSANS:Event:binnedData
488        Wave xLoc = root:Packages:NIST:VSANS:Event:xLoc
489        Wave yLoc = root:Packages:NIST:VSANS:Event:yLoc
490
491// now with the number of slices and max time, process the events
492
493        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
494        NVAR nslices = root:Packages:NIST:VSANS:Event:gEvent_nslices
495
496        SetDataFolder root:Packages:NIST:VSANS:Event            //don't count on the folder remaining here
497       
498//      Make/D/O/N=(XBINS,YBINS,nslices) slicedData
499        Make/D/O/N=(NTUBES,YBINS,nslices) slicedData
500               
501        Wave slicedData = slicedData
502        Wave rescaledTime = rescaledTime
503        Wave timePt = timePt
504//      Make/O/D/N=(XBINS,YBINS) tmpData
505        Make/O/D/N=(NTUBES,YBINS) tmpData
506        Make/O/D/N=(nslices+1) binEndTime,binCount
507        Make/O/D/N=(nslices) timeWidth
508        Wave timeWidth = timeWidth
509        Wave binEndTime = binEndTime
510        Wave binCount = binCount
511
512        variable ii,del,p1,p2,t1,t2
513        del = t_longest/nslices
514
515        slicedData = 0
516        binEndTime[0]=0
517        BinCount[nslices]=0
518
519
520        String binTypeStr=""
521        ControlInfo /W=VSANS_EventModePanel popup0
522        binTypeStr = S_value
523       
524        strswitch(binTypeStr)   // string switch
525                case "Equal":           // execute if case matches expression
526                        V_SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
527                        break                                           // exit from switch
528                case "Fibonacci":               // execute if case matches expression
529                        V_SetFibonacciBins(binEndTime,timeWidth,nslices,t_longest)
530                        break
531                case "Log":             // execute if case matches expression
532                        V_SetLogBins(binEndTime,timeWidth,nslices,t_longest)
533                        break
534                case "Custom":          // execute if case matches expression
535                        //bins are set by the user on the panel - assume it's good to go
536                        break
537                default:                                                        // optional default expression executed
538                        DoAlert 0,"No match for bin type, Equal bins used"
539                        V_SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
540        endswitch
541
542
543// now before binning, sort the data
544
545        //this is slow - undoing the sorting and starting over, but if you don't,
546        // you'll never be able to undo the sort
547        //
548        SetDataFolder root:Packages:NIST:VSANS:Event:
549
550s_tic()
551        if(WaveExists($"root:Packages:NIST:VSANS:Event:OscSortIndex") == 0 )
552                Duplicate/O rescaledTime OscSortIndex
553                MakeIndex rescaledTime OscSortIndex
554                IndexSort OscSortIndex, yLoc,xLoc,timePt,rescaledTime   
555                //SetDataFolder root:Packages:NIST:VSANS:Event
556                V_IndexForHistogram(xLoc,yLoc,binnedData)                       // index the events AFTER sorting
557                //SetDataFolder root:
558        Endif
559       
560printf "sort time = "
561s_toc()
562
563        Wave index = root:Packages:NIST:VSANS:Event:SavedIndex          //this is the histogram index
564
565s_tic()
566        for(ii=0;ii<nslices;ii+=1)
567                if(ii==0)
568//                      t1 = ii*del
569//                      t2 = (ii+1)*del
570                        p1 = BinarySearch(rescaledTime,0)
571                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])
572                else
573//                      t2 = (ii+1)*del
574                        p1 = p2+1               //one more than the old one
575                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])               
576                endif
577
578        // typically zero will never be a valid time value in oscillatory mode. in "stream" mode, the first is normalized to == 0
579        // but not here - times are what they are.
580                if(p1 == -1)
581                        Printf "p1 = -1 Binary search off the end %15.10g <?? %15.10g\r", 0, rescaledTime[0]
582                        p1 = 0          //set to the first point if it's off the end
583                Endif
584               
585                if(p2 == -2)
586                        Printf "p2 = -2 Binary search off the end %15.10g >?? %15.10g\r", binEndTime[ii+1], rescaledTime[numpnts(rescaledTime)-1]
587                        p2 = numpnts(rescaledTime)-1            //set to the last point if it's off the end
588                Endif
589//              Print p1,p2
590
591
592                tmpData=0
593                V_JointHistogramWithRange(xLoc,yLoc,tmpData,index,p1,p2)
594                slicedData[][][ii] = tmpData[p][q]
595               
596//              binEndTime[ii+1] = t2
597                binCount[ii] = sum(tmpData,-inf,inf)
598        endfor
599printf "histogram time = "
600s_toc()
601
602        Duplicate/O slicedData,root:Packages:NIST:VSANS:Event:dispsliceData,root:Packages:NIST:VSANS:Event:logSlicedData
603        Wave logSlicedData = root:Packages:NIST:VSANS:Event:logSlicedData
604        logslicedData = log(slicedData)
605
606        SetDataFolder root:
607        return(0)
608End
609
610// for a "continuous exposure"
611//
612// if there is a sort of these events, I need to re-index the events for the histogram
613// - see the oscillatory mode  - and sort the events here, then immediately re-index for the histogram
614// - but with the added complication that I need to always remember to index for the histogram, every time
615// - since I don't know if I've sorted or un-sorted. Osc mode always forces a re-sort and a re-index
616//
617Function V_Stream_ProcessEventLog(ctrlName)
618        String ctrlName
619
620//      NVAR slicewidth = root:Packages:NIST:gTISANE_slicewidth
621
622       
623//      Make/O/D/N=(XBINS,YBINS) root:Packages:NIST:VSANS:Event:binnedData
624        Make/O/D/N=(NTUBES,YBINS) root:Packages:NIST:VSANS:Event:binnedData
625       
626        Wave binnedData = root:Packages:NIST:VSANS:Event:binnedData
627        Wave xLoc = root:Packages:NIST:VSANS:Event:xLoc
628        Wave yLoc = root:Packages:NIST:VSANS:Event:yLoc
629
630// now with the number of slices and max time, process the events
631
632        NVAR yesSortStream = root:Packages:NIST:VSANS:Event:gSortStreamEvents           //do I sort the events?
633        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
634        NVAR nslices = root:Packages:NIST:VSANS:Event:gEvent_nslices
635
636        SetDataFolder root:Packages:NIST:VSANS:Event            //don't count on the folder remaining here
637       
638//      Make/D/O/N=(XBINS,YBINS,nslices) slicedData
639        Make/D/O/N=(NTUBES,YBINS,nslices) slicedData
640               
641        Wave slicedData = slicedData
642        Wave rescaledTime = rescaledTime
643//      Make/O/D/N=(XBINS,YBINS) tmpData
644        Make/O/D/N=(NTUBES,YBINS) tmpData
645        Make/O/D/N=(nslices+1) binEndTime,binCount//,binStartTime
646        Make/O/D/N=(nslices) timeWidth
647        Wave binEndTime = binEndTime
648        Wave timeWidth = timeWidth
649        Wave binCount = binCount
650
651        variable ii,del,p1,p2,t1,t2
652        del = t_longest/nslices
653
654        slicedData = 0
655        binEndTime[0]=0
656        BinCount[nslices]=0
657       
658        String binTypeStr=""
659        ControlInfo /W=VSANS_EventModePanel popup0
660        binTypeStr = S_value
661       
662        strswitch(binTypeStr)   // string switch
663                case "Equal":           // execute if case matches expression
664                        V_SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
665                        break                                           // exit from switch
666                case "Fibonacci":               // execute if case matches expression
667                        V_SetFibonacciBins(binEndTime,timeWidth,nslices,t_longest)
668                        break
669                case "Log":             // execute if case matches expression
670                        V_SetLogBins(binEndTime,timeWidth,nslices,t_longest)
671                        break
672                case "Custom":          // execute if case matches expression
673                        //bins are set by the user on the panel - assume it's good to go
674                        break
675                default:                                                        // optional default expression executed
676                        DoAlert 0,"No match for bin type, Equal bins used"
677                        V_SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
678        endswitch
679
680// TODO
681// the global exists for this switch, but it is not implemented - not sure whether
682// it's correct to implement this at all --
683//
684        if(yesSortStream == 1)
685                V_SortTimeData()
686        endif
687       
688// index the events before binning
689// if there is a sort of these events, I need to re-index the events for the histogram
690//      SetDataFolder root:Packages:NIST:VSANS:Event
691        V_IndexForHistogram(xLoc,yLoc,binnedData)
692//      SetDataFolder root:
693        Wave index = root:Packages:NIST:VSANS:Event:SavedIndex          //the index for the histogram
694       
695       
696        for(ii=0;ii<nslices;ii+=1)
697                if(ii==0)
698//                      t1 = ii*del
699//                      t2 = (ii+1)*del
700                        p1 = BinarySearch(rescaledTime,0)
701                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])
702                else
703//                      t2 = (ii+1)*del
704                        p1 = p2+1               //one more than the old one
705                        p2 = BinarySearch(rescaledTime,binEndTime[ii+1])               
706                endif
707
708                if(p1 == -1)
709                        Printf "p1 = -1 Binary search off the end %15.10g <?? %15.10g\r", 0, rescaledTime[0]
710                        p1 = 0          //set to the first point if it's off the end
711                Endif
712                if(p2 == -2)
713                        Printf "p2 = -2 Binary search off the end %15.10g >?? %15.10g\r", binEndTime[ii+1], rescaledTime[numpnts(rescaledTime)-1]
714                        p2 = numpnts(rescaledTime)-1            //set to the last point if it's off the end
715                Endif
716//              Print p1,p2
717
718
719                tmpData=0
720                V_JointHistogramWithRange(xLoc,yLoc,tmpData,index,p1,p2)
721                slicedData[][][ii] = tmpData[p][q]
722               
723//              binEndTime[ii+1] = t2
724                binCount[ii] = sum(tmpData,-inf,inf)
725        endfor
726
727        Duplicate/O slicedData,root:Packages:NIST:VSANS:Event:dispsliceData,root:Packages:NIST:VSANS:Event:logSlicedData
728        Wave logSlicedData = root:Packages:NIST:VSANS:Event:logSlicedData
729        logslicedData = log(slicedData)
730
731        SetDataFolder root:
732        return(0)
733End
734
735
736Proc    V_UndoTheSorting()
737        V_Osc_UndoSort()
738End
739
740// for oscillatory mode
741//
742// -- this takes the previously generated index, and un-sorts the data to restore to the
743// "as-collected" state
744//
745Function V_Osc_UndoSort()
746
747        SetDataFolder root:Packages:NIST:VSANS:Event            //don't count on the folder remaining here
748        Wave rescaledTime = rescaledTime
749        Wave OscSortIndex = OscSortIndex
750        Wave yLoc = yLoc
751        Wave xLoc = xLoc
752        Wave timePt = timePt
753
754        Sort OscSortIndex OscSortIndex,yLoc,xLoc,timePt,rescaledTime
755
756        KillWaves/Z OscSortIndex
757       
758        SetDataFolder root:
759        return(0)
760End
761
762
763// now before binning, sort the data
764//
765//this is slow - undoing the sorting and starting over, but if you don't,
766// you'll never be able to undo the sort
767//
768Function V_SortTimeData()
769
770
771        SetDataFolder root:Packages:NIST:VSANS:Event:
772
773        KillWaves/Z OscSortIndex
774       
775        if(WaveExists($"root:Packages:NIST:VSANS:Event:OscSortIndex") == 0 )
776                Duplicate/O rescaledTime OscSortIndex
777                MakeIndex rescaledTime OscSortIndex
778                IndexSort OscSortIndex, yLoc,xLoc,timePt,rescaledTime   
779        Endif
780       
781        SetDataFolder root:
782        return(0)
783End
784
785
786
787Function V_SetLinearBins(binEndTime,timeWidth,nslices,t_longest)
788        Wave binEndTime,timeWidth
789        Variable nslices,t_longest
790
791        Variable del,ii,t2
792        binEndTime[0]=0         //so the bar graph plots right...
793        del = t_longest/nslices
794       
795        for(ii=0;ii<nslices;ii+=1)
796                t2 = (ii+1)*del
797                binEndTime[ii+1] = t2
798        endfor
799        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
800
801        timeWidth = binEndTime[p+1]-binEndTime[p]
802
803        return(0)       
804End
805
806// TODO
807// either get this to work, or scrap it entirely. it currently isn't on the popup
808// so it can't be accessed
809Function V_SetLogBins(binEndTime,timeWidth,nslices,t_longest)
810        Wave binEndTime,timeWidth
811        Variable nslices,t_longest
812
813        Variable tMin,ii
814
815        Wave rescaledTime = root:Packages:NIST:VSANS:Event:rescaledTime
816       
817        binEndTime[0]=0         //so the bar graph plots right...
818
819        // just like the log-scaled q-points
820        tMin = rescaledTime[1]/1                        //just a guess... can't use tMin=0, and rescaledTime[0] == 0 by definition
821        Print rescaledTime[1], tMin
822        for(ii=0;ii<nslices;ii+=1)
823                binEndTime[ii+1] =alog(log(tMin) + (ii+1)*((log(t_longest)-log(tMin))/nslices))
824        endfor
825        binEndTime[ii+1] = t_longest            //otherwise floating point errors such that the last time point is off the end of the Binary search
826       
827        timeWidth = binEndTime[p+1]-binEndTime[p]
828
829        return(0)
830End
831
832Function V_MakeFibonacciWave(w,num)
833        Wave w
834        Variable num
835
836        //skip the initial zero
837        Variable f1,f2,ii
838        f1=1
839        f2=1
840        w[0] = f1
841        w[1] = f2
842        for(ii=2;ii<num;ii+=1)
843                w[ii] = f1+f2
844                f1=f2
845                f2=w[ii]
846        endfor
847               
848        return(0)
849end
850
851Function V_SetFibonacciBins(binEndTime,timeWidth,nslices,t_longest)
852        Wave binEndTime,timeWidth
853        Variable nslices,t_longest
854
855        Variable tMin,ii,total,t2,tmp
856        Make/O/D/N=(nslices) fibo
857        fibo=0
858        V_MakeFibonacciWave(fibo,nslices)
859       
860//      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}
861
862        binEndTime[0]=0         //so the bar graph plots right...
863        total = sum(fibo,0,nslices-1)           //total number of "pieces"
864       
865        tmp=0
866        for(ii=0;ii<nslices;ii+=1)
867                t2 = sum(fibo,0,ii)/total*t_longest
868                binEndTime[ii+1] = t2
869        endfor
870        binEndTime[ii+1] = t_longest            //otherwise floating point errors such that the last time point is off the end of the Binary search
871       
872        timeWidth = binEndTime[p+1]-binEndTime[p]
873       
874        return(0)
875End
876
877
878
879// TODO:
880//
881//
882//     
883Function V_LoadEventLog_Button(ctrlName) : ButtonControl
884        String ctrlName
885
886        NVAR mode=root:Packages:NIST:VSANS:Event:gEvent_mode
887        Variable err=0
888        Variable fileref,totBytes
889        NVAR fileTooLarge = root:Packages:NIST:VSANS:Event:gEventFileTooLarge           //limit load to 150MB
890
891        SVAR filename = root:Packages:NIST:VSANS:Event:gEvent_logfile
892        NVAR nslices = root:Packages:NIST:VSANS:Event:gEvent_nslices
893        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
894       
895        String fileFilters = "All Files:.*;Data Files (*.txt):.txt;"
896        String abortStr
897       
898        PathInfo catPathName
899        if(V_flag==0)
900                DoAlert 0,"Please 'Pick Path' to the data from the Main (yellow) Panel."
901                return(0)
902        endif
903       
904        Open/R/D/P=catPathName/F=fileFilters fileref
905        filename = S_filename
906        if(strlen(S_filename) == 0)
907                // user cancelled
908                DoAlert 0,"No file selected, no file loaded."
909                return(1)
910        endif
911
912// TODO - decide if I want (or need) to keep this       
913/// Abort if the files are too large
914//      Open/R fileref as fileName
915//              FStatus fileref
916//      Close fileref
917//
918//      totBytes = V_logEOF/1e6         //in MB
919//      if(totBytes > fileTooLarge)
920//              sprintf abortStr,"File is %g MB, larger than the limit of %g MB. Split and Decimate.",totBytes,fileTooLarge
921//              Abort abortStr
922//      endif
923//     
924//      Print "TotalBytes = ",totBytes
925       
926
927        SetDataFolder root:Packages:NIST:VSANS:Event:
928
929// load in the event file and decode it
930       
931//      V_readFakeEventFile(fileName)
932        V_LoadEvents()                  // this now loads, decodes, and returns location, tube, and timePt
933        SetDataFolder root:Packages:NIST:VSANS:Event:                   //GBLoadWave in V_LoadEvents sets back to root:
934
935// Now, I have tube, location, and timePt (no units yet)
936// assign to the proper panels
937
938// TODO:
939// x- (YES - this is MUCH faster) what if I do the JointHistogram first, then break out the blocks of the
940//  3D sliced data into the individual panels. Then the sort operation could be skipped,
941//  since it would implicitly be done during the histogram operation
942// x- go back and redimension as needed to get the 128 x 192 histogram to work
943// x- MatrixOp or a wave assignemt should be able to break up the 3D
944//
945
946                KillWaves/Z timePt,xLoc,yLoc
947                Duplicate/O eventTime timePt
948
949// TODO:
950// x- for processing, initially treat all of the tubes along x, and 128 pixels along y
951//   panels can be transposed later as needed to get the orientation correct
952
953                Duplicate/O tube xLoc
954                Duplicate/O location yLoc
955               
956                Redimension/D xLoc,yLoc,timePt 
957               
958//s_tic()
959//      V_SortAndSplitEvents()
960//
961//Printf "File sort and split time (s) = "
962//s_toc()
963
964
965//
966// switch the "active" panel to the selected group (1-4) (5 concatenates them all together)
967//
968// copy the set of tubes over to the "active" set that is to be histogrammed
969// and redimension them to be sure that they are double precision
970//
971
972//      V_SwitchTubeGroup(1)
973
974//     
975//tic()
976        Wave timePt=timePt
977        Wave xLoc=xLoc
978        Wave yLoc=yLoc
979        V_CleanupTimes(xLoc,yLoc,timePt)                //remove zeroes
980//toc()
981       
982        NVAR gResol = root:Packages:NIST:VSANS:Event:gResol             //timeStep in clock frequency (Hz)
983/////
984// now do a little processing of the times based on the type of data
985//     
986
987// TODO:
988//  -- the time scaling is NOT done. it is still in raw ticks.
989//
990        if(mode == MODE_STREAM)         // continuous "Stream" mode - start from zero
991                Duplicate/O timePt rescaledTime
992                rescaledTime = 1*(timePt-timePt[0])             //convert to nanoseconds and start from zero
993                t_longest = waveMax(rescaledTime)               //should be the last point     
994        endif
995       
996        if(mode == MODE_OSCILL)         // oscillatory mode - don't adjust the times, we get periodic t0 to reset t=0
997                Duplicate/O timePt rescaledTime
998                rescaledTime *= 1                       //convert to nanoseconds and that's all
999                t_longest = waveMax(rescaledTime)               //if oscillatory, won't be the last point, so get it this way
1000       
1001                KillWaves/Z OscSortIndex                        //to make sure that there is no old index hanging around
1002        endif
1003
1004// MODE_TISANE
1005
1006// MODE_TOF
1007        if(mode == MODE_TOF)            // TOF mode - don't adjust the times, we get periodic t0 to reset t=0
1008                Duplicate/O timePt rescaledTime
1009                rescaledTime *= 1                       //convert to nanoseconds and that's all
1010                t_longest = waveMax(rescaledTime)               //if oscillatory, won't be the last point, so get it this way
1011       
1012                KillWaves/Z OscSortIndex                        //to make sure that there is no old index hanging around
1013        endif
1014
1015        SetDataFolder root:
1016
1017        STRUCT WMButtonAction ba
1018        ba.eventCode = 2
1019        V_ShowEventDataButtonProc(ba)
1020
1021        return(0)
1022End
1023
1024
1025
1026
1027//
1028// -- MUCH faster to count the number of lines to remove, then delete (N)
1029// rather then delete them one-by-one in the do-loop
1030Function V_CleanupTimes(xLoc,yLoc,timePt)
1031        Wave xLoc,yLoc,timePt
1032
1033        // start at the back and remove zeros
1034        Variable num=numpnts(xLoc),ii,numToRemove
1035
1036        numToRemove = 0
1037        ii=num
1038        do
1039                ii -= 1
1040                if(timePt[ii] == 0 && xLoc[ii] == 0 && yLoc[ii] == 0)
1041                        numToRemove += 1
1042                endif
1043        while(timePt[ii-1] == 0 && xLoc[ii-1] == 0 && yLoc[ii-1] == 0)
1044       
1045        if(numToRemove != 0)
1046                DeletePoints ii, numToRemove, xLoc,yLoc,timePt
1047        endif
1048       
1049        return(0)
1050End
1051
1052Function V_LogIntEvent_Proc(ctrlName,checked) : CheckBoxControl
1053        String ctrlName
1054        Variable checked
1055               
1056        SetDataFolder root:Packages:NIST:VSANS:Event
1057       
1058        Wave slicedData = slicedData
1059        Wave logSlicedData = logSlicedData
1060        Wave dispSliceData = dispSliceData
1061       
1062        if(checked)
1063                logslicedData = log(slicedData)
1064                Duplicate/O logslicedData dispsliceData
1065        else
1066                Duplicate/O slicedData dispsliceData
1067        endif
1068
1069        NVAR selectedslice = root:Packages:NIST:VSANS:Event:gEvent_tsdisp
1070
1071        V_sliceSelectEvent_Proc("", selectedslice, "", "")
1072
1073        SetDataFolder root:
1074
1075End
1076
1077
1078// TODO (DONE)
1079// this "fails" for data sets that have 3 or 4 slices, as the ModifyImage command
1080// interprets the data as being RGB - and so does nothing.
1081// need to find a way around this
1082//
1083////  When first plotted, AppendImage/G=1 flag prevents interpretation as RGB so 3, 4 slices display correctly
1084///
1085// I could modify this procedure to use the log = 0|1 keyword for the log Z display
1086// rather than creating a duplicate wave of log(data)
1087//
1088Function V_sliceSelectEvent_Proc(ctrlName, varNum, varStr, varName) : SetVariableControl
1089        String ctrlName
1090        Variable varNum
1091        String varStr
1092        String varName
1093       
1094        NVAR nslices = root:Packages:NIST:VSANS:Event:gEvent_nslices
1095        NVAR selectedslice = root:Packages:NIST:VSANS:Event:gEvent_tsdisp
1096       
1097        if(varNum < 0)
1098                selectedslice = 0
1099                DoUpdate
1100        elseif (varNum > nslices-1)
1101                selectedslice = nslices-1
1102                DoUpdate
1103        else
1104                ModifyImage/W=VSANS_EventModePanel#Event_slicegraph ''#0 plane = varNum
1105        endif
1106
1107End
1108
1109Function V_DifferentiatedTime()
1110
1111        Wave rescaledTime = root:Packages:NIST:VSANS:Event:rescaledTime
1112
1113        SetDataFolder root:Packages:NIST:VSANS:Event:
1114               
1115        Differentiate rescaledTime/D=rescaledTime_DIF
1116//      Display rescaledTime,rescaledTime_DIF
1117        DoWindow/F V_Differentiated_Time
1118        if(V_flag == 0)
1119                Display/N=V_Differentiated_Time/K=1 rescaledTime_DIF
1120                Legend
1121                Modifygraph gaps=0
1122                ModifyGraph zero(left)=1
1123                Label left "\\Z14Delta (dt/event)"
1124                Label bottom "\\Z14Event number"
1125        endif
1126       
1127        SetDataFolder root:
1128       
1129        return(0)
1130End
1131
1132
1133//
1134// for the bit shifts, see the decimal-binary conversion
1135// http://www.binaryconvert.com/convert_unsigned_int.html
1136//
1137//  for 64-bit values:
1138// http://calc.penjee.com
1139//
1140//              K0 = 536870912
1141//              Print (K0 & 0x08000000)/134217728       //bit 27 only, shift by 2^27
1142//              Print (K0 & 0x10000000)/268435456               //bit 28 only, shift by 2^28
1143//              Print (K0 & 0x20000000)/536870912               //bit 29 only, shift by 2^29
1144//
1145//
1146//
1147// This function loads the events, and decodes them.
1148// Assigning them to detector panels is a separate function
1149//
1150//
1151//
1152Function V_LoadEvents()
1153       
1154        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
1155       
1156        SVAR filepathstr = root:Packages:NIST:VSANS:Event:gEvent_logfile
1157        SVAR dispStr = root:Packages:NIST:VSANS:Event:gEventDisplayString
1158       
1159        SetDataFolder root:Packages:NIST:VSANS:Event
1160
1161        Variable refnum
1162        String buffer
1163        String fileStr,tmpStr
1164        Variable verbose
1165        Variable xval,yval
1166        Variable numXYevents,totBytes
1167
1168//  to read a VSANS event file:
1169//
1170// - get the file name
1171//      - read the header (all of it, since I need parts of it) (maybe read as a struct? but I don't know the size!)
1172// - move to EOF and close
1173//
1174// - Use GBLoadWave to read the 64-bit events in
1175
1176
1177/// globals to report the header back for use or status
1178        SVAR gVSANSStr = root:Packages:NIST:VSANS:Event:gVsansStr
1179        NVAR gRevision = root:Packages:NIST:VSANS:Event:gRevision
1180        NVAR gOffset = root:Packages:NIST:VSANS:Event:gOffset           // = 22 bytes if no disabled tubes
1181        NVAR gTime1 = root:Packages:NIST:VSANS:Event:gTime1
1182        NVAR gTime2 = root:Packages:NIST:VSANS:Event:gTime2
1183        NVAR gTime3 = root:Packages:NIST:VSANS:Event:gTime3
1184        NVAR gTime4 = root:Packages:NIST:VSANS:Event:gTime4     // these 4 time pieces are supposed to be 8 bytes total
1185        NVAR gTime5 = root:Packages:NIST:VSANS:Event:gTime5     // these 5 time pieces are supposed to be 10 bytes total
1186        SVAR gDetStr = root:Packages:NIST:VSANS:Event:gDetStr
1187        NVAR gVolt = root:Packages:NIST:VSANS:Event:gVolt
1188        NVAR gResol = root:Packages:NIST:VSANS:Event:gResol             //time resolution in nanoseconds
1189/////
1190
1191        gVSANSStr = PadString(gVSANSStr,5,0x20)         //pad to 5 bytes
1192        gDetStr = PadString(gDetStr,1,0x20)                             //pad to 1 byte
1193
1194        numXYevents = 0
1195
1196
1197        Open/R refnum as filepathstr
1198       
1199s_tic()
1200
1201        FBinRead refnum, gVSANSStr
1202        FBinRead/F=2/U refnum, gRevision
1203        FBinRead/F=2/U refnum, gOffset
1204        FBinRead/F=2/U refnum, gTime1
1205        FBinRead/F=2/U refnum, gTime2
1206        FBinRead/F=2/U refnum, gTime3
1207        FBinRead/F=2/U refnum, gTime4
1208        FBinRead/F=2/U refnum, gTime5
1209        FBinRead refnum, gDetStr
1210        FBinRead/F=2/U refnum, gVolt
1211        FBinRead/F=3/U refnum, gResol
1212
1213        FStatus refnum
1214        FSetPos refnum, V_logEOF
1215       
1216        Close refnum
1217       
1218// number of data bytes
1219        numXYevents = (V_logEOF-gOffset)/8
1220        Print "Number of data values = ",numXYevents
1221       
1222        GBLoadWave/B/T={192,192}/W=1/S=(gOffset) filepathstr
1223       
1224        Duplicate/O $(StringFromList(0,S_waveNames)) V_Events
1225        KillWaves/Z $(StringFromList(0,S_waveNames))
1226
1227Printf "Time to read file (s) = "
1228s_toc()
1229
1230
1231        totBytes = V_logEOF
1232        Print "total bytes = ", totBytes
1233       
1234
1235// V_Events is the uint64 wave that was read in
1236//
1237////// Now decode the events
1238
1239
1240s_tic()
1241        WAVE V_Events = V_Events
1242        uint64 val,b1,b2,btime
1243
1244       
1245        Variable num,ii
1246        num=numpnts(V_Events)
1247       
1248        Make/O/L/U/N=(num) eventTime                    //64 bit unsigned
1249        Make/O/U/B/N=(num) tube,location                //8 bit unsigned
1250
1251// MultiThread is about 10x faster than the for loop
1252 MultiThread tube = (V_Events[p]) & 0xFF       
1253 MultiThread location = (V_Events[p] >> 8 ) & 0xFF     
1254 MultiThread eventTime = (V_Events[p] >> 16)
1255       
1256//      for(ii=0;ii<num;ii+=1)
1257//              val = V_Events[ii]
1258//             
1259////            b1 = (val >> 56 ) & 0xFF                        // = 255, last two bytes, after shifting
1260////            b2 = (val >> 48 ) & 0xFF       
1261////            btime = val & 0xFFFFFFFFFFFF    // = really big number, last 6 bytes
1262//
1263//              b1 = val & 0xFF
1264//              b2 = (val >> 8) & 0xFF
1265//              btime = (val >> 16)
1266//
1267//
1268//              tube[ii] = b1
1269//              location[ii] = b2
1270//              eventTime[ii] = btime
1271//             
1272//      endfor
1273
1274Printf "File decode time (s) = "
1275s_toc()
1276
1277//      KillWaves/Z timePt,xLoc,yLoc
1278//      Rename tube xLoc
1279//      Rename location yLoc
1280//      Rename eventTime timePt
1281//     
1282//      Redimension/D xLoc,yLoc,timePt
1283       
1284
1285// TODO
1286// add more to the status display of the file load/decode
1287//     
1288        // dispStr will be displayed on the panel
1289        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
1290       
1291        sprintf tmpStr, "%s: %d total bytes\r",fileStr,totBytes
1292        dispStr = tmpStr
1293        sprintf tmpStr,"numXYevents = %d\r",numXYevents
1294        dispStr += tmpStr
1295//      sPrintf tmpStr,"\rBad Rollover Events = %d (%4.4g %% of events)",numBad,numBad/numXYevents*100
1296//      dispStr += tmpStr
1297//      sPrintf tmpStr,"\rTotal Events Removed = %d (%4.4g %% of events)",numRemoved,numRemoved/numXYevents*100
1298//      dispStr += tmpStr
1299
1300        SetDataFolder root:
1301       
1302        return(0)
1303       
1304End
1305
1306////////////////
1307////
1308//// This calls the XOP, as an operation to load the events
1309////
1310//// -- it's about 35x faster than the Igor code, so I guess that's OK.
1311////
1312//// conditional compile the whole inner workings in case XOP is not present
1313//Function LoadEvents_XOP()
1314//#if (exists("EventLoadWave")==4)
1315//     
1316////    NVAR time_msw = root:Packages:NIST:VSANS:Event:gEvent_time_msw
1317////    NVAR time_lsw = root:Packages:NIST:VSANS:Event:gEvent_time_lsw
1318//      NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
1319//     
1320//      SVAR filepathstr = root:Packages:NIST:VSANS:Event:gEvent_logfile
1321//      SVAR dispStr = root:Packages:NIST:VSANS:Event:gEventDisplayString
1322//     
1323//      SetDataFolder root:Packages:NIST:VSANS:Event
1324//
1325//
1326//
1327//      Variable fileref
1328//      String buffer
1329//      String fileStr,tmpStr
1330//      Variable dataval,timeval,type,numLines,verbose,verbose3
1331//      Variable xval,yval,rollBit,nRoll,roll_time,bit29,bit28,bit27
1332//      Variable ii,flaggedEvent,rolloverHappened,numBad=0,tmpPP=0,tmpT0=0
1333//      Variable Xmax, yMax
1334//     
1335//      xMax = 127              // number the detector from 0->127
1336//      yMax = 127
1337//     
1338//      numLines = 0
1339//
1340//      //Have to declare local variables for Loadwave so that this compiles without XOP.
1341//      String S_waveNames
1342//      //  and those for the XOP
1343//      Variable V_nXYevents,V_num1,V_num2,V_num3,V_num0,V_totBytes,V_numPP,V_numT0,V_numDL,V_numFF,V_numZero
1344//      Variable V_numBad,V_numRemoved
1345//     
1346//      // what I really need is the number of XY events
1347//      Variable numXYevents,num1,num2,num3,num0,totBytes,numPP,numT0,numDL,numFF,numZero
1348//      Variable numRemoved
1349//      numXYevents = 0
1350//      num0 = 0
1351//      num1 = 0
1352//      num2 = 0
1353//      num3 = 0
1354//      numPP = 0
1355//      numT0 = 0
1356//      numDL = 0
1357//      numFF = 0
1358//      numZero = 0
1359//      numRemoved = 0
1360//
1361//// get the total number of bytes in the file
1362//      Open/R fileref as filepathstr
1363//              FStatus fileref
1364//      Close fileref
1365//
1366//      totBytes = V_logEOF
1367//      Print "total bytes = ", totBytes
1368//     
1369////
1370////    Print "scan only"
1371////    tic()
1372////            EventLoadWave/R/N=EventWave/W filepathstr
1373////    toc()
1374//
1375//////
1376////
1377////  use the XOP operation to load in the data
1378//// -- this does everything - the pre-scan and creating the waves
1379////
1380//// need to zero the waves before loading, just in case
1381////
1382//
1383//      NVAR removeBadEvents = root:Packages:NIST:VSANS:Event:gRemoveBadEvents
1384//
1385//s_tic()
1386//
1387////    Wave/Z wave0=wave0
1388////    Wave/Z wave1=wave1
1389////    Wave/Z wave2=wave2
1390////
1391////    if(WaveExists(wave0))
1392////            MultiThread wave0=0
1393////    endif
1394////    if(WaveExists(wave1))
1395////            MultiThread wave1=0
1396////    endif
1397////    if(WaveExists(wave2))
1398////            MultiThread wave2=0
1399////    endif
1400//
1401//      if(removeBadEvents)
1402//              EventLoadWave/R/N=EventWave filepathstr
1403//      else
1404//              EventLoadWave/N=EventWave  filepathstr
1405//      endif
1406//
1407//
1408//      Print "XOP files loaded = ",S_waveNames
1409//
1410//////          -- copy the waves over to xLoc,yLoc,timePt
1411//      Wave/Z EventWave0=EventWave0
1412//      Wave/Z EventWave1=EventWave1
1413//      Wave/Z EventWave2=EventWave2
1414//     
1415//     
1416//      Duplicate/O EventWave0,xLoc
1417//      KillWaves/Z EventWave0
1418//
1419//      Duplicate/O EventWave1,yLoc
1420//      KillWaves/Z EventWave1
1421//
1422//      Duplicate/O EventWave2,timePt
1423//      KillWaves/Z EventWave2
1424//
1425//// could do this, but rescaled time will neeed to be converted to SP (or DP)
1426//// and Igor loader was written with Make generating SP/DP waves
1427//      // /I/U is unsigned 32-bit integer (for the time)
1428//      // /B/U is unsigned 8-bit integer (max val=255) for the x and y values
1429//     
1430////    Redimension/B/U xLoc,yLoc
1431////    Redimension/I/U timePt
1432//
1433//      // access the variables from the XOP
1434//      numT0 = V_numT0
1435//      numPP = V_numPP
1436//      num0 = V_num0
1437//      num1 = V_num1
1438//      num2 = V_num2
1439//      num3 = V_num3
1440//      numXYevents = V_nXYevents
1441//      numZero = V_numZero
1442//      numBad = V_numBad
1443//      numRemoved = V_numRemoved
1444//     
1445//      Print "(XOP) numT0 = ",numT0   
1446//      Print "num0 = ",num0   
1447//      Print "num1 = ",num1   
1448//      Print "num2 = ",num2   
1449//      Print "num3 = ",num3   
1450//     
1451//
1452//// dispStr will be displayed on the panel
1453//      fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
1454//     
1455//      sprintf tmpStr, "%s: %d total bytes\r",fileStr,totBytes
1456//      dispStr = tmpStr
1457//      sprintf tmpStr,"numXYevents = %d\r",numXYevents
1458//      dispStr += tmpStr
1459//      sprintf tmpStr,"PP = %d  :  ",numPP
1460//      dispStr += tmpStr
1461//      sprintf tmpStr,"ZeroData = %d\r",numZero
1462//      dispStr += tmpStr
1463//      sprintf tmpStr,"Rollover = %d",num3
1464//      dispStr += tmpStr
1465//
1466//      s_toc()
1467//     
1468//      Print "Events removed (XOP) = ",numRemoved
1469//     
1470//      sPrintf tmpStr,"\rBad Rollover Events = %d (%4.4g %% of events)",numBad,numBad/numXYevents*100
1471//      dispStr += tmpStr
1472//      sPrintf tmpStr,"\rTotal Events Removed = %d (%4.4g %% of events)",numRemoved,numRemoved/numXYevents*100
1473//      dispStr += tmpStr
1474//
1475//
1476//// simply to compile a table of # XY vs # bytes
1477////    Wave/Z nxy = root:numberXY
1478////    Wave/Z nBytes = root:numberBytes
1479////    if(WaveExists(nxy) && WaveExists(nBytes))
1480////            InsertPoints 0, 1, nxy,nBytes
1481////            nxy[0] = numXYevents
1482////            nBytes[0] = totBytes
1483////    endif
1484//
1485//      SetDataFolder root:
1486//
1487//#endif       
1488//      return(0)
1489//     
1490//End
1491
1492//////////////
1493
1494Proc V_BinEventBarGraph()
1495       
1496        DoWindow/F V_EventBarGraph
1497        if(V_flag == 0)
1498                PauseUpdate; Silent 1           // building window...
1499                String fldrSav0= GetDataFolder(1)
1500                SetDataFolder root:Packages:NIST:VSANS:Event:
1501                Display /W=(110,705,610,1132)/N=V_EventBarGraph /K=1 binCount vs binEndTime
1502                SetDataFolder fldrSav0
1503                ModifyGraph mode=5
1504                ModifyGraph marker=19
1505                ModifyGraph lSize=2
1506                ModifyGraph rgb=(0,0,0)
1507                ModifyGraph msize=2
1508                ModifyGraph hbFill=2
1509                ModifyGraph gaps=0
1510                ModifyGraph usePlusRGB=1
1511                ModifyGraph toMode=0
1512                ModifyGraph useBarStrokeRGB=1
1513                ModifyGraph standoff=0
1514                SetAxis left 0,*
1515                Label bottom "\\Z14Time (seconds)"
1516                Label left "\\Z14Number of Events"
1517        endif
1518End
1519
1520
1521Proc V_ShowBinTable()
1522
1523        DoWindow/F V_BinEventTable
1524        if(V_flag == 0)
1525                PauseUpdate; Silent 1           // building window...
1526                String fldrSav0= GetDataFolder(1)
1527                SetDataFolder root:Packages:NIST:VSANS:Event:
1528                Edit/W=(498,699,1003,955) /K=1/N=V_BinEventTable binCount,binEndTime,timeWidth
1529                ModifyTable format(Point)=1,sigDigits(binEndTime)=8,width(binEndTime)=100
1530                SetDataFolder fldrSav0
1531        endif
1532EndMacro
1533
1534
1535// only show the first 1500 data points
1536//
1537Proc V_ShowRescaledTimeGraph()
1538
1539        DoWindow/F V_RescaledTimeGraph
1540        if(V_flag == 0)
1541                PauseUpdate; Silent 1           // building window...
1542                String fldrSav0= GetDataFolder(1)
1543                SetDataFolder root:Packages:NIST:VSANS:Event:
1544                Display /W=(25,44,486,356)/K=1/N=V_RescaledTimeGraph rescaledTime
1545                SetDataFolder fldrSav0
1546                ModifyGraph mode=4
1547                ModifyGraph marker=19
1548                ModifyGraph rgb(rescaledTime)=(0,0,0)
1549                ModifyGraph msize=1
1550//              SetAxis/A=2 left                        //only autoscale the visible data (based on the bottom limits)
1551                SetAxis bottom 0,1500
1552                ErrorBars rescaledTime OFF
1553                Label left "\\Z14Time (seconds)"
1554                Label bottom "\\Z14Event number"
1555                ShowInfo
1556        endif
1557       
1558EndMacro
1559
1560
1561
1562//Proc ExportSlicesAsVAX(firstNum,prefix)
1563//      Variable firstNum=1
1564//      String prefix="SAMPL"
1565//
1566//      SaveSlicesAsVAX(firstNum,prefix[0,4])           //make sure that the prefix is 5 chars
1567//End
1568
1569////////// procedures to be able to export the slices as RAW VAX files.
1570////
1571//// 1- load the raw data file to use the header (it must already be in RAW)
1572//// 1.5- copy the raw data to the temp folder (STO)
1573//// 1.7- ask for the prefix and starting run number (these are passed in)
1574//// 2- copy the slice of data to the temp folder (STO)
1575//// 3- touch up the time/counts in the slice header values in STO
1576//// 4- write out the VAX file
1577//// 5- repeat (2-4) for the number of slices
1578////
1579////
1580//Function SaveSlicesAsVAX(firstNum,prefix)
1581//      Variable firstNum
1582//      String prefix
1583//
1584//      DoAlert 1,"Is the full data file loaded as a RAW data file? If not, load it and start over..."
1585//      if(V_flag == 2)
1586//              return (0)
1587//      endif
1588//     
1589//// copy the contents of RAW to STO so I can work from there
1590//      CopyWorkContents("RAW","STO")
1591//
1592//      // now declare all of the waves, now that they are sure to be there
1593//
1594//      WAVE slicedData=root:Packages:NIST:VSANS:Event:slicedData
1595//      Make/O/D/N=(128,128) curSlice
1596//     
1597//      NVAR nslices = root:Packages:NIST:VSANS:Event:gEvent_nslices
1598//      WAVE binEndTime = root:Packages:NIST:VSANS:Event:binEndTime
1599//
1600//      Wave rw=root:Packages:NIST:STO:realsRead
1601//      Wave iw=root:Packages:NIST:STO:integersRead
1602//      Wave/T tw=root:Packages:NIST:STO:textRead
1603//      Wave data=root:Packages:NIST:STO:data
1604//      Wave linear_data=root:Packages:NIST:STO:linear_data
1605//     
1606//     
1607//      Wave rw_raw=root:Packages:NIST:RAW:realsRead
1608//      Wave iw_raw=root:Packages:NIST:RAW:integersRead
1609//      Wave/T tw_raw=root:Packages:NIST:RAW:textRead
1610//
1611//// for generating the alphanumeric
1612//      String timeStr= secs2date(datetime,-1)
1613//      String monthStr=StringFromList(1, timeStr  ,"/")
1614//      String numStr="",labelStr
1615//
1616//      Variable ii,err,binFraction
1617//     
1618//      for(ii=0;ii<nslices;ii+=1)
1619//
1620//              //get the current slice and put it in the STO folder
1621//              curSlice = slicedData[p][q][ii]
1622//              data = curSlice
1623//              linear_data = curSlice
1624//             
1625//              // touch up the header as needed
1626//              // count time = iw[2]
1627//              // monCt = rw[0]
1628//              // detCt = rw[2]
1629//              //tw[0] must now be the file name
1630//              //
1631//              // count time = fraction of total binning * total count time
1632//              binFraction = (binEndTime[ii+1]-binEndTime[ii])/(binEndTime[nslices]-binEndTime[0])
1633//             
1634//              iw[2] = trunc(binFraction*iw_raw[2])
1635//              rw[0] = trunc(binFraction*rw_raw[0])
1636//              rw[2] = sum(curSlice,-inf,inf)          //total counts in slice
1637//     
1638//              if(firstNum<10)
1639//                      numStr = "00"+num2str(firstNum)
1640//              else
1641//                      if(firstNum<100)
1642//                              numStr = "0"+num2str(firstNum)
1643//                      else
1644//                              numStr = num2str(firstNum)
1645//                      Endif
1646//              Endif   
1647//              tw[0] = prefix+numstr+".SA2_EVE_"+(num2char(str2num(monthStr)+64))+numStr
1648//              labelStr = tw_raw[6]
1649//             
1650//              labelStr = PadString(labelStr,60,0x20)  //60 fortran-style spaces
1651//              tw[6] = labelStr[0,59]
1652//             
1653//              //write out the file - this uses the tw[0] and home path
1654//              Write_VAXRaw_Data("STO","",0)
1655//
1656//              //increment the run number, alpha
1657//              firstNum += 1   
1658//      endfor
1659//
1660//      return(0)
1661//End
1662//
1663
1664
1665
1666
1667/////////////
1668//The histogramming
1669//
1670// 6 AUG 2012
1671//
1672// from Igor Exchange, RGerkin
1673//  http://www.igorexchange.com/node/1373
1674// -- see the related thread on the mailing list
1675//
1676//Function Setup_JointHistogram()
1677//
1678////    tic()
1679//
1680//      make/D /o/n=1000000 data1=gnoise(1), data2=gnoise(1)
1681//      make/D /o/n=(25,25) myHist
1682//      setscale x,-3,3,myHist
1683//      setscale y,-3,3,myHist
1684//      IndexForHistogram(data1,data2,myhist)
1685//      Wave index=SavedIndex
1686//      JointHistogram(data1,data2,myHist,index)
1687//      NewImage myHist
1688//     
1689////    toc()
1690//     
1691//End
1692
1693
1694// this is not used - it now conflicts with the name of a built-in function in Igor 7
1695//
1696Function xJointHistogram(w0,w1,hist,index)
1697        wave w0,w1,hist,index
1698 
1699        variable bins0=dimsize(hist,0)
1700        variable bins1=dimsize(hist,1)
1701        variable n=numpnts(w0)
1702        variable left0=dimoffset(hist,0)
1703        variable left1=dimoffset(hist,1)
1704        variable right0=left0+bins0*dimdelta(hist,0)
1705        variable right1=left1+bins1*dimdelta(hist,1)
1706       
1707        // Compute the histogram and redimension it. 
1708        histogram /b={0,1,bins0*bins1} index,hist
1709        redimension/D /n=(bins0,bins1) hist // Redimension to 2D. 
1710        setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
1711        setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
1712End
1713
1714
1715// histogram with a point range
1716//
1717// x- just need to send x2pnt or findLevel, or something similar to define the POINT
1718// values
1719//
1720// x- can also speed this up since the index only needs to be done once, so the
1721// histogram operation can be done separately, as the bins require
1722//
1723//
1724Function V_JointHistogramWithRange(w0,w1,hist,index,pt1,pt2)
1725        wave w0,w1,hist,index
1726        Variable pt1,pt2
1727 
1728        variable bins0=dimsize(hist,0)
1729        variable bins1=dimsize(hist,1)
1730        variable n=numpnts(w0)
1731        variable left0=dimoffset(hist,0)
1732        variable left1=dimoffset(hist,1)
1733        variable right0=left0+bins0*dimdelta(hist,0)
1734        variable right1=left1+bins1*dimdelta(hist,1)
1735
1736        // Compute the histogram and redimension it. 
1737        histogram /b={0,1,bins0*bins1}/R=[pt1,pt2] index,hist
1738        redimension/D /n=(bins0,bins1) hist // Redimension to 2D. 
1739        setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
1740        setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
1741End
1742
1743
1744// just does the indexing, creates wave SavedIndex in the current folder for the index
1745//
1746Function V_IndexForHistogram(w0,w1,hist)
1747        wave w0,w1,hist
1748 
1749        variable bins0=dimsize(hist,0)
1750        variable bins1=dimsize(hist,1)
1751        variable n=numpnts(w0)
1752        variable left0=dimoffset(hist,0)
1753        variable left1=dimoffset(hist,1)
1754        variable right0=left0+bins0*dimdelta(hist,0)
1755        variable right1=left1+bins1*dimdelta(hist,1)
1756 
1757        // Scale between 0 and the number of bins to create an index wave. 
1758        if(ThreadProcessorCount<4) // For older machines, matrixop is faster. 
1759                matrixop /free idx=round(bins0*(w0-left0)/(right0-left0))+bins0*round(bins1*(w1-left1)/(right1-left1))
1760        else // For newer machines with many cores, multithreading with make is faster. 
1761                make/free/n=(n) idx
1762                multithread idx=round(bins0*(w0-left0)/(right0-left0))+bins0*round(bins1*(w1-left1)/(right1-left1))
1763        endif
1764 
1765        KillWaves/Z SavedIndex
1766        MoveWave idx,SavedIndex
1767       
1768//      // Compute the histogram and redimension it. 
1769//      histogram /b={0,1,bins0*bins1} idx,hist
1770//      redimension /n=(bins0,bins1) hist // Redimension to 2D. 
1771//      setscale x,left0,right0,hist // Fix the histogram scaling in the x-dimension. 
1772//      setscale y,left1,right1,hist // Fix the histogram scaling in the y-dimension. 
1773End
1774
1775
1776
1777
1778
1779////////////// Post-processing of the event mode data
1780//
1781//
1782// TODO:
1783// -- this is ALL geared towards ordela event mode data and the 6.7s errors, and bad signal
1784//   I don't know if I'll need any of this for the VSANS event data.
1785//
1786//
1787Proc V_ShowEventCorrectionPanel()
1788        DoWindow/F V_EventCorrectionPanel
1789        if(V_flag ==0)
1790                V_EventCorrectionPanel()
1791        EndIf
1792End
1793
1794Proc V_EventCorrectionPanel()
1795
1796        PauseUpdate; Silent 1           // building window...
1797        SetDataFolder root:Packages:NIST:VSANS:Event:
1798       
1799        if(exists("rescaledTime") == 1)
1800                Display /W=(35,44,761,533)/K=2 rescaledTime
1801                DoWindow/C V_EventCorrectionPanel
1802                ModifyGraph mode=4
1803                ModifyGraph marker=19
1804                ModifyGraph rgb=(0,0,0)
1805                ModifyGraph msize=1
1806                ErrorBars rescaledTime OFF
1807                Label left "\\Z14Time (seconds)"
1808                Label bottom "\\Z14Event number"       
1809                SetAxis bottom 0,0.10*numpnts(rescaledTime)             //show 1st 10% of data for speed in displaying
1810               
1811                ControlBar 100
1812                Button button0,pos={18,12},size={70,20},proc=V_EC_AddCursorButtonProc,title="Cursors"
1813                Button button1,pos={153,12},size={80,20},proc=V_EC_AddTimeButtonProc,title="Add time"
1814                Button button2,pos={153,38},size={80,20},proc=V_EC_SubtractTimeButtonProc,title="Subtr time"
1815                Button button3,pos={153,64},size={90,20},proc=V_EC_TrimPointsButtonProc,title="Trim points"
1816                Button button4,pos={295+150,12},size={90,20},proc=V_EC_SaveWavesButtonProc,title="Save Waves"
1817                Button button5,pos={295,64},size={100,20},proc=V_EC_FindOutlierButton,title="Find Outlier"
1818                Button button6,pos={18,38},size={80,20},proc=V_EC_ShowAllButtonProc,title="All Data"
1819                Button button7,pos={683,12},size={30,20},proc=V_EC_HelpButtonProc,title="?"
1820                Button button8,pos={658,72},size={60,20},proc=V_EC_DoneButtonProc,title="Done"
1821       
1822                Button button9,pos={295,12},size={110,20},proc=V_EC_FindStepButton_down,title="Find Step Down"
1823                Button button10,pos={295,38},size={110,20},proc=V_EC_FindStepButton_up,title="Find Step Up"
1824                Button button11,pos={295+150,38},size={110,20},proc=V_EC_DoDifferential,title="Differential"
1825               
1826               
1827        else
1828                DoAlert 0, "Please load some event data, then you'll have something to edit."
1829        endif
1830       
1831        SetDataFolder root:
1832       
1833EndMacro
1834
1835Function V_EC_AddCursorButtonProc(ba) : ButtonControl
1836        STRUCT WMButtonAction &ba
1837
1838        switch( ba.eventCode )
1839                case 2: // mouse up
1840                        // click code here
1841                        SetDataFolder root:Packages:NIST:VSANS:Event:
1842                       
1843                        Wave rescaledTime = rescaledTime
1844                        Cursor/P A rescaledTime 0
1845                        Cursor/P B rescaledTime numpnts(rescaledTime)-1
1846                        ShowInfo
1847                        SetDataFolder root:
1848                        break
1849                case -1: // control being killed
1850                        break
1851        endswitch
1852
1853        return 0
1854End
1855
1856// updates the longest time (as does every operation of adjusting the data)
1857//
1858Function V_EC_AddTimeButtonProc(ba) : ButtonControl
1859        STRUCT WMButtonAction &ba
1860
1861        switch( ba.eventCode )
1862                case 2: // mouse up
1863                        // click code here
1864                        SetDataFolder root:Packages:NIST:VSANS:Event:
1865                       
1866                        Wave rescaledTime = rescaledTime
1867                        Wave timePt = timePt
1868                        Variable rollTime,rollTicks,ptA,ptB,lo,hi
1869                       
1870                        rollTicks = 2^26                                // in ticks
1871                        rollTime = 2^26*1e-7            // in seconds
1872                        ptA = pcsr(A)
1873                        ptB = pcsr(B)
1874                        lo=min(ptA,ptB)
1875                        hi=max(ptA,ptB)
1876
1877                        MultiThread timePt[lo,hi] += rollTicks
1878                        MultiThread rescaledTime[lo,hi] += rollTime
1879
1880                        // updates the longest time (as does every operation of adjusting the data)
1881                        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
1882                        t_longest = waveMax(rescaledTime)
1883                       
1884                        SetDataFolder root:
1885                        break
1886                case -1: // control being killed
1887                        break
1888        endswitch
1889
1890        return 0
1891End
1892
1893Function V_EC_SubtractTimeButtonProc(ba) : ButtonControl
1894        STRUCT WMButtonAction &ba
1895
1896        switch( ba.eventCode )
1897                case 2: // mouse up
1898                        // click code here
1899                        SetDataFolder root:Packages:NIST:VSANS:Event:
1900                       
1901                        Wave rescaledTime = rescaledTime
1902                        Wave timePt = timePt
1903                        Variable rollTime,rollTicks,ptA,ptB,lo,hi
1904                       
1905                        rollTicks = 2^26                                // in ticks
1906                        rollTime = 2^26*1e-7            // in seconds
1907                        ptA = pcsr(A)
1908                        ptB = pcsr(B)
1909                        lo=min(ptA,ptB)
1910                        hi=max(ptA,ptB)
1911                       
1912                        MultiThread timePt[lo,hi] -= rollTicks
1913                        MultiThread rescaledTime[lo,hi] -= rollTime
1914
1915                        // updates the longest time (as does every operation of adjusting the data)
1916                        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
1917                        t_longest = waveMax(rescaledTime)
1918                       
1919                        SetDataFolder root:
1920                       
1921                        break
1922                case -1: // control being killed
1923                        break
1924        endswitch
1925
1926        return 0
1927End
1928
1929// points removed are inclusive
1930//
1931// put both cursors on the same point to remove just that single point
1932//
1933Function V_EC_TrimPointsButtonProc(ba) : ButtonControl
1934        STRUCT WMButtonAction &ba
1935
1936        switch( ba.eventCode )
1937                case 2: // mouse up
1938                        // click code here
1939                        SetDataFolder root:Packages:NIST:VSANS:Event:
1940                       
1941                        Wave rescaledTime = rescaledTime
1942                        Wave timePt = timePt
1943                        Wave xLoc = xLoc
1944                        Wave yLoc = yLoc
1945                        Variable rollTime,ptA,ptB,numElements,lo,hi
1946                       
1947                        rollTime = 2^26*1e-7            // in seconds
1948                        ptA = pcsr(A)
1949                        ptB = pcsr(B)
1950                        lo=min(ptA,ptB)
1951                        hi=max(ptA,ptB)                 
1952                        numElements = abs(ptA-ptB)+1                    //so points removed are inclusive
1953                        DeletePoints lo, numElements, rescaledTime,timePt,xLoc,yLoc
1954                       
1955                        printf "Points %g to %g have been deleted in rescaledTime, timePt, xLoc, and yLoc\r",ptA,ptB
1956                       
1957                        // updates the longest time (as does every operation of adjusting the data)
1958                        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
1959                        t_longest = waveMax(rescaledTime)
1960                       
1961                        SetDataFolder root:
1962                       
1963                        break
1964                case -1: // control being killed
1965                        break
1966        endswitch
1967
1968        return 0
1969End
1970
1971// un-sort the data first, then save it
1972Function V_EC_SaveWavesButtonProc(ba) : ButtonControl
1973        STRUCT WMButtonAction &ba
1974
1975        switch( ba.eventCode )
1976                case 2: // mouse up
1977                        // click code here
1978                       
1979//                      Execute "UndoTheSorting()"
1980                       
1981                        SetDataFolder root:Packages:NIST:VSANS:Event:
1982                       
1983                        Wave rescaledTime = rescaledTime
1984                        Wave timePt = timePt
1985                        Wave xLoc = xLoc
1986                        Wave yLoc = yLoc
1987                        Save/T xLoc,yLoc,timePt ,rescaledTime           //will ask for a name
1988                       
1989                        SetDataFolder root:
1990                        break
1991                case -1: // control being killed
1992                        break
1993        endswitch
1994
1995        return 0
1996End
1997
1998//
1999// this duplicates all of the bits that would be done if the "load" button was pressed
2000//
2001Function V_EC_ImportWavesButtonProc(ba) : ButtonControl
2002        STRUCT WMButtonAction &ba
2003
2004        switch( ba.eventCode )
2005                case 2: // mouse up
2006                        // click code here
2007                        SetDataFolder root:Packages:NIST:VSANS:Event:
2008
2009                        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
2010                        SVAR dispStr = root:Packages:NIST:VSANS:Event:gEventDisplayString
2011                        String tmpStr="",fileStr,filePathStr
2012                       
2013                        // load in the waves, saved as Igor text to preserve the data type
2014                        LoadWave/T/O/P=catPathName
2015                        filePathStr = S_fileName
2016                        if(strlen(S_fileName) == 0)
2017                                //user cancelled
2018                                DoAlert 0,"No file selected, nothing done."
2019                                return(0)
2020                        endif
2021                       
2022                        NVAR mode = root:Packages:NIST:VSANS:Event:gEvent_Mode                          // ==0 for "stream", ==1 for Oscillatory
2023                        // clear out the old sort index, if present, since new data is being loaded
2024                        KillWaves/Z OscSortIndex
2025                        Wave timePt=timePt
2026                        Wave rescaledTime=rescaledTime
2027                       
2028                        t_longest = waveMax(rescaledTime)               //should be the last point
2029                       
2030       
2031                        fileStr = ParseFilePath(0, filepathstr, ":", 1, 0)
2032                        sprintf tmpStr, "%s: a user-modified event file\r",fileStr
2033                        dispStr = tmpStr
2034       
2035                        SetDataFolder root:
2036                        break
2037                case -1: // control being killed
2038                        break
2039        endswitch
2040
2041        return 0
2042End
2043
2044
2045Function V_EC_ShowAllButtonProc(ba) : ButtonControl
2046        STRUCT WMButtonAction &ba
2047
2048        switch( ba.eventCode )
2049                case 2: // mouse up
2050                        // click code here
2051                        SetAxis/A
2052                        break
2053                case -1: // control being killed
2054                        break
2055        endswitch
2056
2057        return 0
2058End
2059
2060Function V_EC_HelpButtonProc(ba) : ButtonControl
2061        STRUCT WMButtonAction &ba
2062
2063        switch( ba.eventCode )
2064                case 2: // mouse up
2065                        // click code here
2066                        DisplayHelpTopic/Z "Event Mode Data[Correcting for things that go wrong]"
2067                        break
2068                case -1: // control being killed
2069                        break
2070        endswitch
2071
2072        return 0
2073End
2074
2075Function V_EC_DoneButtonProc(ba) : ButtonControl
2076        STRUCT WMButtonAction &ba
2077
2078        switch( ba.eventCode )
2079                case 2: // mouse up
2080                        // click code here
2081                        DoWindow/K V_EventCorrectionPanel
2082                        break
2083                case -1: // control being killed
2084                        break
2085        endswitch
2086
2087        return 0
2088End
2089
2090//upDown 5 or -5 looks for spikes +5 or -5 std deviations from mean
2091Function V_PutCursorsAtStep(upDown)
2092        Variable upDown
2093       
2094        SetDataFolder root:Packages:NIST:VSANS:Event:
2095
2096        Wave rescaledTime=rescaledTime
2097        Wave rescaledTime_DIF=rescaledTime_DIF
2098        Variable avg,pt,zoom
2099       
2100        zoom = 200              //points in each direction
2101       
2102        WaveStats/M=1/Q rescaledTime_DIF
2103        avg = V_avg
2104               
2105        FindLevel/P/Q rescaledTime_DIF avg*upDown
2106        if(V_flag==0)
2107                pt = V_levelX
2108                WaveStats/Q/R=[pt-zoom,pt+zoom] rescaledTime            // find the max/min y-vallues within the point range
2109        else
2110                Print "Level not found"
2111                return(0)
2112        endif
2113       
2114        Variable loLeft,hiLeft, loBottom,hiBottom
2115        loLeft = V_min*0.98             //+/- 2%
2116        hiLeft = V_max*1.02
2117       
2118        SetAxis left loLeft,hiLeft
2119        SetAxis bottom pnt2x(rescaledTime,pt-zoom),pnt2x(rescaledTime,pt+zoom)
2120       
2121        Cursor/P A rescaledTime pt+2    //at the point
2122        Cursor/P B rescaledTime numpnts(rescaledTime)-1         //at the end
2123
2124        SetDataFolder root:
2125
2126        return(0)
2127End
2128
2129
2130// find the max (or min) of the rescaled time set
2131// and place both cursors there
2132Function V_fFindOutlier()
2133
2134        SetDataFolder root:Packages:NIST:VSANS:Event:
2135
2136        Wave rescaledTime=rescaledTime
2137        Variable avg,pt,zoom,maxPt,minPt,maxVal,minVal
2138       
2139        zoom = 200              //points in each direction
2140       
2141        WaveStats/M=1/Q rescaledTime
2142        maxPt = V_maxLoc
2143        minPt = V_minLoc
2144        avg = V_avg
2145        maxVal = abs(V_max)
2146        minVal = abs(V_min)
2147
2148        pt = abs(maxVal - avg) > abs(minVal - avg) ? maxPt : minPt
2149       
2150//      Variable loLeft,hiLeft, loBottom,hiBottom
2151//      loLeft = V_min*0.98             //+/- 2%
2152//      hiLeft = V_max*1.02
2153       
2154//      SetAxis left loLeft,hiLeft
2155//      SetAxis bottom pnt2x(rescaledTime,pt-zoom),pnt2x(rescaledTime,pt+zoom)
2156       
2157        Cursor/P A rescaledTime pt              //at the point
2158        Cursor/P B rescaledTime pt              //at the same point
2159
2160        SetDataFolder root:
2161       
2162        return(0)
2163End
2164
2165Function V_EC_FindStepButton_down(ctrlName) : ButtonControl
2166        String ctrlName
2167       
2168//      Variable upDown = -5
2169        NVAR upDown = root:Packages:NIST:VSANS:Event:gStepTolerance
2170       
2171        V_PutCursorsAtStep(-1*upDown)
2172
2173        return(0)
2174end
2175
2176
2177Function V_EC_FindStepButton_up(ctrlName) : ButtonControl
2178        String ctrlName
2179       
2180//      Variable upDown = 5
2181        NVAR upDown = root:Packages:NIST:VSANS:Event:gStepTolerance
2182
2183        V_PutCursorsAtStep(upDown)
2184
2185        return(0)
2186end
2187
2188// if the Trim button section is uncommented, it's "Zap outlier"
2189//
2190Function V_EC_FindOutlierButton(ctrlName) : ButtonControl
2191        String ctrlName
2192       
2193        V_fFindOutlier()
2194//
2195//      STRUCT WMButtonAction ba
2196//      ba.eventCode = 2
2197//
2198//      EC_TrimPointsButtonProc(ba)
2199
2200        return(0)
2201end
2202
2203Function V_EC_DoDifferential(ctrlName) : ButtonControl
2204        String ctrlName
2205       
2206        V_DifferentiatedTime()
2207        DoWindow/F V_EventCorrectionPanel
2208       
2209        //if trace is not on graph, add it
2210        SetDataFolder root:Packages:NIST:VSANS:Event:
2211
2212        String list = WaveList("*_DIF", ";", "WIN:V_EventCorrectionPanel")
2213        if(strlen(list) == 0)
2214                AppendToGraph/R rescaledTime_DIF
2215                ModifyGraph msize=1,rgb(rescaledTime_DIF)=(65535,0,0)
2216                ReorderTraces rescaledTime,{rescaledTime_DIF}           // put the differential behind the event data
2217        endif
2218        SetDataFolder root:
2219        return(0)
2220end
2221
2222//////////////   Custom Bins  /////////////////////
2223//
2224//
2225//
2226// make sure that the bins are defined and the waves exist before
2227// trying to draw the panel
2228//
2229Proc V_Show_CustomBinPanel()
2230        DoWindow/F V_CustomBinPanel
2231        if(V_flag ==0)
2232                V_Init_CustomBins()
2233                V_CustomBinPanel()
2234        EndIf
2235End
2236
2237
2238Function V_Init_CustomBins()
2239
2240        NVAR nSlice = root:Packages:NIST:VSANS:Event:gEvent_nslices
2241        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
2242
2243        Variable/G root:Packages:NIST:VSANS:Event:gEvent_ForceTmaxBin=1         //==1 to enforce t_longest in user-defined custom bins
2244
2245        SetDataFolder root:Packages:NIST:VSANS:Event:
2246               
2247        Make/O/D/N=(nSlice) timeWidth
2248        Make/O/D/N=(nSlice+1) binEndTime,binCount
2249       
2250        timeWidth = t_longest/nslice
2251        binEndTime = p
2252        binCount = p+1 
2253       
2254        SetDataFolder root:
2255       
2256        return(0)
2257End
2258
2259////////////////       
2260//
2261// Allow custom definitions of the bin widths
2262//
2263// Define by the number of bins, and the time width of each bin
2264//
2265// This shares the number of slices and the maximum time with the main panel
2266//
2267Proc V_CustomBinPanel()
2268        PauseUpdate; Silent 1           // building window...
2269        NewPanel /W=(130,44,851,455)/K=2 /N=V_CustomBinPanel
2270        DoWindow/C V_CustomBinPanel
2271        ModifyPanel fixedSize=1//,noEdit =1
2272        SetDrawLayer UserBack
2273       
2274        Button button0,pos={654,42}, size={50,20},title="Done",fSize=12
2275        Button button0,proc=V_CB_Done_Proc
2276        Button button1,pos={663,14},size={40,20},proc=V_CB_HelpButtonProc,title="?"
2277        Button button2,pos={216,42},size={80,20},title="Update",proc=V_CB_UpdateWavesButton     
2278        SetVariable setvar1,pos={23,13},size={160,20},title="Number of slices",fSize=12
2279        SetVariable setvar1,proc=CB_NumSlicesSetVarProc,value=root:Packages:NIST:VSANS:Event:gEvent_nslices
2280        SetVariable setvar2,pos={24,44},size={160,20},title="Max Time (s)",fSize=10
2281        SetVariable setvar2,value=root:Packages:NIST:VSANS:Event:gEvent_t_longest       
2282
2283        CheckBox chkbox1,pos={216,14},title="Enforce Max Time?"
2284        CheckBox chkbox1,variable = root:Packages:NIST:VSANS:Event:gEvent_ForceTmaxBin
2285        Button button3,pos={500,14},size={90,20},proc=V_CB_SaveBinsButtonProc,title="Save Bins"
2286        Button button4,pos={500,42},size={100,20},proc=V_CB_ImportBinsButtonProc,title="Import Bins"   
2287               
2288        SetDataFolder root:Packages:NIST:VSANS:Event:
2289
2290        Display/W=(291,86,706,395)/HOST=V_CustomBinPanel/N=BarGraph binCount vs binEndTime
2291        ModifyGraph mode=5
2292        ModifyGraph marker=19
2293        ModifyGraph lSize=2
2294        ModifyGraph rgb=(0,0,0)
2295        ModifyGraph msize=2
2296        ModifyGraph hbFill=2
2297        ModifyGraph gaps=0
2298        ModifyGraph usePlusRGB=1
2299        ModifyGraph toMode=1
2300        ModifyGraph useBarStrokeRGB=1
2301        ModifyGraph standoff=0
2302        SetAxis left 0,*
2303        Label bottom "\\Z14Time (seconds)"
2304        Label left "\\Z14Number of Events"
2305        SetActiveSubwindow ##
2306       
2307        // and the table
2308        Edit/W=(13,87,280,394)/HOST=V_CustomBinPanel/N=T0
2309        AppendToTable/W=V_CustomBinPanel#T0 timeWidth,binEndTime
2310        ModifyTable width(Point)=40
2311        SetActiveSubwindow ##
2312       
2313        SetDataFolder root:
2314       
2315EndMacro
2316
2317// save the bins - use Igor Text format
2318//
2319Function V_CB_SaveBinsButtonProc(ba) : ButtonControl
2320        STRUCT WMButtonAction &ba
2321
2322        switch( ba.eventCode )
2323                case 2: // mouse up
2324                        // click code here
2325
2326                        SetDataFolder root:Packages:NIST:VSANS:Event:
2327
2328                        Wave timeWidth = timeWidth
2329                        Wave binEndTime = binEndTime
2330                       
2331                        Save/T timeWidth,binEndTime                     //will ask for a name
2332
2333                        break
2334                case -1: // control being killed
2335                        break
2336        endswitch
2337
2338        SetDataFolder root:
2339       
2340        return 0
2341End
2342
2343// Import the bins - use Igor Text format
2344//
2345// -- be sure that the number of bins is reset
2346// -?- how about the t_longest? - this should be set by the load, not here
2347//
2348// -- loads in timeWidth and binEndTime
2349//
2350Function V_CB_ImportBinsButtonProc(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:VSANS:Event:gEvent_nslices
2357
2358                        SetDataFolder root:Packages:NIST:VSANS:Event:
2359
2360                        // prompt for the load of data
2361                        LoadWave/T/O
2362                        if(strlen(S_fileName) == 0)
2363                                //user cancelled
2364                                DoAlert 0,"No file selected, nothing done."
2365                                return(0)
2366                        endif
2367
2368                        Wave timeWidth = timeWidth
2369                        nSlice = numpnts(timeWidth)
2370                       
2371                        break
2372                case -1: // control being killed
2373                        break
2374        endswitch
2375
2376        SetDataFolder root:
2377       
2378        return 0
2379End
2380
2381
2382
2383//
2384// can either use the widths as stated -- then the end time may not
2385// match the actual end time of the data set
2386//
2387// -- or --
2388//
2389// enforce the end time of the data set to be the end time of the bins,
2390// then the last bin width must be reset to force the constraint
2391//
2392//
2393Function V_CB_UpdateWavesButton(ba) : ButtonControl
2394        STRUCT WMButtonAction &ba
2395
2396        switch( ba.eventCode )
2397                case 2: // mouse up
2398                        // click code here
2399                        NVAR nSlice = root:Packages:NIST:VSANS:Event:gEvent_nslices
2400                        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
2401                        NVAR enforceTmax = root:Packages:NIST:VSANS:Event:gEvent_ForceTmaxBin
2402                       
2403                        // update the waves, and recalculate everything for the display
2404                        SetDataFolder root:Packages:NIST:VSANS:Event:
2405
2406                        Wave timeWidth = timeWidth
2407                        Wave binEndTime = binEndTime
2408                        Wave binCount = binCount
2409                       
2410                        // use the widths as entered
2411                        binEndTime[0] = 0
2412                        binEndTime[1,] = binEndTime[p-1] + timeWidth[p-1]
2413                       
2414                        // enforce the longest time as the end bin time
2415                        // note that this changes the last time width
2416                        if(enforceTmax)
2417                                binEndTime[nSlice] = t_longest
2418                                timeWidth[nSlice-1] = t_longest - binEndTime[nSlice-1]
2419                        endif
2420                       
2421                        binCount = p+1
2422                        binCount[nSlice] = 0            // last point is zero, just for display
2423//                      binCount *= sign(timeWidth)             //to alert to negative time bins
2424                       
2425                        // make the timeWidth bold and red if the widths are negative
2426                        WaveStats/Q timeWidth
2427                        if(V_min < 0)
2428                                ModifyTable/W=V_CustomBinPanel#T0 style(timeWidth)=1,rgb(timeWidth)=(65535,0,0)                 
2429                        else
2430                                ModifyTable/W=V_CustomBinPanel#T0 style(timeWidth)=0,rgb(timeWidth)=(0,0,0)                     
2431                        endif
2432                       
2433                        break
2434                case -1: // control being killed
2435                        break
2436        endswitch
2437
2438        SetDataFolder root:
2439       
2440        return 0
2441End
2442
2443Function V_CB_HelpButtonProc(ba) : ButtonControl
2444        STRUCT WMButtonAction &ba
2445
2446        switch( ba.eventCode )
2447                case 2: // mouse up
2448                        // click code here
2449                        DisplayHelpTopic/Z "Event Mode Data[Setting up Custom Bin Widths]"
2450                        break
2451                case -1: // control being killed
2452                        break
2453        endswitch
2454
2455        return 0
2456End
2457
2458Function V_CB_Done_Proc(ba) : ButtonControl
2459        STRUCT WMButtonAction &ba
2460       
2461        String win = ba.win
2462        switch (ba.eventCode)
2463                case 2:
2464                        DoWindow/K V_CustomBinPanel
2465                        break
2466        endswitch
2467        return(0)
2468End
2469
2470
2471Function V_CB_NumSlicesSetVarProc(sva) : SetVariableControl
2472        STRUCT WMSetVariableAction &sva
2473
2474        switch( sva.eventCode )
2475                case 1: // mouse up
2476                case 2: // Enter key
2477                case 3: // Live update
2478                        Variable dval = sva.dval
2479                        String sval = sva.sval
2480                        SetDataFolder root:Packages:NIST:VSANS:Event:
2481
2482                        Wave timeWidth = timeWidth
2483                        Wave binEndTime = binEndTime
2484                       
2485                        Redimension/N=(dval) timeWidth
2486                        Redimension/N=(dval+1) binEndTime,binCount
2487                       
2488                        SetDataFolder root:
2489                       
2490                        break
2491                case -1: // control being killed
2492                        break
2493        endswitch
2494
2495        return 0
2496End
2497
2498
2499///////////////////
2500//
2501// utility to split a large file
2502// 100 MB is the recommended size
2503// events can be clipped here, so be sure to trim the ends of the
2504// resulting files as needed.
2505//
2506// - works like the unix 'split' command
2507//
2508//
2509
2510Proc V_SplitBigFile(splitSize, baseStr)
2511        Variable splitSize = 100
2512        String baseStr="split"
2513        Prompt splitSize,"Target file size, in MB"
2514        Prompt baseStr,"File prefix, number will be appended"
2515       
2516       
2517        V_fSplitBigFile(splitSize, baseStr)
2518       
2519        V_ShowSplitFileTable()
2520End
2521
2522Function/S V_fSplitBigFile(splitSize, baseStr)
2523        Variable splitSize
2524        String baseStr         
2525
2526
2527        String fileName=""              // File name, partial path, full path or "" for dialog.
2528        Variable refNum
2529        String str
2530        SVAR listStr = root:Packages:NIST:VSANS:Event:gSplitFileList
2531       
2532        listStr=""              //initialize output list
2533
2534        Variable readSize=1e6           //1 MB
2535        Make/O/B/U/N=(readSize) aBlob                   //1MB worth
2536        Variable numSplit
2537        Variable num,ii,jj,outRef,frac
2538        String thePath, outStr
2539       
2540        Printf "SplitSize = %u MB\r",splitSize
2541        splitSize = trunc(splitSize) * 1e6              // now in bytes
2542       
2543       
2544        // Open file for read.
2545        Open/R/Z=2/F="????"/P=catPathName refNum as fileName
2546        thePath = ParseFilePath(1, S_fileName, ":", 1, 0)
2547        Print "thePath = ",thePath
2548       
2549        // Store results from Open in a safe place.
2550        Variable err = V_flag
2551        String fullPath = S_fileName
2552
2553        if (err == -1)
2554                Print "cancelled by user."
2555                return ("")
2556        endif
2557
2558        FStatus refNum
2559       
2560        Printf "total # bytes = %u\r",V_logEOF
2561
2562        numSplit=0
2563        if(V_logEOF > splitSize)
2564                numSplit = trunc(V_logEOF/splitSize)
2565        endif
2566
2567        frac = V_logEOF - numSplit*splitSize
2568        Print "numSplit = ",numSplit
2569        Printf "frac = %u\r",frac
2570       
2571        num=0
2572        if(frac > readSize)
2573                num = trunc(frac/readSize)
2574        endif
2575
2576       
2577        frac = frac - num*readSize
2578
2579        Print "num = ",num
2580        Printf "frac = %u\r",frac
2581       
2582//      baseStr = "split"
2583       
2584        for(ii=0;ii<numSplit;ii+=1)
2585                outStr = (thePath+baseStr+num2str(ii))
2586//              Print "outStr = ",outStr
2587                Open outRef as outStr
2588
2589                for(jj=0;jj<(splitSize/readSize);jj+=1)
2590                        FBinRead refNum,aBlob
2591                        FBinWrite outRef,aBlob
2592                endfor
2593
2594                Close outRef
2595//              listStr += outStr+";"
2596                listStr += baseStr+num2str(ii)+";"
2597        endfor
2598
2599        Make/O/B/U/N=(frac) leftover
2600        // ii was already incremented past the loop
2601        outStr = (thePath+baseStr+num2str(ii))
2602        Open outRef as outStr
2603        for(jj=0;jj<num;jj+=1)
2604                FBinRead refNum,aBlob
2605                FBinWrite outRef,aBlob
2606        endfor
2607        FBinRead refNum,leftover
2608        FBinWrite outRef,leftover
2609
2610        Close outRef
2611//      listStr += outStr+";"
2612        listStr += baseStr+num2str(ii)+";"
2613
2614        FSetPos refNum,V_logEOF
2615        Close refNum
2616       
2617        KillWaves/Z aBlob,leftover
2618        return(listStr)
2619End
2620
2621//// allows the list of loaded files to be edited
2622//Function ShowSplitFileTable()
2623//
2624//      SVAR str = root:Packages:NIST:VSANS:Event:gSplitFileList
2625//     
2626//      WAVE/T/Z tw = root:Packages:NIST:VSANS:Event:SplitFileWave
2627//      if(waveExists(tw) != 1)
2628//              Make/O/T/N=1 root:Packages:NIST:VSANS:Event:SplitFileWave
2629//              WAVE/T/Z tw = root:Packages:NIST:VSANS:Event:SplitFileWave
2630//      endif
2631//
2632//      List2TextWave(str,tw)
2633//      Edit tw
2634//
2635//      return(0)
2636//End
2637
2638
2639//// save the sliced data, and accumulate slices
2640//  *** this works with sliced data -- that is data that has been PROCESSED
2641//
2642// need some way of ensuring that the slices match up since I'm blindly adding them together.
2643//
2644// mode = 0             wipe out the old accumulated, copy slicedData to accumulatedData
2645// mode = 1             add current slicedData to accumulatedData
2646// mode = 2             copy accumulatedData to slicedData in preparation of export or display
2647// mode = 3             unused...
2648//
2649//      "Split Large File",SplitBigFile()
2650//      "Accumulate First Slice",AccumulateSlices(0)
2651//      "Add Current Slice",AccumulateSlices(1)
2652//      "Display Accumulated Slices",AccumulateSlices(2)       
2653//
2654Function V_AccumulateSlicesButton(ctrlName) : ButtonControl
2655        String ctrlName
2656       
2657        Variable mode
2658        mode = str2num(ctrlName[strlen(ctrlName)-1])
2659//      Print "mode=",mode
2660        V_AccumulateSlices(mode)
2661       
2662        return(0)
2663End
2664
2665Function V_AccumulateSlices(mode)
2666        Variable mode
2667       
2668        SetDataFolder root:Packages:NIST:VSANS:Event:
2669
2670        switch(mode)   
2671                case 0:
2672                        DoAlert 0,"The current data has been copied to the accumulated set. You are now ready to add more data."
2673                        KillWaves/Z accumulatedData
2674                        Duplicate/O slicedData accumulatedData         
2675                        break
2676                case 1:
2677                        DoAlert 0,"The current data has been added to the accumulated data. You can add more data."
2678                        Wave acc=accumulatedData
2679                        Wave cur=slicedData
2680                        acc += cur
2681                        break
2682                case 2:
2683                        DoAlert 0,"The accumulated data is now the display data and is ready for display or export."
2684                        Duplicate/O accumulatedData slicedData
2685                        // do something to "touch" the display to force it to update
2686                        NVAR gLog = root:Packages:NIST:VSANS:Event:gEvent_logint
2687                        V_LogIntEvent_Proc("",gLog)
2688                        break
2689                default:                       
2690                               
2691        endswitch
2692
2693        SetDataFolder root:
2694        return(0)
2695end
2696
2697
2698////////////////////////////////////////////
2699//
2700// Panel and procedures for decimation
2701//
2702////////////////////////////////////////////
2703
2704//Function E_ShowDecimateButton(ctrlName) : ButtonControl
2705//      String ctrlName
2706//
2707//      DoWindow/F DecimatePanel
2708//      if(V_flag ==0)
2709//              Execute "DecimatePanel()"
2710//      endif
2711//End
2712//
2713//
2714//Proc DecimatePanel() //: Panel
2715//     
2716//      PauseUpdate; Silent 1           // building window...
2717//      NewPanel /W=(1602,44,1961,380)/K=1
2718////    ShowTools/A
2719//      Button button0,pos={29,15},size={100,20},proc=SplitFileButtonProc,title="Split Big File"
2720//      SetVariable setvar0,pos={182,55},size={150,15},title="Decimation factor",fsize=10
2721//      SetVariable setvar0,limits={1,inf,1},value= root:Packages:NIST:VSANS:Event:gDecimation
2722//      Button button1,pos={26,245},size={150,20},proc=LoadDecimateButtonProc,title="Load and Decimate"
2723//      Button button2,pos={25,277},size={150,20},proc=ConcatenateButtonProc,title="Concatenate"
2724//      Button button3,pos={25,305},size={150,20},proc=DisplayConcatenatedButtonProc,title="Display Concatenated"
2725//      Button button4,pos={29,52},size={130,20},proc=Stream_LoadDecim,title="Load From List"
2726//     
2727//      GroupBox group0 title="Manual Controls",size={185,112},pos={14,220}
2728//EndMacro
2729
2730
2731Function V_SplitFileButtonProc(ctrlName) : ButtonControl
2732        String ctrlName
2733
2734        Execute "V_SplitBigFile()"
2735End
2736
2737
2738// show all of the data
2739//
2740Proc V_ShowDecimatedGraph()
2741
2742        DoWindow/F V_DecimatedGraph
2743        if(V_flag == 0)
2744                PauseUpdate; Silent 1           // building window...
2745                String fldrSav0= GetDataFolder(1)
2746                SetDataFolder root:Packages:NIST:VSANS:Event:
2747                Display /W=(25,44,486,356)/K=1/N=V_DecimatedGraph rescaledTime_dec
2748                SetDataFolder fldrSav0
2749                ModifyGraph mode=4
2750                ModifyGraph marker=19
2751                ModifyGraph rgb(rescaledTime_dec)=(0,0,0)
2752                ModifyGraph msize=1
2753                ErrorBars rescaledTime_dec OFF
2754                Label left "\\Z14Time (seconds)"
2755                Label bottom "\\Z14Event number"
2756                ShowInfo
2757        endif
2758       
2759EndMacro
2760
2761// data has NOT been processed
2762//
2763// so work with x,y,t, and rescaled time
2764// variables -- t_longest
2765Function V_ConcatenateButtonProc(ctrlName) : ButtonControl
2766        String ctrlName
2767       
2768        DoAlert 1,"Is this the first file?"
2769        Variable first = V_flag
2770       
2771        V_fConcatenateButton(first)
2772       
2773        return(0)
2774End
2775
2776Function V_fConcatenateButton(first)
2777        Variable first
2778
2779
2780        SetDataFolder root:Packages:NIST:VSANS:Event:
2781
2782        Wave timePt_dTmp=timePt_dTmp
2783        Wave xLoc_dTmp=xLoc_dTmp
2784        Wave yLoc_dTmp=yLoc_dTmp
2785        Wave rescaledTime_dTmp=rescaledTime_dTmp
2786       
2787        NVAR t_longest_dec = root:Packages:NIST:VSANS:Event:gEvent_t_longest_decimated
2788        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
2789       
2790       
2791        if(first==1)            //1==yes, 2==no
2792                //then copy the files over, adjusting the time to start from zero
2793                // rescaledTime starts from zero (set by the loader)
2794
2795                timePt_dTmp -= timePt_dTmp[0]                   //subtract the first value
2796               
2797                Duplicate/O timePt_dTmp timePt_dec
2798                Duplicate/O xLoc_dTmp xLoc_dec
2799                Duplicate/O yLoc_dTmp yLoc_dec
2800                Duplicate/O rescaledTime_dTmp rescaledTime_dec
2801               
2802                t_longest_dec = t_longest
2803       
2804        else
2805                // concatenate the files + adjust the time
2806                Wave timePt_dec=timePt_dec
2807                Wave xLoc_dec=xLoc_dec
2808                Wave yLoc_dec=yLoc_dec
2809                Wave rescaledTime_dec=rescaledTime_dec
2810
2811                // adjust the times -- assuming they add
2812                // rescaledTime starts from zero (set by the loader)
2813                //
2814                //
2815                rescaledTime_dTmp += rescaledTime_dec[numpnts(rescaledTime_dec)-1]
2816                rescaledTime_dTmp += abs(rescaledTime_dec[numpnts(rescaledTime_dec)-1] - rescaledTime_dec[numpnts(rescaledTime_dec)-2])
2817               
2818                timePt_dTmp -= timePt_dTmp[0]                   //subtract the first value     
2819               
2820                timePt_dTmp += timePt_dec[numpnts(timePt_dec)-1]                // offset by the last point
2821                timePt_dTmp += abs(timePt_dec[numpnts(timePt_dec)-1] - timePt_dec[numpnts(timePt_dec)-2])               // plus delta so there's not a flat step
2822               
2823                Concatenate/NP/O {timePt_dec,timePt_dTmp}, tmp
2824                Duplicate/O tmp timePt_dec
2825               
2826                Concatenate/NP/O {xLoc_dec,xLoc_dTmp}, tmp
2827                Duplicate/O tmp xLoc_dec
2828               
2829                Concatenate/NP/O {yLoc_dec,yLoc_dTmp}, tmp
2830                Duplicate/O tmp yLoc_dec
2831               
2832                Concatenate/NP/O {rescaledTime_dec,rescaledTime_dTmp}, tmp
2833                Duplicate/O tmp rescaledTime_dec
2834               
2835
2836                KillWaves tmp
2837
2838                t_longest_dec = rescaledTime_dec[numpnts(rescaledTime_dec)-1]
2839
2840        endif
2841       
2842       
2843        SetDataFolder root:
2844       
2845        return(0)
2846
2847End
2848
2849Function V_DisplayConcatenatedButtonProc(ctrlName) : ButtonControl
2850        String ctrlName
2851
2852        //copy the files over to the display set for processing
2853        SetDataFolder root:Packages:NIST:VSANS:Event:
2854
2855        Wave timePt_dec=timePt_dec
2856        Wave xLoc_dec=xLoc_dec
2857        Wave yLoc_dec=yLoc_dec
2858        Wave rescaledTime_dec=rescaledTime_dec
2859               
2860        NVAR t_longest_dec = root:Packages:NIST:VSANS:Event:gEvent_t_longest_decimated
2861        NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
2862       
2863        Duplicate/O timePt_dec timePt
2864        Duplicate/O xLoc_dec xLoc
2865        Duplicate/O yLoc_dec yLoc
2866        Duplicate/O rescaledTime_dec rescaledTime
2867       
2868        t_longest = t_longest_dec       
2869       
2870        SetDataFolder root:
2871       
2872        return(0)
2873
2874End
2875
2876
2877
2878// unused, old testing procedure
2879Function V_LoadDecimateButtonProc(ctrlName) : ButtonControl
2880        String ctrlName
2881
2882        V_LoadEventLog_Button("")
2883       
2884        // now decimate
2885        SetDataFolder root:Packages:NIST:VSANS:Event:
2886
2887        Wave timePt=timePt
2888        Wave xLoc=xLoc
2889        Wave yLoc=yLoc
2890        NVAR t_longest_dec = root:Packages:NIST:VSANS:Event:gEvent_t_longest_decimated
2891
2892        NVAR decimation = root:Packages:NIST:VSANS:Event:gDecimation
2893
2894
2895        Duplicate/O timePt, timePt_dTmp
2896        Duplicate/O xLoc, xLoc_dTmp
2897        Duplicate/O yLoc, yLoc_dTmp
2898        Resample/DOWN=(decimation)/N=1 timePt_dTmp
2899        Resample/DOWN=(decimation)/N=1 xLoc_dTmp
2900        Resample/DOWN=(decimation)/N=1 yLoc_dTmp
2901
2902
2903        Duplicate/O timePt_dTmp rescaledTime_dTmp
2904        rescaledTime_dTmp = 1e-7*(timePt_dTmp - timePt_dTmp[0])         //convert to seconds and start from zero
2905        t_longest_dec = waveMax(rescaledTime_dTmp)              //should be the last point
2906
2907        SetDataFolder root:
2908
2909       
2910End
2911
2912
2913
2914
2915
2916
2917
2918////
2919//// loads a list of files, decimating each chunk as it is read in
2920////
2921//Function Stream_LoadDecim(ctrlName)
2922//      String ctrlName
2923//     
2924//      Variable fileref
2925//
2926//      SVAR filename = root:Packages:NIST:VSANS:Event:gEvent_logfile
2927//      NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
2928//
2929//      SVAR listStr = root:Packages:NIST:VSANS:Event:gSplitFileList
2930//      NVAR t_longest_dec = root:Packages:NIST:VSANS:Event:gEvent_t_longest_decimated
2931//      NVAR decimation = root:Packages:NIST:VSANS:Event:gDecimation
2932//
2933//      String pathStr
2934//      PathInfo catPathName
2935//      pathStr = S_Path
2936//
2937//// if "stream" mode is not checked - abort
2938//      NVAR gEventModeRadioVal= root:Packages:NIST:VSANS:Event:gEvent_mode
2939//      if(gEventModeRadioVal != MODE_STREAM)
2940//              Abort "The mode must be 'Stream' to use this function"
2941//              return(0)
2942//      endif
2943//
2944//// if the list has been edited, turn it into a list
2945//      WAVE/T/Z tw = root:Packages:NIST:VSANS:Event:SplitFileWave
2946//      if(WaveExists(tw))
2947//              listStr = TextWave2SemiList(tw)
2948//      else
2949//              ShowSplitFileTable()
2950//              DoAlert 0,"Enter the file names in the table, then click 'Load From List' again."
2951//              return(0)
2952//      endif
2953//     
2954//
2955//      //loop through everything in the list
2956//      Variable num,ii
2957//      num = ItemsInList(listStr)
2958//     
2959//      for(ii=0;ii<num;ii+=1)
2960//
2961//// (1) load the file, prepending the path             
2962//              filename = pathStr + StringFromList(ii, listStr  ,";")
2963//             
2964//
2965//#if (exists("EventLoadWave")==4)
2966//              LoadEvents_XOP()
2967//#else
2968//              LoadEvents()
2969//#endif       
2970//
2971//              SetDataFolder root:Packages:NIST:VSANS:Event:                   //LoadEvents sets back to root:
2972//
2973//              Wave timePt=timePt
2974//              Wave xLoc=xLoc
2975//              Wave yLoc=yLoc
2976//              CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
2977//
2978//              Duplicate/O timePt rescaledTime
2979//              rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
2980//              t_longest = waveMax(rescaledTime)               //should be the last point
2981//             
2982//// (2) do the decimation, just on timePt. create rescaledTime from the decimated timePt       
2983//             
2984//              Duplicate/O timePt, timePt_dTmp
2985//              Duplicate/O xLoc, xLoc_dTmp
2986//              Duplicate/O yLoc, yLoc_dTmp
2987//              Resample/DOWN=(decimation)/N=1 timePt_dTmp
2988//              Resample/DOWN=(decimation)/N=1 xLoc_dTmp
2989//              Resample/DOWN=(decimation)/N=1 yLoc_dTmp
2990//     
2991//     
2992//              Duplicate/O timePt_dTmp rescaledTime_dTmp
2993//              rescaledTime_dTmp = 1e-7*(timePt_dTmp - timePt_dTmp[0])         //convert to seconds and start from zero
2994//              t_longest_dec = waveMax(rescaledTime_dTmp)              //should be the last point
2995//             
2996//
2997//// (3) concatenate
2998//              fConcatenateButton(ii+1)                //passes 1 for the first time, >1 each other time
2999//     
3000//      endfor
3001//
3002//////          Now that everything is decimated and concatenated, create the rescaled time wave
3003////    SetDataFolder root:Packages:NIST:VSANS:Event:                   //LoadEvents sets back to root:
3004////    Wave timePt_dec = timePt_dec
3005////    Duplicate/O timePt_dec rescaledTime_dec
3006////    rescaledTime_dec = 1e-7*(timePt_dec - timePt_dec[0])            //convert to seconds and start from zero
3007////    t_longest_dec = waveMax(rescaledTime_dec)               //should be the last point
3008//     
3009//      DisplayConcatenatedButtonProc("")
3010//     
3011//      SetDataFolder root:
3012//
3013//      return(0)
3014//End
3015//
3016//Function ShowList_ToLoad(ctrlName)
3017//      String ctrlName
3018//     
3019//      ShowSplitFileTable()
3020//     
3021//      return(0)
3022//End
3023
3024
3025////
3026//// loads a list of files that have been adjusted and saved
3027//// -- does not decimate
3028////
3029//Function Stream_LoadAdjustedList(ctrlName)
3030//      String ctrlName
3031//     
3032//      Variable fileref
3033//
3034//      SVAR filename = root:Packages:NIST:VSANS:Event:gEvent_logfile
3035//      NVAR t_longest = root:Packages:NIST:VSANS:Event:gEvent_t_longest
3036//
3037//      SVAR listStr = root:Packages:NIST:VSANS:Event:gSplitFileList
3038//      NVAR t_longest_dec = root:Packages:NIST:VSANS:Event:gEvent_t_longest_decimated
3039////    NVAR decimation = root:Packages:NIST:VSANS:Event:gDecimation
3040//
3041//      String pathStr
3042//      PathInfo catPathName
3043//      pathStr = S_Path
3044//
3045//// if "stream" mode is not checked - abort
3046//      NVAR gEventModeRadioVal= root:Packages:NIST:VSANS:Event:gEvent_mode
3047//      if(gEventModeRadioVal != MODE_STREAM)
3048//              Abort "The mode must be 'Stream' to use this function"
3049//              return(0)
3050//      endif
3051//
3052//// if the list has been edited, turn it into a list
3053//      WAVE/T/Z tw = root:Packages:NIST:VSANS:Event:SplitFileWave
3054//      if(WaveExists(tw))
3055//              listStr = TextWave2SemiList(tw)
3056//      else
3057//              ShowSplitFileTable()
3058//              DoAlert 0,"Enter the file names in the table, then click 'Load From List' again."
3059//              return(0)
3060//      endif
3061//     
3062//
3063//      //loop through everything in the list
3064//      Variable num,ii
3065//      num = ItemsInList(listStr)
3066//     
3067//      for(ii=0;ii<num;ii+=1)
3068//
3069//// (1) load the file, prepending the path             
3070//              filename = pathStr + StringFromList(ii, listStr  ,";")
3071//             
3072//              SetDataFolder root:Packages:NIST:VSANS:Event:
3073//              LoadWave/T/O fileName
3074//
3075//              SetDataFolder root:Packages:NIST:VSANS:Event:                   //LoadEvents sets back to root: ??
3076//
3077//// this is what is loaded -- _dec extension is what is concatenated, and will be copied back later
3078//              Wave timePt=timePt
3079//              Wave xLoc=xLoc
3080//              Wave yLoc=yLoc
3081//              Wave rescaledTime=rescaledTime
3082//
3083////            CleanupTimes(xLoc,yLoc,timePt)          //remove zeroes
3084//
3085////            Duplicate/O timePt rescaledTime
3086////            rescaledTime = 1e-7*(timePt-timePt[0])          //convert to seconds and start from zero
3087////            t_longest = waveMax(rescaledTime)               //should be the last point
3088//             
3089//// (2) No decimation
3090//             
3091//              Duplicate/O timePt, timePt_dTmp
3092//              Duplicate/O xLoc, xLoc_dTmp
3093//              Duplicate/O yLoc, yLoc_dTmp
3094//              Duplicate/O rescaledTime, rescaledTime_dTmp
3095//
3096//
3097//// (3) concatenate
3098//              fConcatenateButton(ii+1)                //passes 1 for the first time, >1 each other time
3099//     
3100//      endfor
3101//     
3102//      DisplayConcatenatedButtonProc("")               // this resets the longest time, too
3103//             
3104//      SetDataFolder root:
3105//
3106//      return(0)
3107//End
3108//
3109///////////////////////////////////////
3110//
3111//// dd-mon-yyyy hh:mm:ss -> Event file name
3112//// the VAX uses 24 hr time for hh
3113////
3114//// scans as string elements since I'm reconstructing a string name
3115//Function/S DateAndTime2HSTName(dateandtime)
3116//      string dateAndTime
3117//     
3118//      String day,yr,hh,mm,ss,time_secs
3119//      Variable mon
3120//      string str,monStr,fileStr
3121//     
3122//      str=dateandtime
3123//      sscanf str,"%2s-%3s-%4s %2s:%2s:%2s",day,monStr,yr,hh,mm,ss
3124//      mon = monStr2num(monStr)
3125//
3126//      fileStr = "Event"+yr+num2str(mon)+day+hh+mm+ss+".hst"
3127//      Print fileStr
3128//
3129//      return(fileStr)
3130//end
3131//
3132//// dd-mon-yyyy hh:mm:ss -> Event file name
3133//// the VAX uses 24 hr time for hh
3134////
3135//// scans as string elements since I'm reconstructing a string name
3136//Function DateAndTime2HSTNumber(dateandtime)
3137//      string dateAndTime
3138//     
3139//      String day,yr,hh,mm,ss,time_secs
3140//      Variable mon,num
3141//      string str,monStr,fileStr
3142//     
3143//      str=dateandtime
3144//      sscanf str,"%2s-%3s-%4s %2s:%2s:%2s",day,monStr,yr,hh,mm,ss
3145//      mon = monStr2num(monStr)
3146//
3147//      fileStr = yr+num2str(mon)+day+hh+mm+ss
3148//      num = str2num(fileStr)
3149//
3150//      return(num)
3151//end
3152//
3153//Function HSTName2Num(str)
3154//      String str
3155//     
3156//      Variable num
3157//      sscanf str,"Event%d.hst",num
3158//      return(num)
3159//end
3160///////////////////////////////
Note: See TracBrowser for help on using the repository browser.