The Origin Forum
File Exchange
Try Origin for Free
The Origin Forum
Home | Profile | Register | Active Topics | Members | Search | FAQ | Send File to Tech support
Username:
Password:
Save Password
Forgot your Password? | Admin Options

 All Forums
 Origin Forum for Programming
 LabTalk Forum
 Performing FFT on a limited number of rows
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic Lock Topic Edit Topic Delete Topic New Topic Reply to Topic

kaiousama

Japan
Posts

Posted - 09/08/2004 :  6:24:56 PM  Show Profile  Edit Topic  Reply with Quote  View user's IP address  Delete Topic
Hi, i'm facing problems in performing FFT on a limited range of rows:
I want to perform FFT only over the range the user selected on a plot via the "data selector" tool.
So i've created the following script, setting fft.start and fft.size according with mks1 / mks2 values.

Running the script for a limited range of rows selected on the plot, the "fype" procedure reports the correct values
for mks1 / mks2 in the script window but the FFT calculation lasts exacltly in the same time amount and produce exactly
the sameal results as performing FFT over the whole dataset (tried with the pClamp sample file contained
in the \pClamp\96322002.abf directory of my Origin 6.0 installation).

Doing the same selection in the plot with the "data selector" and performing FFT via origin's menu does take
only a little amount of the time needed for an FFT over the whole data, indicating that performing FFT via origin's menu
does correctly perform FFT over the selected range only, while performing FFT with my script does result in a FFT over the whole dataset no matter what.

Can you help me to understand what's wrong with my script?

Thanks.

[fft]

//------------------------------------------------------------------------------
// FFT COMPUTATION
//------------------------------------------------------------------------------

%Z=%H; // Store active worksheet name in %Z variable

fft.reset( ); // Reset previous fft settings
fft.forward=1; // 1= forward 0=backward
fft.forward.timeData$=%Z_Time; // Time values dataset
fft.forward.tdelta=%Z_Time[2]-%Z_Time[1]; // Sampling interval
fft.forward.realData$=%Z_Avg; // Values dataset

if ((mks1!=-1)&&(mks2!=-1))
{
fft.start=mks1;
fft.size=mks2-mks1;
type Performing FFT between $(mks1) and $(mks2);
}
else
{
type Performing FFT over the whole data;
}

window -t W fft %ZFFT; // Output worksheet

fft.output.samplingdata$=%ZFFT_Freq;
fft.output.realdata$=%ZFFT_Real;
fft.output.imagdata$=%ZFFT_Imag;
fft.output.ampdata$=%ZFFT_r;
fft.output.phasedata$=%ZFFT_Phi;
fft.output.powerdata$=%ZFFT_Power;

fft.spectrum=1; // 1=amplitude spectrum 2= Power spectrum
fft.real=1; // 1=Real FFT 0=complex FFT
fft.normalize=1; // 1= normalize magnitudes 0= leave unchanged
fft.shifted=0; // 1= shift results 0=leave unshifted
fft.windowing=1; // 1= rectangular
fft.unwrap=0; // 1=unwrap 0=do not unwrap
fft.convention=1; // 0=Engineering 1=science (this is the right property)

fft.forward( ); // Execute Forward FFT
//------------------------------------------------------------------------------

Origin Version : 6.0
Operating System: windows XP

Mike Buess

USA
3037 Posts

Posted - 09/08/2004 :  7:49:39 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
It's possible that fft.nextPowerOf2 remains set by the total dataset size so you might try something like this...

if ((mks1!=-1)&&(mks2!=-1))
{
fft.start=mks1;
fft.size=mks2-mks1;
type Performing FFT between $(mks1) and $(mks2);
zpt=1;
for(i=1;i>0;i++) {zpt*=2; if(zpt>fft.size) break};
fft.nextPowerOf2=zpt;
}

Mike Buess
Origin WebRing Member
Go to Top of Page

kaiousama

Japan
Posts

Posted - 09/09/2004 :  04:14:23 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
quote:

It's possible that fft.nextPowerOf2 remains set by the total dataset size so you might try something like this...



You are right, the fft.NextPowerOf2 remained setted to zero.

Unfortunately even this fix doen't solve the problem, probaly there is something else wrong.... i think now all the fft object's properties are set, is maybe the order I declared the properties not correct?

Regards.
Go to Top of Page

Mike Buess

USA
3037 Posts

Posted - 09/09/2004 :  07:46:14 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
Now I remember also having problems using the fft object on a range of data. My solution was to copy that range to another worksheet, fft from there and copy results back (if needed).

Mike Buess
Origin WebRing Member
Go to Top of Page

kaiousama

Japan
Posts

Posted - 09/09/2004 :  09:17:31 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
Thanks Mike, these are those kind of problems i can spend days without finding a solution ^_^

In order to copy the selected range into temporary datasets i encountered another one problem, this is the situation:

