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 :)

I was pulled away for a few days. I would like to get back to this. What I want to do is create a generic averaging routine that can be used on any data. I deal with a number of instruments that collect one second data. I would like to average this data using the requested averaging time and the time wave. After the averaging is complete end up with wave names that have variprefix as the prefix for the real wave names so if some of the waves that I load are "Red_signal", "green_signal" and I average for 2 minutes the resulting wave names would be "Min2_avg_Red_Signal," "Min2_avg_Green_Signal". Then I would need to declare the existing wave names so that they can be plotted with something like "Display Min2_avg_Green_signal vs Min2_avg_Igortime" I hope this makes sense and clear things up. Thanks for any help that you provide.

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 ListoWaves
 
    Wave/Wave  WL = ListToWaveRefWave(Listowaves,0) //Declares all of the waves in the selected folder
                                                    //so they can used as if they were declared by name
//Someone suggested this but When this is uncommented it doesn't compile
//  Print WL[1][1]
//  Print WL[0]
//  Display WL[1] vs WL[0]
        
END

 

I think it might help if you read some of the documentation about how to process lists of waves. To bring it up, execute:

DisplayHelpTopic "Processing Lists of Waves"

 

I read the "Processing Lists of Waves" text an I think that what I'm trying to do is not possible. I'm trying to avoid writing these types of lines of code for each instrument and any new wave groups that I load into an experiment:

    Wave Extinction_Blue_cat,Extinction_green_cat,Extinction_red_cat
    Wave LastBaseLine_Blue_cat,LastBaseLine_green_cat,LastBaseLine_red_cat
    Wave Loss_Blue_cat,...
    Wave Pressure_Blue_Cat,...
    Wave Signal_Blue_cat,...

and so on for 10-15 groups of wave names for each instrument. These group names vary depending on the instrument that generates them. So I guess i can create the wave lists one time and use a CASE statement or some other method to make these calls. Thanks for the help.

 

Scott


 

> What I want to do is create a generic averaging routine that can be used on any data.

The above aim is framed too vaguely. You appear to want the following:

I have collected a set of N waves, each with npts points, into one data folder. I want to choose a specific set of M waves from those N waves. I want to choose the M waves using wild-card criteria to select by specific patterns in the wave names. I want to average each of my chosen waves over a defined step increment Delta. I want the averaging process to create a new wave with a name using a prefix that is generated using the increment Delta and the name of the wave that was averaged. The newly created wave will typically be npts/Delta in length.

First, create a function to average one input wave into a new wave.

// @brief averages an input wave over a specific number of points
// @input string wave name and variable number of points for averaging
// @output creates a new wave, overwriting any existing wave of the new name
// @caveats presumes that the function is run on a specific data folder
Function ave_aspecificwave(string inputwave, variable aveN)

Test this function on various waves in a data folder using the command line input. Go to the next step only after you have the above completed. For example, calling on the command line should give the desired result wave.

ave_aspecificwave("Extinction_Blue_cat",20) --> ave20_Extinction_Blue_cat

Second, create a function to return a list of waves in a data folder selected using a wild-card input. You may find some insights using the example in the link below.

https://www.wavemetrics.com/forum/general/example-return-string-list-wa…

Third, create a function that loops through the wave names in the generated list, passing each wave name to the averaging function created in the first step.

When all this is done, you can use the wild-card input to average all blue waves by 20

ave_asetofwaves("*_blue*", 20) --> generates averages over all "blue" waves

In summary, you are trying to build multiple steps in one function. Create functions to do only one specific step, then assemble the individual functions appropriately.

> I think that what I'm trying to do is not possible.

What you are trying to do is entirely possible. How you are trying to do it appears to be impossibly confounding.

//Someone suggested this but When this is uncommented it doesn't compile
//  Print WL[1][1]
//  Print WL[0]
//  Display WL[1] vs WL[0]

