How to split one wave into multiple waves
Salome_V
Hi,
I would like to split one wave into equally sized waves. I am new to coding and I was hoping to get some help.
Thanks a lot in advance.
Salome
function split(waveID)
wave waveID
variable nPoints = DimSize (waveID,0)
Variable i, x
for (i = 0; i < nPoints; i+=81)
for (x = 2; x < 14; x+=1)
duplicate/R=[i] waveID, wavex
endfor
endfor
end
wave waveID
variable nPoints = DimSize (waveID,0)
Variable i, x
for (i = 0; i < nPoints; i+=81)
for (x = 2; x < 14; x+=1)
duplicate/R=[i] waveID, wavex
endfor
endfor
end
Hi Salome,
You are very close. Here is how I would approach it and make it a bit more general. The first thing that caught my eye was the interval of 81 which is not a common number and I was wondering if it was accurate. Since Igor Pro starts at 0, going from 0 up to but not including 81 actually gives you 81 points and not 80 as is sometimes the real goal. To that end I have also brought the sample size into the parameters which makes the overall function a bit more reusable. From there I determine the number of possible subsets and do not assume that there is an event multiple which cause an error if it is applied to a wave with a non-even number of subsets.
The duplicate function now goes through each chuck of the input wave and creates a subset. For the output wave name, notice I create a base name as a string and then convert the index value to a string to concatenate onto the base name and use the $ operation to have Igor use the value of the string. You could further extend the function to take a base name as an input parameter. In your code the use of "wavex" does not change as you increment x. Wavex is just reused and actually will case an error the second time the duplicate function is called because it was created the first pass and will be used again the next time. This is one reason I have also included the /O overwrite flag. Usually when writing code you need to test it a couple of times and if you don't use the overwrite you need to remember to delete the created waves before each run.
I hope this helps and if I was bit too basic please forgive me, better too basic than too obscure.
Andy
wave waveID
variable samplesize
Variable HowMany
HowMany = floor(Numpnts(WaveID)/samplesize)
String NewBaseName ="NewName_"
Variable index
For(index=0;index<Howmany;index+=1)
Duplicate/O/R=[index*samplesize,(index+1)*samplesize-1] waveID, $(NewBaseName+num2str(index))
endfor
End
March 29, 2021 at 08:49 am - Permalink
Another approach would be to first redimension the 1D wave into a 2D wave where each column of the 2D wave represents what you want to become 1 wave in the output. Then use the SplitWaves operation to split that 2D wave into multiple 1D waves.
March 29, 2021 at 09:01 am - Permalink
In reply to Hi Salome, You are very… by hegedus
Thank you Andy! Both for the code and for detailed explanation.
Best regards,
Salome
March 29, 2021 at 11:20 pm - Permalink
Hi,
Thank you for helping me out last time.
I am trying to modify the code to normalize the data. If e.g I have a long wave that I split into 12 waves, for the first 6 waves I need to subtract the first points ( wave0-=wave[0], wave1-=wave1[0],… etc). However, for the last 6 waves (wave6-wave11) I need to subtract first values from the first 6 waves respectively (wave6-=wave[0], wave7-=wave[1], etc). The code does the normalization of the first 6 waves right but gives me wrong values for the other half.
I would appreciate a lot if somebody can help me to find the mistake.
Thanks in advance for your help!
wave waveID
variable samplesize
variable timeint
make/O /N=(samplesize) timewave=timeint*p
Variable HowMany
HowMany = floor(Numpnts(WaveID)/samplesize)
String Phase1 ="Phase1_"
String Phase2 ="Phase2_"
String Phase1Norm ="P1Norm_"
String Phase2Norm ="P2Norm_"
Variable index
For (index=0;index<=Howmany/2;index+=1)
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $"TEMPphase1" // $(Phase1+num2str(index))
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $"TEMPp1norm" //$(Phase1Norm+num2str(index))
wave Tempphase1, TempP1norm
Tempp1norm-=tempphase1[0]
DUplicate /O/D TEMPP1norm,$(Phase1Norm+num2str(index))
DUplicate /O/D TEMPPhase1,$(Phase1+num2str(index))
endfor
For (index=howmany/2+1;index<=Howmany;index+=1)
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $"TEMPphase2" // $(Phase2+num2str(index))
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $"TEMPp2norm" //$(Phase2Norm+num2str(index))
wave TEMPphase2,TEMPp2norm
Tempp2norm=tempphase1[0]
DUplicate /O/D TEMPP2norm,$(Phase2Norm+num2str(index))
endfor
End
Salome
August 11, 2021 at 06:10 am - Permalink
Your first loop has finished, so when you do this (I guess you forgot a minus sign):
Tempp2norm-=tempphase1[0]
then tempphase1 is stuck in your last part extracted from waveID in loop one. A solution would be to access the right point for normalization from waveID directly or just have one loop, where you decide with an if branch what to use for normalization. E.g., if your index is above howmany/2 then switch to the Phase2 naming scheme, but use the Phase1 waves for normalization. By the way, if you are creating throwaway waves like tempphase, you can also use the /Free flag instead of /O, which makes these waves disappear at the end of execution.
August 11, 2021 at 08:26 am - Permalink
In reply to Your first loop has finished… by chozo
Hi and Thank you for the answer,
The truth is I tried to use if loops/branch but it gives me the same wrong values for the second set of the normalized waves. I am very new to coding so probably I don't know how to use the tempwaves right.
Thanks again for your help,
Salome
wave waveID
variable samplesize
variable timeint
make/O /N=(samplesize) timewave=timeint*p
Variable HowMany
HowMany = floor(Numpnts(WaveID)/samplesize)
String Phase1 ="Phase1_"
String Phase2 ="Phase2_"
String Phase1Norm ="P1Norm_"
String Phase2Norm ="P2Norm_"
Variable index
For (index=0;index<=Howmany;index+=1)
if (index<=Howmany/2)
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $"TEMPphase1" // $(Phase1+num2str(index))
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $"TEMPp1norm" //$(Phase1Norm+num2str(index))
wave Tempphase1, TempP1norm
Tempp1norm-=tempphase1[0]
DUplicate /O/D TEMPP1norm,$(Phase1Norm+num2str(index))
DUplicate /O/D TEMPPhase1,$(Phase1+num2str(index))
else
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $"TEMPphase2" // $(Phase2+num2str(index))
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $"TEMPp2norm" //$(Phase2Norm+num2str(index))
wave TEMPphase2,TEMPp2norm
Tempp2norm-=tempphase1[0]
DUplicate /O/D TEMPP2norm,$(Phase2Norm+num2str(index))
endif
endfor
End
r the second set of the normilized way.
August 11, 2021 at 10:39 am - Permalink
Here is an alternative approach that is based on aclight suggestion:
wave waveID
variable samplesize
Variable nCols=floor(Numpnts(WaveID)/samplesize)
Duplicate/Free WaveID,dummyWave
Redimension/N=(sampleSize,nCols) dummyWave
// create a matrix wave from the original but subtract the first column
MatrixOP/O/free normMatrix=dummyWave-rowRepeat(row(dummyWave,0),sampleSize)
if(dataFolderExists("clutter"))
doAlert 1,"Clutter datafolder exists. OK to erase?"
if(V_flag==1)
KillDataFolder/z Clutter
else
return 0
endif
endif
///SplitWave/DDF=clutter/N=ww dummyWave
SplitWave/DDF=clutter/N=normw normMatrix
// At this point you have all the waves that you want.
End
August 11, 2021 at 05:20 pm - Permalink
Here, this may work (couldn't test it though):
wave waveID
variable samplesize
variable timeint
Make/O/N=(samplesize) timewave=timeint*p
Variable HowMany = floor(Numpnts(WaveID)/samplesize)
String Phase1 ="Phase1_"
String Phase2 ="Phase2_"
String Phase1Norm ="P1Norm_"
String Phase2Norm ="P2Norm_"
Variable index
for (index=0; index <= HowMany; index+=1)
if (index <= HowMany/2)
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $(Phase1+num2str(index))
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $(Phase1Norm+num2str(index))
Wave Tempphase1 = $(Phase1+num2str(index))
Wave TempP1norm = $(Phase1Norm+num2str(index))
TempP1norm -= Tempphase1[0]
else
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $(Phase2+num2str(index))
Duplicate/O/D/R=[index*samplesize,(index+1)*samplesize-1] waveID, $(Phase2Norm+num2str(index))
Wave Tempphase1 = $(Phase1+num2str(index-HowMany/2))
Wave TempP2norm = $(Phase2Norm+num2str(index))
TempP2norm -= Tempphase1[0]
endif
endfor
return 0
End
Note how I refer to the waves from the first branch in the second branch by using index-HowMany/2. This may need debugging depending on whether HowMany is even or odd.
August 11, 2021 at 08:29 pm - Permalink
I think this might do the job as well.
Function split_wave(wave iwave, variable nsplit)
variable npts, ic, nSize, ni, nf
string dName
npts = numpnts(iwave)
nSize = floor(npts/nsplit)
// the first one
sprintf dName "%s%d", splitPrefix, 0
duplicate/O iwave $dName
wave theSplit = $dName
theSplit[nSize,npts-1] = NaN
// the middle ones
for (ic=1;ic<nsplit-1;ic+=1)
sprintf dName "%s%d", splitPrefix, ic
duplicate/O iwave $dName
wave theSplit = $dName
ni = ic*nSize - 1
nf = ni + nSize + 1
theSplit[0,ni] = NaN
theSplit[nf,npts-1] = NaN
endfor
// the last one
sprintf dName "%s%d", splitPrefix, nsplit-1
duplicate/O iwave $dName
wave theSplit = $dName
theSplit[0,nf-1] = NaN
for (ic=0;ic<nsplit;ic+=1)
sprintf dName "%s%d", splitPrefix, ic
wave theSplit = $dName
WaveTransform zapNaNs theSplit
endfor
return 0
end
To test this, try on the command line input:
split_wave(testwave,6)
This will give you six waves. The first five are 167 points. The last wave contains the overflow points.
August 12, 2021 at 07:58 am - Permalink
In reply to Here, this may work (couldn… by chozo
Hi again and thanks a lot!
I tested the code and I only needed to change <= into < in the following lines
for (index=0; index < HowMany; index+=1)
if (index < HowMany/2)
and it worked :-)
Thanks again for your help!
Best regards,
Salome
August 26, 2021 at 12:50 am - Permalink
In reply to I think this might do the… by jjweimer
Thanks a lot for the code,
I tried it and it works for splitting :-)
Best regards,
Salome
August 26, 2021 at 12:55 am - Permalink
In reply to Here is an alternative… by Igor
Thanks a lot for the code!
I tested it and it does not normilize second set of waves right. But one of the codes suggested here works so I will go with it :-)
Thanks a lot again,
Best regards,
Salome
August 26, 2021 at 01:00 am - Permalink