How to work with multiple waves in a loop

Hi Everyone,
I am a new user of Igor. I am trying to do a calculation in a loop which involves loading a text file which is a 2D matrix, storing it in a wave which has the dimension of my desired matrix and then doing a bunch of calculations with it and finally displaying a graph. I do this in a loop as I need to open multiple files at once. My problem is I am not being able to change the wave names at every iteration of the loop. So, to summarize my procedure starts by opening multiple files and loading them with separate wave names but as soon as I try to do calculations on them I can do that only once as it encounters the same wave in the second iteration and stops. Please can any one help me how to solve this problem. My procedure looks like this.
Function/S OpenMultiFileDialog()
    Variable refNum
    String message = "Select one or more files"
    String outputPaths
    String fileFilters = "Binary Files (*.bin):.bin;"
    fileFilters += "All Files:.*;"

    Open /D /R /MULT=1 /F=fileFilters /M=message refNum
    outputPaths = S_fileName
   
    if (strlen(outputPaths) == 0)
        Print "Cancelled"
    else
        Variable numFilesSelected = ItemsInList(outputPaths, "\r")
        Variable i
        for(i=0; i<numFilesSelected; i+=1)
            String path = StringFromList(i, outputPaths, "\r")
            GBLoadWave/B/T={80,80} path                //Here I am loading my files in respective waves.
            Duplicate/O wave0,rwave                    //Here I would like to change wave0 to wave1, wave2... at every iteration.
            Redimension/N=(512,480) rwave
            Make/N=(512,480)/W CDR
            CDR=0.5*((rwave)+abs(rwave))     //I would like to change the wave CDR to CDR1.CDR2...at every iteration.
            Display;AppendImage CDR;DelayUpdate
            ModifyImage CDR ctab= {*,80,Rainbow,1}
            ModifyGraph width=566.929,height=566.929
            SetAxis left -0.5,512
            endfor
    endif
    return outputPaths
end


Thank you very much.
You probably want to have a look at
displayhelptopic "Converting a String into a Reference Using $"
and the chapter IV-1 of the manual. It's worth to have a look.
Also have a look at num2str.
HJ
HJ was being wise in teaching you how to fish... here I'll just give you the fish. I haven't tested this, but it does compile.

For the GBLoadWave operation, Igor will set the string S_waveNames with a semicolon list of the names of waves that were loaded. You can use this info to refer to the loaded waves.

Changes that I propose have comments beginning //***

Function/S OpenMultiFileDialog()
    Variable refNum
    String message = "Select one or more files"
    String outputPaths
    String fileFilters = "Binary Files (*.bin):.bin;"
    String sWaveName = ""   //***
    String sCDRname = ""    //***
    String sMsg = ""
    fileFilters += "All Files:.*;"
 
    Open /D /R /MULT=1 /F=fileFilters /M=message refNum
    outputPaths = S_fileName
 
    if (strlen(outputPaths) == 0)
        Print "Cancelled"
    else
        Variable numFilesSelected = ItemsInList(outputPaths, "\r")
        Variable i
        for(i=0; i<numFilesSelected; i+=1)
            String path = StringFromList(i, outputPaths, "\r")
            GBLoadWave/B/T={80,80} path                //Here I am loading my files in respective waves.
            sWaveName = stringfromlist(0, S_waveNames)  //***Get name Igor assigned to loaded wave
            if( strlen( sWaveName ) == 0 )            //***Make sure a wave was loaded; exit loop if not.
                sMsg = "No Wave was loaded for iteration: " + num2str(i)    //***error message
                DoAlert /T="OpenMultiFileDialog", 0, sMsg   //***post alert
                break                                     //***error, exit loop
            endif
            Duplicate/O $sWaveName,rwave                //***Operate on the newly loaded wave.
            Redimension/N=(512,480) rwave
            sCDRname = "CDR" + num2str(i)                 //***name for new output wave
            Make/N=(512,480)/W $sCDRname
            Wave CDR = $sCDRname                       //***create reference to new CDRx wave
            CDR=0.5*((rwave)+abs(rwave))               //I would like to change the wave CDR to CDR1.CDR2...at every iteration.
            Display;AppendImage CDR;DelayUpdate
            ModifyImage CDR ctab= {*,80,Rainbow,1}
            ModifyGraph width=566.929,height=566.929
            SetAxis left -0.5,512
        endfor
    endif
    return outputPaths
End

