Using filename to name waves.

Dear All,

I am trying to create a simple script that would automatically load and rename my waves as I import them from files within a data folder. Each file contains columns each referring to different measurements of a given sample. They are therefore related by the sample, which is indicated in the filename. File names are quite structured, for example: 25C_Cell1_1, 25C_Cell1_2 up to 25_Cell1_35 (for example).

Each file contains different columns containing different properties that were measured, Time, Property1, Property2, etc

I now would like for Igor to load them, and rename them by calling the filename and adding a letter that would specify which property that wave refers too. For example, instead of loading and calling the waves wave0, wave1, wave2, etc. It should call it T_Filename, P1_Filename, P2_Filename. The original data is enough organized that I can say that Wave0 will correspond to time, wave1 to property 1, wave2 to property 2, etc.

Can I do this immediately on the /A= flag of Loadwave? Below you find my miserable attempt to do this. Here you see WaveX as the file, but the result is not just the filename, but the whole path.

Please let me know your thoughts.

Kind regards,

Ricardo
PS: Some print commands are just there to guide me to what the script is doing.

#pragma rtGlobals=3     // Use modern global access method and strict wave access.
Menu "Macros"
    "Load and Rename TXT Data", LoadAndRename()


Function/S LoadAndRename()
variable RefNum
String message = "Select one or more files"
String InFile
String fileFilters = "Data Files (*.txt,*.dat,*.csv):.txt,.dat,.csv;"
fileFilters += "All Files:.*;"

Open /D /R /MULT=1 /F=fileFilters /M=message RefNum
InFile = S_fileName
Print "The RefNUM is: ", refNum
Print "The Selected Files are: ", InFile