Oops, sorry, the double brackets in WL[1][1] won't work here because the compiler thinks it's a 2D wave (I was probably working on my C course when I wrote it :(   ).

Here is a working version:

wave wa= WL[1]  //wa is the second wave in the list
 
print wa[0]   
print wa    //this will print the whole wave
print WL[1]  //however this doesn't behave like the previous line (does it print the reference ?)
 
Display WL[1] vs WL[0]  //this works

If you mainly work with references but sometimes need to get back to the name you can use the functions nameofwave and GetWavesDataFolder: 

 

make/o wa,wb,wc
 
String ListofWaves = "wa;wb;wc"
 
Wave/Wave  WL = ListToWaveRefWave(Listofwaves,0) 
 
string name=nameofwave(WL[1])  //name of the second wave
print name 
 
string fullname = GetWavesDataFolder(WL[1], 2 )   //full path
 print fullname

 

Hi--

     Thanks you all for the programming tip and suggestions. We have veered off of my original question, which was: how can I programmatically declare waves so they can be called in the rest of my function. I've written the logic in the past to average 3 or 4 waves. So I just called them like in the example below one wave at a time. See the snippet below. I want to develop a loop to make the call " Wave wavename0, wavename1, wavename2

I just don't to do this for a lot of waves if I can do it using a for loop.

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 ListoWaves
 
    //Wave/Wave  WL = ListToWaveRefWave(Listowaves,0) //Declares all of the waves in the selected folder
                                                    //so they can used as if they were declared by name
//  I want to replace this with
    Wave IgorTime_cat
    Wave Extinction_Blue_cat,Extinction_green_cat,Extinction_red_cat
    Wave LastBaseLine_Blue_cat,LastBaseLine_green_cat,LastBaseLine_red_cat
    Wave Loss_Blue_cat,Loss_green_cat,Loss_Red_cat
    Wave Pressure_Blue_Cat,Pressure_Green_Cat,Pressure_Red_Cat
    Wave Signal_Blue_cat,Signal_Green_cat,Signal_Red_cat
 
//With something like this
    For(a=0;a<numwaves;a+=1)
        Wave Listowaves[a]
    ENDFOR
    
// So I can do something like this:
    Display Extinction_Blue_cat vs Igortime_cat
    Appendtograph Extinction_Green_cat vs Igortime_cat
 
        
END     

Thanks for the help

ssmith911

I think the problem is that you don't actually want to do what you think you want to do, because it doesn't make much sense to want to do that in Igor.

However we all seem to have a problem understanding what you actually want to accomplish in the end, and we we've not been able to help you get there. You are stuck on asking to do something that doesn't make sense, and the rest of us are stuck trying to understand why you want to do that.

I recommend that you create a small example that shows how to create some waves and possibly other objects that have the same organization your actual data has, but with limited complexity. Then, using only the command line, do the type of analysis that you want to do on those waves, including making the graphs to display the end result.

Then describe what parts of this you want to make more flexible. For example, your example waves might be named "wave1_green", "wave2_green", etc. If you want to do a similar analysis for other colors, you might say something like "I want to separately calculate the average of all waves with the "_green", "_blue", and "_red" suffixes.

   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
 

I don't understand the philosophy here. It seems you have a well defined protocol for naming waves.   You should use your naming protocol, I don't see any reason for using generic wildcards "*" here and it makes the whole code much more complicated.

For example, I recently worked on a code to make fits of different datasets using different models.  The wave names would be something like this (simplified here):

string  nydata=datasetprefix+"_ydata";  wave ydata=$nydata

string  nxdata=datasetprefix+"_xdata"; wave xdata=$nxdata

string nfitydata="fit_"+modelprefix+"_"+ nydata

etc.

I don't need any wildcards in the app.

Now if you want to process data from different datasets, first make a function to take the list of dataset names from a text wave.  You can edit manually such a text wave (can be practical for cases when you don't want to include all existing data). Once tested, you can write another function that will create such a list given some criterions (the only function needing search with wildcards, and you can test this function independently).  

 

 

 

 

 

I try to give this a shot as well. Maybe your confusion comes from thinking that the external wave name and the 'internal' declaration inside a function needs to be the same, which is not at all the case. So something like this:

Wave IgorTime_cat

is implicitly the same as this:

Wave IgorTime_cat = theCurrentDF:IgorTime_cat

Here the internal name inside the function is IgorTime_cat, which refers to a wave with name IgorTime_cat inside some folder. But the internal name can be anything and can also be reassigned as often as you like / need.

Here is a start, which for now simply displays all waves vs your time wave:

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
    // maybe add some checks here that the prompt was successful
    
    String prefix = "Min"+num2str(AvgTime)+"_avg"// Creates Prefix based on averaging time
    String wvlist = Wavelist("!IgorTime_cat",";","DP:1") //"DP:1" selects only dbl precision float  
    Wave xWave = IgorTime_cat // assumes fixed name; could also be made dynamic
    Display
    for(string current : ListToTextWave(wvlist,";"))
        Wave yWave = $current // successively refers to all waves in the list
        Appendtograph yWave vs xWave
    endfor
End

You see that 'yWave' successively gets reassigned and reused in the following expression. So you never need a ton of Wave assignments if you can reasonably construct a string list or wave-reference wave with the contents you want to process as input for a loop or similar construct.

Pawel et al.--

     Perhaps you are right. I may be making this more difficult that it needs to be. On top of that my attempts at explaining what I'm trying to accomplish is muddying the water for you guys...I apologize for that. Allow me to try one more time to be more specific:

When declaring waves for future use in a function if there are only 6 or 7 waves then this is fine:

Wave IgorTime_cat
Wave Extinction_Blue_cat,Extinction_green_cat,Extinction_red_cat
Wave LastBaseLine_Blue_cat,LastBaseLine_green_cat,LastBaseLine_red_cat

 

Now if there are 30 waves, or more, that need to be declared and may change depending on the instrument the amount of typing becomes excessive not to mention the possible typos that would occur (LOL). So what I'm trying to code is a generic way to declare all of the waves in the current datafolder, so they can be used, by the actual wavename. This way I can move this snippet of code to other functions for the wave declaration part of the new function. Now there may not be an easy way to do this. If not thats fine. I'll just have to create specific wave declarations for each function I create. I am using this as a way to learn how to code in Igor and make the code a littIe simplier in the future. I hope this clears it up. Thank you so much for your patience and help.

So what I'm trying to code is a generic way to declare all of the waves in the current datafolder, so they can be used, by the actual wavename. 

OK. You cannot hard-code a generic function to define a wave reference to any random wave in any random data folder exactly by the actual name of the (randomly) chosen wave. (*) Since you cannot do what you want for one wave, you cannot do what you want for a set of waves.

What you can do is assign a specifically pre-named wave reference to a string that is a (randomly chosen) wave name. So,

WAVE my_named_wave = my_named_wave // impossible for automation to hard-code
WAVE currwaveref = $currentwavename // identically possible to code and run automatically

Hope this finally clears up your question.

* You may be able to achieve you desire by generating a text file with all the required WAVE my_funkywaveN = my_funkywaveN assignments, reading back the text file via an INPUT + INCLUDE method, and forcing a re-compile of the Igor Pro procedure. But I bet even the experts would not want to phuzt around giving you further advice for such an approach.

Hello ssmith911,

Did you have a look at my example above? This goes in the same direction as the answer by jj. There should never ever be a need to hard-code names into functions. The Wave assignment is precisely there for declaring 'links' to arbitrary waves for use inside a function. So instead of:

Display Extinction_Blue_cat vs Igortime_cat
Appendtograph Extinction_Green_cat vs Igortime_cat

you can simply write something like:

Wave y1 = Extinction_Blue_cat
Wave y2 = Extinction_Green_cat
Wave xw = Igortime_cat
 
Display y1 vs xw
Appendtograph y2 vs xw

Which can ultimately be exchanged for a string assignment:

Wave y1 = $stringfromalist1
Wave y2 = $stringfromalist2
Wave xw = $stringfromanotherlist1
 
Display y1 vs xw
Appendtograph y2 vs xw

Why would you want to use the actual wave name for this if the name can change depending on what you load in?

Hello,

Based on other suggestions and my previous thoughts here is an example of how such a code might be structured.  Note that I separated processing and display:  processing is easier to group by data types "Signal" etc, but I see you want to make graphs assembling different colors so doing both at the same time isn't practical.  The functions compile but have to be completed with the averaging code.  You will also notice that I removed "WaveList" entirely so you have to supply a list of colors to the function (eg. edit a text wave in a table).  I think that for an unexperienced programmer this is a much easier starting point , rather than scanning the folder and trying to sort through everything that can be found there, it is also much more flexible (you can select which instruments are to include). Later you can try to write a function that scans a given folder to prepare lists of colors, animals etc. for a more automated processing.

 

Edit:  I have updated the code to include absolute paths for the data waves.

// generic averaging function
function averagewave(wtime, nw_orig, nw_avg, avgtime)
wave wtime //timewave
variable avgtime  //averaging time
string nw_orig //name  of the original wave
string nw_avg  //name of the averaged wave to create
 
wave w_orig=$nw_orig
 
//creation of averaged wave ...
 
 
end
 
 
//process data for a single color
// set path to "" for current folder, otherwise "root:myfolder:"
Function ProcessData_single(string colorprefix, variable avgtime, string path) 
    
 
    String avgprefix = "Min"+num2str(AvgTime)+"_avg_"// Creates Prefix based on averaging time
 
    Wave timeWave = IgorTime_cat // assumes fixed name; could also be passed as argument
    
 
    string nw_Extinction=path+"Extinction_"+colorprefix+"_cat"   
          //uncomment this if you want to manipulate the wave directly in the code below: 
                //wave w_Extinction=$nw_Extinction 
     string nw_LastBaseLine=path+"LastBaseLine_"+colorprefix+"_cat"
              // wave w_LastBaseLine=$w_LastBaseLine
     
     string nw_Loss=path+"Loss_"+colorprefix+"_cat"
              // wave w_Loss=$nw_Loss
    string nw_Pressure=path+"Pressure_"+colorprefix+"_cat"
              // wave  w_Pressure=$ nw_Pressure
    string nw_Signal=path+"Signal_"+colorprefix+"_cat"
              // wave w_Signal=$nw_Signal
    
    
    //process ...
     
    averagewave(timewave, nw_Extinction, avgprefix+nw_Extinction, avgtime)
    averagewave(timewave, nw_Signal, avgprefix+nw_Signal, avgtime)
    averagewave(timewave, nw_Loss, avgprefix+nw_Loss, avgtime)
    //...
    
end
 
 
//make a graph assembling data from different colors 
// set path to "" for current folder, otherwise "root:myfolder:"
   
Function DisplayDatavscolor(wave timewave, string typeprefix, wave/T colorlist, string path) 
 
//typeprefix can be the original wave like "Extinction_" or averaged wave like "Min5_avg_Extinction_"
// path could be included in typeprefix but I a&dded a separated argument for clarity (or future mods)
    
        
     string title=typeprefix+" vs color"
    display as title  
    
    variable i
    for(i=0; i<numpnts(colorlist); i+=1)
       
       string nw_data=path+typeprefix+colorlist[i]+"_cat"
       wave w_data = $nw_data
       
       Appendtograph w_data vs timewave 
 
    endfor  
  
end
 
 
//process/display data for a list of colors  
//(text wave, edit in table or type eg. make/o/n=3 list={"red,"blue","green""})
//set path to "" for current folder, otherwise "root:myfolder:"
Function ProcessData_multiple(wave/T colorlist, variable avgtime, string path)     
    
    
 Wave timeWave = IgorTime_cat // assumes fixed name; could also be made dynamic (passed as argument) 
 
variable i
for(i=0; i<numpnts(colorlist); i+=1)
 
   ProcessData_single(colorlist[i], avgtime, path) 
 
endfor
 
//make graphs for original data:
 
DisplayDatavscolor(timewave, path+"Extinction", colorlist, path) 
DisplayDatavscolor(timewave, path+"Loss", colorlist,path)
DisplayDatavscolor(timewave, path+"Signal", colorlist, path)
//...
 
String avgprefix = "Min"+num2str(AvgTime)+"_avg_"// Creates Prefix based on averaging time
 
//make graphs for averaged data:
 
DisplayDatavscolor(timewave, path+avgprefix+"Extinction", colorlist,path) 
DisplayDatavscolor(timewave, path+avgprefix+"Loss", colorlist, path)
DisplayDatavscolor(timewave, path+avgprefix+"Signal", colorlist, path)
//...
 
end    

 

It seems that you want all the waves to be declared in your code, but you don't want to write out the declarations in your code.

Since you want to work with hard-coded waves, you may as well have the waves declared in the code.

How about this to generate the declarations, without typos, (at the time of writing the code):

Menu "Edit"
    "Insert References to all waves in DF", /Q, InsertWaveReferences()
End
 
function InsertWaveReferences() 
    string strTemp = GetScrapText()
    wave/wave ww = ListToWaveRefWave(WaveList("*",";","DP:1"))
    for (wave w : ww)
        PutScrapText "wave " + NameOfWave(w) + "\r"
        DoIgorMenu "Edit", "Paste"
    endfor
    PutScrapText strTemp
end

note that this code needs to be compiled to work, best to keep it in an independent module.

If the names of the waves are not static, there's no point in hard-coding.

if you want to set up wave references in a separate function, then you could perhaps use a structure:

Structure StructWithWaves
    wave w[5] // an array of five wave references
    wave/T wt
    wave foo
EndStructure
 
function init(struct StructWithWaves &s)
    int i
    for (i=0;i<5;i++)
        wave s.w[i] = WaveRefIndexedDFR(:, i)
    endfor
    wave/Z s.foo = nothing
    wave/T s.wt = aTextWave
end
 
function structTest()
    struct StructWithWaves s
    init(s)
    print "second wave in DF is ", nameofwave(s.w[1])   
end

You could also use StructFill with static wave names:

DisplayHelpTopic "StructFill"

Ok, thanks. I'll have a look at these options. I really appreciate the help from all of you.

ssmith911

Hi Tony,

Nice hacking !  But probably pointless for his application. And you are destroying my educational work :)

Sorry, Pawel, I couldn't resist muddying the waters.

ssmith did say that he wants to create wave references in a separate function, and the only way that I know of to do that is with structures.

structure ClowderOfCats
    Wave IgorTime_cat
    Wave Extinction_Blue_cat
    Wave Extinction_green_cat
    Wave Extinction_red_cat
    Wave LastBaseLine_Blue_cat
    Wave LastBaseLine_green_cat
    Wave LastBaseLine_red_cat
    Wave Loss_Blue_cat
    Wave Loss_green_cat
    Wave Loss_Red_cat
    Wave Pressure_Blue_Cat
    Wave Pressure_Green_Cat
    Wave Pressure_Red_Cat
    Wave Signal_Blue_cat
    Wave Signal_Green_cat
    Wave Signal_Red_cat
endStructure
 
function MyProcess()
    Struct ClowderOfCats, s
    StructFill s
    print nameOfWave(s.Extinction_Blue_cat)
end

 

I might mention right here that I once shipped a WaveMetrics procedure with a simple function code generator. It wrote a notebook file that could be #included as a procedure window. It used the various Execute/P commands to #include it automatically and compile it. It was such a disaster that I pulled it out of our releases on a point release, not even a major release. It's extraordinarily difficult to make such code generators work reliably.

@ssmith911, I may not have completely understood what you want to do and may have missed details (it's a long thread), but depending on the nature of your data set, there may be another way to work on it that doesn't need explicit declaration of the source waves. Say you have the following waves in the current data folder:

Make/O Extinction_Blue_cat,Extinction_green_cat,Extinction_red_cat,LastBaseLine_Blue_cat,LastBaseLine_green_cat,LastBaseLine_red_cat

you can work on the "extinction" set simply by something like:

function ProcessData(string type)
    // get subset of 1D waves in current datafolder
    string ListOfWaves = Wavelist("*"+type+"*", ";", "DIMS:1")
    // create 2D wave with local wave reference; Wave names are stored as dimlabels
    Concatenate/O/DL (ListOfWaves), $"M_"+type
    wave w = $"M_"+type
    // do something with data of interest; make average
    MatrixOP/O W_Avg = averagecols(w^t)
    // Display data based on DimLabels
    Display w[][%$type+"_Blue_cat"] 
end

Then call:

processData("extinction")

 This assumes that all waves are 1D and have the same length.