Results 1 to 4 of 4

Thread: QwtSpectrogram, Change axis numbers

  1. #1
    Join Date
    Jul 2017
    Posts
    7
    Thanks
    5
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Question QwtSpectrogram, Change axis numbers

    I want to draw a spectrogram with size 2000*2000. However, i don't want the axis scale numbers to be from 0 to 2000, but rather a linear transformation, where 2000 is mapped to a certain number (e.g. 120), and the rest of the values are mapped accordingly.

    I declare a
    Qt Code:
    1. QwtPlotSpectrogram * spectrogram
    To copy to clipboard, switch view to plain text mode 

    instance, and i use setData() function to pass a SpectrogramData instance:
    Qt Code:
    1. class SpectrogramData : public QwtMatrixRasterData, public QwtLinearScaleEngine {
    2. private:
    3. std::vector<std::vector<double>> data_;
    4. public:
    5. SpectrogramData();
    6. ~SpectrogramData();
    7. void setData(std::vector<std::vector<double>> & data) { data_ = data; }
    8. virtual double value(double x, double y) const{ return data_[x][y]; }
    9. };
    To copy to clipboard, switch view to plain text mode 

    Then i initialize the QwtPlot:
    Qt Code:
    1. plot_ = new QwtPlot(this);
    2. ...
    3. spectrogram_ = new QwtPlotSpectrogram();
    4. spectrogram_data_ = new SpectrogramData();
    5. ...
    6. spectrogram_->setData(spectrogram_data_);
    7. spectrogram_->attach(plot_);
    To copy to clipboard, switch view to plain text mode 


    The problem is that when i draw something, i have to use setInterval() on the spectrogram_data object, but the values 0 and 2000, for min and max, that i pass in order to fully draw the 2000*2000 matrix, set the axis to 0-2000 as well. If i give smaller values to setInterval() then part of the matrix is not drawn.

    What i tried is to use QwtTranform, since i want a linear transformation, but as i am given to understand, it does not behave the way i want:
    Qt Code:
    1. class AxisTransformation : public QwtTransform {
    2. private:
    3. double prev_start_, prev_end_;
    4. double new_start_, new_end_;
    5. public:
    6. AxisTransformation(double prev_start, double prev_end, double new_start, double new_end) : prev_start_(prev_start), prev_end_(prev_end), new_start_(new_start), new_end_(new_end) {}
    7. virtual double transform(double value) const {
    8. return new_value = new_start_ + (new_end_ - new_start_) * (value - prev_start_) / (prev_end_ - prev_start_);
    9. }
    10. virtual double invTransform(double value) const {
    11. return new_value = prev_start_ + (prev_end_ - prev_start_) * (value - new_start_) / (new_end_ - new_start_);
    12. }
    13. AxisTransformation * copy() const {
    14. return new AxisTransformation(*this);
    15. }
    16. };
    To copy to clipboard, switch view to plain text mode 
    along with
    Qt Code:
    1. AxisTransformation * t = new AxisTransformation(0, 2000, 0, 120);
    2. QwtScaleWidget * axis_x_bottom = plot_->axisWidget(QwtPlot::xBottom);
    3. axis_x_bottom->setTransformation(t);
    To copy to clipboard, switch view to plain text mode 

    So how can i fully draw the 2000*2000 matrix, but specifying the axis numbers displayed to be from 0 to 120?

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

    Default Re: QwtSpectrogram, Change axis numbers

    Better remove all what you did so far and restart with something like that:

    Qt Code:
    1. class SpectrogramData: public QwtRasterData
    2. {
    3. public:
    4. SpectrogramData()
    5. {
    6. m_intervals[ Qt::XAxis ] = QwtInterval( 0, 120 );
    7. m_intervals[ Qt::YAxis ] = QwtInterval( 0, 120 );
    8. m_intervals[ Qt::ZAxis ] = ...
    9. }
    10.  
    11. virtual QwtInterval interval( Qt::Axis axis ) const
    12. {
    13. if ( axis >= 0 && axis <= 2 )
    14. return m_intervals[ axis ];
    15.  
    16. return QwtInterval();
    17. }
    18.  
    19. virtual double value( double x, double y ) const
    20. {
    21. double value = ...; // find the value corresponding to x/y in your vector
    22. return value;
    23. }
    24.  
    25. private:
    26. QwtInterval m_intervals[3];
    27. };
    To copy to clipboard, switch view to plain text mode 

    If you don't insist on using std::vector you could use QwtMatrixRasterData like demonstrated in the rasterview example. You get at least bilinear interpolation and a valid pixel hint for free.

    Uwe

  3. #3
    Join Date
    Jul 2017
    Posts
    7
    Thanks
    5
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QwtSpectrogram, Change axis numbers

    So, as i am given to understand, i should map the values myself into the data, which i did and it seems to work!
    I thought that just changing what values are displayed in the x-axis should be much easier.

    The problem with the rasterview example is that if i use setValueMatrix() to set the data, without subclassing and using value(x,y) overloading, then the rendering time is much higher, i think. The subclassing way seems to be the fastest way.

    Also, how many values are picked in the QwtInterval 0-120, and how are they picked. I mean, i want to achieve a certain resolution based on the data and, obviously, 2000*2000 cannot be rendered in a small window.

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

    Default Re: QwtSpectrogram, Change axis numbers

    Quote Originally Posted by kkaz View Post
    I thought that just changing what values are displayed in the x-axis should be much easier.
    You can set the axes manually using QwtPlot::setAxisScale or you rely on autoscaling, what is based on the bounding rectangle of the plot items. In your case the bounding rectangle depends on the intervals returned by raster data.
    So there is nothing difficult about this - beside, that you are not setting the proper intervals. Return [0,120] and that's it.

    Quote Originally Posted by kkaz View Post
    The problem with the rasterview example is that if i use setValueMatrix() to set the data, without subclassing and using value(x,y) overloading, then the rendering time is much higher, i think.
    You might not want to copy your data only because of API reasons, but there is no performance benefit from not using it.

    Quote Originally Posted by kkaz View Post
    Also, how many values are picked in the QwtInterval 0-120, and how are they picked.
    The spectrogram has to create a QImage from the data, what is a matrix of RGB values. Position and size are found from the resolution of the data ( YourRasterData::pixelHint() ) and the resolution of the target device ( usually the screen ). Then it simply runs over the pixels of the image, calculates the corresponding position in plot coordinates and requests the value by calling YourRasterData::value(). Finally it maps the value into a RGB value and stores it in the image.

    Calculating the value for a given position usually requires some sort resampling - this is what needs to be done inside of QwtRasterData::value(). Most implementations do some sort of nearest neighbor ( = simple and fast ), but of course you might lose significant pixels when the resolution of the image is too low. If this is not acceptable in your case you need to do calculate the value by taking adjacent values into count. In the end it is performance vs. quality.

    When using QwtMatrixRasterData the resolution of the data can be calculated on its own ( you don't need to implement a pixelHint ) and bilinear interpolation as resampling algo is available. Or in other words: this is the option, for everyone who is not interested in these details.

    Uwe

Similar Threads

  1. Replies: 2
    Last Post: 22nd September 2014, 08:40
  2. Replies: 1
    Last Post: 11th February 2014, 22:31
  3. Replies: 2
    Last Post: 26th January 2012, 16:31
  4. Replies: 5
    Last Post: 12th August 2011, 23:55
  5. Replies: 12
    Last Post: 18th May 2011, 21:40

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.