The active window is the graph window where the user selected FFT range with Data selector tool, I need to access X and Y datasets plotted in the graph.
Is there a way to retrieve X and Y axis datasets from plotted layer?
Alternatively, is there a way to retrieve the name of the worksheet used to create a certain layer (%H variable cannot be used since it stores the graph window)?

pratically i'd like to add these lines:

create Hidden -wd (mks2-mks1) Time Value;
copy -b mks1 X Hidden_Time -b 1 -e (mks2-mks1);
copy -b mks1 Y Hidden_Value -b 1 -e (mks2-mks1);

but i don't know how to retrieve X and Y datasets from the graph or from the original dataset.

Sincerely.

Edited by - kaiousama on 09/09/2004 09:22:04 AM
Go to Top of Page

Mike Buess

USA
3037 Posts

Posted - 09/09/2004 :  10:12:14 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
%C is the name of the active dataset. %(%W, @Xn) is the name of the X column in wks %W...

%W=%[%C,'_']; // name of wks containing %C
%A=%(%W, @Xn); // name of X dataset
copy -b mks1 %A Hidden_Time -b 1 -e (mks2-mks1);
copy -b mks1 %C Hidden_Value -b 1 -e (mks2-mks1);

Mike Buess
Origin WebRing Member
Go to Top of Page

kaiousama

Japan
Posts

Posted - 09/09/2004 :  12:18:57 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
I was able to retrieve the correct X & Y datasets but still something didn't work.
try to plot a line graph and select some range with data selector, then call this script:

//-----------------------------------------------------------
[copyrange]

%Z=%[%C,'_']; // name of wks containing %C
%A=%Z_%(%Z, @Xn); // name of X dataset
%B=%C;

ty %A;
ty %B;
ty $(mks1);
ty $(mks2);

create tmp -w (mks2-mks1) Time Value; // create a temporary worksheet
copy -b mks1 %A tmp_Time -b 1 -e (mks2-mks1); // copy X dataset
copy -b mks1 %B tmp_Value -b 1 -e (mks2-mks1); // copy Y dataset

//----------------------------------------------------------

It reports the correct values of mks1, mk2, %A, %B, but it isn't able to copy the range from %A to tmp_Time and from %B to tmp_Value.
It apparently seems that copy() function doesn't like variables mks1 and mks2 because if you directly put numbers instead of mks1/2 the dataset are copied:

copy -b 1 %A tmp_Time -b 1 -e 10; // copy X dataset
copy -b 1 %B tmp_Value -b 1 -e 10; // copy Y dataset

Any idea of what's wrong? are there other ways to copy a part of a dataset into another one?

Edited by - kaiousama on 09/09/2004 12:21:10 PM
Go to Top of Page

Mike Buess

USA
3037 Posts

Posted - 09/09/2004 :  12:48:02 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
I've used variable indices many times with the copy command. Sometimes it doesn't like expressions so you might try this...

npt=mks2-mks1;
create tmp -w npt Time Value; // create a temporary worksheet
copy -b mks1 %A tmp_Time -b 1 -e npt; // copy X dataset
copy -b mks1 %B tmp_Value -b 1 -e npt; // copy Y dataset

Mike Buess
Origin WebRing Member
Go to Top of Page

kaiousama

Japan
Posts

Posted - 09/09/2004 :  4:36:28 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
Interesting developements are on the way:

I've tested your last suggestion and did copy ntp amount of rows, but unfortunately first row was blank and rows are copyed from the very first one ant not from mks1, so i supposed that something's wrong with mks1, and effectively the following script completely fix the problem:

npt=mks2-mks1;
start=mks1
create tmp -w npt Time Value; // create a temporary worksheet
copy -b start %A tmp_Time -b 1 -e npt; // copy X dataset
copy -b start %B tmp_Value -b 1 -e npt; // copy Y dataset

Something's probably wrong in mks definition or in the copy() routine implementation that makes them uncompatible.

Solved even this matter i thought i'd reached the happy end, but i noticed another interesting thing:

I've now created the FFT script fully functional (you find the script at the end of the reply) that performs an FFT over the selection range of a plotted graph (or over the whole graph if no selection is avaible).
This function exactly reproduces the origin's fft menu command except that you don't have to select fft preferences.
So I tested my scripts result against origin's menu command expecting to obtain the sameal result.... but i was wrong:

Performing FFT over the whole graph (no selection) provides the same results as origin fft menu command.

Performing fft over a selected range in the graph provides different FFT results.

So i checked better leaving the temporary worksheet visible after FFT changing this line in my script (create tmp -wd delta Time Value;) and disabling tmp worksheet closing statement.

Analysing tmp worksheet, the selection range is correctly copied, and as final test i performed origin fft menu command over tmp worksheet data and the results are exactly equal to my Script results.

