Wave reference confusion in code

Hi, 

Kindly see the attached image for code. 

I am sure that this has a straightforward solution but I am somehow stuck. 

I have a 1D textwave called "analytename" that contains names. I also have a 2D wave called "dataJan2231". Each column of dataJan2231 is a timeseries for the names listed in the 1D wave analytename. The first thing I needed to do was to extract each column from the 2D wave as a 1D wave and name those individual 1D waves according to the names contained in "analytename". This I succeeded in doing as shown in the first 9 lines of code. 

Now, the next step is where I am stuck. Within the same 'for loop' (on line 5 in attached code) that extracts a column from dataJan2231 into an individual 1D wave and gives it a name, I am also trying to run a code that takes the same newly made 1D wave and generates another 1D wave that is a time-averaged version of this wave (e.g. the original new 1D wave is per second timeseries and the time-averaged version will have hourly averages of it).

So in summary, within the same for loop, a column is extracted from the 2D wave as a 1D wave, the 1D wave gets named and then is hourly-averaged. The hourly-averaged data is put into a new 1D wave.   

As marked in the code with yellow and green on lines 9 and 11, I somehow need the code to understand that- $name - is the name of the input wave at "wave2avg" and "waveAvg" needs to be the output wave with name- $name_avg. I just can't figure out how to do this. I would be very thankful for your advice! 

Many Thanks and Regards, 

Peeyush   

Code

Yes, wave referencing can be confusing at times, but here is a simple rule you can work with: In principle, you have to create a wave reference using the Wave declaration, but in some cases internal functions will do that for you (also always only for simple object names, i.e., not involving $ or something). It does not hurt however, if you add a proper wave declaration anyway, and only leave it out when you are sure what you are doing (for example, when having an obvious simple command like make wave0).

In your case, you have several options how to proceed. First, I assume your average wave does not exist, and you have to create it as well. The first and most recognizable option is always to give a wave declaration after the make command:

Make/D/O/N=(DimSize(dataJan2231,0)) $name
Make/D/O/N=(DimSize(dataJan2231,0)) $(name+"_avg")
Wave wave2avg = $name
Wave waveAvg = $(name+"_avg")

Now you can work with both later on. A second option lately is to use a special flag inline. This one is actually not documented for the individual commands, if I see correctly, but you can read more about it here:

DisplayHelpTopic "Inline WAVE Reference Statements"

Anyway, it goes like this:

Make/D/O/N=(DimSize(dataJan2231,0)) $name   /wave=wave2avg
Make/D/O/N=(DimSize(dataJan2231,0)) $(name+"_avg")  /wave=waveAvg

Note that you should not use make/WAVE, which is instead the flag to create wave-reference waves.

A third option, which should rather be avoided and does not work with wave assignments is to just use the $ operator every time. It is OK for a short succession of operations, I guess. This is what you have used in your code as well:

Duplicate/O ... $name
Redimension/N ... $name

Hope that helps.

Hi Chozo, 

Thanks a lot for such a detailed response and tips! So my issue got resolved and the program compiled, but when I tried to run it, it gave the following error: 

"While executing WaveStats, the following error occurred: Expected wave name" .. couldn't figure out why this should happen..

Function names() //create individual 1D waves for each analyte
wave/T analytename
wave dataJan2231
//wave startwav,endwav
//killwaves/Z stopWave,startWave
//duplicate endwav,stopWave
//duplicate startwav,startWave
variable i
for(i=0;i<dimsize(dataJan2231,1);i+=1)
string name = analytename[i]
killwaves/Z $name
make/n=(dimsize(dataJan2231,0))$name
Duplicate/O/RMD=[][i+1] dataJan2231,$name
Redimension/N=(dimsize(dataJan2231,0))$name

killwaves/Z $(name+"_avg1")
//duplicate timewave,timeWave
make/n=(dimsize(dataJan2231,0))$(name+"_avg1")
wave wave2avg=$name
wave waveAvg=$(name+"_avg1")

waveAvg=nan

Wave timeWave, wave2avg, waveAvg, startWave, stopWave
    variable WASflag

    variable start, stop, numpts_start=numpnts(startWave)
   
           
   
   
//Different author-------- 
    for(i=0;i<numpts_start;i+=1)
        start = FindFirstGE(timeWave, startWave[i], start)
        if (WASflag)
            stop = FindRightMostLE(timeWave, stopWave[i], stop)
        else
            stop = FindRightMostL(timeWave, stopWave[i], stop) 
        endif

        if (stop < start)   // catch index out of range error. (e.g. if there are WAS cans taken after end of flight.)
            continue
        endif
        if (WASflag)
            if ( (timeWave[start]>=startWave[i])&&(timeWave[stop]<=stopWave[i])  )         
                WaveStats/M=1/Q/R=[start,stop] wave2avg
                waveAvg[i]=V_avg       
            endif
        else
            if ( (timeWave[start]>=startWave[i])&&(timeWave[stop]<stopWave[i])  )          
                WaveStats/M=1/Q/R=[start,stop] wave2avg
                waveAvg[i]=V_avg       
            endif
        endif
//-----------      
    endfor


endfor
end

 

Never mind, I just got the code to run. I had to remove the wave reference for wave2Avg and waveAvg from the second place. However, the code is only running for the first name in the analytename textwave and generating just one 1D wave, when it is supposed to do the same processing for all names and generate multiple 1D waves. Wondering why this should be case.. 

Yes, having the second Wave declaration overwrites your first one with the implicit

Wave wave2avg = currentfolder:wave2avg

Anyway, it seems like you are trying to fit different pieces of code together in the whack-a-mole error hunting style. In my experience it is often faster to build the code piece by piece and test that everything makes sense and works instead of copying large chunks over. For example, you are running two for loops with the same counter i. I guess this is your current problem, since the inner loop exhausts the counter and makes your outer loop stop after the first execution.

One quick question: Could you please advise on how to name individual columns of a 2D wave? Lets say I have a (10,5) 2D wave. Now, besides column index, I wish for each column to have a name from a 1D text wave that contains names. Much thanks! 

Hi

I have started using dimlabels quite a bit.  For example instead of passing global variables, I have a single wave and then label each row with the name.  When I create a function I only need to pass the single wave which makes code maintenance much easier.  Also if I put the wave in a table I can see all my "variables" and their values.  Very handy.

To set the column label is the similar to row label setting.  Note there are some constraints on the text for the label.

From manual:

SetDimLabel dimNumber,dimIndex,label,wavelist


The SetDimLabel operation sets the dimension label or dimension element label to the specified label.
Parameters
dimNumber  is one of the following:
0:    Rows
1:    Columns
2:    Layers
3:    Chunks

In this case label is the exact text that label will take, but you can use $textwave[0] and it will use the value from the first point of text wave as the label.

Andy

For this SetDimLabel is your friend. You need to call this command once for each column in your wave, either in a loop or like:

SetDimLabel 1,0,thisIsAName, my2Dwave
SetDimLabel 1,1,'this is another Name', my2Dwave
SetDimLabel 1,2,$setFromString, my2Dwave
String nameFromWave = my1Dtextwave[2]
SetDimLabel 1,3,$nameFromWave, my2Dwave
SetDimLabel 1,4,'names are limited to 255 bytes', my2Dwave

 

Hi Chozo and Andy, 

This is great and I have made notes. Thanks a lot for these tips! 

Sincerely, 

Peeyush