Hello,
Thank you so much for your replies. I have been going through the display help topics you have mentioned, but it s an uphill struggle to get the theory to work in a short time. :) Thank you so much for the help jtigor. The procedure worked fine. I have now added few lines to subtract a background matrix from the loaded image file. This background matrix is loaded only once , so it needn't change with every iteration. However, in order to subtract it I needed to store it in different wave names at every iteration of the loop. I am not very comfortable with the procedure as I create copies of a wave which I don't really need. Is there a way out from this? Here is the total procedure .
I have indicated my additions with an arrow like this "<----" . Hope this is not too complicated.
sisignal=s1signa#pragma rtGlobals=1     // Use modern global access method.
macro background()
GBLoadWave/B/T={80,80}/W=1 "Usr1:b126lab:Desktop:20151130155509_Centroid512A.bin"
Rename wave0,b00
Redimension/N=(512,480) b00
Make/N=(512,480)/W/U b0
b0=2*b00
end
macro plot_background()
Display;AppendImage b0;DelayUpdate
ModifyImage b0 ctab= {*,80,Rainbow,1}
ModifyGraph width=566.929,height=566.929
SetAxis left -0.5,512
end
Function/S OpenMultiFileDialog()
    Variable refNum
    String message = "Select one or more files"
    String outputPaths
    String fileFilters = "Binary Files (*.bin):.bin;"
    String sWaveName = ""   //***
    String sCDRname = ""    //***
    String sm0=""              // <-----
    String sMsg = ""
    fileFilters += "All Files:.*;"
 
    Open /D /R /MULT=1 /F=fileFilters /M=message refNum
    outputPaths = S_fileName
 
    if (strlen(outputPaths) == 0)
        Print "Cancelled"
    else
        Variable numFilesSelected = ItemsInList(outputPaths, "\r")
        Variable i
            for(i=0; i<numFilesSelected; i+=1)
            String path = StringFromList(i, outputPaths, "\r")
            GBLoadWave/B/T={80,80} path                //Here I am loading my files in respective waves.
            sWaveName = stringfromlist(0, S_waveNames)  //***Get name Igor assigned to loaded wave
            if( strlen( sWaveName ) == 0 )            //***Make sure a wave was loaded; exit loop if not.
                sMsg = "No Wave was loaded for iteration: " + num2str(i)    //***error message
                DoAlert /T="OpenMultiFileDialog", 0, sMsg   //***post alert
                break                                     //***error, exit loop
            endif
            Duplicate/O $sWaveName,rwave                //***Operate on the newly loaded wave.
            Redimension/N=(512,480) rwave
            sCDRname = "CDR" + num2str(i)                 //***name for new output wave
            Make/N=(512,480)/W $sCDRname
            sm0="bb"+num2str(i)                             // <---- New output wave for background
            Duplicate/O b0,$sm0                               // <------ Duplicating the original background wave
            Wave CDR = $sCDRname                        //***create reference to new CDRx wave
            Wave m0=$sm0                                     // <------- Creating refernce for nrew background wave
            CDR=0.5*((rwave-m0)+abs(rwave-m0))               //<------ I have subtracted the background wave here
            Display;AppendImage $sCDRname;DelayUpdate
            ModifyImage $sCDRname ctab= {*,80,Rainbow,1}
            ModifyGraph width=566.929,height=566.929
            SetAxis left -0.5,512
            endfor
            endif
end


Thank you once more. It is very encouraging to see the procedure working fine.
Ananya
Quote:
My problem is I am not being able to change the wave names at every iteration of the loop.


Here is a simple example:

Function Test()
    Make/O wave0, wave1, wave2
   
    String list = "wave0;wave1;wave1;"
   
    Variable numItems = ItemsInList(list)
    Variable i
    for(i=0; i<numItems; i+=1)
        String item = StringFromList(i, list)
        Wave w = $item
        Print NameOfWave(w)
    endfor
End

ananya.sen wrote:
Hello,
I have now added few lines to subtract a background matrix from the loaded image file. This background matrix is loaded only once , so it needn't change with every iteration. However, in order to subtract it I needed to store it in different wave names at every iteration of the loop. I am not very comfortable with the procedure as I create copies of a wave which I don't really need. Is there a way out from this?

Ananya


If I correctly understand what you want to do, you don't need to duplicate the background wave each iteration. Create a reference to it once, outside of the loop and use that same reference for each iteration of the loop.

