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

Last change on this file since 1074 was 1060, checked in by srkline, 5 years ago

renaming of event mode utilities to appear in the list next to the main event mode file.

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