Average Waves question

Hi,

I have an experiment with several XY pairs that I would like to average. The X data is variable (∆) between waves, but runs from -20ish to 120ish. All have a common point at 0. I would like to use the Average Waves package to generate an average wave trace with scaling such that it has a point at 0 (for curve fitting purposes). Right now, the scaling of the average means the interpolation does not happen at 0. My question is:

How does the panel decide what scaling and how many points to use for the average, and can this be changed?

If I knew how the scaling worked I could create two extra XY pairs for each wave at the beginning and end of the waves at constant X such that the average wave placed a point at 0. Hopefully this makes sense.

Any help would be very much appreciated.
Average Waves just takes a bunch of waves and averages them down to one wave. It does it row-wise; it takes each of the row 0 points, averages them and uses the average as the row 0 point in the new wave. It doesn't actually care about X scaling.

It sounds to me like what you want to do is just beyond the scope of Average Waves. You probably need to write a special-purpose function to do the job.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Thank you for your reply. The Average Waves panel does do the averaging row by row when the X scaling is constant. But it doesn't do it like this when the X scaling between waves is variable. For example, I have 11 XY wave pairs with ~54 points each. Average waves generates an average wave with 216 points and constant ∆. I assumed that it somehow decides the density of points and then averages at each ∆X using interpolation of the original waves to find the level at that value of X to then generate the average value.

My solution for now is to check the number of points for the average wave (say 216).
Make a new XY pair with {-20, -10, 0, 10, 195} and {1, nan, 0, nan, 1}. My real data start at >-20 and finish at <+120.
Make the average again. It still generates 216 points, but now ∆=1 so that it puts a point at 0.
sjr51 wrote:
Thank you for your reply. The Average Waves panel does do the averaging row by row when the X scaling is constant. But it doesn't do it like this when the X scaling between waves is variable.


That's because scaling is irrelevant if they all have the same scaling.

Since you have waves with different scaling, I would write a script to do the following.

1. Determine common x-range of all waves provided (data points outside this range can't really be averaged). Ignore step 1 if all waves have same outer limits for x.
2. Create waves for results (XY)
3. use the interp function to interpolate the value from each data wave at the desired output x-value
4. Average these interpolated values
5. Repeat 2-4 for each X value in range.
Well, what do you know- when I first wrote WavesAverage.ipf Jim Prouty enhanced it to pay attention to X scaling and to do interpolation for mismatched X values. A brief scan of the code didn't really enlighten me as to the method it uses for picking the X values for output, though. Maybe Jim can tell us.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
johnweeks wrote:
Well, what do you know- when I first wrote WavesAverage.ipf Jim Prouty enhanced it to pay attention to X scaling and to do interpolation for mismatched X values. A brief scan of the code didn't really enlighten me as to the method it uses for picking the X values for output, though. Maybe Jim can tell us.


fWaveAverage() has a non-point-for-point mode that kicks in with mismatched waves such as you describe.

The X values generated are interpolated X values to encompass the min x to max x range (computed over all the waves). The number of points in the result is increased to compensate for this interpolation (with safeguarding against too many points):
    else
        // can't do point-for-point because of different point range or scaling or there are multiple X waves
        Variable firstAvePoint,lastAvePoint,point,xVal,yVal
       
        Variable newLength= 1 + round(abs(maxXmax - minXmin) / minDeltaX)
        maxLength= min(maxLength*4,newLength)   // avoid the case where one very small deltaX in an XY pair causes a huge wave to be created.
   
        Make/N=(maxLength)/D/O $AveName
        Wave/Z AveW=$AveName
        AveW= 0
        Wave w=$StringFromList(0,ListOfWaves)  
        CopyScales w, AveW // just to get the data and x units
        SetScale/I x, minXmin, maxXmax, AveW    // set X scaling to all-encompassing range

        Make/O/N=(maxLength)/FREE TempNWave= 0


Then each wave's contribution is computed by Y interpolation and summed into AveW while keeping track of the number of waves contributing to the sum at each point in TempNWave:

   
        for (i = 0; i < numWaves; i += 1)
            thisXMin= xRange[i][0]
            thisXMax= xRange[i][1]
            if( thisXMin > thisXMax )   // swapped X range (X values decrease with increasing point number)
                tmp= thisXMin
                thisXMin= thisXMax
                thisXMax= tmp
            endif
            firstAvePoint= ceil(x2pnt(AveW,thisXMin))   // truncate the partial point numbers...
            lastAvePoint= floor(x2pnt(AveW,thisXMax))   // ... by indenting slightly
            WAVE wy=$StringFromList(i,ListOfWaves)
            Wave/Z wx= $StringFromList(i,ListOfXWaves)
            for (point = firstAvePoint; point <= lastAvePoint; point += 1)
                xVal= pnt2x(AveW, point)
                if( WaveExists(wx) )
                    yVal= interp(xVal, wx, wy)
                else
                    yVal= wy(xVal)
                endif
                if (numtype(yVal) == 0)
                    AveW[point] += yVal
                    TempNWave[point] += 1
                endif
            endfor
        endfor
   


--Jim Prouty
Software Engineer, WaveMetrics, Inc.
Dear Jim,

Thank you for this - exactly what I was after. The panel is very useful for our experiments, thanks!