Results 1 to 9 of 9

Thread: How to change axis scale with out changing data series?

  1. #1
    Join Date
    Jan 2010
    Posts
    28
    Thanks
    4
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default How to change axis scale with out changing data series?

    I have an FFT to plot. The FFT data is stored in a QwtSeriesData object (this is Qwt6 and Qt4.6.2 BTW) so it is stored as a magnitude only, with the sample position (index) being the x-axis value.

    When plotted in this form I have a graph which shows the FFT as magnitude (dBFS) on the y-axis against FFT sample bin on the x-axis (the sample bin is effectively the FFT point size).

    This is OK for some applications as knowing the frequency bin in useful, however it is more normal to plot the FFT as magnitude against frequency. The conversion from FFT bin to frequency is a simple scale factor. Is it possible to do this by simply modifying the way the x-axis is scaled?

    I am sure this is possible, but maybe the search criteria I have tried do match anything posted on the forum, so possible apologies in advance if this is an obvious answer. Or if its in the Qwt docs maybe again I am looking at the wrong thing. I thought it was something to do with the scale engines but am not so sure now.

    Cheers

    Oh forgot to say, I am plotting multiple curves on a single plot and was using the auto scale to set the appropriate scale for all plots. Not sure if this changes how this is done.
    Last edited by mike_the_tv; 22nd April 2010 at 16:13.

  2. #2
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,277
    Thanked 871 Times in 819 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to change axis scale with out changing data series?

    Why not overloading QwtSeriesData::sample() and do your "FFT bin -> frequency" conversion there. If you have implemented YourSeriesData::boundingRect() ( something you could do to improve the performance of autoscaling ) you have to do the same there again.

    Uwe

  3. #3
    Join Date
    Jan 2010
    Posts
    28
    Thanks
    4
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to change axis scale with out changing data series?

    Quote Originally Posted by Uwe View Post
    Why not overloading QwtSeriesData::sample() and do your "FFT bin -> frequency" conversion there. If you have implemented YourSeriesData::boundingRect() ( something you could do to improve the performance of autoscaling ) you have to do the same there again.

    Uwe
    Yes I have implemented my own QwtSeriesData and overridden the boundingRect(). For my raw data I set the bounding rectable to be fixed at the sample range of my data, for example 12 bit data ranges over -2048 to +2047, even if the data is smaller. This just stops the plot axises from varying when the data magnitude changes, someting which looks better when you are repeatedly replotting variable data. The x-axis range for my data I set to be simply the number of sample, say 1024, which works fine for raw data.

    The FFT data's bounding box can be similarly optimised without calculating the min and max ranges. Again though the x-axis is just the calculated data index, this being the FFT bin. To plot the FFT data against frequency however I need to plot from say 0Hz to 500MHz as opposed to 0 to 1023 for the FFT bin. That is each bin equates to 488kHz.

    If I modify the bounding rectangle should I report the rectangle as 0-500MHz on the x-axis then? If I do that will the plot widget not request display points from 0 to 500,000,000 as opposed to 0-1023? Or am I missing something here?

    I can see for scaling say my y-axis data, which I need to do with the raw data at some point to display input signal range in mVolts as opposed to sample value, by simply getting my series data class to return the point at the requested index modified on the fly my the conversion factor from sample value to mV. I don't understand how this an be done for the x-axis data, hence I thought I could simply modify how the x-axis is scaled or transformed.

    What is the linear scale engine and transform engine classes for then on the axis?

    Cheers

  4. #4
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,277
    Thanked 871 Times in 819 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to change axis scale with out changing data series?

    Quote Originally Posted by mike_the_tv View Post
    If I modify the bounding rectangle should I report the rectangle as 0-500MHz on the x-axis then? If I do that will the plot widget not request display points from 0 to 500,000,000 as opposed to 0-1023?8
    And it gets them, when you modify the x value in YourSeriaData::sample() in the same way.
    What is the linear scale engine and transform engine classes for then on the axis?
    A scale engine is for calculating alignment and tick positions for the axis scales. The scale maps are for translating from plot/scale coordinates into paint device coordinates ( f.e pixels on widgets ).

    Uwe

  5. #5
    Join Date
    Jan 2010
    Posts
    28
    Thanks
    4
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to change axis scale with out changing data series?

    Quote Originally Posted by Uwe View Post
    And it gets them, when you modify the x value in YourSeriaData::sample() in the same way.
    Just to check I understand, are you saying that for my data stored in an array from say 0-1023 I should report the bounding rect as 0-500,000,000, then in the series data class sample() implementation map requested indexes 0-488,000 to my first real sample point (data[0]), 488,001-976,000 to the second sample point (data[1]), etc. (488,000 is approx 500MHz / 1024)?

    Is this rather inefficient as the sample() member will be called 500 million times as opposed to 1024 times?

    I can see in the general case, and not just my application, that using the QwtSeriesData object to represent what is essentially 1D linear data without an x-value, this being implicit in the data array index, that the scale you want to apply to the x-axis when plotted may not be the sample index but some other linear scale.

    A scale engine is for calculating alignment and tick positions for the axis scales. The scale maps are for translating from plot/scale coordinates into paint device coordinates ( f.e pixels on widgets ).

    Uwe
    OK this was the conclusion I had come to after diging more deeply in the docs and code.

  6. #6
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,277
    Thanked 871 Times in 819 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to change axis scale with out changing data series?

    Quote Originally Posted by mike_the_tv View Post
    Is this rather inefficient as the sample() member will be called 500 million times as opposed to 1024 times?
    QwtSeriesData::sample() is QwtSeriesData::size() times called regardless what your axes ranges are or what values you return. In your example it should be 1024 for both situations.

    Note, that you are returning points only. If you want to translate your points into a x1-x2, y representations, you need an item similar/derived from QwtPlotHistogram.

    Uwe

  7. #7
    Join Date
    Jan 2010
    Posts
    28
    Thanks
    4
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to change axis scale with out changing data series?

    Quote Originally Posted by Uwe View Post
    QwtSeriesData::sample() is QwtSeriesData::size() times called regardless what your axes ranges are or what values you return. In your example it should be 1024 for both situations.

    Note, that you are returning points only. If you want to translate your points into a x1-x2, y representations, you need an item similar/derived from QwtPlotHistogram.

    Uwe
    Thanks for the reply. I did a quick hack to see what would happen if I change the rectangle for the data, and what I get is the data plotted hard up against the left hand side as the x-axis scale is now many times larget than the data index. It was however only called 1024 times within sample().

    I am not sure I have understood your suggestions therefore. Changing the bounding rectangle has sort of done what I expected. The plot has used it to scale the x-axis, but the data is not expanded to fill this range. The data index is being treated as the x-axis value, hence the data being all squashed up on the left side.

    Maybe the answer is in your Note at the bottom, but I don't quite understand what you mean by the x1-x2, y representation.

    Would I be better off picking a different representation for my data? You kindly suggested this format in a post a while back and up till trying to plot the data against slightly adjusted axis it has worked very well, excellent library.

    Just to be clear about what I have implemented so far, as it is possible I have done this bit wrong. I took the QwtSeriesData class and derived MyPlotData (all Qwt 6 still). I have added various members to this class to allow me to reallocate memory when my sample data lengths change. Therefore when I start a capture of data (time domain samples) I call a resize() member to reallocate the internal buffer and set the size() member and a default bounding box. I then get the pointer to that data with a call to samples(). This buffer is passed to a class outside the GUI space which collects data from a sensor based on a regular sampling clock for say 1024 periods, therefore I get a float array with 1024 values in it.

    When the capture is complete the GUI gets called to do a replot. For the raw data this can be plotted as is, i.e. the values stored in the array are the y-axis values, and the array index the x-axis points. Raw data plots show the data magnitude (y axis) against sample number (x-axis). The data is then FFT'd to give another MyPlotData object. This is allocated the correct size for the FFT result, the FFT calculated from the raw MyPlotData class and placed into the FFT MyPlotData class object. Again this is still a series data object. As said before, the value in the array is the FFT magnitude, and the array index the FFT bin number, which is just a linear contiguous count from 0, just like the original raw datas sample index.

    All I really need to do is change how the series datas array index is interpreted. Instead if being a contiguous array I need it to be sparse. Data points will still be connected pint to point, and will look exactly as if the x-axis was the array index.

    Changing the bounding rectangle just seems to change the plottable area the plot widgets canvas covers, hence when the series data is requested with sample(index), the index is used by the plot widget as the x-axis value. I can't modify this index in the sample() call so can't change how the plot widget uses this value.

    I could effectively oversample the series data array by claiming to the plot widget that the size is say 500,000,000 but internally for each sample(index) request map N values to a single underlying data value in the actual FFT data array, which lets say is 1024 in size. This would kill performance however.

    I guess back to my earlier question, am I using the wrong data type for doing this operation, or can I acheive the effect I am after by a bit of back door manipulation of the x-axis thereby avoiding the need to modify the data itself.

    At some point soon I also need to add zooming and panning to this so I may be back

    Thanks for the help it is much appreciated.

  8. #8
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,277
    Thanked 871 Times in 819 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to change axis scale with out changing data series?

    The conversion from FFT bin to frequency is a simple scale factor
    Ok, lets call this factor 'f'.
    I am not sure I have understood your suggestions therefore.
    Assuming you have your values in m_data, what is an array of doubles:

    Qt Code:
    1. virtual QPointF YourSeriesData::sample(size_t i) const
    2. {
    3. return QPointF( f * toFFTbin(i), m_data[i]); // do your scaling here
    4. }
    To copy to clipboard, switch view to plain text mode 

    Uwe
    Last edited by Uwe; 24th April 2010 at 10:19.

  9. #9
    Join Date
    Jan 2010
    Posts
    28
    Thanks
    4
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to change axis scale with out changing data series?

    Quote Originally Posted by Uwe View Post
    Ok, lets call this factor 'f'.

    Assuming you have your values in m_data, what is an array of doubles:

    Qt Code:
    1. virtual QPointF YourSeriesData::sample(size_t i) const
    2. {
    3. return QPointF( f * toFFTbin(i), m_data[i]); // do your scaling here
    4. }
    To copy to clipboard, switch view to plain text mode 

    Uwe
    Now I see how it works. Sorry for being such an idiot. The answer was right there in front of my own eyes. The sample() function does not just return the y value but the x as well, and I can modify the x value to convert my 0-1024 to 0-500MHz.

    Thanks for the being so patient.

Similar Threads

  1. Replies: 1
    Last Post: 19th May 2009, 11:14
  2. qwp plot axis scale
    By Cal in forum Qwt
    Replies: 1
    Last Post: 11th May 2009, 17:10
  3. Axis with a probability scale
    By Lister in forum Qwt
    Replies: 1
    Last Post: 5th May 2009, 06:45
  4. Axis won't stay at new scale setting
    By Maxicatten in forum Qwt
    Replies: 5
    Last Post: 9th April 2009, 04:03
  5. 4 axis auto scale..
    By Vincenzo in forum Qwt
    Replies: 0
    Last Post: 22nd March 2009, 01:12

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.