Use Wavelist to programmatically declare and use waves

Hi--

      The goal of this function is average one second data to some other value, say one minute. I want to use Wavelist or some other method, to determine the wave names in the selected folder, and then average them, plot them, etc.. The problem I'm currently having is I cant get the function to compile because the call for declaration is incorrect. Once I figure out how to be able to work with the waves that Wavelist has identified as being in the directory I can move on. For instance let's say I want to next graph ListoWaves[0] vs Timewave then I can move on. See inserted code. As usual thanks in advance for any help.

ssmith

    String ListoWaves = Wavelist("*",";","DP:1") //"DP:1" selects only dbl precision float waves to be averaged, eliminates text waves
    String Timewave = Wavelist("*time*",";","DP:1") //Identifies the time wave
//  Print ListoWaves
//  Print Timewave
    Variable NumWaves = ItemsinList(ListoWaves) //finds the number of items in wavelist
//  Print Numwaves
    Wave/T WL = ListToTextWave(Listowaves,";")
    FOR(e=0;e<(NumWaves);e+=1)
        Wave WaveDeclare = $WL[e]
    ENDFOR

 


 

If I put your code in a function, the compiler complains that your variable e is not declared. If I add this before the for loop, it then compiles:

 

Variable e

 

Note that I would suggest not using "e" as the name of a variable since it's also the name of a built-in function and that could be confusing, but it's allowed.

Note that since Igor 9 you can also do a range-based loop, which would get rid of the variable e and would collapse the latter half of your code into a convenient expression:

for (String curr : ListToTextWave(ListoWaves,";"))
    WAVE WaveDeclare = $curr
endfor

Also note that with your current method of creating the lists, Timewave is contained within ListoWaves. Maybe you want that, but if not you either want to use:

String ListoWaves = Wavelist("!*time*",";","DP:1")

or run RemoveFromList() later.

Hi All--

     This code doesn't compile. It fails at the first print statement. See the attached file. Again I'm trying to declare all of the waves in the current folder so I don't have to list/declare them individually in addition to making it versatile. This way it can be used to create averages for different wave names. It also doesn't compile if I switch the FOR loops. My guess is that I'm trying to use waves (Extinction_Blue_cat, IgorTime_Cat) before they are declared. Any help is greatly appreciated. Thanks.

ssmith

 

 

 

 

Function AverageCAPSDAQData()
 
//The function creates averaged data of the waves in the current data folder
 
 
    Variable avgTime
    Prompt avgtime,"Enter Averaging Time in Minutes"
    Doprompt "Data Averaging Time",avgTime
    String VariPrefix = "Min"+num2str(AvgTime)+"_avg"// Creates Prefix based on averaging time
    variable a,b,c,d,f
    
    String ListoWaves = Wavelist("*",";","DP:1") //"DP:1" selects only dbl precision float waves to be averaged, eliminates text waves
    String Timewave = Wavelist("*time*",";","DP:1") //Identifies the time wave
//  Print ListoWaves
//  Print Timewave
    Variable NumWaves = ItemsinList(ListoWaves) //finds the number of items in wavelist
//  Print Numwaves
 
//  Wave/T WL = ListToTextWave(Listowaves,";")
//  FOR(f=0;f<(NumWaves);f+=1)
//      Wave WaveDeclare = $WL[f]
//  ENDFOR
    for (String curr : ListToTextWave(ListoWaves,";"))
        WAVE WaveDeclare = $curr
    endfor
Print Extinction_Blue_cat[0]
Print IgorTime_cat[0]
Display Extinction_Blue_cat vs igortime_cat
 
        
END     

 

Compilation Error.png (86.12 KB)

The declaration

WAVE WaveDeclare = $curr

associates the local wave name "WaveDeclare" with the wave whose name is in the string variable. Therefore it doesn't make sense to repeat such a declaration in a loop: at the end WaveDeclare will be associated with the last wave in the list. You need different local names for different waves.

You may try a function like:

function/wave name2wave(string name)
 
wave/z w=$name
 
if (!WaveExists(w))
   abort "the wave "+name+" does not exist"
endif
 
return w
end

and then :

wave Extinction_Blue_cat=name2wave("Extinction_Blue_cat")
wave IgorTime_cat=name2wave("IgorTime_cat")
 
print Extinction_Blue_cat[0]

etc.

but the following will work too (without local name):

print name2wave("Extinction_Blue_cat")[0]  // will quit here if blue cats don't exist

I think that I may not be making myself clear here, sorry about that. I have loaded a file that has created a series of waves seen in the data browser in the attached image. The wave names correspond to the variables the instruments save. In order to manipulate the waves they need to be declared using the "Wave wavename" statement. Depending on which instrument the data comes from the waves names will be different. I'm trying to programmatically declare the wave names without listing each actual wave name. Perhaps ListToTextWave is not correct maybe ListToWaveRefWave is a better way to go? 

