synchronize time base for multiple waves

A recent experiment was run where two datasets were obtained from two different instruments.  The instruments ran independently and saved the measured data to separate files.  I now would like to plot the output of one dataset versus the values from the second.  Since both datasets were one different "clocks" and sampling rates, does anyone have a routine to place both datasets under the same time scale.  This would allow me to plot the measured values against each other rather than only versus time.

Hi,

If each data set has regular sampling frequency, you can set the wave scaling for the start and time between each point.  Then you can graph the data sets as normal and the scaling will adjust their positions as appropriate.

If the sampling is less regular and you have the time at each data point, then plot the xy pair as appropriate.

If you need to get values for the same time interval from each data set, then I would create a base wave with the time points of interest and interpolate the values from each data set.

Andy

I would like to point out a possible fundamental problem with regard to the two separate instruments. If each reports times derived from its own clock (or sampling base), their clock frequencies may not agree, even if the nominal frequencies are the same. Depending on the sampling rates and your desired accuracy, this could be a problem. In a past data acquisition experiment using Igor Pro, I had to synchronize two PCI cards with a common external clock.

I constantly have to deal with this very problem - time is the worst invention IMHO - my strategy is to create a regular reference time base and expand all the errant data onto that time base.

For example say in your example you have insturent 1 sampling at nominally 1hz but drifting around that value, instrument 2 samples at 5 hz probably also drifting around a bit. Decide what data rate you eventually want your data at - say try 1 hz. You can average data on an uneven time base using this peice of (inefficient) code. Beware a free wave is returned , you could modify it to use a pass-by-refference or however you like:

//___________________________________________________________________________________________________  
// average a wave which may be on an uneven timebase
Function/WAVE AvgDateTime(Wave dataWv, Wave timeWv, double secs)

    [double beginPnt, double endPnt] = WaveMinAndMax(timeWv)
    int n = round((endPnt - beginPnt) / secs),i,j,k
   
    Make /O /N=(n) /FREE outWv = NaN
   
    do
        FindValue /Z /S=(i) /V=(beginPnt + (i+1 * secs)) /T=(secs / 2) timeWV
       
        k = V_value
       
        WaveStats /Q /M=1 /R=[j,k] dataWv
       
        outWv[i] = V_avg
       
        j = V_value
       
        i++
    while (i < n)  
   
    return outWv
End

I probably wouldn't bother averaging your 1hz data, but if there is also no harm in it.

You can then expand the data onto an even time base by first getting the data limits:

//___________________________________________________________________________________________________  
// get the limits of waves passed as a list
Function [double minVar,double maxVar] findLimits(String wavList)

    int num = ItemsInList(wavList),i
    Make /O /D /FREE /N=(2 * num) limits
   
    for (i = 0;i<num;i++)
        Wave wav = $StringFromList(i,wavList)
       
        WaveStats /Q /M=1 wav // there may be NaN values
       
        limits[2*i,2*i+1] = {V_min,V_max}
    endfor
   
    [minVar,maxVar] = WaveMinandMax(limits) // get the limits
   
    return [minVar,maxVar]
End

Make the even time base, I'm assuminmg the instrument time data is already in Igor time:

// get the extent of the time variables - you could manually set your own limits
[double minVar, doublemaxVar] = findLimits("insrument_1_time;instrument_2_time;")

// make a regular time wave
Make /D /N=(1 + maxVar - minVar) timewave = x+minVar

Expand out the data onto the regular time wave:

delta would be 0.5 in the case of 1hz data
t1 is the instrument time wave
t2 is the reference regular time wave
w1 is the data to be expanded 

Again a free wave is returned, but you could modify that

//___________________________________________________________________________________________________
// Performs an expansion but doesn't round t1 and t2 to even fractional seconds. Finds nearest time in t2 within the supplied delta.
// Especially useful for data at faster than 1Hz that isn't on an even time base.
// 20200303 added ability to expand 2D waves, assumes dim0 is the one being expanded
Function/WAVE expand2nearest(t1, w1, t2, delta)
    wave t1, w1, t2
    variable delta
   
    variable x1, x2, n1, n2 , diff1, diff2
    n1 = numpnts(t1)    //length of timewave1
    n2 = numpnts(t2)    //length of timewave2
   
    Make /N=(n2,DimSize(w1,1)) /FREE w2=NaN
   
    do
        diff1 = abs(t2[x2] - t1[x1])
        if (x1+1<n1)
            diff2 = abs(t2[x2] - t1[x1+1])  // only test this if not on last row of t1, else it will be index out of range error.
        else   
            diff2=diff1
        endif
        if ((diff1 <=  diff2) * (diff1 <= delta) * (numtype(w1[x1]) == 0))    //if this difference is smaller than the next difference, and difference is less than delta, and isn't NaN.
            w2[x2][]=w1[x1][q]
            x1+=1
            if (x1 == n1)   // That was the last point for w1, so break. We're done.
                break
            endif
           
            if (x1+1 < n1)
                if ((abs(t1[x1] - t2[x2])) < (abs(t1[x1+1] - t2[x2])))  //only increment x2 if the NEXT point in t1 is farther from t2 than the current point in t1
                    x2+=1
                endif
            else        // can't test if next row would be closer because this is last row of w1. Just test if within delta.
                if (abs(t1[x1] - t2[x2]) > delta)
                    x2+=1
                endif
            endif
        else
            if ( t2[x2] < t1[x1] )
                x2+=1
            else
                x1+=1
            endif
        endif
    while((x2 < n2 )&&(x1< n1))
   
    return w2
end

 

In reply to by cpr

Thank you for the code, it will be helpful with the full experiment as I will have multiple waves to apply the routine to.  The interpolation routine worked but required redundant effort.  Running a procedure multiple times is more straightforward.