Maybe there is a bug in origin's fft menu command when performed on a selection range, please can you check/test the script in order to confirm/trash my hypotesis?

Sincerely.


[fft]

//------------------------------------------------------------------------------
// FFT COMPUTATION
//------------------------------------------------------------------------------

%Z=%[%C,'_']; // name of wks containing Active dataset %C
%A=%Z_%(%Z, @Xn); // name of X dataset (wks_dataset)
%B=%C; // name of Y dataset (wks_daset)

ty [-----] F F T [-----]; // debug info
ty [Times dataset = %A]; // debug info
ty [Values dataset= %B]; // debug info

if ((mks1!=-1)&&(mks2!=-1))
{
start=mks1; // start from selection
delta=mks2-mks1; // selection range dimension
type Performing FFT between $(mks1) and $(mks2);// debug info
}
else
{
start=1; // start from first row
delta=%Z!wks.nrows; // process all rows
type Performing FFT over the whole data; // debug info
}

fft.reset( ); // Reset previous fft settings
fft.start=1; // These poperties doesn't work for fft object but i set them anyway
fft.size=delta; // These poperties doesn't work for fft object but i set them anyway

zpt=1; // next power of 2 after selected range rows amount
for(i=1;i>0;i++){zpt*=2; if(zpt>delta) break};
fft.nextPowerOf2=zpt; // set the proper power of 2 accoring to fft.size
type next power of 2 is $(zpt); // debug info

create tmp -wd delta Time Value; // create a temporary worksheet --> Replace -wd with -w for debug <--
copy -b start %A tmp_Time -b 1 -e delta; // copy X dataset
copy -b start %B tmp_Value -b 1 -e delta; // copy Y dataset

fft.forward=1; // 1= forward 0=backward
fft.forward.timeData$=tmp_Time; // Time values dataset
fft.forward.tdelta=tmp_Time[2]-tmp_Time[1]; // Sampling interval
fft.forward.realData$=tmp_Value; // Values dataset
fft.forward.imagData$=""; // Set imaginary to Null

window -t W fft %ZFFT; // Output worksheet

fft.output.samplingdata$=%ZFFT_Freq;
fft.output.realdata$=%ZFFT_Real;
fft.output.imagdata$=%ZFFT_Imag;
fft.output.ampdata$=%ZFFT_r;
fft.output.phasedata$=%ZFFT_Phi;
fft.output.powerdata$=%ZFFT_Power;

fft.real=1; // 1=Real FFT 0=complex FFT
fft.spectrum=1; // 1=amplitude spectrum 2= Power spectrum
fft.normalize=1; // 1=normalize magnitudes 0=leave unchanged
fft.shifted=0; // 1=shift results 0=leave unshifted
fft.windowing=1; // 1=rectangular
fft.unwrap=0; // 1=unwrap 0=do not unwrap
fft.convention=1; // 0=Engineering 1=science (this is the right property)

fft.forward( ); // Execute Forward FFT
window -c tmp; // Close tmp worksheet --> disable this line to debug <--
Go to Top of Page

Mike Buess

USA
3037 Posts

Posted - 09/09/2004 :  5:21:57 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
A couple of comments...

First, my original suggestion about fft.nextPowerOf2 might have been a red herring. It's not clear from the fft documentation whether that value should be an exponent or a total number of points (n or 2^n). You might check it's value in the script window after running the FFT menu command. (I usually zero-fill prior to FFT and haven't paid much attention to this property.)

Second, and probably of no importance, is the fact the range mks1 to mks2 contains one more point than you are using. In other words, the number of points in the selection range is npt=mks2-mks1+1. If the difference between Origin's and your script's results are minor you might look at that.

Mike Buess
Origin WebRing Member
Go to Top of Page

kaiousama

Japan
Posts

Posted - 09/14/2004 :  10:25:04 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
Soved! the problem was nor my script nor origins' fft menu command.
It was the sample data i used wrong, the dataset contained some empty values that results in fft errors.
I've re-checked my function's results against Origin's fft command's ones on good datasets and all's gone right the obtained results are identical.

quote:
It's not clear from the fft documentation whether that value should be an exponent or a total number of points (n or 2^n). You might check it's value in the script window after running the FFT menu command. (I usually zero-fill prior to FFT and haven't paid much attention to this property.)


Checked, fft.nextpowerof2 value is the total number of point, so the code you suggested before is right, from this point of view.

Maybe fft.nextpowerof2 wants the power of 2 closest to sample amount , not always the next. I've noticed it because sometimes, after fft, samples number in frequency domain do not correspond to the specified nextpowerof2 but to the previous one.


Edited by - kaiousama on 09/14/2004 10:34:01 AM
Go to Top of Page
  Previous Topic Topic Next Topic Lock Topic Edit Topic Delete Topic New Topic Reply to Topic
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
The Origin Forum © 2020 Originlab Corporation Go To Top Of Page
Snitz Forums 2000