Interpolate in different waves
zixuan.cheng
Hi,all
I have 3 1D waves: 1 data/time wave, and 2 number waves. They are presumably all 5Hz data, but not strictly 5Hz data. Occasionally only 4 data per second or less. I now want to interpolate them all into full strict 5Hz data, is there such a method in Igor?
Cheers,
Mortoo
I recommend that you start experimenting with Analysis->Interpolate using linear interpolation.
For background information, execute:
DisplayHelpTopic "Interpolation"
If you need further help, I recommend that you attach a sample set of 3 waves here.
May 26, 2022 at 01:05 pm - Permalink
Hi Hrodstein,
Thank you for the reply. I tried the Interpolation. But it changed the rest of the data when interpolating.
I attached 3 waves here, 1 time wave and 2 data wave.
I would like to know how can I interpolate the missing data with the neighbouring value.
Cheers,
Mortoo
June 5, 2022 at 02:45 pm - Permalink
In reply to I recommend that you start… by hrodstein
Hi Hrodstein,
Thank you for the reply. I tried the Interpolation. But it changed the rest of the data when interpolating.
I attached 3 waves here, 1 time wave and 2 data wave.
I would like to know how can I interpolate the missing data with the neighbouring value.
Cheers,
Mortoo
June 6, 2022 at 06:30 am - Permalink
I examined your time wave. It is in fractional seconds. To see that, display it in a table and then choose Table->Format->Show Fractional Seconds.
I then created a table containing the time wave and the difference in seconds from each point in the time wave to the next point in the time wave. Looking at this in a table, I see something like:
2021-12-18 00:00:00.432 0.1959996223449707
2021-12-18 00:00:00.628 0.2030000686645508
2021-12-18 00:00:00.831 0.1970000267028809
2021-12-18 00:00:01.028 0.2030000686645508
2021-12-18 00:00:01.231 0.1970000267028809
2021-12-18 00:00:01.428 0.2039999961853027
2021-12-18 00:00:01.632 0.1960000991821289
2021-12-18 00:00:01.828 0.1999998092651367
2021-12-18 00:00:02.028 0.2030000686645508
Notice that the time differences (last column) are of unequal magnitude.
I then executed this to find the average time difference:
Print mean(timeDiffs), WaveMin(timeDiffs), WaveMax(timeDiffs)
This printed 0.208185 0 2.19483
I then did a histogram of timeDiffs:
So your times are roughly 5Hz on average but not consistently close to 5Hz.
You wrote:
I did that with this command:
Interpolate2/T=1/I=3/N=(numOutputPoints)/Y=$dataOutName timeIn, dataIn
This command is from a function that I wrote called Create5HzData. It is in the attached experiment. It uses linear interpolation (/T=1) with "X From Dest" (/I=3). "X From Dest" allows precise control over the X locations at which the input data is sampled. The output is a waveform with the X data represented in the wave's X scaling.
Here are graphs, also from the attached experiment, showing the original data (data0 vs timeW - I renamed your waves for simplicity):
You can see that the output data, which is sampled every 0.2 seconds, clearly differs from the input data (note the bottom around 12:00 PM). This is because your data is very noisy. Therefore sampling every 0.2 seconds will miss the positive and negative peaks. Consequently the interpolated data is not a very good representation of your input data.
Although this does achieve your goal to "interpolate them all into full strict 5Hz data", the result is likely not what you are looking for. I think this problem will affect any kind of straightforward sampling.
Because of the nature of your data, I can't think of a practical way to achieve the goal. How to proceed depends on what you intend to do with the data.
June 6, 2022 at 03:27 pm - Permalink
In reply to I examined your time wave… by hrodstein
Hi Hrodstein,
Thank you for the help. Sorry for the misunderstanding. These 3 waves of data are collected directly from the instrument. So unequal magnitude is Okay for me. The "strict" I mean is just 5 data in 1 second. My goal is to interpolate the missing points by the neighbouring points. To make sure they are exactly 5 data per second, without changing other data.
Cheers,
Mortoo
June 6, 2022 at 04:51 pm - Permalink
To make sure they are exactly 5 data per second, without changing other data.
I don't think there is a simple solution for this. I think it would require custom programming and even then I'm not sure it is feasible.
As a start to understanding the difficulty, think about the fact that each 1 second interval in your time wave is potentially different from the others in unpredictable ways. Try taking the first 10 seconds and manually deciding where you would insert a point in each 1 second interval.
June 6, 2022 at 06:14 pm - Permalink
In reply to To make sure they are… by hrodstein
Hi Hrodstein,
How about creating a "strict" 5Hz time wave like
2021/12/18 00:00:00.00
2021/12/18 00:00:00:02
2021/12/18 00:00:00.04
......
and using a command to filter out data from the raw data within 0.2 seconds of the "strict" data to make a new wave. Unmatched data is displayed as NaN.
Is there a command for this filtering function in Igor pro? Can "BinarySearch" command works here?
Cheers,
Mortoo
June 7, 2022 at 04:08 am - Permalink
This is what I did with interpolation. It would work with smooth data but not with spikey data, especially with very spikey like you have.
If you can come up with a fairly detailed algorithm to choose the data values for those times you have identified (every 0.2 seconds), then it could be programmed. I can not think of an algorithm that preserves the meaning of the data.
I don't understand that.
I'm not sure what you mean by "filtering function". Some possibilities are Smooth, Extract, FilterFIR, and FilterIIR, but I don't see how any of them helps.
June 7, 2022 at 05:38 am - Permalink
In reply to Hi Hrodstein, How about… by zixuan.cheng
assuming monotonic time waves, this function selects the nearest point within plus-or-minus 0.1 seconds
wave /D oldTimeWave, newTimeWave
wave oldDataWave, newDataWave
int i, imax, j, jmax
imax = numpnts(newTimeWave)
jmax = numpnts(oldTimeWave)
variable diff
for (i=0,j=0;i<imax&&j<jmax;)
diff = newTimeWave[i] - oldTimeWave[j]
if (diff > 0.1)
j++
continue
elseif (j<jmax-2 && abs(newTimeWave[i]-oldTimeWave[j+1])<abs(diff))
j++
continue
endif
if (abs(diff) < 0.1)
newDataWave[i] = oldDataWave[j]
//j++
// incrementing j here prevents us from considering this point again, even though it may be a closer match for i+1
else
newDataWave[i] = NaN
endif
i++
endfor
end
June 7, 2022 at 05:46 am - Permalink
In reply to How about creating a "strict… by hrodstein
Hi Hrodstein,
Sorry for the misunderstanding. I mean to create a new datawave with the same length as the "strict" 5Hz datetimewave. The data points of the new wave are selected from the most recent data from the old datawave.
Cheers,
Mortoo
June 7, 2022 at 05:58 am - Permalink
In reply to zixuan.cheng wrote: and… by tony
Hi Tony,
Thanks for helping me again! I tried this function and it makes a wave with some gaps, but enough data points, which is exactly what I need. Thank you so much!
Another question is how to fill these gaps with neighbouring data.
Cheers,
Mortoo
June 7, 2022 at 06:04 am - Permalink
In reply to Hi Tony, Thanks for helping… by zixuan.cheng
Hi Tony,
I replaced the "newDataWave[i] = NaN" by "newDataWave[i] = oldDataWave[j]" to fill the NaNs:
newDataWave[i] = oldDataWave[j]
j++
else
newDataWave[i] = oldDataWave[j]
Thank you so much.
Mortoo
June 7, 2022 at 07:55 am - Permalink
In reply to Hi Tony, I replaced the … by zixuan.cheng
For simply the closest point in time, I think this works, and fixes an error in the previous version:
wave /D oldTimeWave, newTimeWave
wave oldDataWave, newDataWave
int i, imax, j, jmax
imax = numpnts(newTimeWave)
jmax = numpnts(oldTimeWave)
for (i=0,j=0;i<imax&&j<jmax;)
if (j<jmax-2 && abs(newTimeWave[i]-oldTimeWave[j+1])<abs(newTimeWave[i] - oldTimeWave[j]))
j++
continue
endif
newDataWave[i] = oldDataWave[j]
i++
endfor
end
June 7, 2022 at 08:24 am - Permalink