if (strlen(InFile) == 0)
Print "File Contains No Data - Script was Cancelled!!"
else
Variable numFilesSelected = ItemsInList(InFile, "\r")
Variable i
for(i=0; i String WaveX = StringFromList(i, InFile, "\r")
Printf "%d: %s\r", i, WaveX

// Add commands here to load the actual waves.
LoadWave/A/D/G/W/K=2 WaveX // The Flag "/G" indicates that the data is GENERAL TEXT
String ForceWave = "T_"+WaveX
String baseName = CleanupName(InFile,0)
Print "THIS IS THE BASENAME: ", baseName
Print "this is ForceWave ", ForceWave
Print "numFilesSelected ******* ", numFilesSelected

endfor
endif
Killwaves/A/Z/F
Print "*********************** END OF SCRIPT ********************************"
return InFile // Will be empty if user canceled

END
Use ParseFilePath to obtain various parts of a file path.

For example, to get the wave name without the extension from the full path using your string variable:

ParseFilePath(3, WaveX, ":", 0, 0)
After using ParseFilePath to get the file name (not the path, just the name), use the LoadWave/B flag to tell LoadWave what name to use for the wave.
Than you very much for the suggestions. So it works.
Within the File, not all columns/waves are relevant. So I decided to let Igor autoname them (wave0, wave1, ...), Kill unnecessary waves, duplicate the relevant ones with the required name, and then kill all autonamed waves before proceeding to the next file.

Function/S LoadAndRename()
    variable RefNum
    String message = "Select one or more files"
    String InFile
    String fileFilters = "Data Files (*.txt,*.dat,*.csv):.txt,.dat,.csv;"
    fileFilters += "All Files:.*;"
 
    Open /D /R /MULT=1 /F=fileFilters /M=message RefNum
    InFile = S_fileName
    Print "The RefNUM is: ", refNum
    Print "The Selected Files are: ", InFile
 
    if (strlen(InFile) == 0)
        Print "File Contains No Data - Script was Cancelled!!"
    else
        Variable numFilesSelected = ItemsInList(InFile, "\r")
        Variable i
        for(i=0; i<numFilesSelected; i+=1)
            String WaveX = StringFromList(i, InFile, "\r")
            Printf "%d: %s\r", i, WaveX
            String FileName = ParseFilePath(3, WaveX, ":", 0, 0)
            // Add commands here to load the actual waves.
            LoadWave/A/D/G/W/K=2 WaveX // The Flag "/G" indicates that the data is GENERAL TEXT
            Wave Wave0, Wave1, Wave2, Wave3, Wave4
            Killwaves Wave0, Wave1, Wave2, Wave3, Wave4 //First 5 Waves are unimportant
            Wave Wave5, Wave6, Wave7, wave8, Wave9
            Duplicate/O Wave5 $("F_"+FileName+"_Ext")/WAVE=ForceWave_Extend
            Duplicate/O Wave6 $("T_"+FileName+"_Ext")/WAVE=TimeWave_Extend
            Duplicate/O Wave7 $("Sep_"+FileName+"_Ext")/WAVE=SepWave_Extend
            Killwaves Wave5, Wave6, Wave7, Wave8, Wave9     //Clean up
            Wave Wave10, Wave11, Wave12, Wave13, Wave14
            Duplicate/O Wave11 $("F_"+FileName+"_Pause")/WAVE=ForceWave_Pause
            Duplicate/O Wave12 $("T_"+FileName+"_Pause")/WAVE=TimeWave_Pause
            Duplicate/O Wave13 $("Sep_"+FileName+"_Pause")/WAVE=SepWave_Pause
            Killwaves Wave10, Wave11, Wave12, Wave13, Wave14    //Clean up
           
        endfor
    endif
    Print "*********************** END OF SCRIPT ********************************"
    return InFile       // Will be empty if user canceled
   
END


There must be a more streamlined way to do this. Can I for example use LoadWave to tell Igor to pick only specific blocks of Data?
Although data is delimited by a space, I have been importing data as General Text because so far this has worked out better than using delimited text as import mode.

I place below an example of what the original TXT Files look like. Each contains 15 datasets separaded by a space, and a bunch of annotations. Is there a way to specifically collect selected columns of data from such a file?

Thanks for the suggestions!!


# TEXT
# TEXT
# TEXT
# TEXT

# MORE TEXT
# MORE TEXT
# MORE TEXT

-3.365417E-10 0.0017089844 8.612418E-6 5.9999998E-6 -2.5E-5
-3.3551864E-10 0.005126953 8.610098E-6 5.9999998E-6 -2.5E-5
-3.3567965E-10 0.008544922 8.607764E-6 5.9999998E-6 -2.5E-5
-3.3599612E-10 0.011962891 8.605427E-6 5.9999998E-6 -2.5E-5


# TEXT
# TEXT
# TEXT
# TEXT

# MORE TEXT
# MORE TEXT
# MORE TEXT

-3.365417E-10 0.0017089844 8.612418E-6 5.9999998E-6 -2.5E-5
-3.3551864E-10 0.005126953 8.610098E-6 5.9999998E-6 -2.5E-5
-3.3567965E-10 0.008544922 8.607764E-6 5.9999998E-6 -2.5E-5
-3.3599612E-10 0.011962891 8.605427E-6 5.9999998E-6 -2.5E-5

# TEXT
# TEXT
# TEXT
# TEXT

# MORE TEXT
# MORE TEXT
# MORE TEXT

-3.365417E-10 0.0017089844 8.612418E-6 5.9999998E-6 -2.5E-5
-3.3551864E-10 0.005126953 8.610098E-6 5.9999998E-6 -2.5E-5
-3.3567965E-10 0.008544922 8.607764E-6 5.9999998E-6 -2.5E-5
-3.3599612E-10 0.011962891 8.605427E-6 5.9999998E-6 -2.5E-5

Quote:
So I decided to let Igor autoname them (wave0, wave1, ...), Kill unnecessary waves


If may not be of interest to you but ...

You can tell LoadWave to skip loading a column by specifying its name as '_skip_' using the /B flag.
Thank you hrodstein!! I looked at the documentation. It seems to me that by using the /B flag, I would then have to name the waves being extracted with a known name. In my case, I would like to name the waves in a dynamic way, whereby the name is given by the file name being read. Hence, the duplicate & killwaves pair. But I don't see how to accomplish that operation as part of the specifications of a flag.

Also, rather than skipping columns I was wondering if it would be possible to immediately tell which column number to extract the wave. I understand I could also use Rename rather than duplicate, but I still have to extract unnecessary waves and then kill them. Or do I?

Many thanks,

R.
Quote:
It seems to me that by using the /B flag, I would then have to name the waves being extracted with a known name.


You can construct the /B parameter using strings calculated based on the file name that you determine from S_fileName. For example:
String filePath = StringFromList(i, InFile, "\r")
String fileName = ParseFilePath(3, filePath, ":", 0, 0)  // Get file name, without extension, from path
String singleQuote = "'"
String semicolon = ";"
String columnInfoStr = ""
columnInfoStr += "N=" + singleQuote + fileName + "_Time" + singleQuote + semicolon
columnInfoStr += "N=" + singleQuote + fileName + "_Property1" + singleQuote + semicolon
columnInfoStr += "N=" + singleQuote + fileName + "_Property2" + singleQuote + semicolon
columnInfoStr += "N='_skip_';"  // Skip Property3 as we don't care about it
columnInfoStr += "N=" + singleQuote + fileName + "_Property4" + singleQuote + semicolon
LoadWave/A/O/D/G/K=2/B=columnInfoStr filePath


Quote:
Also, rather than skipping columns I was wondering if it would be possible to immediately tell which column number to extract the wave.


I don't understand this.

You can load a range of columns, rather than all columns, using the /L flag.

Quote:
I understand I could also use Rename rather than duplicate, but I still have to extract unnecessary waves and then kill them. Or do I?


Using Rename after LoadWave is problematic because if a wave already exists with the name you want to use, you Rename will fail. This is one of the benefits of /B - it can override waves with existing names, if you include the /O flag.

If you can't use /B for some reason then I would use Duplicate/O followed by KillWaves. This effectively accomplishes a rename without the problem explained in the preceding paragraph.
Thank you!! This is quite a help!! I was not aware we could write things in this way - comparing this to my duplicate/kill waves it's like comparing calligraphy with cave painting!! Thank you!!!