Results 1 to 3 of 3

Thread: QwtDateScaleEngine how to set the date range?

  1. #1
    Join Date
    Nov 2014
    Posts
    4
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default QwtDateScaleEngine how to set the date range?

    Hello,

    I've read a few questions on the forum and googled for it, yet I can't figure out how to properly set the date range.

    I have a CSV file I load into memory, and use boost::gregorian_date, which I then convert into QDate like so:
    Qt Code:
    1. auto first = csvdata.Rows().front().date;
    2. auto last = csvdata.Rows().back().date;
    3.  
    4. QDateTime start ( QDate( first.year(), first.month(), first.day() ), QTime( 0, 0, 0 ) );
    5. QDateTime end ( QDate( last.year(), last.month(), last.day() ), QTime( 0, 0, 0 ) );
    6.  
    7. auto * scaleDraw = new QwtDateScaleDraw( Qt::UTC );
    8. scaleDraw->setDateFormat( QwtDate::Day, QString("dd-mm-yyyy") );
    9.  
    10. auto * scaleEngine = new QwtDateScaleEngine( Qt::UTC );
    11.  
    12. plot.setAxisScaleEngine( QwtPlot::xBottom, scaleEngine );
    13. plot.setAxisScale( QwtPlot::xBottom, start.toTime_t(), end.toTime_t() , 24 * 3600 * 30 );
    14. plot.setAxisScaleDraw( QwtPlot::xBottom, scaleDraw );
    15.  
    16. plot.setAxisLabelRotation( QwtPlot::xBottom, -90.0 );
    17. plot.setAxisLabelAlignment( QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom );
    To copy to clipboard, switch view to plain text mode 

    I then plot a simple moving average curve, which is essentialy an
    Qt Code:
    1. std::pair<double, boost::gregorian_date> sma;
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. QwtPlotCurve * sma_curve = new QwtPlotCurve();
    2. QPolygonF points;
    3. for ( int i = 0; i < sma.size()-1; i++ )
    4. {
    5. static boost::posix_time::ptime epoch ( boost::gregorian::date( 1970, 1, 1 ) );
    6. auto secs = ( boost::posix_time::ptime ( sma[i].second, boost::posix_time::seconds(0) ) - epoch ).total_seconds();
    7. points << QPointF( secs, sma[i].first );
    8. }
    9.  
    10. sma_curve->setSamples( points );
    To copy to clipboard, switch view to plain text mode 

    Yet, the date range on the bottom is always starting from the unix time (Jan 1970).
    I'm obviously doing something wrong.
    Also, the date label for the axis, is not set to dd-mm-yyyyy, but rather to hh:mm DD dd MM yyyy

    Yet the plotted data is correct, just misaligned to the actual dates (which in this case should be 2012-Feb-01 to 2014-Nov-12).


    plot_error.jpg


    Can someone please help?

    PS: I'm using qwt 6.1.1 from the svn repository.

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

    Default Re: QwtDateScaleEngine how to set the date range?

    Better use the following methods to convert between QDateTime to double:

    Qt Code:
    1. QDateTime QwtDate::toDateTime( double value, Qt::TimeSpec timeSpec );
    2. double QwtDate::toDouble( const QDateTime &dateTime );
    To copy to clipboard, switch view to plain text mode 
    Concerning the format of the labels: it depends on the interval type, what is a classification of the scale interval - not of a specific value- and in your case the scale is not identified as being in days.
    The classification is done in QwtDateScaleDraw::intervalType according to the current major ticks of the axis.

    Uwe

  3. #3
    Join Date
    Nov 2014
    Posts
    4
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: QwtDateScaleEngine how to set the date range?

    Uwe,

    Thank you very much for the reply.
    But I'm still very confused.
    Qt Code:
    1. plot.setAxisScale( QwtPlot::xBottom, QwtDate::toDouble( start ), QwtDate::toDouble( end ) , 24 * 3600 * 1000 );
    To copy to clipboard, switch view to plain text mode 
    Makes no difference.

    As far as I understand, the interval type seem to differ?
    I was using seconds as the smallest interval.
    I've set the setDateFormat as Days, which is what I would rather use.
    Qt Code:
    1. auto * scaleDraw = new QwtDateScaleDraw( Qt::UTC );
    2. scaleDraw->setDateFormat( QwtDate::Day, QString("dd-mm-yyyy") );
    To copy to clipboard, switch view to plain text mode 
    When I try to to set the axis starting date, by using seconds elapsed since the unix epoch:
    Qt Code:
    1. plot.setAxisScale( QwtPlot::xBottom, start.toTime_t(), end.toTime_t() , 24 * 3600 * 30 );
    To copy to clipboard, switch view to plain text mode 
    The interval is wrong, because what I see is a starding date a few seconds after the unix epoch.
    Yet
    Qt Code:
    1. QwtPlot::setAxisScale (int axisId, double min, double max, double step=0)
    To copy to clipboard, switch view to plain text mode 
    asks for my minimal and maximum value, and the step size, so my minimal step size are the days elapsed from start date since the epoch, and the max size are the days elapsed from end date since the epoch.

    So, I re-factored by trying to use days only this time:
    Qt Code:
    1. QDateTime epoch ( QDate( 1970, 1, 1 ), QTime(0,0,0) );
    To copy to clipboard, switch view to plain text mode 
    and then tried to reset the axis, to use days, incremented monthly (every 30 days label):
    Qt Code:
    1. plot.setAxisScale( QwtPlot::xBottom, epoch.daysTo( start ), epoch.daysTo( end ) , 30 );
    To copy to clipboard, switch view to plain text mode 
    To my suprise, I am still getting the epoch in 1970, although I have set it to days, the increment appears to be in miliseconds, as the y axis labels increment only by ms.
    Which implies that I cannot set directly the DateScale to use days, because it uses some other interval?
    I don't want the second or milliseconds to be the smallest interval, but only a days. How do I achieve that?
    Qt Code:
    1. QwtDate::IntervalType
    To copy to clipboard, switch view to plain text mode 
    Is protected. How do I use it without creating a class that inherits from it? Or is that the way it must be used?

    Finally, I populate the plot values, using days elapsed like so:
    Qt Code:
    1. QPolygonF points;
    2. for ( const auto & p: sma )
    3. {
    4. QDateTime date ( QDate( p.second.year(), p.second.month(), p.second.day() ), QTime(0,0,0) );
    5. points << QPointF( epoch.daysTo( date ), p.first );
    6. }
    To copy to clipboard, switch view to plain text mode 

    Which draws a correct curve of my data.

    Thank you very much for your help!

    #EDIT

    Nevermind, I finally figured it out, I had to multiply by the amount of milliseconds in a day, like so:

    Qt Code:
    1. double x = 86400000.;
    2. plot.setAxisScale( QwtPlot::xBottom, epoch.daysTo( start ) * x, epoch.daysTo( end ) * x , 30 * x );
    3. ...
    4. for ( const auto & p: sma )
    5. {
    6. QDateTime date ( QDate( p.second.year(), p.second.month(), p.second.day() ), QTime(0,0,0) );
    7. points << QPointF( epoch.daysTo( date ) * x, p.first );
    8. }
    To copy to clipboard, switch view to plain text mode 

    This fixed botht he labels, and the date alignment.
    Last edited by alexge233; 20th November 2014 at 19:29.

Similar Threads

  1. Replies: 1
    Last Post: 5th March 2014, 00:41
  2. set the range in textedit
    By sangee in forum Qt Programming
    Replies: 3
    Last Post: 21st August 2012, 07:37
  3. QDoubleVlaidator range
    By johnmauer in forum Qt Programming
    Replies: 1
    Last Post: 20th October 2010, 16:08
  4. Out of range detection
    By zgulser in forum Qt Programming
    Replies: 2
    Last Post: 6th February 2009, 09:32
  5. How to default Date-Edit Widget to system date
    By JohnToddSr in forum Qt Tools
    Replies: 4
    Last Post: 17th January 2007, 19:18

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.