How to access referenced waves?

Hello everybody,

when I create a textwave and use this textwave to create numeric waves dependend on a variable in a loop, how can I actually access these waves?
A more elaborate explanation of what I am trying to do:
Another function not mentioned here screens all Igor folders in a specific directory for waves to analyze and creates the analysis waves inside a new subfolder in each folder. The function below is supposed to check whether such an "Parameter_" folder exists and if it exists, shall list all Parameter_waves inside and evaluate means of a couple of subranges (defined by a manually created wave "baseline_avg_values) inside these waves. The evaluated means like "baseline" and "avg150" are supposed to be written in the same subfolder.

In parallel - and this is my problem - the evaluated means shall be written in some "cumulative waves" in the main directory so that I have all averages of one Parameter of all experiments (or folders) in one wave that I can then test for statistic significance.
To summarize and leaving out the loops, I tried to do this by creating a textwave first and then creating the numeric waves dependent on the number of waves to be analyzed, which works well.

But how can I easily access these created (referenced) waves?
The example below does not compile when I leave out the "//" in the third line, of course, because with the brackets I do only access the different rows of the original textwave, not the created numeric waves ("$ can't be used that way in a function" )...

Make/O/T analysis_order ={"A_avg", "A_avgsem"}
Make/O/N=(count_DFR) root:test:$analysis_order[wi]
//root:test:$analysis_order[wi]=mean(the_move, baseline_avg_values[0],baseline_avg_values[1])


That probably al sounds confusing so here is the full code, which I already reduced. I do hope that it is not too complicated:
#pragma rtGlobals=3     // Use modern global access method and strict wave access.

Function test_Analysis1()

Setdatafolder root:test
   
string objname, wtm
variable index, count, wi, count_A, count_DFR

DFREF dfr = GetDataFolderDFR()
count_DFR=countobjectsDFR(dfr, 4)

Make/O/T analysis_order ={"A_avg", "A_avgsem"}

for(index = 0; index < count_DFR; index+=1)    
  objName = GetIndexedObjNameDFR(dfr, 4, index)
  SetDataFolder objname
     
  if (DataFolderExists ("Parameter_"+objname))
    SetDataFolder "Parameter_"+objname
    wtm=WaveList(objname+"*",";","")
    count_A=ItemsInList(wtm)
    Make/O/N=(count_A) Baseline, avg150
   
    for(wi = 0; wi < count_A; wi+=1)
      wave baseline_avg_values
      wave the_move=$StringfromList(wi,wtm)
      Make/O/N=(count_DFR) root:test:$analysis_order[wi]
      Baseline[wi]=mean(the_move, baseline_avg_values[0],baseline_avg_values[1])
      avg150[wi]=mean(the_move, baseline_avg_values[2],baseline_avg_values[3])
      //root:test:$analysis_order[wi]=mean(the_move, baseline_avg_values[0],baseline_avg_values[1])
    endfor
   
  endif
 
  SetDataFolder dfr
 
endfor
     
End


I thought of an quick&dirty work-around by just creating a list of the created waves in the main directory and then access these individually or by maybe creating 2D waves but I belive that there is a more elegant solution that I am just to blind or incapable to see.

I am looking forward to your help!

Best regards,

Martin
What you are missing here is a wave reference. You are using it already to point to external waves like baseline_avg_values. But every time you want to work with a wave in a function you need to tell Igor first how it is called and where it is. There are several things Igor needs to know, such as wave type, wave name inside the function, and location and name in the folder structure. You wrote wave baseline_avg_values, but actually Igor reads something like this wave/D baseline_avg_values = (the current folder:)baseline_avg_values. Since you left out all this additional information, Igor is assuming the rest (e.g., you gave just one name, which probably means there is a wave called like this in the current folder AND you want to work with the exact same name inside the function). You probably noticed that you are not using such a WAVE statement for Baseline and avg150. That's because the MAKE statement was so kind to do that already, which only works in the most simple cases. So what you need for your analysis_order wave is a statement like: wave/T myavgtextdata = root:test:$(analysis_order[wi]). Note the '/T' flag, which hints Igor that this data is text (only omit these flags for standard numerical data). But even with that, your 'equal' assignment will not work, since you can't fill in numerical data into a text wave. Use num2str(...) or a similar function for this:
myavgtextdata[wi]=num2str(mean(the_move, baseline_avg_values[0],baseline_avg_values[1]))

Try this command for further reference: DisplayHelpTopic "Accessing Waves In Functions"
Hi chozo!

Thanks for your reply!

chozo wrote:
What you are missing here is a wave reference. You are using it already to point to external waves like baseline_avg_values. But every time you want to work with a wave in a function you need to tell Igor first how it is called and where it is. There are several things Igor needs to know, such as wave type, wave name inside the function, and location and name in the folder structure. You wrote wave baseline_avg_values, but actually Igor reads something like this wave/D baseline_avg_values = (the current folder:)baseline_avg_values. Since you left out all this additional information, Igor is assuming the rest (e.g., you gave just one name, which probably means there is a wave called like this in the current folder AND you want to work with the exact same name inside the function). You probably noticed that you are not using such a WAVE statement for Baseline and avg150. That's because the MAKE statement was so kind to do that already, which only works in the most simple cases.


I left a couple of wave references out that have been there before, as soon as I saw that there is no compilation error.

chozo wrote:

So what you need for your analysis_order wave is a statement like: wave/T myavgtextdata = root:test:$(analysis_order[wi]). Note the '/T' flag, which hints Igor that this data is text (only omit these flags for standard numerical data).


I tried that before writing the above post and it does not compile because of the error mentioned above ("Can't use $ that way in a function")

chozo wrote:

But even with that, your 'equal' assignment will not work, since you can't fill in numerical data into a text wave. Use num2str(...) or a similar function for this:
myavgtextdata[wi]=num2str(mean(the_move, baseline_avg_values[0],baseline_avg_values[1]))


I tried that to but this does not really address my main problem since when I convert any num2string it is still overwriting my "analysis_order" wave instead of filling in the values successively in the created waves. Obviously because I am adressing the original wave and not the created wave. And I just do not know how to access the freshly created waves...
OK, forget my comment regarding the '/T' flag and num2str. I see that you are trying to reference numerical waves by using names from a text wave.
But the rest of my comment is still valid. The wave reference didn't work for you because Igor doesn't know analysis_order is a text wave, so it complains about using numerical data for a string! In your posted example however it should work, since the simple make statement Make/O/T analysis_order ={"A_avg", "A_avgsem"} creates this reference for you. So I guess you accidentally fixed the compile error while simplifying the problem. For reference, the following compiles just fine (and probably works, too):
Function test_Analysis1()
 
Setdatafolder root:test
 
string objname, wtm
variable index, count, wi, count_A, count_DFR
 
DFREF dfr = GetDataFolderDFR()
count_DFR=countobjectsDFR(dfr, 4)
 
Make/O/T analysis_order ={"A_avg", "A_avgsem"}
 
for(index = 0; index < count_DFR; index+=1)    
  objName = GetIndexedObjNameDFR(dfr, 4, index)
  SetDataFolder objname
 
  if (DataFolderExists ("Parameter_"+objname))
    SetDataFolder "Parameter_"+objname
    wtm=WaveList(objname+"*",";","")
    count_A=ItemsInList(wtm)
    Make/O/N=(count_A) Baseline, avg150
 
    for(wi = 0; wi < count_A; wi+=1)
      wave baseline_avg_values
      wave the_move=$StringfromList(wi,wtm)
      Make/O/N=(count_DFR) root:test:$analysis_order[wi]
      wave myavgdata = root:test:$(analysis_order[wi])
      Baseline[wi]=mean(the_move, baseline_avg_values[0],baseline_avg_values[1])
      avg150[wi]=mean(the_move, baseline_avg_values[2],baseline_avg_values[3])
      myavgdata[wi]=mean(the_move, baseline_avg_values[0],baseline_avg_values[1])
    endfor
 
  endif
 
  SetDataFolder dfr
 
endfor
 
End
It actually compiles&works now, thanks a lot! Assigning the reference to a wave (myavgdata) did the trick. For the cumulative results, I just needed to change the index of that wave from "wi" to "index" so that it actually loops through the different folders (experiments).
Now it makes sense: By assigning a wave to the string expression I am able to use that created wave and assign numbers to individual rows of that wave without accidentally changing the actual assignment. So it was more some kind of "logic" problem.

Thanks again!

Great that you could get it to work.
I guess you overcame the 'logic' problem already, but just to clarify: The 'wave' statement only creates a named pointer to an existing wave. So of course you didn't create a wave named myavgdata but rather a 'traffic sign' with that name. Which data you point at can be defined in many ways, one of them, like you did, by pulling the wave name out of another (text) wave holding these names as strings. I think it hinders the learning experience a bit that 'make' also creates these references, somewhat obscuring the crucial part this plays in functions.