Yes,  in this case ListToWaveRefWave  is indeed the function you need to get a wave containing a list of wave references from a list of wave names.  It is basically equivalent to calling "name2wave" in a loop, assigning a wave reference to each string of the list.

 

 

Thanks. Using the Igor help for the function I've been trying to get this to compile but I'm not having any luck. I'm sure the syntax is wrong but I'm not good enough to see it. Can you help?

Function AverageCAPSDAQData()
 
//The function creates averaged data of the waves in the current data folder
 
 
    Variable avgTime
    Prompt avgtime,"Enter Averaging Time in Minutes"
    Doprompt "Data Averaging Time",avgTime
    String VariPrefix = "Min"+num2str(AvgTime)+"_avg"// Creates Prefix based on averaging time
    variable a,b,c,d,f
    
    String ListoWaves = Wavelist("*",";","DP:1") //"DP:1" selects only dbl precision float waves to be averaged, eliminates text waves
    String Timewave = Wavelist("*time*",";","DP:1") //Identifies the time wave
 
    Variable NumWaves = ItemsinList(ListoWaves) //finds the number of items in wavelist
 
    Wave/Wave  WL = ListToWaveRefWave(Listowaves,0)
    FOR(f=0;f<(NumWaves);f+=1)
        Wave WL[f]
    ENDFOR
    
END 

 

Look at my just updated answer.  The function ListToWaverefWave already performs the loop you are trying to do in the following lines (for f=0 etc.), just drop this for loop. After the instruction 

Wave/Wave  WL = ListToWaveRefWave(Listowaves,0)

WL[0]  will be the reference to the first wave of the list, e.g. WL[0][0]  is the value of the first element of the first wave etc.

WL[1]  will be the reference to the second wave of the list, e.g. WL[1][0]  is the value of the first element of the second wave etc.

etc.

still curious where are those blue cats...

For each iteration of your for loop, the wave that the wave reference variable (WL) points to changes.

If you know there will be a wave named "Extinction_Blue_cat" in the current data folder and you need to reference that specific wave, you should just declare a wave reference variable for that wave. You might need to create a lot of wave references if you have a lot of waves you need to reference by name.

 

Yes, I was hoping to declare them programmatically, so I would not have to make 25 wave declarations, and then in later functions call them by their actual wave name. Is that possible or do I have to associate the actual name with the reference? It sounds like I just have to declare each of the waves by name so I can manipulate them using the actual wave name?

Consider the following code:

// Makes \a numWaves in the current data folder.
Function MakeWaves(Variable numWaves)
    Variable n
    String thisWaveName
    For(n=0; n < numWaves; n++)
        thisWaveName = "wave" + num2str(n)
        Make/O/N=3 $(thisWaveName) = n
    EndFor
End
 
// Returns the total sum of all waves named "wave*"
// in the current data folder.
Function SumAllPoints()
    String waveNameList = WaveList("wave*", ";", "")
    Variable numWaves = ItemsInList(waveNameList, ";")
    Variable n
    Variable thisSum, totalSum
    For (n=0; n < numWaves; n++)
        WAVE thisWave = $(StringFromList(n, waveNameList, ";"))
        thisSum = sum(thisWave)
        totalSum += thisSum
    EndFor
    print "The total sum is:", totalSum
End

You can execute these functions like this:

MakeWaves(10)
sumallpoints()
  The total sum is:  135

Inside the for loop of SumAllPoints, I am declaring a wave reference each iteration through the loop so I can then access that wave to call the sum function. This works for any number of waves named "wave*" in the current data folder.

NOTE: What I wrote above is not the most efficient way to do what I did, I'm just trying to make an example of how to programmatically create a wave reference.

If you will always have a wave named timewave in the current data folder, just reference it like this:

WAVE timewave

If the name of the wave you want to use for that purpose might change, you can do something like:

WAVE timewave = $("timewave" + num2str(someVariable))

I'm not sure what you're actually trying to do so I can't give you code to do exactly that.

I'm not sure I understand your question but I will repeat:

The function name2wave I proposed assigns a name to a wave reference and returns this reference. The Igor function ListToWaveRefWave does the same for a list of wavenames.  Now if you want to select some specific names based on common prefixes, suffixes etc. you can use string manipulation functions like cmpstr, ListMatch or similar.  You now have all the tools you asked for. If you still don't know how to code your app it's not a question of Igor syntax, it's a question of how to organize a code to make an app (more difficult and demanding more experience). Maybe if you tell us with more details where the blue cats are we might think how to help you to organize your app :)