Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Multiple real time plots/charts

Multiple real time plots/charts

Scheduled Pinned Locked Moved Unsolved General and Desktop
16 Posts 5 Posters 10.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    framet
    wrote on 1 Mar 2017, 12:59 last edited by
    #1

    Hey guys,

    Since QT uses a single thread for the GUI I'm experiencing, as expected, low performance when displaying 8 and more charts fed with real time data.
    I've tried the QCharts, qcustomplot, qwtPlot. All with and without openGL enabled.
    So far the best performance comes with qcustomplot.

    What would you suggest me to do, to display 10-20 real time charts without performance drop?
    Fork a single chart app and use ipc for data exchange?

    Best regards
    framet

    J 1 Reply Last reply 1 Mar 2017, 13:15
    0
    • F framet
      1 Mar 2017, 12:59

      Hey guys,

      Since QT uses a single thread for the GUI I'm experiencing, as expected, low performance when displaying 8 and more charts fed with real time data.
      I've tried the QCharts, qcustomplot, qwtPlot. All with and without openGL enabled.
      So far the best performance comes with qcustomplot.

      What would you suggest me to do, to display 10-20 real time charts without performance drop?
      Fork a single chart app and use ipc for data exchange?

      Best regards
      framet

      J Offline
      J Offline
      jsulm
      Lifetime Qt Champion
      wrote on 1 Mar 2017, 13:15 last edited by
      #2

      @framet How often do you update all these charts?

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • F Offline
        F Offline
        framet
        wrote on 1 Mar 2017, 13:24 last edited by
        #3

        @jsulm The real time data comes in over UDP at about 50 Hz in a separate thread. Then the data will be distributed with a QTimer with 20 HZ.

        1 Reply Last reply
        0
        • V Offline
          V Offline
          VRonin
          wrote on 1 Mar 2017, 13:24 last edited by
          #4

          using QChart, how do you update real time data?

          if you receive the "8 and more" data point at the same time (or at least synchronously) you can subclass QAbstractTableModel and update all the values in a signle operation and cause a single repaint of the chart itself (using a model mapper as bridge between the model and the chart)

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          F 1 Reply Last reply 1 Mar 2017, 13:29
          1
          • V VRonin
            1 Mar 2017, 13:24

            using QChart, how do you update real time data?

            if you receive the "8 and more" data point at the same time (or at least synchronously) you can subclass QAbstractTableModel and update all the values in a signle operation and cause a single repaint of the chart itself (using a model mapper as bridge between the model and the chart)

            F Offline
            F Offline
            framet
            wrote on 1 Mar 2017, 13:29 last edited by
            #5

            @VRonin I have "8 and more" charts simultaneously open and not one chart with 8 and more data points. Each chart does not have more than 3 data point series. As I understand the QAbstractTableModel is only for one single chart correct? So this probably wont safe me the majority of the performance but is still a good point for QCharts.

            V 1 Reply Last reply 1 Mar 2017, 14:22
            0
            • F framet
              1 Mar 2017, 13:29

              @VRonin I have "8 and more" charts simultaneously open and not one chart with 8 and more data points. Each chart does not have more than 3 data point series. As I understand the QAbstractTableModel is only for one single chart correct? So this probably wont safe me the majority of the performance but is still a good point for QCharts.

              V Offline
              V Offline
              VRonin
              wrote on 1 Mar 2017, 14:22 last edited by
              #6

              @framet said in Multiple real time plots/charts:

              QAbstractTableModel is only for one single chart correct?

              Nope. actually it QAbstractTableModel is perfect for when you have more than 1 chart.

              How did you try to update the charts before?

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              F 2 Replies Last reply 1 Mar 2017, 15:14
              1
              • V VRonin
                1 Mar 2017, 14:22

                @framet said in Multiple real time plots/charts:

                QAbstractTableModel is only for one single chart correct?

                Nope. actually it QAbstractTableModel is perfect for when you have more than 1 chart.

                How did you try to update the charts before?

                F Offline
                F Offline
                framet
                wrote on 1 Mar 2017, 15:14 last edited by
                #7

                @VRonin I'm currently not in the office so I cannot check to be 100% but i think i just added the to the respective QLineSeries.

                1 Reply Last reply
                0
                • V VRonin
                  1 Mar 2017, 14:22

                  @framet said in Multiple real time plots/charts:

                  QAbstractTableModel is only for one single chart correct?

                  Nope. actually it QAbstractTableModel is perfect for when you have more than 1 chart.

                  How did you try to update the charts before?

                  F Offline
                  F Offline
                  framet
                  wrote on 6 Mar 2017, 10:00 last edited by framet 3 Jun 2017, 10:31
                  #8

                  @VRonin said in Multiple real time plots/charts:

                  Nope. actually it QAbstractTableModel is perfect for when you have more than 1 chart.

                  hey @VRonin im currently working on a test with QAbstractTableModel.
                  I have a model with 100 rows and 4 columns. If new values would overflow the memory a just start at row zero again.
                  The problem what I have and I can't find any solution for it is that when I update a specific row and emit dataChanged(topLeft,bottomRight) with the updated values QChart updates/repaints the hole model which leads to flickering when you go above 10 HZ.

                  Is there a way to reimplement this QChart behavior or is there a flag to set?

                  Cheers
                  framet

                  Edit: here is an example with 2 HZ https://imgur.com/a/DYR7L

                  Edit 2: just found out with linesSeries.setUseOpenGL() decreases the flickering

                  1 Reply Last reply
                  0
                  • V Offline
                    V Offline
                    VRonin
                    wrote on 6 Mar 2017, 10:34 last edited by
                    #9

                    Wow, it's unbelievably slow... I'll prepare a minimal example and see if I get the same

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    0
                    • F Offline
                      F Offline
                      framet
                      wrote on 6 Mar 2017, 11:15 last edited by framet 3 Jun 2017, 11:22
                      #10

                      Below are two tests with TableModel (100,4)

                      Both tests run with 20 HZ
                      With OpenGL on LineSeries enabled

                      Test 1) Single chart https://imgur.com/a/Sfe20
                      Test 2) 6 charts http://imgur.com/a/Fpicu

                      With OpenGL on LineSeries disabled
                      Test 3) 6 charts http://imgur.com/a/mnFag

                      As you can see the problem of QT getting slower with more charts relaying on the same Model still exists.

                      Edit: just to clarify YES the test before was with 2 HZ and those tests here are with 20 HZ :)

                      1 Reply Last reply
                      0
                      • V Offline
                        V Offline
                        VRonin
                        wrote on 6 Mar 2017, 13:58 last edited by VRonin 3 Jun 2017, 14:05
                        #11

                        Tryed:

                        #include <QWidget>
                        #include <QTimer>
                        #include <QStandardItemModel>
                        #include <QtCharts/QChart>
                        #include <QtCharts/QChartView>
                        #include <QGridLayout>
                        #include <QtCharts/QVXYModelMapper>
                        #include <QtCharts/QLineSeries>
                        #include <cmath>
                        
                        QT_CHARTS_USE_NAMESPACE
                        
                        class TestChart : public QWidget
                        {
                            Q_OBJECT
                                Q_DISABLE_COPY(TestChart)
                        public:
                            explicit TestChart(QWidget *parent = Q_NULLPTR)
                                :QWidget(parent)
                                , maixLength(360)
                                , frequency(20.0)
                                , shift(0.0)
                                , currentCounter(0.0)
                                , pi(std::acos(-1))
                            {
                                m_model = new QStandardItemModel(this);
                                m_model->insertColumns(0, 3);
                                //m_model->insertRows(0, maixLength);
                        
                                m_updateTimer = new QTimer(this);
                                m_updateTimer->setInterval(1000.0 / frequency);
                                connect(m_updateTimer, &QTimer::timeout, this, &TestChart::addSeriesData);
                        
                                QGridLayout* mainLay = new QGridLayout(this);
                        
                                
                        
                                for (int i = 0; i < 15; ++i) {
                                    QLineSeries *sineSeries = new QLineSeries;
                                    sineSeries->setName("Sine Wave");
                                    QVXYModelMapper *mapper = new QVXYModelMapper(this);
                                    mapper->setXColumn(0);
                                    mapper->setYColumn(1);
                                    mapper->setSeries(sineSeries);
                                    mapper->setModel(m_model);
                                    sineSeries->setColor(Qt::red);
                        
                                    QLineSeries *cosineSeries = new QLineSeries;
                                    cosineSeries->setName("Cosine Wave");
                                    mapper = new QVXYModelMapper(this);
                                    mapper->setXColumn(0);
                                    mapper->setYColumn(2);
                                    mapper->setSeries(cosineSeries);
                                    mapper->setModel(m_model);
                                    cosineSeries->setColor(Qt::blue);
                        
                                    QChart *chart = new QChart();
                                    chart->legend()->hide();
                                    chart->addSeries(sineSeries);
                                    chart->addSeries(cosineSeries);
                                    chart->createDefaultAxes();
                                    chart->axisX(sineSeries)->setMin(0);
                                    chart->axisX(sineSeries)->setMax(maixLength);
                                    chart->axisX(cosineSeries)->setMin(0);
                                    chart->axisX(cosineSeries)->setMax(maixLength);
                                    chart->axisY(sineSeries)->setMin(-1);
                                    chart->axisY(sineSeries)->setMax(1);
                                    chart->axisY(cosineSeries)->setMin(-1);
                                    chart->axisY(cosineSeries)->setMax(1);
                        
                                    chart->setTitle("Simple line chart example");
                                    QChartView *chartView = new QChartView(chart);
                                    chartView->setRenderHint(QPainter::Antialiasing);
                                    mainLay->addWidget(chartView,i/5,i%5 );
                                }
                        
                                m_updateTimer->start();
                            }
                        private slots:
                            void addSeriesData()
                            {
                                if (m_model->rowCount() <= currentCounter)
                                    m_model->insertRows(m_model->rowCount(), currentCounter - m_model->rowCount() + 1);
                                m_model->setData(m_model->index(currentCounter, 0), currentCounter);
                                m_model->setData(m_model->index(currentCounter, 1), std::sin((shift+currentCounter)*pi / 180.0));
                                m_model->setData(m_model->index(currentCounter, 2), std::cos((shift + currentCounter)*pi / 180.0));
                                currentCounter += 1.0;
                                if (currentCounter >= maixLength) {
                                    currentCounter = 0.0;
                                    shift += 90;
                                }
                            }
                        
                        private:
                            const double pi;
                            double shift;
                            double currentCounter;
                            double frequency;
                            QTimer* m_updateTimer;
                            QAbstractItemModel* m_model;
                            const int maixLength;
                        };
                        

                        15 charts, you are right, 20Hz it's not great even if in release mode is better.

                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                        ~Napoleon Bonaparte

                        On a crusade to banish setIndexWidget() from the holy land of Qt

                        1 Reply Last reply
                        0
                        • F Offline
                          F Offline
                          framet
                          wrote on 6 Mar 2017, 14:09 last edited by
                          #12

                          Do you have any idea how to get 15 charts without severe performance issues?
                          Except outsourcing single Charts to seperate Qt-Applications and send data over ipc or something in this direction.

                          1 Reply Last reply
                          0
                          • V Offline
                            V Offline
                            VRonin
                            wrote on 6 Mar 2017, 14:30 last edited by VRonin 3 Jun 2017, 20:06
                            #13

                            I think yo have to decouple the data arrival frequency to the frequency you send the data to the chart.

                            In the QAbstractTableModel instead of emitting dataChanged() directly, every time a new datapoint arrives (re)start a signle shot timer that emits the signal. I'll try implementing it and update this post

                            EDIT:

                            My method increased but not to an acceptable level. I have to give up

                            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                            ~Napoleon Bonaparte

                            On a crusade to banish setIndexWidget() from the holy land of Qt

                            1 Reply Last reply
                            2
                            • F Offline
                              F Offline
                              framet
                              wrote on 7 Mar 2017, 07:41 last edited by
                              #14

                              @VRonin thank you for your time and effort!!!

                              I still have some ideas left. Will post it here when one gives an acceptable result.

                              cheers!

                              M 1 Reply Last reply 11 Jan 2020, 14:45
                              0
                              • F framet
                                7 Mar 2017, 07:41

                                @VRonin thank you for your time and effort!!!

                                I still have some ideas left. Will post it here when one gives an acceptable result.

                                cheers!

                                M Offline
                                M Offline
                                MaxBec
                                wrote on 11 Jan 2020, 14:45 last edited by
                                #15

                                @framet Hey framet. Did you find a solution?

                                1 Reply Last reply
                                0
                                • L Offline
                                  L Offline
                                  LeandroTeixeira
                                  wrote on 19 Sept 2020, 14:24 last edited by
                                  #16

                                  I am working with a application that has 12 curves and I am have the same problem, if I increase the number of curves, the performance decrease. I use qcustomplot. I need to plot 300pixels/second. Does anyone have some ideas?

                                  1 Reply Last reply
                                  0

                                  • Login

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved