source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/VSANS/V_Utilities_General.ipf @ 1044

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

Significant changes to the base READ of individual data fields from data files. Now, if the field requested is from a WORK file, and it does not exist, an error condition is returned (or a null wave). Calling procedures are responsible for handling errors. This prevents a string of open file dialogs if fields are missing from a file if they were never in the file to begin with (like sensor logs, polarization hardware, etc.)

New get/write calls were added for the updated temperature sensor fields.

group_ID is now only in the sample block, not the duplicated in the reduction block, and is correctly a number not a string.

File size: 33.4 KB
Line 
1#pragma TextEncoding = "MacRoman"               // For details execute DisplayHelpTopic "The TextEncoding Pragma"
2#pragma rtGlobals=3             // Use modern global access method and strict wave access.
3
4//
5//              general utilities
6//
7// for use by multiple panels and packages
8
9
10//prompts user to choose the local folder that contains the SANS Data
11//only one folder can be used, and its path is catPathName (and is a NAME, not a string)
12//this will overwrite the path selection
13//returns 1 if no path selected as error condition, or if user cancelled
14Function V_PickPath()
15       
16        //set the global string to the selected pathname
17        NewPath/O/M="pick the SANS data folder" catPathName
18        if(V_Flag != 0)
19                return(1)               //user cancelled
20        endif
21       
22        PathInfo/S catPathName
23        String dum = S_path
24        String alertStr = ""
25        alertStr = "You must set the path to Charlotte through a Mapped Network Drive, not through the Network Neighborhood"
26        //alertStr += "  Please see the manual for details."
27        if (V_flag == 0)
28                //path does not exist - no folder selected
29                String/G root:Packges:NIST:VSANS:Globals:gCatPathStr = "no folder selected"
30                return(1)
31        else
32        // SRK 2016, for windows 10, try to eliminate this restriction 
33        //---- connecting through the network neighborhood seems to be perfectly fine except for
34        //     path issues with GBLoadWave, which only affects VAX data sets
35               
36//              print igorinfo(3)
37//              //set the global to the path (as a string)
38//              // need 4 \ since it is the escape character
39//              if(cmpstr("\\\\",dum[0,1])==0)  //Windows user going through network neighborhood
40//                      DoAlert 0,alertStr
41//                      KillPath catPathName
42//                      return(1)
43//              endif
44                String/G root:Packges:NIST:VSANS:Globals:gCatPathStr = dum
45                return(0)               //no error
46        endif
47       
48End
49
50//
51// entry from the Main Panel
52//
53Proc V_ChangeDisplay(type)
54        String type
55        Prompt type,"WORK data type to display",popup,"RAW;SAM;EMP;BGD;ADJ;"
56
57// make sure that data exists before passing this on...
58       
59        if(V_DataExists(type) > 0)
60                V_UpdateDisplayInformation(type)
61        else
62                DoAlert 0,"No data in "+type
63        endif
64End
65
66// TODO
67//
68// very simple function to look for something in a work folder
69// -- only checks for FR data to exist, assumes everything else is there
70// -- can't use the V_get() functions, these will try to load data if it's not there!
71Function V_DataExists(type)
72        String type
73       
74        Wave/Z w = $("root:Packages:NIST:VSANS:"+type+":entry:instrument:detector_FR:data")
75       
76        return(WaveExists(w))
77end
78//
79// tests if two values are close enough to each other
80// very useful since ICE came to be
81//
82// tol is an absolute value (since input v1 or v2 may be zero, can't reliably
83// use a percentage
84Function V_CloseEnough(v1,v2,tol)
85        Variable v1, v2, tol
86
87        if(abs(v1-v2) < tol)
88                return(1)
89        else
90                return(0)
91        endif
92End
93
94
95
96// TODO:
97// -- this must be called as needed to force a re-read of the data from disk
98//    "as needed" means that when an operation is done that needs to ensure
99//     a fresh read from disk, it must take care of the kill.
100// -- the ksBaseDFPath needs to be removed. It's currently pointing to RawVSANS, which is
101//    really not used as intended anymore.
102//
103Function V_KillNamedDataFolder(fname)
104        String fname
105       
106        Variable err=0
107       
108        String folderStr = V_GetFileNameFromPathNoSemi(fname)
109        folderStr = V_RemoveDotExtension(folderStr)
110       
111        KillDataFolder/Z $(ksBaseDFPath+folderStr)
112        err = V_flag
113       
114        return(err)
115end
116
117// TODO:
118// x- this still does not quite work. If there are no sub folders present in the RawVSANS folder
119//    it still thinks there is (1) item there.
120// -- if I replace the semicolon with a comma, it thinks there are two folders present and appears
121//    to delete the RawVSANS folder itself! seems very dangerous...this is because DataFolderDir returns
122//    a comma delimited list, but with a semicolon and \r at the end. need to remove these...
123//
124// NOTE -- use V_CleanupData_w_Progress(0,1) to get a progress bar - since this will take more than
125//     a few seconds to complete, especially if a file catalog was done, or a "batch" patching, etc.
126//
127// *** this appears to be unused, in favor of V_CleanupData_w_Progress(0,1)  **********
128//
129Function V_CleanOutRawVSANS()
130
131        SetDataFolder root:Packages:NIST:VSANS:RawVSANS:
132       
133        // get a list of the data folders there
134        // kill them all if possible
135        String list,item
136        Variable numFolders,ii,pt
137       
138        list = DataFolderDir(1)
139        // this has FOLDERS: at the beginning and is comma-delimited
140        list = list[8,strlen(list)]
141        pt = strsearch(list,";",inf,1)
142        list = list[0,pt-1]                     //remove the ";\r" from the end of the string
143//      print list
144       
145        numFolders = ItemsInList(list , ",")
146//      Print List
147//      print strlen(list)
148
149        for(ii=0;ii<numFolders;ii+=1)
150                item = StringFromList(ii, list ,",")
151//              Print item
152                KillDataFolder/Z $(item)
153        endfor
154
155        list = DataFolderDir(1)
156        list = list[8,strlen(list)]
157        pt = strsearch(list,";",inf,1)
158        list = list[0,pt-1]
159        numFolders = ItemsInList(list, ",")
160        Printf "%g RawVSANS folders could not be killed\r",numFolders
161               
162        SetDataFolder root:
163        return(0)
164End
165
166//
167// examples straight from Wavemetrics help file topic "Progress Windows"
168// Try simpletest(0,0) and simpletest(1,0), simpletest(0,1) and simpletest(1,1)
169//
170//
171// look for simpletest() function in Wavemetrics help file topic "Progress Windows"
172//  this is a modified version.
173//
174// call with (1,1) to get the candystripe bar
175// call with (0,1) to the the "countdown" bar as they are killed
176//
177Function V_CleanupData_w_Progress(indefinite, useIgorDraw)
178        Variable indefinite
179        Variable useIgorDraw            // True to use Igor's own draw method rather than native
180       
181        Variable num,numToClean
182       
183        // is there anything there to be killed?
184        num = V_CleanOutOneRawVSANS()
185        numToClean = num
186        if(num <= 0)
187                return(0)
188        endif
189       
190        // there are some folders to kill, so proceed
191       
192        NewPanel /N=ProgressPanel /W=(285,111,739,193)
193        ValDisplay valdisp0,win=ProgressPanel,pos={18,32},size={342,18},limits={0,num,0},barmisc={0,0}
194        ValDisplay valdisp0,win=ProgressPanel,value= _NUM:0
195        DrawText 20,24,"Cleaning up old files... Please Wait..."
196       
197        if( indefinite )
198                ValDisplay valdisp0,win=ProgressPanel,mode= 4   // candy stripe
199        else
200                ValDisplay valdisp0,win=ProgressPanel,mode= 3   // bar with no fractional part
201        endif
202        if( useIgorDraw )
203                ValDisplay valdisp0,win=ProgressPanel,highColor=(15000,45535,15000)             //(0,65535,0)
204        endif
205        Button bStop,win=ProgressPanel,pos={375,32},size={50,20},title="Stop"
206        DoUpdate /W=ProgressPanel /E=1  // mark this as our progress window
207
208        do
209                num = V_CleanOutOneRawVSANS()
210                if( V_Flag == 2 || num == 0 || num == -1)       // either "stop" or clean exit, or "done" exit from function
211                        break
212                endif
213               
214                ValDisplay valdisp0,win=ProgressPanel,value= _NUM:num,win=ProgressPanel
215                DoUpdate /W=ProgressPanel
216        while(1)
217       
218
219        KillWindow ProgressPanel
220        return(numToClean)
221End
222
223
224// TODO:
225// x- this still does not quite work. If there are no sub folders present in the RawVSANS folder
226//    it still thinks there is (1) item there.
227// -- if I replace the semicolon with a comma, it thinks there are two folders present and appears
228//    to delete the RawVSANS folder itself! seems very dangerous...this is because DataFolderDir returns
229//    a comma delimited list, but with a semicolon and \r at the end. need to remove these...
230//
231// -- for use with progress bar, kills only one folder, returns the new number of folders left
232// -- if n(in) = n(out), nothing was able to be killed, so return "done" code
233Function V_CleanOutOneRawVSANS()
234
235        SetDataFolder root:Packages:NIST:VSANS:RawVSANS:
236       
237        // get a list of the data folders there
238        // kill them all if possible
239        String list,item
240        Variable numFolders,ii,pt,numIn
241       
242        list = DataFolderDir(1)
243        // this has FOLDERS: at the beginning and is comma-delimited
244        list = list[8,strlen(list)]
245        pt = strsearch(list,";",inf,1)
246        list = list[0,pt-1]                     //remove the ";\r" from the end of the string
247//      print list
248       
249        numFolders = ItemsInList(list , ",")
250        numIn = numFolders
251//      Print List
252//      print strlen(list)
253
254        if(numIn > 0)
255                item = StringFromList(0, list ,",")
256//              Print item
257                KillDataFolder/Z $(item)
258        endif
259
260        list = DataFolderDir(1)
261        list = list[8,strlen(list)]
262        pt = strsearch(list,";",inf,1)
263        list = list[0,pt-1]
264        numFolders = ItemsInList(list, ",")
265       
266        if(numIn == numFolders)
267                Printf "%g RawVSANS folders could not be killed\r",numFolders
268                SetDataFolder root:
269
270                return (-1)
271        endif
272       
273        SetDataFolder root:     
274        return(numFolders)
275End
276
277
278
279
280
281//given a filename of a SANS data filename of the form
282// name.anything
283//returns the name as a string without the ".fbdfasga" extension
284//
285// returns the input string if a "." can't be found (maybe it wasn't there)
286Function/S V_RemoveDotExtension(item)
287        String item
288        String invalid = item   //
289        Variable num=-1
290       
291        //find the "dot"
292        String runStr=""
293        Variable pos = strsearch(item,".",0)
294        if(pos == -1)
295                //"dot" not found
296                return (invalid)
297        else
298                //found, get all of the characters preceeding it
299                runStr = item[0,pos-1]
300                return (runStr)
301        Endif
302End
303
304//returns a string containing filename (WITHOUT the ;vers)
305//the input string is a full path to the file (Mac-style, still works on Win in IGOR)
306//with the folders separated by colons
307//
308// called by MaskUtils.ipf, ProtocolAsPanel.ipf, WriteQIS.ipf
309//
310Function/S V_GetFileNameFromPathNoSemi(fullPath)
311        String fullPath
312       
313        Variable offset1,offset2
314        String filename=""
315        //String PartialPath
316        offset1 = 0
317        do
318                offset2 = StrSearch(fullPath, ":", offset1)
319                if (offset2 == -1)                              // no more colons ?
320                        fileName = FullPath[offset1,strlen(FullPath) ]
321                        //PartialPath = FullPath[0, offset1-1]
322                        break
323                endif
324                offset1 = offset2+1
325        while (1)
326       
327        //remove version number from name, if it's there - format should be: filename;N
328        filename =  StringFromList(0,filename,";")              //returns null if error
329       
330        Return filename
331End
332
333//
334// -- this was copied directly, no changes , from PlotUtils_Macro_v40
335//
336// returns the path to the file, or null if the user cancelled
337// fancy use of optional parameters
338//
339// enforce short file names (25 characters)
340Function/S V_DoSaveFileDialog(msg,[fname,suffix])
341        String msg,fname,suffix
342        Variable refNum
343//      String message = "Save the file as"
344
345        if(ParamIsDefault(fname))
346//              Print "fname not supplied"
347                fname = ""
348        endif
349        if(ParamIsDefault(suffix))
350//              Print "suffix not supplied"
351                suffix = ""
352        endif
353       
354        String outputPath,tmpName,testStr
355        Variable badLength=0,maxLength=25,l1,l2
356       
357       
358        tmpName = fname + suffix
359       
360        do
361                badLength=0
362                Open/D/M=msg/T="????" refNum as tmpName         //OS will allow 255 characters, but then I can't read it back in!
363                outputPath = S_fileName
364               
365                testStr = ParseFilePath(0, outputPath, ":", 1, 0)               //just the filename
366                if(strlen(testStr)==0)
367                        break           //cancel, allow exit
368                endif
369                if(strlen(testStr) > maxLength)
370                        badlength = 1
371                        DoAlert 2,"File name is too long. Is\r"+testStr[0,maxLength-1]+"\rOK?"
372                        if(V_flag==3)
373                                outputPath = ""
374                                break
375                        endif
376                        if(V_flag==1)                   //my suggested name is OK, so trim the output
377                                badlength=0
378                                l1 = strlen(testStr)            //too long length
379                                l1 = l1-maxLength               //number to trim
380                                //Print outputPath
381                                l2=strlen(outputPath)
382                                outputPath = outputPath[0,l2-1-l1]
383                                //Print "modified  ",outputPath
384                        endif
385                        //if(V_flag==2)  do nothing, let it go around again
386                endif
387               
388        while(badLength)
389       
390        return outputPath
391End
392
393
394
395//
396// this will only load the data into RAW, overwriting whatever is there. no copy is put in rawVSANS
397//
398Function V_LoadAndPlotRAW_wName(fname)
399        String fname
400
401        Variable err=   V_LoadHDF5Data(fname,"RAW")                     // load the data
402//      Print "Load err = "+num2str(err)
403        if(!err)
404                SVAR hdfDF = root:file_name                     // last file loaded, may not be the safest way to pass
405                String folder = StringFromList(0,hdfDF,".")
406               
407                // this (in SANS) just passes directly to fRawWindowHook()
408                V_UpdateDisplayInformation("RAW")               // plot the data in whatever folder type
409                               
410                // set the global to display ONLY if the load was called from here, not from the
411                // other routines that load data (to read in values)
412                SVAR gLastFile =        root:Packages:NIST:VSANS:Globals:gLastLoadedFile
413                gLastFile = hdfDF
414        endif
415End
416
417
418
419//
420// previous/next button needs these functions
421// as well as many other utilities that manipulate the data file names
422// and parse run numbers.
423//
424
425
426// TODO
427// x- load in the proper file
428// x- re-click the I(q) button
429// x- be sure that the globals are updated w/ filename
430// -- getting the file_name from the root: global is a poor choice.
431//     Need a better, more reliable solution than this
432// -- make a copy of "oldName" that is local and not the SVAR, as the SVAR changes
433//    when the next file is loaded in (if it's not in RawVSANS), resulting in a "skipped" file number
434//
435//displays next (or previous) file in series of run numbers
436//file is read from disk, if path is set and the file number is present
437//increment +1, adds 1 to run number, -1 subtracts one
438//
439// will automatically step a gap of 10 run numbers, but nothing larger. Don't want to loop too long
440// trying to find a file (frustrating), don't want to look past the end of the run numbers (waste)
441// -- may find a more elegant solution later.
442//
443Function V_LoadPlotAndDisplayRAW(increment)
444        Variable increment
445
446        Variable i,val
447        String filename,tmp,curFileName
448        //take the currently displayed RAW file
449        SVAR oldName = root:Packages:NIST:VSANS:Globals:gLastLoadedFile
450        oldname = V_RemoveAllSpaces(oldname)            //
451        curFileName = oldName
452//      print oldName
453       
454        filename = oldname
455//      for (i = 0; i < abs(increment); i += 1)
456//              filename = GetPrevNextRawFile(filename,increment/abs(increment))
457//      endfor 
458        i = 1
459        val = increment
460        do
461//              print filename,val
462                filename = V_GetPrevNextRawFile(filename,val)
463//              print "new= ",filename
464               
465                val = i*increment
466                i+=1
467                tmp = ParseFilePath(0, filename, ":", 1, 0)
468
469//              print val,strlen(tmp),strlen(oldname)
470//              print cmpstr(tmp,oldname)
471
472                if(strlen(tmp) == 0)            //in some cases, a null string can be returned - handle gracefully
473                        return(0)
474                endif
475               
476        while( (cmpstr(tmp,curFileName) == 0) && i < 11)
477//      print filename
478       
479        // display the specified RAW data file
480        // this is the set of steps done in DisplayMainButtonProc(ctrlName) : ButtonControl
481        Variable err=   V_LoadHDF5Data(filename,"RAW")                  // load the data, set the global w/file name loaded
482//      Print "Load err = "+num2str(err)
483        if(!err)
484                SVAR hdfDF = root:file_name                     // last file loaded, may not be the safest way to pass
485                String folder = StringFromList(0,hdfDF,".")
486               
487                // this (in SANS) just passes directly to fRawWindowHook()
488                V_UpdateDisplayInformation("RAW")       // plot the data in whatever folder type
489               
490                // set the global to display ONLY if the load was called from here, not from the
491                // other routines that load data (to read in values)
492                SVAR gLastLoad = root:Packages:NIST:VSANS:Globals:gLastLoadedFile
493                gLastLoad = hdfDF
494        endif
495
496        // TODO
497        // x- update the 1D plotting as needed. these are SANS calls (OK for now, but will need to be better)
498        //do the average and plot (either the default, or what is on the panel currently)
499        SVAR type = root:Packages:NIST:VSANS:Globals:gCurDispType
500        type = "RAW"
501        V_PlotData_Panel()              // read the binType from the panel
502        Variable binType = V_GetBinningPopMode()
503        V_BinningModePopup("",binType,"")               // does default circular binning and updates the graph
504
505
506        return(0)
507End
508
509
510// Return the full path:filename that represents the previous or next file.
511// Input is current filename and increment.
512// Increment should be -1 or 1
513// -1 => previous file
514// 1 => next file
515//
516// V_CheckIfRawData(fname)
517//
518Function/S V_GetPrevNextRawFile(curfilename, prevnext)
519        String curfilename
520        Variable prevnext
521
522        String filename
523       
524        //get the run number
525        Variable num = V_GetRunNumFromFile(curfilename)
526               
527        //find the next specified file by number
528        fileName = V_FindFileFromRunNumber(num+prevnext)
529
530        if(cmpstr(fileName,"")==0)
531                //null return, do nothing
532                fileName = V_FindFileFromRunNumber(num)         //returns the full path, not just curFileName
533        Endif
534
535        Return filename
536End
537
538
539//returns a string containing the full path to the file containing the
540//run number "num". The null string is returned if no valid file can be found
541//the path "catPathName" used and is hard-wired, will abort if this path does not exist
542//the file returned will be a RAW VSANS data file, other types of files are
543//filtered out.
544//
545//
546// -- with the run numbers incrementing from 1, there is no need to add leading zeros to the
547//    file names. simply add the number and go.
548//
549// called by Buttons.ipf and Transmission.ipf, and locally by parsing routines
550//
551Function/S V_FindFileFromRunNumber(num)
552        Variable num
553       
554        String fullName="",partialName="",item=""
555        //get list of raw data files in folder that match "num"
556
557        String numStr=""
558        numStr = num2str(num)
559
560        //make sure that path exists
561        PathInfo catPathName
562        String path = S_path
563        if (V_flag == 0)
564                Abort "folder path does not exist - use Pick Path button"
565        Endif
566        String list="",newList="",testStr=""
567       
568        list = IndexedFile(catPathName,-1,"????")       //get all files in folder
569        //find (the) one with the number in the run # location in the name
570        Variable numItems,ii,runFound,isRAW
571        numItems = ItemsInList(list,";")                //get the new number of items in the list
572        ii=0
573        do
574                //parse through the list in this order:
575                // 1 - does item contain run number (as a string) "TTTTTnnn.SAn_XXX_Tyyy"
576                // 2 - exclude by isRaw? (to minimize disk access)
577                item = StringFromList(ii, list  ,";" )
578                if(strlen(item) != 0)
579                        //find the run number, if it exists as a three character string
580                        testStr = V_GetRunNumStrFromFile(item)
581                        runFound= cmpstr(numStr,testStr)        //compare the three character strings, 0 if equal
582                        if(runFound == 0)
583                                //the run Number was found
584                                //build valid filename
585                                partialName = V_FindValidFileName(item)
586                                if(strlen(partialName) != 0)            //non-null return from FindValidFileName()
587                                        fullName = path + partialName
588                                        //check if RAW, if so,this must be the file!
589                                        isRAW = V_CheckIfRawData(fullName)
590                                        if(isRaw)
591                                                //print "is raw, ",fullname
592                                                //stop here
593                                                return(fullname)
594                                        Endif
595                                Endif
596                        Endif
597                Endif
598                ii+=1
599        while(ii<numItems)              //process all items in list
600        Return ("")     //null return if file not found in list
601End
602
603//
604// TODO x- for VSANS Nexus files, how do I quickly identify if a file is
605//   RAW VSANS data? I don't want to generate any errors, but I want to quickly
606//   weed out the reduced data sets, etc. from file catalogs.
607//      (check the instrument name...)
608
609// TODO -- as was written by SANS, this function is expecting fname to be the path:fileName
610// - but are the V_get() functions OK with getting a full path, and what do they
611//  do when they fail? I don't want them to spit up another open file dialog
612//
613// -- problem -- if "sans1234.abs" is passed, then V_getStringFromHDF5(fname,path,num)
614//  will remove the extension and look for the sans1234 folder -- which may or may not be present.
615//  If it is present, then sans1234 validates as RAW data -- which is incorrect!
616// -- so I need a way to exclude everything that does not have the proper extension...
617//
618//
619Function V_CheckIfRawData(fname)
620        String fname
621       
622        String testStr=""
623
624// check for the proper raw data extension
625        if( stringmatch(fname,"*.nxs.ngv*") )
626                // name appears OK, proceed
627                testStr = V_getInstrumentName(fname)
628
629                if(cmpstr(testStr,"NG3-VSANS") == 0)
630                        //testStr exists, ASSUMING it's a raw VSANS data file
631                        Return(1)
632                else
633                        //some other file
634                        Return(0)
635                Endif
636       
637        else
638                // not a proper raw VSANS file name
639                return(0)
640               
641        endif   
642       
643
644End
645
646// TODO x- need to fill in correctly by determining this from the INTENT field
647//
648Function V_isTransFile(fname)
649        String fname
650       
651        Variable refnum,totalBytes
652        String testStr=""
653       
654        testStr = V_getReduction_intent(fname)
655
656        if(cmpstr(testStr,"TRANSMISSION") == 0)         //
657                //yes, a transmission file
658                Return(1)
659        else
660                //some other file intent
661                Return(0)
662        Endif
663End
664
665
666Function V_GetRunNumFromFile(item)
667        String item
668       
669        String str = V_GetRunNumStrFromFile(item)
670       
671        return(str2num(str))
672end
673
674
675// TODO -- the file name structure for VSANS file is undecided
676// so some of these base functions will need to change
677//
678//given a filename of a VSANS data filename of the form
679// sansNNNN.nxs.ngv
680//returns the run number "NNNN" as a STRING of (x) characters
681//
682// -- the run number incements from 1, so the number of digits is UNKNOWN
683// -- number starts at position [4] (the 5th character)
684// -- number ends with the character prior to the first "."
685//
686//returns "ABCD" as an invalid file number
687//
688// local function to aid in locating files by run number
689//
690Function/S V_GetRunNumStrFromFile(item)
691        String item
692        String invalid = "ABCD" //"ABCD" is not a valid run number, since it's text
693        Variable num=-1
694       
695        //find the "dot"
696        String runStr=""
697        Variable numChar = 4
698        Variable pos = strsearch(item,".",0)
699        if(pos == -1)
700                //"dot" not found
701                return (invalid)
702        else
703                //found, get the characters preceeding it, but still after the "sans" characters
704                if (pos-1 < 4)
705                        //not enough characters
706                        return (invalid)
707                else
708                        runStr = item[4,pos-1]
709                        return (runStr)
710                Endif
711        Endif
712End
713
714//Function attempts to find valid filename from partial name by checking for
715// the existence of the file on disk.
716// - checks as is
717// - strips spaces
718// - permutations of upper/lowercase
719//
720// added 11/99 - uppercase and lowercase versions of the file are tried, if necessary
721// since from marquee, the filename field (textread[0]) must be used, and can be a mix of                       //02JUL13
722// upper/lowercase letters, while the filename on the server (should) be all caps
723// now makes repeated calls to ValidFileString()
724//
725// returns a valid filename (No path prepended) or a null string
726//
727// called by any functions, both external and local
728//
729Function/S V_FindValidFilename(partialName)
730        String PartialName
731       
732        String retStr=""
733       
734        //try name with no changes - to allow for ABS files that have spaces in the names 12APR04
735        retStr = V_ValidFileString(partialName)
736        if(cmpstr(retStr,"") !=0)
737                //non-null return
738                return(retStr)
739        Endif
740       
741        //if the partial name is derived from the file header, there can be spaces at the beginning
742        //or in the middle of the filename - depending on the prefix and initials used
743        //
744        //remove any leading spaces from the name before starting
745        partialName = V_RemoveAllSpaces(partialName)
746       
747        //try name with no spaces
748        retStr = V_ValidFileString(partialName)
749        if(cmpstr(retStr,"") !=0)
750                //non-null return
751                return(retStr)
752        Endif
753       
754        //try all UPPERCASE
755        partialName = UpperStr(partialName)
756        retStr = V_ValidFileString(partialName)
757        if(cmpstr(retStr,"") !=0)
758                //non-null return
759                return(retStr)
760        Endif
761       
762        //try all lowercase (ret null if failure)
763        partialName = LowerStr(partialName)
764        retStr = V_ValidFileString(partialName)
765        if(cmpstr(retStr,"") !=0)
766                //non-null return
767                return(retStr)
768        else
769                return(retStr)
770        Endif
771End
772
773
774// Function checks for the existence of a file
775// partialName;vers (to account for VAX filenaming conventions)
776// The partial name is tried first with no version number
777//
778// *** the PATH is hard-wired to catPathName (which is assumed to exist)
779// version numers up to ;10 are tried
780// only the "name;vers" is returned if successful. The path is not prepended
781//
782// local function
783//
784// TODO -- is this really necessary anymore for the NON-VAX files of VSANS.
785// -- can this be made a pass-through, or will there be another function that is needed for VSANS?
786//
787Function/S V_ValidFileString(partialName)
788        String partialName
789       
790        String tempName = "",msg=""
791        Variable ii,refnum
792       
793        ii=0
794        do
795                if(ii==0)
796                        //first pass, try the partialName
797                        tempName = partialName
798                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName     //Does open file (/Z flag)
799                        if(V_flag == 0)
800                                //file exists
801                                Close refnum            //YES needed,
802                                break
803                        endif
804                else
805                        tempName = partialName + ";" + num2str(ii)
806                        Open/Z/R/T="????TEXT"/P=catPathName refnum tempName
807                        if(V_flag == 0)
808                                //file exists
809                                Close refnum
810                                break
811                        endif
812                Endif
813                ii+=1
814                //print "ii=",ii
815        while(ii<11)
816        //go get the selected bits of information, using tempName, which exists
817        if(ii>=11)
818                //msg = partialName + " not found. is version number > 11?"
819                //DoAlert 0, msg
820                //PathInfo catPathName
821                //Print S_Path
822                Return ("")             //use null string as error condition
823        Endif
824       
825        Return (tempName)
826End
827
828//function to remove all spaces from names when searching for filenames
829//the filename (as saved) will never have interior spaces (TTTTTnnn_AB _Bnnn)
830//but the text field in the header WILL, if less than 3 characters were used for the
831//user's initials, and can have leading spaces if prefix was less than 5 characters
832//
833//returns a string identical to the original string, except with the interior spaces removed
834//
835// local function for file name manipulation
836//
837Function/S V_RemoveAllSpaces(str)
838        String str
839       
840        String tempstr = str
841        Variable ii,spc,len             //should never be more than 2 or 3 trailing spaces in a filename
842        ii=0
843        do
844                len = strlen(tempStr)
845                spc = strsearch(tempStr," ",0)          //is the last character a space?
846                if (spc == -1)
847                        break           //no more spaces found, get out
848                endif
849                str = tempstr
850                tempStr = str[0,(spc-1)] + str[(spc+1),(len-1)] //remove the space from the string
851        While(1)        //should never be more than 2 or 3
852       
853        If(strlen(tempStr) < 1)
854                tempStr = ""            //be sure to return a null string if problem found
855        Endif
856       
857        //Print strlen(tempstr)
858       
859        Return(tempStr)
860               
861End
862
863// returns a list of raw data files in the catPathName directory on disk
864// - list is SEMICOLON-delimited
865//
866// TODO: decide how to do this...
867// (1)
868// checks each file in the directory to see if it is a RAW data file by
869// call to V_CheckIfRawData() which currently looks for the instrument name in the file.
870// -- CON - this is excruciatingly slow, and by checking a field in the file, has to load in the
871//  ENTIRE data file, and will load EVERY file in the folder. ugh.
872//
873// (2)
874// as was done for VAX files, look for a specific string in the file name as written by the acquisition
875//  (was .saN), now key on ".nxs.ngv"?
876//
877// called by PatchFiles.ipf, Tile_2D.ipf
878//
879Function/S V_GetRawDataFileList()
880       
881        //make sure that path exists
882        PathInfo catPathName
883        if (V_flag == 0)
884                Abort "Folder path does not exist - use Pick Path button on Main Panel"
885        Endif
886        String path = S_Path
887       
888        String list=IndexedFile(catPathName,-1,"????")
889        String newList="",item="",validName="",fullName=""
890        Variable num=ItemsInList(list,";"),ii
891       
892        for(ii=0;ii<num;ii+=1)
893                item = StringFromList(ii, list  ,";")
894
895                validName = V_FindValidFileName(item)
896                if(strlen(validName) != 0)              //non-null return from FindValidFileName()
897                        fullName = path + validName             
898
899        //method (1)                   
900//                      if(V_CheckIfRawData(item))
901//                              newlist += item + ";"
902//                      endif
903
904        //method (2)                   
905                        if( stringmatch(item,"*.nxs.ngv*") )
906                                newlist += item + ";"
907                        endif
908
909                       
910                endif
911                //print "ii=",ii
912        endfor
913        newList = SortList(newList,";",0)
914        return(newList)
915End
916
917//
918// TODO:
919// -- does this need to be more sophisticated?
920//
921// simple "not" of V_GetRawDataFileList()
922Function/S V_Get_NotRawDataFileList()
923       
924        //make sure that path exists
925        PathInfo catPathName
926        if (V_flag == 0)
927                Abort "Folder path does not exist - use Pick Path button on Main Panel"
928        Endif
929        String path = S_Path
930       
931        String list=IndexedFile(catPathName,-1,"????")
932        String newList="",item="",validName="",fullName=""
933        Variable num=ItemsInList(list,";"),ii
934       
935        for(ii=0;ii<num;ii+=1)
936                item = StringFromList(ii, list  ,";")
937
938//              validName = V_FindValidFileName(item)
939//              if(strlen(validName) != 0)              //non-null return from FindValidFileName()
940//                      fullName = path + validName             
941
942        //method (2)                   
943                        if( !stringmatch(item,"*.nxs.ngv*") )
944                                newlist += item + ";"
945                        endif
946
947                       
948//              endif
949                //print "ii=",ii
950        endfor
951        newList = SortList(newList,";",0)
952        return(newList)
953End
954
955
956//the following is a WaveMetrics procedure from <StrMatchList>
957// MatchList(matchStr,list,sep)
958// Returns the items of the list whose items match matchStr
959// The lists are separated by the sep character, usually ";"
960//
961// matchStr may be something like "abc", in which case it is identical to CmpStr
962// matchStr may also be "*" to match anything, "abc*" to match anything starting with "abc",
963//      "*abc" to match anything ending with "abc".
964// matchStr may also begin with "!" to indicate a match to anything not matching the rest of
965//      the pattern.
966// At most one "*" and one "!" are allowed in matchStr, otherwise the results are not guaranteed.
967//
968Function/S V_MyMatchList(matchStr,list,sep)
969        String matchStr,list,sep
970        String item,outList=""
971        Variable n=strlen(list)
972        Variable en,st=0
973        do
974                en= strsearch(list,sep,st)
975                if( en < 0 )
976                        if( st < n-1 )
977                                en= n   // no trailing separator
978                                sep=""  // don't put sep in output, either
979                        else
980                                break   // no more items in list
981                        endif
982                endif
983                item=list[st,en-1]
984                if( V_MyStrMatch(matchStr,item) == 0 )
985                        outlist += item+sep
986                Endif
987                st=en+1
988        while (st < n ) // exit is by break, above
989        return outlist
990End
991
992//the following is a WaveMetrics procedure from <StrMatchList>
993// StrMatch(matchStr,str)
994// Returns 0 if the pattern in matchStr matches str, else it returns 1
995//
996// matchStr may be something like "abc", in which case it is identical to CmpStr
997// matchStr may also be "*" to match anything, "abc*" to match anything starting with "abc",
998//      "*abc" to match anything ending with "abc".
999// matchStr may also begin with "!" to indicate a match to anything not matching the rest of
1000//      the pattern.
1001// At most one "*" and one "!" are allowed in matchStr, otherwise the results are not guaranteed.
1002//
1003Function V_MyStrMatch(matchStr,str)
1004        String matchStr,str
1005        Variable match = 1              // 0 means match
1006        Variable invert= strsearch(matchStr,"!",0) == 0
1007        if( invert )
1008                matchStr[0,0]=""        // remove the "!"
1009        endif
1010        Variable st=0,en=strlen(str)-1
1011        Variable starPos= strsearch(matchStr,"*",0)
1012        if( starPos >= 0 )      // have a star
1013                if( starPos == 0 )      // at start
1014                        matchStr[0,0]=""                                // remove star at start
1015                else                                    // at end
1016                        matchStr[starPos,999999]=""     // remove star and rest of (ignored, illegal) pattern
1017                endif
1018                Variable len=strlen(matchStr)
1019                if( len > 0 )
1020                        if(starPos == 0)        // star at start, match must be at end
1021                                st=en-len+1
1022                        else
1023                                en=len-1        // star at end, match at start
1024                        endif
1025                else
1026                        str=""  // so that "*" matches anything
1027                endif
1028        endif
1029        match= !CmpStr(matchStr,str[st,en])==0  // 1 or 0
1030        if( invert )
1031                match= 1-match
1032        endif
1033        return match
1034End
1035
1036
1037//input is a list of run numbers, and output is a list of filenames (not the full path)
1038//*** input list must be COMMA delimited***
1039//output is equivalent to selecting from the CAT table
1040//if some or all of the list items are valid filenames, keep them...
1041//if an error is encountered, notify of the offending element and return a null list
1042//
1043//output is COMMA delimited
1044//
1045// this routine is expecting that the "ask", "none" special cases are handled elsewhere
1046//and not passed here
1047//
1048// called by Marquee.ipf, MultipleReduce.ipf, ProtocolAsPanel.ipf
1049//
1050Function/S V_ParseRunNumberList(list)
1051        String list
1052       
1053        String newList="",item="",tempStr=""
1054        Variable num,ii,runNum
1055       
1056        //expand number ranges, if any
1057        list = V_ExpandNumRanges(list)
1058       
1059        num=itemsinlist(list,",")
1060       
1061        for(ii=0;ii<num;ii+=1)
1062                //get the item
1063                item = StringFromList(ii,list,",")
1064                //is it already a valid filename?
1065                tempStr=V_FindValidFilename(item) //returns filename if good, null if error
1066                if(strlen(tempstr)!=0)
1067                        //valid name, add to list
1068                        //Print "it's a file"
1069                        newList += tempStr + ","
1070                else
1071                        //not a valid name
1072                        //is it a number?
1073                        runNum=str2num(item)
1074                        //print runnum
1075                        if(numtype(runNum) != 0)
1076                                //not a number -  maybe an error                       
1077                                DoAlert 0,"List item "+item+" is not a valid run number or filename. Please enter a valid number or filename."
1078                                return("")
1079                        else
1080                                //a run number or an error
1081                                tempStr = V_GetFileNameFromPathNoSemi( V_FindFileFromRunNumber(runNum) )
1082                                if(strlen(tempstr)==0)
1083                                        //file not found, error
1084                                        DoAlert 0,"List item "+item+" is not a valid run number. Please enter a valid number."
1085                                        return("")
1086                                else
1087                                        newList += tempStr + ","
1088                                endif
1089                        endif
1090                endif
1091        endfor          //loop over all items in list
1092       
1093        return(newList)
1094End
1095
1096//takes a comma delimited list that MAY contain number range, and
1097//expands any range of run numbers into a comma-delimited list...
1098//and returns the new list - if not a range, return unchanged
1099//
1100// local function
1101//
1102Function/S V_ExpandNumRanges(list)
1103        String list
1104       
1105        String newList="",dash="-",item,str
1106        Variable num,ii,hasDash
1107       
1108        num=itemsinlist(list,",")
1109//      print num
1110        for(ii=0;ii<num;ii+=1)
1111                //get the item
1112                item = StringFromList(ii,list,",")
1113                //does it contain a dash?
1114                hasDash = strsearch(item,dash,0)                //-1 if no dash found
1115                if(hasDash == -1)
1116                        //not a range, keep it in the list
1117                        newList += item + ","
1118                else
1119                        //has a dash (so it's a range), expand (or add null)
1120                        newList += V_ListFromDash(item)         
1121                endif
1122        endfor
1123       
1124        return newList
1125End
1126
1127//be sure to add a trailing comma to the return string...
1128//
1129// local function
1130//
1131Function/S V_ListFromDash(item)
1132        String item
1133       
1134        String numList="",loStr="",hiStr=""
1135        Variable lo,hi,ii
1136       
1137        loStr=StringFromList(0,item,"-")        //treat the range as a list
1138        hiStr=StringFromList(1,item,"-")
1139        lo=str2num(loStr)
1140        hi=str2num(hiStr)
1141        if( (numtype(lo) != 0) || (numtype(hi) !=0 ) || (lo > hi) )
1142                numList=""
1143                return numList
1144        endif
1145        for(ii=lo;ii<=hi;ii+=1)
1146                numList += num2str(ii) + ","
1147        endfor
1148       
1149        Return numList
1150End
1151
1152//*********************
1153// List utilities
1154//*********************
1155Function/WAVE V_List2TextWave(list,sep,waveStr)
1156        String list,sep,waveStr
1157       
1158        Variable n= ItemsInList(list,sep)
1159        Make/O/T/N=(n) $waveStr= StringFromList(p,list,sep)
1160        return $waveStr
1161End
1162
1163Function/WAVE V_List2NumWave(list,sep,waveStr)
1164        String list,sep,waveStr
1165       
1166        Variable n= ItemsInList(list,sep)
1167        Make/O/D/N=(n) $waveStr= str2num( StringFromList(p,list,sep) )
1168        return $waveStr
1169End
1170
1171Function /S V_TextWave2List(w,sep)
1172        Wave/T w
1173        String sep
1174       
1175        String newList=""
1176        Variable n=numpnts(w),ii=0
1177        do
1178                newList += w[ii] + sep
1179                ii+=1
1180        while(ii<n)
1181        return(newList)
1182End
1183
1184//for numerical waves
1185Function/S V_NumWave2List(w,sep)
1186        Wave w
1187        String sep
1188       
1189        String newList="",temp=""
1190        Variable n=numpnts(w),ii=0,val
1191        do
1192                val=w[ii]
1193                temp=""
1194                sprintf temp,"%g",val
1195                newList += temp
1196                newList += sep
1197                ii+=1
1198        while(ii<n)
1199        return(newList)
1200End
Note: See TracBrowser for help on using the repository browser.