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

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

cleaning up a lot of the TODO items from the code.

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