If the background wave is in the current directory (same one image waves are loaded into) you can create the reference using
Wave b0
or
Wave b0 = b0
If the wave is in a different directory you need to give the path to it:
Wave b0 = root:subdir1:subdir2:b0


Function/S OpenMultiFileDialog()
    Variable refNum
    String message = "Select one or more files"
    String outputPaths
    String fileFilters = "Binary Files (*.bin):.bin;"
    String sWaveName = ""   //***
    String sCDRname = ""    //***
    String sm0=""              // <-----
    String sMsg = ""
    fileFilters += "All Files:.*;"
 
    Open /D /R /MULT=1 /F=fileFilters /M=message refNum
    outputPaths = S_fileName
   
    Wave b0 = b0            //*****reference to background wave
   
    if (strlen(outputPaths) == 0)
        Print "Cancelled"
    else
        Variable numFilesSelected = ItemsInList(outputPaths, "\r")
        Variable i
        for(i=0; i<numFilesSelected; i+=1)
            String path = StringFromList(i, outputPaths, "\r")
            GBLoadWave/B/T={80,80} path                //Here I am loading my files in respective waves.
            sWaveName = stringfromlist(0, S_waveNames)  //***Get name Igor assigned to loaded wave
            if( strlen( sWaveName ) == 0 )            //***Make sure a wave was loaded; exit loop if not.
                sMsg = "No Wave was loaded for iteration: " + num2str(i)    //***error message
                DoAlert /T="OpenMultiFileDialog", 0, sMsg   //***post alert
                break                                     //***error, exit loop
            endif
            Duplicate/O $sWaveName,rwave                //***Operate on the newly loaded wave.
            Redimension/N=(512,480) rwave
            sCDRname = "CDR" + num2str(i)                 //***name for new output wave
            Make/N=(512,480)/W $sCDRname
            Wave CDR = $sCDRname                        //***create reference to new CDRx wave
            CDR=0.5*((rwave-b0)+abs(rwave-b0))               //*****b0 is the background wave
            Display;AppendImage $sCDRname;DelayUpdate
            ModifyImage $sCDRname ctab= {*,80,Rainbow,1}
            ModifyGraph width=566.929,height=566.929
            SetAxis left -0.5,512
        endfor
    endif
end
Hello,
Thank You!! Yes it works fine now without generating excess files. The only thing about the procedure which I find strange is if I want to load multiple files for the second time it tells me that there are waves of similar names present. So I added the following code to kill those waves before doing the calculation.
Duplicate/O $sWaveName,rwave                                         //Operate on the newly loaded wave.
            Redimension/N=(512,480) rwave
            sImagename = "Image" + num2str(i)
            If (WaveExists($sImagename))            //<-----
            KillWaves $sImagename                       //<-----
            endif                                                  //<------                  
            Make/N=(512,480)/W $sImagename
            Wave Image = $sImagename                                           //Creating reference to new CDRx wave
            Image=0.5*((rwave-b0)+abs(rwave-b0))              //   Subtraction of the background wave.
            Display;AppendImage $sImagename;DelayUpdate


The arrows indicate the added lines. When I write this, I get an error message saying " Waves which are part of a function, graph or XOP can't be killed". This is strange to me as I can very well go to the menu and delete those waves manually. I don't understand why the same function doesn't compile in a procedure.

Basically I want to do either of two things:
1. Kill waves which have similar names
2. Start the loop from the last value of i (of previous loop). This way I don't need to kill any waves. (I am struggling to write the procedure for this).

If this has been discussed before, can anyone send me the link to the thread please.

Thanks,
Ananya
There are some ways to achieve your goal(s):
You could
- simply overwrite the existing waves Make /O /N....
- run your index and only create the wave if it does not exist If (!WaveExists($sImagename))
(with or without recalculation of the existing ones)
- store the last used index and initialize the loop with that value (not recommended, error prone)

A way to find the first unused index would be a for-loop which only checks whether the corresponding wave exists and a second loop afterwards *without index initialization* doing the calculation. Copy the sample code to your procedure, adjust the "42" in the second loop to a number larger than your highest image number (but not much), and see what is does.
function test()
variable i
    for (i=0;exists("Image"+num2str(i))==1;i+=1) // quite compact
    endfor
    for (;i<42;i+=1) // <-- nothing in front of ";"
        print i  // here could be your code for new data
    endfor
end


Have a look at the online help for details of commands :-)
HJ