aboutsummaryrefslogtreecommitdiffstats
path: root/stats/statsview.cpp
AgeCommit message (Collapse)Author
2021-02-13statistics: implement primitive "restrict to selection" featureGravatar Berthold Stoeger
Allow the user to restrict the analyzed dives based on the current selection. One button restricts to the current selection and one button resets the restriction. Thus, the user can for example select bars in the bar chart or a range in the scatter plot and perform statistics on these sets. The restriction works on top of the filter. The UI can certainly be improved, but it is a start. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-13statistics: make selection keyboard modifiers more generalGravatar Berthold Stoeger
Up to now, we passed a "shiftPressed" flag to the individual selection functions. To be more general replace by a struct with "shift" and "ctrl" flags. While doing this: 1) Move the struct into a new statsselection file for better encapsulation. 2) Change shift to control in the scatter series, since individual selection of items is usually done with control, not shift. Shift usually means "select range". Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-13statistics: implement rectangle selection in scatter plotGravatar Berthold Stoeger
Allow the user to select regions of the scatter plot using a rectangular selection. When shift is pressed, do an incremental selection. Unfortunately, the list-selection code is so slow that this becomes unusable for a large number of selected dives. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-13statistics: select multiple dives in scatter-plot by shift-clickingGravatar Berthold Stoeger
Somewhat improve selection mechanics in the scatter-plot by allowing additional selections with shift-clicking. When the dives under the mouse are already selected, then deselect them. This appears to be a rather common UI idiom in desktop applications. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-13statistics: show selected dives in scatter plotGravatar Berthold Stoeger
As a visual feedback, show the selected dives in the scatter plot. React to application-wide selection changes. Currently, the dive list is deactivated while in statistics mode, but that may change. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-13statistics: select dives from Scatter PlotGravatar Robert C. Helling
When clicking on items in a plot, select the corresponding dives. This can be useful for data validation. Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-13statistics: replot stats if dives added / removedGravatar Berthold Stoeger
It is crucial to replot the statistics when dives are added / removed, to avoid stale pointers. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-13statistics: use dive instead of count binsGravatar Berthold Stoeger
If we want to make bar charts selectable (when clicking on a bar select the dives the bar represents), then we must store the dives behind bars. Therefore, use dive-based bins instead of count based bins in bar charts and pie charts. This gave some churn because every structure where a count is stored has to be changed to store a vector of dives. Try to use move semantics where possible to avoid duplication of dive lists. On a positive note, the count_dives() function of the binners can now be removed, since it is unused. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-06statistics: don't place labels at half-integer valuesGravatar Berthold Stoeger
Placing labels at half-integer values gives horrible rendering artifacts. Therefore, always round to integer values. The easiest way to do this is right before setting the position. Introduce a helper function to round QPointF in such scenarios. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-06statistics: delete chart items when root node is deletedGravatar Berthold Stoeger
When reparenting the statistics widget, QtQuick deletes the rootNode and all the child nodes. It is unclear whether this is a bug or intended behavior. In any case, it means that the pointers to QSG nodes in the chart items become stale. To avoid this, delete all chart items in the root node's destructor, before QtQuick can do anything. It is unclear from which context this is called (render or UI) and whether this is even valid. In some tests, it seemed to work. The difficulty is that all the stale pointers to chart items have to be deleted as well. All in all, the QSG memory management is a big nuisance and very brittle. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-21statistics: do resizing in UI thread, not render threadGravatar Berthold Stoeger
The updatePaintNode() function, which is run on the render thread detected a geometry change and initiated recalculation of the chart layout. This means that plotAreaChanged() was called in two different thread contexts, which is questionable. Instead, hook into the geometryChanged() function and recalculate the chart items there. This fixes a rendering bug, because the old code would first delete unneeded items and then rerender the chart. Thus, old grid and tick items were still visible. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics/legend: fix dragging legend on touch screenGravatar Dirk Hohndel
While this didn't appear to be needed when dragging the legend with a mouse, on a touch screen for some reason the drag ended after 30 pixels either way horizontally (but no apparent limit vertically). By setting this flag to true, drags on a tablet appear to work as expected. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-20statistics: move colors to statscolors.hGravatar Berthold Stoeger
Most colors were already collected there, but a few were dispersed throughout the source files. For future themeability, move the remaining colors to this common place. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: make confidence area and regression line opt-inGravatar Berthold Stoeger
This is not perfect - the polygon of the confidence area is calculated even if it is not shown. Oh well. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: don't replot chart when changing featuresGravatar Berthold Stoeger
Up to now, when the user changed the visibility of chart features (legend, quartiles, labels, etc.) the whole chart was replot. Instead, only change the visibility status of these items. After all, this modularity is one of the things the conversion to QSG was all about. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: refactor QSG memory managementGravatar Berthold Stoeger
The code was wrong, because it deleted the ChartItems in the main UI thread, not the render thread. This would delete the QSG nodes in the UI thread and then crash on mobile. Therefore refactor this part of the code by adding the items to be deleted to a list that will be deleted by the render thread. As a drop in replacement of std::unique_ptr, implement a silly ChartItemPtr class, which auto-initializes to null. This turns the deterministic and easily controlled memory management into a steaming pile of insanity. Obviously, this can be made much more elegant, but this has to do for now. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: remove QSceneGraphGravatar Berthold Stoeger
All items are now painted with QSG. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: replace chart title by QSG nodeGravatar Berthold Stoeger
This one is trivial, since everything is there already: Replace the QGraphicsSimpleTextItem with a ChartTextItem. Only few functions have to be renamed. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: remove QGraphicsView from StatSeriesGravatar Berthold Stoeger
All series are converted to QSG. Thus, the pointer to the QGraphicsView can be removed from the common base class. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: replace PieSeries by QSG nodesGravatar Berthold Stoeger
Since there are no disk-segment QSG primitives (one could draw a triangle fan, but that doesn't seem optimal), this draws into a pixmap and blits that as a QSG node. Since this is the only series without axis, it needs a function that returns the size of the plot area. This didn't exist, so add it. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: render regression item using QSGNodeGravatar Berthold Stoeger
Render the confidence area and the regression line into a pixmap and show that using a QSGNode. It is unclear whether it is preferred to do it this way or to triangulate the confidence area into triangles to be drawn by the shader. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: keep track of dirty items in double-linked listGravatar Berthold Stoeger
So far the items to be recalculated in the drawing thread had a "dirty" flag and were kept in one array par z-level. Once the series are implemented in terms of QSGNodes, there may lots of these items. To make this more efficient when only one or two of these items change (e.g. highlighting due to mouseover), keep the dirty items in a linked list. Of course, this makes the draw first version of the chart less efficient. There are more fancy ways of implementing the double-linked list, but the few ns gained in the render thread are hardly worth it. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: turn axes into QSGNodeGravatar Berthold Stoeger
Render the labels and the title into a pixmap and render the ticks and the base line using individual QSGNodes. Attempting to render the ticks likewise into the pixmap gave horrible results, because (quite obviously) rendering with QPainter and the QSG shader gives non-matching ticks and grid lines. The memory management had to be changed a bit: The ChartItems were collected in the root QSGNode. However, the axes are added before the first plotting, so this node might not exist. Therefore, store the axes in the StatsView object. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: turn ChartGrid into QSGNodesGravatar Berthold Stoeger
Turn the background grid into QSGNodes. Each grid line is represented by a QSG line item. An alternative would be drawing the grid into a QImage and blasting that onto the screen. It is unclear which one is preferred. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: draw background using a QSGRectangle nodeGravatar Berthold Stoeger
Currently, the background was drawn as solid color onto the chart-scene. This is of course incompatible with doing the grid as QSGNodes. Therefore, make the scene image transparent and use a QSGRectangle as background color. We could also simply omit the background and show the widget's background. However, that would mean setting the background color in two seperate code paths (desktop and mobile). I found no way of directly setting the background of the QQuickItem. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: convert HistogramMarkers to QSGNodesGravatar Berthold Stoeger
This is in analogy to the quartile markers. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: convert QuartileMarkers to QSGNodesGravatar Berthold Stoeger
Slowly converting the QGraphicsScene items to QSGNodes to avoid full replot of the scene. This adds a new abstraction for line-nodes. Since the render() function here is fundamentally different from the pixmap-nodes we had so far, this has to be made virtual. Also, move the quartile markers to their own source file, since the StatsView source file is quite huge already. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: remember position of legend when resizingGravatar Berthold Stoeger
The position of the legend was reset when resizing. This was OK as long as the legend wasn't movable. To avoid resetting the position, store the center position of the legend relatively to the size of the canvas. On resize restore the center to the same relative size. To avoid code duplication, move the sanitizing of the coordinates from the StatsView to the Legend. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: add notion of Z-value to chart itemsGravatar Berthold Stoeger
The chart items were drawn in order of creation. To control this, add a notion of Z-value. In contrast to QGraphicsScene, make this a small integer value. To controll order of drawing, a plain QSGNode is created for every possible Z-Value and items are added to these nodes. Thus, items are rendered by Z-value and if the Z-value is equal by order of creation. Likewise split the list of chart-items into Z-values, so that items can be quickly unregistered: The items that will be removed individually will usuall be part of Z-levels with only few items (e.g. legend, infobox). Z-levels with many items (notably the series) will always be fully rebuilt. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: turn infobox into a QSGNodeGravatar Berthold Stoeger
A small step in converting from QGraphicsScene to QQuickItem. This is the second item to be converted (after the legend) and for now items are drawn in order of creation, which means that the infobox is on top of the legend. This will have to be made deterministic in follow-up commits. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: pass view to seriesGravatar Berthold Stoeger
The series were passed a pointer to the QGraphicsScene to add their item. In the future these items will be replaced by QSGNodes. To add these, the series need a reference to the StatsView. Therefore pass it in the constructor. Once everything is replaces by QSGNodes, remove the QGraphicsScene member. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: implement moving of legendGravatar Berthold Stoeger
Catch mouse move events and move the legend accordingly. Currently, this is the only item that can be dragged and therefore there is no need of doing some kind of fancy interface. Simply keep a pointer to the legend if it is dragged. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: draw legend as a QSGNodeGravatar Berthold Stoeger
In order not to waste CPU by constantly rerendering the chart, we must use these weird OpenGL QSGNode things. The interface is appallingly low-level and unfriendly. As a first test, try to convert the legend. Create a wrapper class that represents a rectangular item with a texture and that will certainly need some (lots of) optimization. Make sure that all low-level QSG-objects are only accessed in the rendering thread. This means that the wrapper has to maintain a notion of "dirtiness" of the state. I.e. which part of the QSG-objects have to be modified. From the low-level wrapper derive a class that draws a rounded rectangle for every resize. The child class of that must then paint on the rectangle after every resize. That looks all not very fortunate, but it displays a legend and will make it possible to move the legend without and drawing operations, only shifting around an OpenGL surface. The render thread goes through all chart-items and rerenders them if dirty. Currently, on deletion of these items, this list is not reset. I.e. currently it is not supported to remove individual items. Only the full scene can be cleared! Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-14Add back central line for linear regressionGravatar Robert C. Helling
Signed-off-by: Robert C. Helling <helling@atdotde.de>
2021-01-14Plot proper confidence regionsGravatar Robert C. Helling
I was coninced that that rather than doing an order of magnitude estimate of the confidence region it's better to have the correct concave shapes that indicate the 95% confidence level for the regression line. It also turned out that the previous expression was missing a factor of 1/sqrt(n). Signed-off-by: Robert C. Helling <helling@atdotde.de>
2021-01-14Indicate goodness of fit of regression lineGravatar Robert C. Helling
The goodness of fit of a regression line is the percentage of the variance of the y values that is explained by the dependence on the x values. Set the alpha value of the regression line to this goodness of fit. Further, set the width of the regression line to a standard deviation of the values from the regression line valies. Signed-off-by: Robert C. Helling <helling@atdotde.de>
2021-01-11statistics: consider overhang of horizontal axesGravatar Berthold Stoeger
The old code didn't consider that labels can peak out of horizontal axes if labels are under ticks. This commit takes this into account. However, it must be noted that this is only heuristics: Before setting the size of the axes, the actual minimum and maximum label are not known, because we round to "nice" numbers. But the size of the axis can only be set after knowing the overhang, leading to a circular dependency. Therefore, the code currently simply uses the minimum and maximum value of the data, hoping that the "nice" values will not format to something significantly larger. We could do a multi-pass scheme, but let's not for now. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10statistics: convert chart to QQuickItemGravatar Berthold Stoeger
It turns out that the wrong base class was used for the chart. QQuickWidget can only be used on desktop, not in a mobile UI. Therefore, turn this into a QQuickItem and move the container QQuickWidget into desktop-only code. Currently, this code is insane: The chart is rendered onto a QGraphicsScene (as it was before), which is then rendered into a QImage, which is transformed into a QSGTexture, which is then projected onto the device. This is performed on every mouse move event, since these events in general change the position of the info-box. The plan is to slowly convert elements such as the info-box into QQuickItems. Browsing the QtQuick documentation, this will not be much fun. Also note that the rendering currently tears, flickers and has antialiasing artifacts, most likely owing to integer (QImage) to floating point (QGraphicsScene, QQuickItem) conversion problems. The data flow is QGraphicsScene (float) -> QImage (int) -> QQuickItem (float). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-06statistics: fix chart features: regression line and median/meanGravatar Berthold Stoeger
The coordinates of these were calculated when creating the feature. This is wrong, because the min/max values of the axes can change on resize to get "nice" number. Therefore, recalculate after resizing. This means that the general "LineMarker" class has to be split into two classes, one for regression lines and one for median/mean markers. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-06statistics: paint custom gridGravatar Berthold Stoeger
With removal of QtCharts' axes, the grid was lost. Readd it. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-06statistics: draw title of axesGravatar Berthold Stoeger
Easy enough to implement, but one weirdness: To get the height of the rotated text, one has to access the width() member of the boundingRect. I'm not sure if that makes sense, but so be it. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-06statistics: replace QtCharts' axesGravatar Berthold Stoeger
Replace by custom implementation, with the ultimate goal to remove the QtCharts module. This doesn't yet display axis titles or a grid. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-06statistics: render titleGravatar Berthold Stoeger
Since we want to get rid of QtCharts, we have to render our own title. Simply keep around a QGraphicsSimpleTextItem and put in the center of the chart. Define the borders to the scene as constants. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-06statistics: save chart in axis classGravatar Berthold Stoeger
The chart was passed as argument to the function recalculating the axis labels. Instead, pass the chart in the constructor of the axes and save it. This gains us flexibility for the future: There will be more functions that need to access the chart (e.g. resizing of the axes). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-04stats: fix line segment intersection mathGravatar Dirk Hohndel
Linear algebra class was a while ago, but somehow this does look more logical to me. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-03statistics: don't crash if the QCharts QML modules aren't foundGravatar Dirk Hohndel
We don't really give a user visible error message which is kind of a problem, but at least we don't crash anymore. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-03statistics: clip regression lineGravatar Berthold Stoeger
A steep regression line would shoot out of the chart. Therefore, clip to the y = minY and y = maxY lines. QtGraphicsScene has its own clipping routines, but they are very general, so let's do this trivial case by hand. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-03statistics: add parentheses around percentage in horizontal barsGravatar Berthold Stoeger
For better visual guidance, format labels as "count (percentage)" in horizontal bar charts. In vertical bar charts two lines are used anyway. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-03statistics: reverse chart selection logicGravatar Berthold Stoeger
The old ways was to select the chart first, then depending on the chart choose the binning. Willem says that it should work the other way round: select the binning (or operation) and make the charts depend on that. I'm not arguing one way or the other, just note that the new way is much more tricky, because it is easy to get unsupported combinations. For example, there is no chart where the first variable is unbinned, but the second axis is binned or has an operation. This makes things distinctly more tricky and this code still needs a thorough audit. Since this is all more tricky, implement a "invalid" chart state. Ideally that should be never shown to the user, but let's try to be defensive. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-02statistics: implement StatsViewGravatar Berthold Stoeger
The StatsView shows the chart described by the StatsState structure. It is based on a QML ChartView. This should make it possible to easily port to mobile. It does not include any of the UI around the chart, viz. the variable and chart selection, etc. The code checking for the statistical significance of the regression line was written by Willem. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at> Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>