added violin plots and an example demonstrating their usage/generation from random data
@ -86,6 +86,7 @@ addSimpleTest(datastore_statistics_2d)
|
||||
addSimpleTest(datastore_regression)
|
||||
addSimpleTest(datastore_groupedstat)
|
||||
addSimpleTest(contourplot)
|
||||
addSimpleTest(violinplot)
|
||||
#addSimpleTest(rgbimageplot_opencv)
|
||||
#addSimpleTest(imageplot_opencv)
|
||||
|
||||
|
@ -62,6 +62,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
||||
<tr><td> \image html jkqtplotter_simpletest_boxplot_small.png
|
||||
<td> \subpage JKQTPlotterBoxplotsGraphs
|
||||
<td> `JKQTPBoxplotVerticalGraph`, `JKQTPBoxplotHorizontalGraph`, ...
|
||||
<tr><td> \image html jkqtplotter_simpletest_violinplot_small.png
|
||||
<td> \subpage JKQTPlotterViolinplotGraphs
|
||||
<td> `JKQTPViolinplotVerticalElement`, `JKQTPViolinplotHorizontalElement`, ...
|
||||
</table>
|
||||
|
||||
|
||||
|
@ -377,6 +377,9 @@ This group assembles graphs that show their data with symbols and optionally wit
|
||||
<tr>
|
||||
<td>\image html jkqtplotter_simpletest_boxplot_small.png
|
||||
<td> JKQTPBoxplotVerticalGraph, JKQTPBoxplotHorizontalGraph
|
||||
<tr>
|
||||
<td>\image html JKQTPViolinplotVerticalElement.png
|
||||
<td> JKQTPViolinplotVerticalElement, JKQTPViolinplotHorizontalElement
|
||||
</table>
|
||||
|
||||
\see \ref jkqtptools_math_statistics_adaptors for shortcuts to calculate statistical properties of data and then adding a plot with the results.
|
||||
@ -418,6 +421,9 @@ This group assembles graphs that show their data with symbols and optionally wit
|
||||
<tr>
|
||||
<td>\image html geo_boxplot_small.png
|
||||
<td> JKQTPBoxplotVerticalElement, JKQTPBoxplotHorizontalElement
|
||||
<tr>
|
||||
<td>\image html JKQTPViolinplotVerticalElement.png
|
||||
<td> JKQTPViolinplotVerticalElement, JKQTPViolinplotHorizontalElement
|
||||
</table>
|
||||
|
||||
Examples:
|
||||
|
@ -26,7 +26,7 @@ Changes, compared to \ref page_whatsnew_V2018_08 "v2018.08" include:
|
||||
<li> changed: using static const variables instead of <code>#define</code> for fixed default values (e.g. JKQTPImageTools::LUTSIZE, JKQTPImageTools::PALETTE_ICON_WIDTH, JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, JKQTMathText::ABS_MIN_LINEWIDTH ...)</li>
|
||||
<li> Updates to JKQTPlotter:
|
||||
<ul>
|
||||
<li> new: added JKQTPSingleColumnSymbolsGraph for single-column data, e.g. drawn as (random) scatter or bee-swar plots </li>
|
||||
<li> new: added JKQTPSingleColumnSymbolsGraph for single-column data, e.g. drawn as (random) scatter or bee-swarm or rug plots </li>
|
||||
<li> new: stacked barcharts with JKQTPBarVerticalStackableGraph, JKQTPBarHorizontalStackableGraph </li>
|
||||
<li> new: use/support of C++11 features (e.g. \c std::function<> and lambda functions in JKQTPXFunctionLineGraph / JKQTPYFunctionLineGraph )</li>
|
||||
<li> new: \ref jkqtpopencvinterface "optional OpenCV interface" </li>
|
||||
@ -46,6 +46,7 @@ Changes, compared to \ref page_whatsnew_V2018_08 "v2018.08" include:
|
||||
<li> new: several new plot symbols, see: JKQTPGraphSymbols </li>
|
||||
<li> new: Statistics library with functions to calculate histograms, regression, kernel density estimates, ... see: \ref jkqtptools_math_statistics </li>
|
||||
<li> new: iterator interface and improved documentation for JKQTPDatastore </li>
|
||||
<li> new: violin plots (see \ref JKQTPlotterViolinplotGraphs ) </li>
|
||||
<li> changed: removed old selection-code and replaced by general highlighting feature </li>
|
||||
<li> changed: JKQTPStepHorizontalGraph has been renamed to JKQTPSpecialLineHorizontalGraph (vertical variants also) and have gained additional features (baseline for filling and drawing of symbols) </li>
|
||||
<li> changed: filled curve graphs (e.g. JKQTPSpecialLineHorizontalGraph) are now merely a specializedly initialized JKQTPSpecialLineHorizontalGraph </li>
|
||||
|
BIN
doc/images/JKQTPGraphViolinplot_BoxViolin.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
doc/images/JKQTPGraphViolinplot_HBoxViolin.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
doc/images/JKQTPGraphViolinplot_HSmoothViolin.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
doc/images/JKQTPGraphViolinplot_HStepViolin.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
doc/images/JKQTPGraphViolinplot_SmoothViolin.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
doc/images/JKQTPGraphViolinplot_StepViolin.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
doc/images/JKQTPGraphViolinplot_ViolinBoth.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
doc/images/JKQTPGraphViolinplot_ViolinBottom.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
doc/images/JKQTPGraphViolinplot_ViolinHBoth.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
doc/images/JKQTPGraphViolinplot_ViolinLeft.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
doc/images/JKQTPGraphViolinplot_ViolinRight.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
doc/images/JKQTPGraphViolinplot_ViolinTop.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
doc/images/JKQTPViolinplotHorizontalElement_elements.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
doc/images/JKQTPViolinplotVerticalElement.png
Normal file
After Width: | Height: | Size: 16 KiB |
@ -24,6 +24,7 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parsedfunctionplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_parsedfunctionplot) | [Plotting Parsed Mathematical Functions as Line Graphs](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_parsedfunctionplot) | `JKQTPXParsedFunctionLineGraph` <br> plotting functions with the internal math equation parser/evaluator |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_geometric_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_geometric) | [Plotting Geometric Objects](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_geometric) | |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_boxplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_boxplot) | [Plotting Box Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_boxplot) | `JKQTPBoxplotVerticalGraph`, `JKQTPBoxplotHorizontalGraph` |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_violinplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_violinplot) | [Plotting Violin Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_violinplot) | `JKQTPViolinplotVerticalElement`, `JKQTPViolinplotHorizontalElement` |
|
||||
|
||||
## Styling the Plot, Keys, Axes, ...
|
||||
|
||||
|
111
examples/simpletest_violinplot/README.md
Normal file
@ -0,0 +1,111 @@
|
||||
# Example (JKQTPlotter): Violin Plots {#JKQTPlotterViolinplotGraphs}
|
||||
|
||||
[TOC]
|
||||
[JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore"
|
||||
[statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library"
|
||||
[JKQTPlotterBoxplotStyling]: @ref JKQTPlotterBoxplotStyling "Styling different aspects of boxplots"
|
||||
|
||||
This project (see [`simpletest_violinplot`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_violinplot) demonstrates how to use JKQTPlotter to draw <a href="https://en.wikipedia.org/wiki/Violin_plot">violin plots</a> using the classes `JKQTPViolinplotVerticalElement` and `JKQTPViolinplotHorizontalElement`. Violin plots can be thought of as an extension to box plots, as they are also used to represent the distribution of a random variable, but contain more info than the "simple" 5-number statistics used for boxplots: Violin Plots show an estimate of the desnsity distribution of the random vriable, e.g. calculated as a kernel density estimate, or as a simple histogram. The Plotting classes themselves do not calculate these estimates, but only draw them into the plot. The density estimates are calculated by functions from the [statisticslibrary].
|
||||
|
||||
The source code of the main application is (see [`jkqtplotter_simpletest_violinplot.cpp`](jkqtplotter_simpletest_violinplot.cpp).
|
||||
|
||||
# Generating a test Dataset
|
||||
|
||||
First we generate some random numbers from a bimodal distribution (and as a by-product also from two single-distributions that form the bimodal):
|
||||
```.cpp
|
||||
size_t randomdatacol1=datastore1->addColumn("random data N(1,1)+N(6,2)");
|
||||
size_t randomdatacol2=datastore1->addColumn("random data N(1,1)");
|
||||
size_t randomdatacol3=datastore1->addColumn("random data N(6,2)");
|
||||
std::random_device rd; // random number generators:
|
||||
std::mt19937 gen{rd()};
|
||||
std::uniform_int_distribution<> ddecide(0,1);
|
||||
std::normal_distribution<> d1{1,1};
|
||||
std::normal_distribution<> d2{6,2};
|
||||
for (size_t i=0; i<50; i++) {
|
||||
double v=0;
|
||||
if (i%2==0) {
|
||||
v=d1(gen);
|
||||
datastore1->appendToColumn(randomdatacol2, v);
|
||||
} else {
|
||||
v=d2(gen);
|
||||
datastore1->appendToColumn(randomdatacol3, v);
|
||||
}
|
||||
datastore1->appendToColumn(randomdatacol1, v);
|
||||
}
|
||||
```
|
||||
|
||||
# Visualizing data as a Rug Plot
|
||||
|
||||
Samples from the bimodal (built from two gaussian distributions `d1` and `d2`) are collected in `randomdatacol1`, whereas `randomdatacol2` and `randomdatacol3` collect those numbers that were drawn from `d1` or `d2` respectively.
|
||||
|
||||
Such data can be visualized by `JKQTPSingleColumnSymbolsGraph`, here using a rug plot (using `gData1->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::RugPlot);` ... but also e.g. a ee swarm plot would be possible):
|
||||
|
||||
```.cpp
|
||||
JKQTPSingleColumnSymbolsGraph* gData1;
|
||||
plot->addGraph(gData1=new JKQTPSingleColumnSymbolsGraph(plot));
|
||||
gData1->setPosition(0);
|
||||
gData1->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::RugPlot);
|
||||
gData1->setDataColumn(randomdatacol1);
|
||||
gData1->setDataDirection(JKQTPSingleColumnSymbolsGraph::DataDirection::Y);
|
||||
```
|
||||
|
||||
# Drawing the (vertical) Violin Plot
|
||||
|
||||
Now we need to calculate the kernel density estimate from the data in `randomdatacol1` and store the result in two new columns `cViol1Cat` and `cViol1Freq`:
|
||||
|
||||
```.cpp
|
||||
size_t cViol1Cat=datastore1->addColumn("violin 1, cat");
|
||||
size_t cViol1Freq=datastore1->addColumn("violin 1, KDE");
|
||||
jkqtpstatKDE1DAutoranged(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1),
|
||||
datastore1->backInserter(cViol1Cat), datastore1->backInserter(cViol1Freq),
|
||||
51, jkqtpstatKernel1DEpanechnikov,
|
||||
jkqtpstatEstimateKDEBandwidth(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
```
|
||||
|
||||
Finally we can add a `JKQTPViolinplotVerticalElement` to the plot and provide it with the kernel density estimate from above and with some additional statistical properties (minimum, maximum, average and median) of the dataset:
|
||||
|
||||
```.cpp
|
||||
JKQTPViolinplotVerticalElement* gViol1;
|
||||
plot->addGraph(gViol1=new JKQTPViolinplotVerticalElement(plot));
|
||||
gViol1->setPos(2);
|
||||
gViol1->setMin(jkqtpstatMinimum(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
gViol1->setMax(jkqtpstatMaximum(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
gViol1->setMean(jkqtpstatAverage(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
gViol1->setMedian(jkqtpstatMedian(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
gViol1->setViolinPositionColumn(cViol1Cat);
|
||||
gViol1->setViolinFrequencyColumn(cViol1Freq);
|
||||
gViol1->setColor(gData1->getSymbolColor());
|
||||
gViol1->setViolinStyle(JKQTPGraphViolinplotStyleMixin::SmoothViolin);
|
||||
gViol1->setViolinPositionMode(JKQTPGraphViolinplotStyleMixin::ViolinBoth);
|
||||
```
|
||||
|
||||
The center of the `gData1` was set to 0 and the center of the violin plot is set to `2`. With `JKQTPViolinplotVerticalElement::setViolinStyle()` you can choose the style of the violin plot and with `JKQTPViolinplotVerticalElement::setViolinPositionMode()` you can select whether the density estimate should be displayed on the left, the right or on both sides of the center-line.
|
||||
|
||||
The result looks like this, if we use the same method as above to calculate also the violin plots for `randomdatacol2` and `randomdatacol3`:
|
||||
|
||||
![jkqtplotter_simpletest_violinplot_vert](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_violinplot_vert.png)
|
||||
|
||||
Note that we set different styles for the three plots with:
|
||||
```.cpp
|
||||
gViol2->setViolinStyle(JKQTPGraphViolinplotStyleMixin::StepViolin); // green plot
|
||||
gViol3->setViolinStyle(JKQTPGraphViolinplotStyleMixin::BoxViolin); // blue plot
|
||||
```
|
||||
|
||||
Also for the green and blue plot, we did not calculate a kernel density estimate, but rather a simple histogram:
|
||||
```.cpp
|
||||
size_t cViol2Cat=datastore1->addColumn("violin 2, cat");
|
||||
size_t cViol2Freq=datastore1->addColumn("violin 2, Histogram");
|
||||
jkqtpstatHistogram1DAutoranged(datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2),
|
||||
datastore1->backInserter(cViol2Cat), datastore1->backInserter(cViol2Freq),
|
||||
21, true, false, JKQTPStatHistogramBinXMode::XIsMid);
|
||||
```
|
||||
|
||||
# Drawing a horizontal Violin Plot
|
||||
|
||||
Finally note that if you use `JKQTPViolinplotHorizontalElement` instead of the `JKQTPViolinplotVerticalElement` used above, you can also draw horizontal violin plots:
|
||||
|
||||
![jkqtplotter_simpletest_violinplot_hor](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_violinplot_hor.png)
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,159 @@
|
||||
/** \example jkqtplotter_simpletest_violinplot->cpp
|
||||
* Shows how to draw Violin-Plot with JKQTPlotter
|
||||
*
|
||||
* \ref JKQTPlotterViolinplotGraphs
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
#include "jkqtplotter/jkqtpgraphsviolinplot.h"
|
||||
#include "jkqtplotter/jkqtpgraphssinglecolumnsymbols.h"
|
||||
#include "jkqtplotter/jkqtpgraphsstatisticsadaptors.h"
|
||||
#include "jkqtcommon/jkqtpstatisticstools.h"
|
||||
#include <random>
|
||||
#include <cmath>
|
||||
|
||||
template <class TGraph, JKQTPSingleColumnSymbolsGraph::DataDirection DataOrientation>
|
||||
void showPlot() {
|
||||
|
||||
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
|
||||
JKQTPlotter* plot=new JKQTPlotter();
|
||||
plot->getPlotter()->setUseAntiAliasingForGraphs(true); // nicer (but slower) plotting
|
||||
plot->getPlotter()->setUseAntiAliasingForSystem(true); // nicer (but slower) plotting
|
||||
plot->getPlotter()->setUseAntiAliasingForText(true); // nicer (but slower) text rendering
|
||||
JKQTPDatastore* datastore1=plot->getDatastore();
|
||||
|
||||
|
||||
// 2. Now we create random data drawn from a bimodal distribution,
|
||||
// also we add each single distribution as a separate column
|
||||
size_t randomdatacol1=datastore1->addColumn("random data N(1,1)+N(6,2)");
|
||||
size_t randomdatacol2=datastore1->addColumn("random data N(1,1)");
|
||||
size_t randomdatacol3=datastore1->addColumn("random data N(6,2)");
|
||||
std::random_device rd; // random number generators:
|
||||
std::mt19937 gen{rd()};
|
||||
std::uniform_int_distribution<> ddecide(0,1);
|
||||
std::normal_distribution<> d1{1,1};
|
||||
std::normal_distribution<> d2{6,2};
|
||||
for (size_t i=0; i<50; i++) {
|
||||
double v=0;
|
||||
if (i%2==0) {
|
||||
v=d1(gen);
|
||||
datastore1->appendToColumn(randomdatacol2, v);
|
||||
} else {
|
||||
v=d2(gen);
|
||||
datastore1->appendToColumn(randomdatacol3, v);
|
||||
}
|
||||
datastore1->appendToColumn(randomdatacol1, v);
|
||||
}
|
||||
const QString d1_latex="$\\mathcal{N}("+jkqtp_floattolatexqstr(d1.mean(), 1)+","+jkqtp_floattolatexqstr(d1.stddev(), 1)+")+\\mathcal{N}("+jkqtp_floattolatexqstr(d2.mean(), 1)+","+jkqtp_floattolatexqstr(d2.stddev(), 1)+")$";
|
||||
const QString d2_latex="$\\mathcal{N}("+jkqtp_floattolatexqstr(d1.mean(), 1)+","+jkqtp_floattolatexqstr(d1.stddev(), 1)+")$";
|
||||
const QString d3_latex="$\\mathcal{N}("+jkqtp_floattolatexqstr(d2.mean(), 1)+","+jkqtp_floattolatexqstr(d2.stddev(), 1)+")$";
|
||||
|
||||
|
||||
// 3. we visualize the data as scatter plots
|
||||
JKQTPSingleColumnSymbolsGraph* gData1;
|
||||
plot->addGraph(gData1=new JKQTPSingleColumnSymbolsGraph(plot));
|
||||
gData1->setPosition(0);
|
||||
gData1->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::RugPlot);
|
||||
gData1->setDataColumn(randomdatacol1);
|
||||
gData1->setTitle(d3_latex);
|
||||
gData1->setDataDirection(DataOrientation);
|
||||
|
||||
JKQTPSingleColumnSymbolsGraph* gData2;
|
||||
plot->addGraph(gData2=new JKQTPSingleColumnSymbolsGraph(plot));
|
||||
gData2->setPosition(5);
|
||||
gData2->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::RugPlot);
|
||||
gData2->setDataColumn(randomdatacol2);
|
||||
gData2->setTitle(d3_latex);
|
||||
gData2->setDataDirection(DataOrientation);
|
||||
|
||||
JKQTPSingleColumnSymbolsGraph* gData3;
|
||||
plot->addGraph(gData3=new JKQTPSingleColumnSymbolsGraph(plot));
|
||||
gData3->setPosition(10);
|
||||
gData3->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::RugPlot);
|
||||
gData3->setDataColumn(randomdatacol3);
|
||||
gData3->setTitle(d3_latex);
|
||||
gData3->setDataDirection(DataOrientation);
|
||||
|
||||
auto pos=JKQTPGraphViolinplotStyleMixin::ViolinBoth;
|
||||
|
||||
// 4. In order to draw violin plots we first need to calculate the
|
||||
// kernel density estimate (KDE) for the violin
|
||||
size_t cViol1Cat=datastore1->addColumn("violin 1, cat");
|
||||
size_t cViol1Freq=datastore1->addColumn("violin 1, KDE");
|
||||
jkqtpstatKDE1DAutoranged(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1),
|
||||
datastore1->backInserter(cViol1Cat), datastore1->backInserter(cViol1Freq),
|
||||
51, jkqtpstatKernel1DEpanechnikov,
|
||||
jkqtpstatEstimateKDEBandwidth(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
TGraph* gViol1;
|
||||
plot->addGraph(gViol1=new TGraph(plot));
|
||||
gViol1->setPos(2);
|
||||
gViol1->setMin(jkqtpstatMinimum(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
gViol1->setMax(jkqtpstatMaximum(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
gViol1->setMean(jkqtpstatAverage(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
gViol1->setMedian(jkqtpstatMedian(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)));
|
||||
gViol1->setViolinPositionColumn(cViol1Cat);
|
||||
gViol1->setViolinFrequencyColumn(cViol1Freq);
|
||||
gViol1->setColor(gData1->getSymbolColor());
|
||||
gViol1->setViolinStyle(JKQTPGraphViolinplotStyleMixin::SmoothViolin);
|
||||
gViol1->setViolinPositionMode(pos);
|
||||
gViol1->setTitle("violin plot "+d1_latex);
|
||||
|
||||
size_t cViol2Cat=datastore1->addColumn("violin 2, cat");
|
||||
size_t cViol2Freq=datastore1->addColumn("violin 2, Histogram");
|
||||
jkqtpstatHistogram1DAutoranged(datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2),
|
||||
datastore1->backInserter(cViol2Cat), datastore1->backInserter(cViol2Freq),
|
||||
21, true, false, JKQTPStatHistogramBinXMode::XIsMid);
|
||||
TGraph* gViol2;
|
||||
plot->addGraph(gViol2=new TGraph(plot));
|
||||
gViol2->setPos(7);
|
||||
gViol2->setMin(jkqtpstatMinimum(datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2)));
|
||||
gViol2->setMax(jkqtpstatMaximum(datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2)));
|
||||
gViol2->setMean(jkqtpstatAverage(datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2)));
|
||||
gViol2->setMedian(jkqtpstatMedian(datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2)));
|
||||
gViol2->setViolinPositionColumn(cViol2Cat);
|
||||
gViol2->setViolinFrequencyColumn(cViol2Freq);
|
||||
gViol2->setColor(gData2->getSymbolColor());
|
||||
gViol2->setViolinStyle(JKQTPGraphViolinplotStyleMixin::StepViolin);
|
||||
gViol2->setViolinPositionMode(pos);
|
||||
gViol2->setTitle("step violin plot "+d2_latex);
|
||||
|
||||
size_t cViol3Cat=datastore1->addColumn("violin 3, cat");
|
||||
size_t cViol3Freq=datastore1->addColumn("violin 3, Histogram");
|
||||
jkqtpstatHistogram1DAutoranged(datastore1->begin(randomdatacol3), datastore1->end(randomdatacol3),
|
||||
datastore1->backInserter(cViol3Cat), datastore1->backInserter(cViol3Freq),
|
||||
10, true, false, JKQTPStatHistogramBinXMode::XIsMid);
|
||||
TGraph* gViol3;
|
||||
plot->addGraph(gViol3=new TGraph(plot));
|
||||
gViol3->setPos(12);
|
||||
gViol3->setMin(jkqtpstatMinimum(datastore1->begin(randomdatacol3), datastore1->end(randomdatacol3)));
|
||||
gViol3->setMax(jkqtpstatMaximum(datastore1->begin(randomdatacol3), datastore1->end(randomdatacol3)));
|
||||
gViol3->setMean(jkqtpstatAverage(datastore1->begin(randomdatacol3), datastore1->end(randomdatacol3)));
|
||||
gViol3->setMedian(jkqtpstatMedian(datastore1->begin(randomdatacol3), datastore1->end(randomdatacol3)));
|
||||
gViol3->setViolinPositionColumn(cViol3Cat);
|
||||
gViol3->setViolinFrequencyColumn(cViol3Freq);
|
||||
gViol3->setColor(gData3->getSymbolColor());
|
||||
gViol3->setViolinStyle(JKQTPGraphViolinplotStyleMixin::BoxViolin);
|
||||
gViol3->setViolinPositionMode(pos);
|
||||
gViol3->setTitle("box violin plot "+d3_latex);
|
||||
|
||||
// autoscale and style the plot
|
||||
plot->zoomToFit();
|
||||
plot->getPlotter()->setKeyPosition(JKQTPKeyInsideBottomRight);
|
||||
plot->setShowZeroAxes(false);
|
||||
plot->getPlotter()->setGridColor(QColor(230,230,230));
|
||||
|
||||
// show plotter and make it a decent size
|
||||
plot->show();
|
||||
plot->resize(800,600);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
showPlot<JKQTPViolinplotHorizontalElement,JKQTPSingleColumnSymbolsGraph::DataDirection::X>();
|
||||
showPlot<JKQTPViolinplotVerticalElement,JKQTPSingleColumnSymbolsGraph::DataDirection::Y>();
|
||||
|
||||
return app.exec();
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
# source code for this simple demo
|
||||
SOURCES = jkqtplotter_simpletest_violinplot.cpp
|
||||
|
||||
# configure Qt
|
||||
CONFIG += link_prl qt
|
||||
QT += core gui xml svg
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
|
||||
|
||||
# output executable name
|
||||
TARGET = jkqtplotter_simpletest_violinplot
|
||||
|
||||
# include JKQTPlotter source code
|
||||
DEPENDPATH += ../../lib ../../staticlib/jkqtplotterlib
|
||||
INCLUDEPATH += ../../lib
|
||||
CONFIG (debug, debug|release) {
|
||||
LIBS += -L../../staticlib/jkqtplotterlib/debug -ljkqtplotterlib_debug
|
||||
} else {
|
||||
LIBS += -L../../staticlib/jkqtplotterlib/release -ljkqtplotterlib
|
||||
}
|
||||
message("LIBS = $$LIBS")
|
||||
|
||||
|
||||
|
||||
win32-msvc*: DEFINES += _USE_MATH_DEFINES
|
||||
win32-msvc*: DEFINES += NOMINMAX
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += jkqtplotterlib jkqtplotter_simpletest_violinplot
|
||||
|
||||
jkqtplotterlib.file = ../../staticlib/jkqtplotterlib/jkqtplotterlib.pro
|
||||
|
||||
jkqtplotter_simpletest_violinplot.file=$$PWD/jkqtplotter_simpletest_violinplot.pro
|
||||
jkqtplotter_simpletest_violinplot.depends = jkqtplotterlib
|
@ -35,6 +35,8 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
|
||||
$$PWD/jkqtplotter/jkqtpgraphsimageoverlays.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphscontour.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsimagergb.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsviolinplot.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsviolinplotstylingmixins.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsstatisticsadaptors.h \
|
||||
$$PWD/jkqtplotter/jkqtplotter.h \
|
||||
$$PWD/jkqtplotter/jkqtplotterstyle.h \
|
||||
@ -77,6 +79,8 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
|
||||
$$PWD/jkqtplotter/jkqtpgraphsimageoverlays.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphscontour.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsimagergb.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsviolinplot.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsviolinplotstylingmixins.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsstatisticsadaptors.cpp \
|
||||
$$PWD/jkqtplotter/jkqtplotter.cpp \
|
||||
$$PWD/jkqtplotter/jkqtplotterstyle.cpp \
|
||||
|
@ -41,12 +41,13 @@
|
||||
|
||||
The second coordinate is:
|
||||
- if positionScatterStyle==NoScatter it is simply the value of position, e.g. <br>\image html JKQTPSingleColumnSymbolsGraph_NoScatter.png
|
||||
- if positionScatterStyle==RugPlot is like a NoScatter-plot, but with lines instead of symbols (see <a href="https://en.wikipedia.org/wiki/Rug_plot">https://en.wikipedia.org/wiki/Rug_plot</a>) <br>\image html JKQTPSingleColumnSymbolsGraph_RugPlot.png
|
||||
- if positionScatterStyle==RandomScatter it scatters around position in the range [position-width/2 ... position+width/2], e.g. <br>\image html JKQTPSingleColumnSymbolsGraph_RandomScatter.png
|
||||
- if positionScatterStyle==BeeSwarmScatter it scatters around position with an algorithm that tries to avoid any overlay of the plot symbols (SLOW!), e.g. <br>\image html JKQTPSingleColumnSymbolsGraph_BeeSwarmScatter.png
|
||||
.
|
||||
All example images above have dataDirection==DataDirection::X !
|
||||
|
||||
\see \ref JKQTPlotterDistributionPlot
|
||||
\see \ref JKQTPlotterDistributionPlot, \ref JKQTPlotterViolinplotGraphs
|
||||
|
||||
*/
|
||||
class JKQTP_LIB_EXPORT JKQTPSingleColumnSymbolsGraph: public JKQTPSingleColumnGraph, public JKQTPGraphSymbolStyleMixin {
|
||||
@ -55,9 +56,9 @@ class JKQTP_LIB_EXPORT JKQTPSingleColumnSymbolsGraph: public JKQTPSingleColumnGr
|
||||
/** \brief describes how data from dataColumn of a JKQTPSingleColumnSymbolsGraph positioned at position */
|
||||
enum ScatterStyle {
|
||||
NoScatter, /*!< \brief missing coordinate is exactly position for every datapoint in dataColumn \image html JKQTPSingleColumnSymbolsGraph_NoScatter.png */
|
||||
RugPlot, /*!< \brief like NoScatter but draws each data-point as a horzintal/vertical line, centered around position, not as a symbol ("rug plot", see e.g. <a href="https://en.wikipedia.org/wiki/Rug_plot">https://en.wikipedia.org/wiki/Rug_plot</a>). \image html JKQTPSingleColumnSymbolsGraph_RugPlot.png */
|
||||
RandomScatter, /*!< \brief missing coordinate scatters around position (with distribution-width width ) \image html JKQTPSingleColumnSymbolsGraph_RandomScatter.png */
|
||||
BeeSwarmScatter, /*!< \brief missing coordinate scatters around position and the algorithm tries to prevent overlay of two symbols ("bee swarm plot", see e.g. <a href="https://www.r-statistics.com/2011/03/beeswarm-boxplot-and-plotting-it-with-r/">https://www.r-statistics.com/2011/03/beeswarm-boxplot-and-plotting-it-with-r/</a>). Note that this algorithm can be rather slow!!! \image html JKQTPSingleColumnSymbolsGraph_BeeSwarmScatter.png */
|
||||
RugPlot, /*!< \brief like NoScatter but draws each data-point as a horzintal/vertical line, centered around position, not as a symbol ("rug plot", see e.g. <a href="https://en.wikipedia.org/wiki/Rug_plot">https://en.wikipedia.org/wiki/Rug_plot</a>). \image html JKQTPSingleColumnSymbolsGraph_RugPlot.png */
|
||||
};
|
||||
|
||||
/** \brief class constructor */
|
||||
|
490
lib/jkqtplotter/jkqtpgraphsviolinplot.cpp
Normal file
@ -0,0 +1,490 @@
|
||||
/*
|
||||
Copyright (c) 2008-2019 Jan W. Krieger (<jan@jkrieger.de>)
|
||||
|
||||
|
||||
|
||||
This software is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License (LGPL) as published by
|
||||
the Free Software Foundation, either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License (LGPL) for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License (LGPL)
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "jkqtplotter/jkqtpgraphsviolinplot.h"
|
||||
#include "jkqtplotter/jkqtpbaseplotter.h"
|
||||
#include <stdlib.h>
|
||||
#include <QDebug>
|
||||
#include <iostream>
|
||||
#include "jkqtplotter/jkqtptools.h"
|
||||
#include "jkqtplotter/jkqtpgraphsimage.h"
|
||||
#include "jkqtplotter/jkqtpbaseelements.h"
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
#define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz<smallestGreaterZero))) smallestGreaterZero=xvsgz;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPViolinplotVerticalElement::JKQTPViolinplotVerticalElement(JKQTBasePlotter* parent):
|
||||
JKQTPPlotObject(parent)
|
||||
{
|
||||
pos=JKQTP_NAN;
|
||||
median=JKQTP_NAN;
|
||||
mean=JKQTP_NAN;
|
||||
min=JKQTP_NAN;
|
||||
max=JKQTP_NAN;
|
||||
drawMean=false;
|
||||
drawMinMax=false;
|
||||
violinPositionColumn=-1;
|
||||
violinFrequencyColumn=-1;
|
||||
|
||||
initViolinplotStyle(parent, parentPlotStyle);
|
||||
setMeanSymbolType(JKQTPPlus);
|
||||
|
||||
}
|
||||
|
||||
JKQTPViolinplotVerticalElement::JKQTPViolinplotVerticalElement(JKQTPlotter* parent):
|
||||
JKQTPViolinplotVerticalElement(parent->getPlotter())
|
||||
{
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::draw(JKQTPEnhancedPainter& painter) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPViolinplotVerticalElement::draw");
|
||||
#endif
|
||||
if (parent==nullptr) return;
|
||||
|
||||
//drawErrorsBefore(painter);
|
||||
{
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
|
||||
const double xv=pos;
|
||||
const double minv=min;
|
||||
const double maxv=max;
|
||||
const double medianv=median;
|
||||
const double meanv=mean;
|
||||
|
||||
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
||||
if (JKQTPIsOKFloat(xv) ) {
|
||||
|
||||
//std::cout<<"boxplot(med="<<medianv<<", min="<<minv<<", max="<<maxv<<", p25="<<p25v<<", p75="<<p75v<<")\n";
|
||||
const double x=transformX(xv);
|
||||
const double min=transformY(minv);
|
||||
const double max=transformY(maxv);
|
||||
const double median=transformY(medianv);
|
||||
const double mean=transformY(meanv);
|
||||
|
||||
// collect single-value labels for hitTest()-data at the bottom of this loop!
|
||||
QStringList labelValues, labelNames;
|
||||
int labMedian=-1, labMean=-1, labMin=-1, labMax=-1;
|
||||
labelNames<<"pos";
|
||||
labelValues<<jkqtp_floattolatexqstr(xv, 3);
|
||||
if (JKQTPIsOKFloat(minv)) { labelNames<<"\\min"; labelValues<<jkqtp_floattolatexqstr(minv, 3); labMin=labelValues.size()-1; }
|
||||
if (JKQTPIsOKFloat(medianv)) {
|
||||
labelNames<<"\\median"; labelValues<<jkqtp_floattolatexqstr(medianv, 3); labMedian=labelValues.size()-1;
|
||||
}
|
||||
if (JKQTPIsOKFloat(meanv)) { labelNames<<"\\mu"; labelValues<<jkqtp_floattolatexqstr(meanv, 3); labMean=labelValues.size()-1; }
|
||||
if (JKQTPIsOKFloat(maxv)) { labelNames<<"\\max"; labelValues<<jkqtp_floattolatexqstr(maxv, 3); labMax=labelValues.size()-1; }
|
||||
|
||||
double w=parent->pt2px(painter,getViolinWidthAbsolute());
|
||||
double xma=x+w/2.0;
|
||||
double xmi=x-w/2.0;
|
||||
|
||||
QVector<double> violPos;
|
||||
if (violinPositionColumn>=0) violPos=transformY(getParent()->getDatastore()->getData(static_cast<size_t>(violinPositionColumn)));
|
||||
QVector<double> violFreq;
|
||||
if (violinFrequencyColumn>=0) violFreq=getParent()->getDatastore()->getData(static_cast<size_t>(violinFrequencyColumn));
|
||||
|
||||
plotVerticalViolinplot(parent, painter, x, xmi, xma, violPos, violFreq, (drawMinMax)?min:JKQTP_NAN, (drawMedian)?median:JKQTP_NAN, (drawMinMax)?max:JKQTP_NAN, (drawMean)?mean:JKQTP_NAN);
|
||||
|
||||
|
||||
if (drawMedian && JKQTPIsOKFloat(medianv)) {
|
||||
if (JKQTPIsOKFloat(medianv)) {
|
||||
QStringList sl=labelValues, sll=labelNames;
|
||||
sl[labMedian]="\\ul{"+sl[labMedian]+"}";
|
||||
sll[labMedian]="\\ul{"+sll[labMedian]+"}";
|
||||
addHitTestData(xv, medianv, "\\ensuremath{\\begin{bmatrix}"+sll.join("\\\\")+"\\end{bmatrix}\\;=\\;\\begin{bmatrix}"+sl.join("\\\\")+"\\end{bmatrix}}");
|
||||
}
|
||||
}
|
||||
if (drawMinMax) {
|
||||
if (JKQTPIsOKFloat(minv)) {
|
||||
QStringList sl=labelValues, sll=labelNames;
|
||||
sl[labMin]="\\ul{"+sl[labMin]+"}";
|
||||
sll[labMin]="\\ul{"+sll[labMin]+"}";
|
||||
addHitTestData(xv, minv, "\\ensuremath{\\begin{bmatrix}"+sll.join("\\\\")+"\\end{bmatrix}\\;=\\;\\begin{bmatrix}"+sl.join("\\\\")+"\\end{bmatrix}}");
|
||||
}
|
||||
if (JKQTPIsOKFloat(maxv)) {
|
||||
QStringList sl=labelValues, sll=labelNames;
|
||||
sl[labMax]="\\ul{"+sl[labMax]+"}";
|
||||
sll[labMax]="\\ul{"+sll[labMax]+"}";
|
||||
addHitTestData(xv, maxv, "\\ensuremath{\\begin{bmatrix}"+sll.join("\\\\")+"\\end{bmatrix}\\;=\\;\\begin{bmatrix}"+sl.join("\\\\")+"\\end{bmatrix}}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (drawMean && JKQTPIsOKFloat(meanv)) {
|
||||
if (JKQTPIsOKFloat(meanv)) {
|
||||
QStringList sl=labelValues, sll=labelNames;
|
||||
sl[labMean]="\\ul{"+sl[labMean]+"}";
|
||||
sll[labMean]="\\ul{"+sll[labMean]+"}";
|
||||
addHitTestData(xv, meanv, "\\ensuremath{\\begin{bmatrix}"+sll.join("\\\\")+"\\end{bmatrix}\\;=\\;\\begin{bmatrix}"+sl.join("\\\\")+"\\end{bmatrix}}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//drawErrorsAfter(painter);
|
||||
}
|
||||
|
||||
|
||||
bool JKQTPViolinplotVerticalElement::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
|
||||
minx=0;
|
||||
maxx=0;
|
||||
smallestGreaterZero=0;
|
||||
|
||||
if (parent==nullptr) return false;
|
||||
|
||||
double xv=pos;
|
||||
double x=transformX(xv);
|
||||
double xma=backtransformX(x-parent->pt2px(getViolinWidthAbsolute(), 72));
|
||||
double xmi=backtransformX(x+parent->pt2px(getViolinWidthAbsolute(), 72));
|
||||
if (xmi>xma) qSwap(xmi,xma);
|
||||
maxx=xma;
|
||||
minx=xmi;
|
||||
double xvsgz;
|
||||
xvsgz=xmi; SmallestGreaterZeroCompare_xvsgz();
|
||||
xvsgz=xma; SmallestGreaterZeroCompare_xvsgz();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JKQTPViolinplotVerticalElement::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
|
||||
miny=0;
|
||||
maxy=0;
|
||||
smallestGreaterZero=0;
|
||||
|
||||
if (parent==nullptr) return false ;
|
||||
|
||||
|
||||
if (drawMedian) {
|
||||
maxy=median;
|
||||
miny=median;
|
||||
}
|
||||
if (min>maxy) maxy=min;
|
||||
if (drawMinMax && (min<miny)) miny=min;
|
||||
if (drawMinMax && (max>maxy)) maxy=max;
|
||||
if (drawMinMax && (max<miny)) miny=max;
|
||||
|
||||
double xvsgz;
|
||||
xvsgz=median; SmallestGreaterZeroCompare_xvsgz();
|
||||
xvsgz=min; SmallestGreaterZeroCompare_xvsgz();
|
||||
xvsgz=max; SmallestGreaterZeroCompare_xvsgz();
|
||||
return true;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setPos(double __value)
|
||||
{
|
||||
this->pos = __value;
|
||||
}
|
||||
|
||||
double JKQTPViolinplotVerticalElement::getPos() const
|
||||
{
|
||||
return this->pos;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setMedian(double __value)
|
||||
{
|
||||
if (this->median != __value) {
|
||||
this->median = __value;
|
||||
drawMedian=true;
|
||||
}
|
||||
}
|
||||
|
||||
double JKQTPViolinplotVerticalElement::getMedian() const
|
||||
{
|
||||
return this->median;
|
||||
}
|
||||
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setMean(double __value)
|
||||
{
|
||||
if (this->mean != __value) {
|
||||
this->mean = __value;
|
||||
drawMean=true;
|
||||
}
|
||||
}
|
||||
|
||||
double JKQTPViolinplotVerticalElement::getMean() const
|
||||
{
|
||||
return this->mean;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setMin(double __value)
|
||||
{
|
||||
if (this->min != __value) {
|
||||
this->min = __value;
|
||||
drawMinMax=true;
|
||||
}
|
||||
}
|
||||
|
||||
double JKQTPViolinplotVerticalElement::getMin() const
|
||||
{
|
||||
return this->min;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setMax(double __value)
|
||||
{
|
||||
if (this->max != __value) {
|
||||
this->max = __value;
|
||||
drawMinMax=true;
|
||||
}
|
||||
}
|
||||
|
||||
double JKQTPViolinplotVerticalElement::getMax() const
|
||||
{
|
||||
return this->max;
|
||||
}
|
||||
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setDrawMean(bool __value)
|
||||
{
|
||||
this->drawMean = __value;
|
||||
}
|
||||
|
||||
bool JKQTPViolinplotVerticalElement::getDrawMean() const
|
||||
{
|
||||
return this->drawMean;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setDrawMedian(bool __value)
|
||||
{
|
||||
this->drawMedian = __value;
|
||||
}
|
||||
|
||||
bool JKQTPViolinplotVerticalElement::getDrawMedian() const
|
||||
{
|
||||
return this->drawMedian;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setDrawMinMax(bool __value)
|
||||
{
|
||||
this->drawMinMax = __value;
|
||||
}
|
||||
|
||||
bool JKQTPViolinplotVerticalElement::getDrawMinMax() const
|
||||
{
|
||||
return this->drawMinMax;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setViolinPositionColumn(int __value)
|
||||
{
|
||||
violinPositionColumn=__value;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setViolinPositionColumn(size_t __value)
|
||||
{
|
||||
violinPositionColumn=static_cast<int>(__value);
|
||||
}
|
||||
|
||||
int JKQTPViolinplotVerticalElement::getViolinPositionColumn() const
|
||||
{
|
||||
return violinPositionColumn;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setViolinFrequencyColumn(int __value)
|
||||
{
|
||||
violinFrequencyColumn=__value;
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setViolinFrequencyColumn(size_t __value)
|
||||
{
|
||||
violinFrequencyColumn=static_cast<int>(__value);
|
||||
}
|
||||
|
||||
int JKQTPViolinplotVerticalElement::getViolinFrequencyColumn() const
|
||||
{
|
||||
return violinFrequencyColumn;
|
||||
}
|
||||
|
||||
|
||||
void JKQTPViolinplotVerticalElement::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
||||
plotVerticalKeyMarker(parent, painter, rect);
|
||||
}
|
||||
|
||||
QColor JKQTPViolinplotVerticalElement::getKeyLabelColor() const {
|
||||
return getLineColor();
|
||||
}
|
||||
|
||||
void JKQTPViolinplotVerticalElement::setColor(QColor c)
|
||||
{
|
||||
setViolinplotColor(c, getParent());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void JKQTPViolinplotHorizontalElement::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
||||
plotHorizontalKeyMarker(parent, painter, rect);
|
||||
}
|
||||
|
||||
bool JKQTPViolinplotHorizontalElement::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
|
||||
minx=0;
|
||||
maxx=0;
|
||||
smallestGreaterZero=0;
|
||||
|
||||
if (parent==nullptr) return false;
|
||||
|
||||
|
||||
if (drawMedian) {
|
||||
maxx=median;
|
||||
minx=median;
|
||||
}
|
||||
if (min>maxx) maxx=min;
|
||||
if (drawMinMax && (min<minx)) minx=min;
|
||||
if (drawMinMax && (max>maxx)) maxx=max;
|
||||
if (drawMinMax && (max<minx)) minx=max;
|
||||
|
||||
double xvsgz;
|
||||
xvsgz=median; SmallestGreaterZeroCompare_xvsgz();
|
||||
xvsgz=min; SmallestGreaterZeroCompare_xvsgz();
|
||||
xvsgz=max; SmallestGreaterZeroCompare_xvsgz();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JKQTPViolinplotHorizontalElement::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
|
||||
miny=0;
|
||||
maxy=0;
|
||||
smallestGreaterZero=0;
|
||||
|
||||
if (parent==nullptr) return false;
|
||||
|
||||
double xv=pos;
|
||||
double x=transformY(xv);
|
||||
double xma=backtransformY(x-parent->pt2px(getViolinWidthAbsolute(), 72));
|
||||
double xmi=backtransformY(x+parent->pt2px(getViolinWidthAbsolute(), 72));
|
||||
if (xmi>xma) qSwap(xmi,xma);
|
||||
maxy=xma;
|
||||
miny=xmi;
|
||||
double xvsgz;
|
||||
xvsgz=xmi; SmallestGreaterZeroCompare_xvsgz();
|
||||
xvsgz=xma; SmallestGreaterZeroCompare_xvsgz();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
JKQTPViolinplotHorizontalElement::JKQTPViolinplotHorizontalElement(JKQTBasePlotter *parent):
|
||||
JKQTPViolinplotVerticalElement(parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPViolinplotHorizontalElement::JKQTPViolinplotHorizontalElement(JKQTPlotter *parent):
|
||||
JKQTPViolinplotHorizontalElement(parent->getPlotter())
|
||||
{
|
||||
}
|
||||
|
||||
void JKQTPViolinplotHorizontalElement::draw(JKQTPEnhancedPainter& painter) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPViolinplotHorizontalElement::draw");
|
||||
#endif
|
||||
if (parent==nullptr) return;
|
||||
|
||||
//drawErrorsBefore(painter);
|
||||
{
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
|
||||
const double yv=pos;
|
||||
const double minv=min;
|
||||
const double maxv=max;
|
||||
const double medianv=median;
|
||||
const double meanv=mean;
|
||||
|
||||
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
||||
if (JKQTPIsOKFloat(yv) ) {
|
||||
|
||||
//std::cout<<"boxplot(med="<<medianv<<", min="<<minv<<", max="<<maxv<<", p25="<<p25v<<", p75="<<p75v<<")\n";
|
||||
const double y=transformY(yv);
|
||||
const double min=transformX(minv);
|
||||
const double max=transformX(maxv);
|
||||
const double median=transformX(medianv);
|
||||
const double mean=transformX(meanv);
|
||||
|
||||
// collect single-value labels for hitTest()-data at the bottom of this loop!
|
||||
QStringList labelValues, labelNames;
|
||||
int labMedian=-1, labMean=-1, labMin=-1, labMax=-1;
|
||||
labelNames<<"pos";
|
||||
labelValues<<jkqtp_floattolatexqstr(yv, 3);
|
||||
if (JKQTPIsOKFloat(minv)) { labelNames<<"\\min"; labelValues<<jkqtp_floattolatexqstr(minv, 3); labMin=labelValues.size()-1; }
|
||||
if (JKQTPIsOKFloat(medianv)) {
|
||||
labelNames<<"\\median"; labelValues<<jkqtp_floattolatexqstr(medianv, 3); labMedian=labelValues.size()-1;
|
||||
}
|
||||
if (JKQTPIsOKFloat(meanv)) { labelNames<<"\\mu"; labelValues<<jkqtp_floattolatexqstr(meanv, 3); labMean=labelValues.size()-1; }
|
||||
if (JKQTPIsOKFloat(maxv)) { labelNames<<"\\max"; labelValues<<jkqtp_floattolatexqstr(maxv, 3); labMax=labelValues.size()-1; }
|
||||
|
||||
double w=parent->pt2px(painter,getViolinWidthAbsolute());
|
||||
double yma=y+w/2.0;
|
||||
double ymi=y-w/2.0;
|
||||
|
||||
QVector<double> violPos;
|
||||
if (violinPositionColumn>=0) violPos=transformX(getParent()->getDatastore()->getData(static_cast<size_t>(violinPositionColumn)));
|
||||
QVector<double> violFreq;
|
||||
if (violinFrequencyColumn>=0) violFreq=getParent()->getDatastore()->getData(static_cast<size_t>(violinFrequencyColumn));
|
||||
|
||||
plotHorizontalViolinplot(parent, painter, y, ymi, yma, violPos, violFreq, (drawMinMax)?min:JKQTP_NAN, (drawMedian)?median:JKQTP_NAN, (drawMinMax)?max:JKQTP_NAN, (drawMean)?mean:JKQTP_NAN);
|
||||
|
||||
|
||||
if (drawMedian && JKQTPIsOKFloat(medianv)) {
|
||||
if (JKQTPIsOKFloat(medianv)) {
|
||||
QStringList sl=labelValues, sll=labelNames;
|
||||
sl[labMedian]="\\ul{"+sl[labMedian]+"}";
|
||||
sll[labMedian]="\\ul{"+sll[labMedian]+"}";
|
||||
addHitTestData(medianv, yv, "\\ensuremath{\\begin{bmatrix}"+sll.join("\\\\")+"\\end{bmatrix}\\;=\\;\\begin{bmatrix}"+sl.join("\\\\")+"\\end{bmatrix}}");
|
||||
} }
|
||||
if (drawMinMax) {
|
||||
if (JKQTPIsOKFloat(minv)) {
|
||||
QStringList sl=labelValues, sll=labelNames;
|
||||
sl[labMin]="\\ul{"+sl[labMin]+"}";
|
||||
sll[labMin]="\\ul{"+sll[labMin]+"}";
|
||||
addHitTestData(minv, yv, "\\ensuremath{\\begin{bmatrix}"+sll.join("\\\\")+"\\end{bmatrix}\\;=\\;\\begin{bmatrix}"+sl.join("\\\\")+"\\end{bmatrix}}");
|
||||
}
|
||||
if (JKQTPIsOKFloat(maxv)) {
|
||||
QStringList sl=labelValues, sll=labelNames;
|
||||
sl[labMax]="\\ul{"+sl[labMax]+"}";
|
||||
sll[labMax]="\\ul{"+sll[labMax]+"}";
|
||||
addHitTestData(maxv, yv, "\\ensuremath{\\begin{bmatrix}"+sll.join("\\\\")+"\\end{bmatrix}\\;=\\;\\begin{bmatrix}"+sl.join("\\\\")+"\\end{bmatrix}}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (drawMean && JKQTPIsOKFloat(meanv)) {
|
||||
if (JKQTPIsOKFloat(meanv)) {
|
||||
QStringList sl=labelValues, sll=labelNames;
|
||||
sl[labMean]="\\ul{"+sl[labMean]+"}";
|
||||
sll[labMean]="\\ul{"+sll[labMean]+"}";
|
||||
addHitTestData(meanv, yv, "\\ensuremath{\\begin{bmatrix}"+sll.join("\\\\")+"\\end{bmatrix}\\;=\\;\\begin{bmatrix}"+sl.join("\\\\")+"\\end{bmatrix}}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//drawErrorsAfter(painter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
222
lib/jkqtplotter/jkqtpgraphsviolinplot.h
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
Copyright (c) 2008-2019 Jan W. Krieger (<jan@jkrieger.de>)
|
||||
|
||||
|
||||
|
||||
This software is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License (LGPL) as published by
|
||||
the Free Software Foundation, either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License (LGPL) for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License (LGPL)
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <QString>
|
||||
#include <QPainter>
|
||||
#include <QPair>
|
||||
#include "jkqtplotter/jkqtptools.h"
|
||||
#include "jkqtcommon/jkqtp_imexport.h"
|
||||
#include "jkqtplotter/jkqtpimagetools.h"
|
||||
#include "jkqtplotter/jkqtpgraphsbase.h"
|
||||
#include "jkqtplotter/jkqtpgraphsviolinplotstylingmixins.h"
|
||||
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
|
||||
|
||||
#ifndef jkqtpgraphsviolinplot_H
|
||||
#define jkqtpgraphsviolinplot_H
|
||||
|
||||
|
||||
|
||||
/*! \brief This implements a single vertical <a href="https://en.wikipedia.org/wiki/Violin_plot">Violin Plot</a> as a "geometric element"
|
||||
\ingroup jkqtplotter_statgraphs
|
||||
\ingroup jkqtplotter_geoplots
|
||||
|
||||
Draws a vertical violin plot in one of the following styles:
|
||||
|
||||
\image html JKQTPGraphViolinplot_SmoothViolin.png
|
||||
|
||||
\image html JKQTPGraphViolinplot_StepViolin.png
|
||||
|
||||
\image html JKQTPGraphViolinplot_BoxViolin.png
|
||||
|
||||
|
||||
This graph/plot element represents a single such plot. Its center is positioned at an x-coordinate provided by setPos().
|
||||
The width of the full plot (left+right!) is given by JKQTPGraphViolinplotStyleMixin::setViolinWidthAbsolute().
|
||||
|
||||
The data is represented partly by single values (e.g. setMedian(), setMin(), ...) and partly by the two columns set with
|
||||
setViolinPositionColumn() and setViolinFrequencyColumn(). The latter two represent a density estimate (or histogram) of the
|
||||
distribution represented by this plot, which is evaluated at the y-positions from setViolinPositionColumn(). For each such
|
||||
y-position a (not necessarily normalized) frequency is given by the values in setViolinFrequencyColumn().
|
||||
|
||||
|
||||
\image html JKQTPViolinplotHorizontalElement_elements.png
|
||||
|
||||
\see \ref JKQTPlotterViolinplotGraphs
|
||||
|
||||
*/
|
||||
class JKQTP_LIB_EXPORT JKQTPViolinplotVerticalElement: public JKQTPPlotObject, public JKQTPGraphViolinplotStyleMixin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
JKQTPViolinplotVerticalElement(JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPViolinplotVerticalElement(JKQTPlotter* parent);
|
||||
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
/** \brief plots a key marker inside the specified rectangle \a rect */
|
||||
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
|
||||
/** \brief returns the color to be used for the key label */
|
||||
virtual QColor getKeyLabelColor() const override;
|
||||
/*! \brief set the color of the graph (colors all elements, based on the given color \a c )*/
|
||||
virtual void setColor(QColor c);
|
||||
|
||||
|
||||
/** \brief get the maximum and minimum x-value of the graph
|
||||
*
|
||||
* The result is given in the two parameters which are call-by-reference parameters!
|
||||
*/
|
||||
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
|
||||
/** \brief get the maximum and minimum y-value of the graph
|
||||
*
|
||||
* The result is given in the two parameters which are call-by-reference parameters!
|
||||
*/
|
||||
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
||||
|
||||
|
||||
/*! \copydoc pos */
|
||||
void setPos(double __value);
|
||||
/*! \copydoc pos */
|
||||
double getPos() const;
|
||||
/*! \copydoc median */
|
||||
void setMedian(double __value);
|
||||
/*! \copydoc median */
|
||||
double getMedian() const;
|
||||
/*! \copydoc mean */
|
||||
void setMean(double __value);
|
||||
/*! \copydoc mean */
|
||||
double getMean() const;
|
||||
/*! \copydoc min */
|
||||
void setMin(double __value);
|
||||
/*! \copydoc min */
|
||||
double getMin() const;
|
||||
/*! \copydoc max */
|
||||
void setMax(double __value);
|
||||
/*! \copydoc max */
|
||||
double getMax() const;
|
||||
|
||||
|
||||
/*! \copydoc drawMean */
|
||||
void setDrawMean(bool __value);
|
||||
/*! \copydoc drawMean */
|
||||
bool getDrawMean() const;
|
||||
/*! \copydoc drawMedian */
|
||||
void setDrawMedian(bool __value);
|
||||
/*! \copydoc drawMedian */
|
||||
bool getDrawMedian() const;
|
||||
/*! \copydoc drawMinMax */
|
||||
void setDrawMinMax(bool __value);
|
||||
/*! \copydoc drawMinMax */
|
||||
bool getDrawMinMax() const;
|
||||
|
||||
|
||||
/*! \copydoc violinPositionColumn */
|
||||
void setViolinPositionColumn(int __value);
|
||||
/*! \copydoc violinPositionColumn */
|
||||
void setViolinPositionColumn(size_t __value);
|
||||
/*! \copydoc violinPositionColumn */
|
||||
int getViolinPositionColumn() const;
|
||||
|
||||
|
||||
/*! \copydoc violinFrequencyColumn */
|
||||
void setViolinFrequencyColumn(int __value);
|
||||
/*! \copydoc violinFrequencyColumn */
|
||||
void setViolinFrequencyColumn(size_t __value);
|
||||
/*! \copydoc violinFrequencyColumn */
|
||||
int getViolinFrequencyColumn() const;
|
||||
protected:
|
||||
|
||||
/** \brief the position of the boxplot on the "other" axis */
|
||||
double pos;
|
||||
/** \brief the median value to be used for the boxplot */
|
||||
double median;
|
||||
/** \brief the mean value to be used for the boxplot */
|
||||
double mean;
|
||||
/** \brief indicates whether to draw the mean */
|
||||
bool drawMean;
|
||||
/** \brief indicates whether to draw the median */
|
||||
bool drawMedian;
|
||||
/** \brief indicates whether to draw the percentiles */
|
||||
bool drawMinMax;
|
||||
/** \brief the minimum value to be used for the boxplot */
|
||||
double min;
|
||||
/** \brief the maximum value to be used for the boxplot */
|
||||
double max;
|
||||
/** \brief column with data for the violin outline: category values (along min-max-axis) */
|
||||
int violinPositionColumn;
|
||||
/** \brief column with data for the violin outline: frequency values (perpendicular to min-max-axis) */
|
||||
int violinFrequencyColumn;
|
||||
};
|
||||
|
||||
|
||||
/*! \brief This implements a single horizontal <a href="https://en.wikipedia.org/wiki/Violin_plot">Violin Plot</a> as a "geometric element"
|
||||
\ingroup jkqtplotter_statgraphs
|
||||
\ingroup jkqtplotter_geoplots
|
||||
|
||||
Draws a horizontal violin plot in one of the following styles:
|
||||
|
||||
\image html JKQTPGraphViolinplot_HSmoothViolin.png
|
||||
|
||||
\image html JKQTPGraphViolinplot_HStepViolin.png
|
||||
|
||||
\image html JKQTPGraphViolinplot_HBoxViolin.png
|
||||
|
||||
This graph/plot element represents a single such plot. Its center is positioned at an y-coordinate provided by setPos().
|
||||
The width of the full plot (top+bottom!) is given by JKQTPGraphViolinplotStyleMixin::setViolinWidthAbsolute().
|
||||
|
||||
The data is represented partly by single values (e.g. setMedian(), setMin(), ...) and partly by the two columns set with
|
||||
setViolinPositionColumn() and setViolinFrequencyColumn(). The latter two represent a density estimate (or histogram) of the
|
||||
distribution represented by this plot, which is evaluated at the x-positions from setViolinPositionColumn(). For each such
|
||||
x-position a (not necessarily normalized) frequency is given by the values in setViolinFrequencyColumn().
|
||||
|
||||
\image html JKQTPViolinplotHorizontalElement_elements.png
|
||||
|
||||
|
||||
\see \ref JKQTPlotterViolinplotGraphs
|
||||
|
||||
*/
|
||||
class JKQTP_LIB_EXPORT JKQTPViolinplotHorizontalElement: public JKQTPViolinplotVerticalElement {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
JKQTPViolinplotHorizontalElement(JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPViolinplotHorizontalElement(JKQTPlotter* parent);
|
||||
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
/** \brief plots a key marker inside the specified rectangle \a rect */
|
||||
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
|
||||
|
||||
|
||||
/** \brief get the maximum and minimum x-value of the graph
|
||||
*
|
||||
* The result is given in the two parameters which are call-by-reference parameters!
|
||||
*/
|
||||
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
|
||||
/** \brief get the maximum and minimum y-value of the graph
|
||||
*
|
||||
* The result is given in the two parameters which are call-by-reference parameters!
|
||||
*/
|
||||
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // jkqtpgraphsviolinplot_H
|
978
lib/jkqtplotter/jkqtpgraphsviolinplotstylingmixins.cpp
Normal file
@ -0,0 +1,978 @@
|
||||
/*
|
||||
Copyright (c) 2008-2019 Jan W. Krieger (<jan@jkrieger.de>)
|
||||
|
||||
|
||||
|
||||
This software is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License (LGPL) as published by
|
||||
the Free Software Foundation, either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License (LGPL) for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License (LGPL)
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "jkqtplotter/jkqtpgraphsviolinplotstylingmixins.h"
|
||||
#include "jkqtplotter/jkqtpbaseplotter.h"
|
||||
#include <stdlib.h>
|
||||
#include <QDebug>
|
||||
#include <iostream>
|
||||
#include "jkqtplotter/jkqtptools.h"
|
||||
#include "jkqtplotter/jkqtpgraphsimage.h"
|
||||
#include "jkqtplotter/jkqtpbaseelements.h"
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
|
||||
|
||||
|
||||
JKQTPGraphViolinplotStyleMixin::JKQTPGraphViolinplotStyleMixin()
|
||||
{
|
||||
|
||||
m_whiskerLinePen=QPen(getLineColor(), getLineWidth());
|
||||
whiskerLineWidth=getLineWidth();
|
||||
m_whiskerCapLinePen=QPen(getLineColor(), getLineWidth());
|
||||
whiskerCapLineWidth=getLineWidth();
|
||||
m_medianLinePen=QPen(getLineColor(), getLineWidth());
|
||||
medianLineWidth=getLineWidth();
|
||||
|
||||
m_meanSymbolLinePen=QPen(getLineColor(), getLineWidth());
|
||||
m_meanSymbolLineWidth=1;
|
||||
m_meanSymbolType=JKQTPGraphSymbols::JKQTPDefaultSymbol;
|
||||
m_meanSymbolSize=12;
|
||||
m_meanSymbolFillColor=m_meanSymbolLinePen.color().lighter();
|
||||
|
||||
|
||||
violinWidthAbsolute=m_meanSymbolSize*6.0;
|
||||
relativeWhiskerWidth=0.5;
|
||||
|
||||
m_violinStyle=ViolinStyle::SmoothViolin;
|
||||
m_violinPositionMode=ViolinPositionMode::ViolinBoth;
|
||||
}
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::initViolinplotStyle(JKQTBasePlotter *parent, int &parentPlotStyle)
|
||||
{
|
||||
setFillStyle(Qt::SolidPattern);
|
||||
setFillColor(parent->getCurrentPlotterStyle().plotBackgroundBrush.color());
|
||||
initLineStyle(parent, parentPlotStyle);
|
||||
if (parent) { // get style settings from parent object
|
||||
if (parentPlotStyle<0) parentPlotStyle=parent->getNextStyle();
|
||||
m_whiskerLinePen.setColor(parent->getPlotStyle(parentPlotStyle).color());
|
||||
m_whiskerLinePen.setStyle(parent->getPlotStyle(parentPlotStyle).style());
|
||||
whiskerLineWidth=parent->getPlotStyle(parentPlotStyle).widthF();
|
||||
m_whiskerCapLinePen.setColor(parent->getPlotStyle(parentPlotStyle).color());
|
||||
m_whiskerCapLinePen.setStyle(parent->getPlotStyle(parentPlotStyle).style());
|
||||
whiskerCapLineWidth=parent->getPlotStyle(parentPlotStyle).widthF();
|
||||
m_medianLinePen.setColor(parent->getPlotStyle(parentPlotStyle).color());
|
||||
m_medianLinePen.setStyle(parent->getPlotStyle(parentPlotStyle).style());
|
||||
medianLineWidth=parent->getPlotStyle(parentPlotStyle).widthF();
|
||||
m_meanSymbolLinePen=QPen(parent->getPlotStyle(parentPlotStyle).color(), parent->getPlotStyle(parentPlotStyle).style());
|
||||
m_meanSymbolSize=parent->getPlotStyle(parentPlotStyle).symbolSize();
|
||||
m_meanSymbolLineWidth=parent->getPlotStyle(parentPlotStyle).symbolLineWidthF();
|
||||
m_meanSymbolType=parent->getPlotStyle(parentPlotStyle).symbol();
|
||||
m_meanSymbolFillColor=parent->getPlotStyle(parentPlotStyle).symbolFillColor();
|
||||
}
|
||||
|
||||
setWhiskerLineColor(getLineColor());
|
||||
setWhiskerCapLineColor(getLineColor());
|
||||
setMedianLineColor(getLineColor());
|
||||
setMeanSymbolType(JKQTPPlus);
|
||||
|
||||
if (m_meanSymbolSize>0) {
|
||||
violinWidthAbsolute=m_meanSymbolSize*6.0;
|
||||
}
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setViolinWidthAbsolute(double __value)
|
||||
{
|
||||
violinWidthAbsolute=__value;
|
||||
}
|
||||
|
||||
double JKQTPGraphViolinplotStyleMixin::getViolinWidthAbsolute() const
|
||||
{
|
||||
return violinWidthAbsolute;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setViolinplotColor(QColor c, JKQTBasePlotter *parent)
|
||||
{
|
||||
setLineColor(c);
|
||||
setFillColor(JKQTPGetDerivedColor(parent->getCurrentPlotterStyle().graphFillColorDerivationMode, c));
|
||||
setMeanColor(c);
|
||||
setMeanFillColor(JKQTPGetDerivedColor(parent->getCurrentPlotterStyle().graphFillColorDerivationMode, c));
|
||||
setWhiskerLineColor(getLineColor());
|
||||
setWhiskerCapLineColor(getLineColor());
|
||||
setMedianLineColor(getLineColor());
|
||||
c.setAlphaF(0.5);
|
||||
setHighlightingLineColor(c);
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setViolinplotColor(QColor c, QColor bc, JKQTBasePlotter *parent)
|
||||
{
|
||||
setViolinplotColor(c, parent);
|
||||
setFillColor(bc);
|
||||
setMeanFillColor(bc);
|
||||
}
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setRelativeWhiskerWidth(double __value)
|
||||
{
|
||||
relativeWhiskerWidth=__value;
|
||||
}
|
||||
|
||||
double JKQTPGraphViolinplotStyleMixin::getRelativeWhiskerWidth() const
|
||||
{
|
||||
return relativeWhiskerWidth;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMeanSymbolType(JKQTPGraphSymbols __value)
|
||||
{
|
||||
m_meanSymbolType=__value;
|
||||
}
|
||||
|
||||
JKQTPGraphSymbols JKQTPGraphViolinplotStyleMixin::getMeanSymbolType() const
|
||||
{
|
||||
return m_meanSymbolType;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMeanSize(double __value)
|
||||
{
|
||||
m_meanSymbolSize=__value;
|
||||
}
|
||||
|
||||
double JKQTPGraphViolinplotStyleMixin::getMeanSize() const
|
||||
{
|
||||
return m_meanSymbolSize;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMeanColor(const QColor &__value)
|
||||
{
|
||||
m_meanSymbolLinePen.setColor(__value);
|
||||
}
|
||||
|
||||
QColor JKQTPGraphViolinplotStyleMixin::getMeanColor() const
|
||||
{
|
||||
return m_meanSymbolLinePen.color();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMeanFillColor(const QColor &__value)
|
||||
{
|
||||
m_meanSymbolFillColor=__value;
|
||||
}
|
||||
|
||||
QColor JKQTPGraphViolinplotStyleMixin::getMeanFillColor() const
|
||||
{
|
||||
return m_meanSymbolFillColor;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMeanLineWidth(double __value)
|
||||
{
|
||||
m_meanSymbolLineWidth=__value;
|
||||
}
|
||||
|
||||
double JKQTPGraphViolinplotStyleMixin::getMeanLineWidth() const
|
||||
{
|
||||
return m_meanSymbolLineWidth;
|
||||
}
|
||||
|
||||
JKQTPGraphViolinplotStyleMixin::ViolinStyle JKQTPGraphViolinplotStyleMixin::getViolinStyle() const
|
||||
{
|
||||
return m_violinStyle;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setViolinStyle(JKQTPGraphViolinplotStyleMixin::ViolinStyle style)
|
||||
{
|
||||
m_violinStyle=style;
|
||||
}
|
||||
|
||||
JKQTPGraphViolinplotStyleMixin::ViolinPositionMode JKQTPGraphViolinplotStyleMixin::getViolinPositionMode() const
|
||||
{
|
||||
return m_violinPositionMode;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setViolinPositionMode(JKQTPGraphViolinplotStyleMixin::ViolinPositionMode positionMode)
|
||||
{
|
||||
m_violinPositionMode=positionMode;
|
||||
}
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMeanLineStyle(Qt::PenStyle __value)
|
||||
{
|
||||
this->m_meanSymbolLinePen.setStyle(__value);
|
||||
}
|
||||
|
||||
Qt::PenStyle JKQTPGraphViolinplotStyleMixin::getMeanLineStyle() const
|
||||
{
|
||||
return this->m_meanSymbolLinePen.style();
|
||||
}
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMeanLineDashOffset(qreal offset)
|
||||
{
|
||||
m_meanSymbolLinePen.setDashOffset(offset);
|
||||
}
|
||||
|
||||
qreal JKQTPGraphViolinplotStyleMixin::getMeanLineDashOffset() const
|
||||
{
|
||||
return m_meanSymbolLinePen.dashOffset();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMeanLineDashPattern(const QVector<qreal> &pattern)
|
||||
{
|
||||
m_meanSymbolLinePen.setDashPattern(pattern);
|
||||
m_meanSymbolLinePen.setStyle(Qt::CustomDashLine);
|
||||
}
|
||||
|
||||
QVector<qreal> JKQTPGraphViolinplotStyleMixin::getMeanLineDashPattern() const
|
||||
{
|
||||
return m_meanSymbolLinePen.dashPattern();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMedianLineWidth(double __value)
|
||||
{
|
||||
medianLineWidth=__value;
|
||||
}
|
||||
|
||||
double JKQTPGraphViolinplotStyleMixin::getMedianLineWidth() const
|
||||
{
|
||||
return medianLineWidth;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMedianLineColor(QColor __value)
|
||||
{
|
||||
m_medianLinePen.setColor(__value);
|
||||
}
|
||||
|
||||
QColor JKQTPGraphViolinplotStyleMixin::getMedianLineColor() const
|
||||
{
|
||||
return m_medianLinePen.color();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMedianLineStyle(Qt::PenStyle __value)
|
||||
{
|
||||
this->m_medianLinePen.setStyle(__value);
|
||||
}
|
||||
|
||||
Qt::PenStyle JKQTPGraphViolinplotStyleMixin::getMedianLineStyle() const
|
||||
{
|
||||
return this->m_medianLinePen.style();
|
||||
}
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMedianLineDashOffset(qreal offset)
|
||||
{
|
||||
m_medianLinePen.setDashOffset(offset);
|
||||
}
|
||||
|
||||
qreal JKQTPGraphViolinplotStyleMixin::getMedianLineDashOffset() const
|
||||
{
|
||||
return m_medianLinePen.dashOffset();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMedianLineDashPattern(const QVector<qreal> &pattern)
|
||||
{
|
||||
m_medianLinePen.setDashPattern(pattern);
|
||||
m_medianLinePen.setStyle(Qt::CustomDashLine);
|
||||
}
|
||||
|
||||
QVector<qreal> JKQTPGraphViolinplotStyleMixin::getMedianLineDashPattern() const
|
||||
{
|
||||
return m_medianLinePen.dashPattern();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMedianLineJoinStyle(Qt::PenJoinStyle style)
|
||||
{
|
||||
m_medianLinePen.setJoinStyle(style);
|
||||
}
|
||||
|
||||
Qt::PenJoinStyle JKQTPGraphViolinplotStyleMixin::getMedianLineJoinStyle() const
|
||||
{
|
||||
return m_medianLinePen.joinStyle();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMedianLineCapStyle(Qt::PenCapStyle style)
|
||||
{
|
||||
m_medianLinePen.setCapStyle(style);
|
||||
}
|
||||
|
||||
Qt::PenCapStyle JKQTPGraphViolinplotStyleMixin::getMedianLineCapStyle() const
|
||||
{
|
||||
return m_medianLinePen.capStyle();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setMedianLineBrush(const QBrush &style)
|
||||
{
|
||||
m_medianLinePen.setBrush(style);
|
||||
}
|
||||
|
||||
QBrush JKQTPGraphViolinplotStyleMixin::getMedianLineBrush() const
|
||||
{
|
||||
return m_medianLinePen.brush();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerLineStyle(Qt::PenStyle __value)
|
||||
{
|
||||
this->m_whiskerLinePen.setStyle(__value);
|
||||
}
|
||||
|
||||
Qt::PenStyle JKQTPGraphViolinplotStyleMixin::getWhiskerLineStyle() const
|
||||
{
|
||||
return this->m_whiskerLinePen.style();
|
||||
}
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerLineWidth(double __value)
|
||||
{
|
||||
whiskerLineWidth=__value;
|
||||
}
|
||||
|
||||
double JKQTPGraphViolinplotStyleMixin::getWhiskerLineWidth() const
|
||||
{
|
||||
return whiskerLineWidth;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerLineColor(QColor __value)
|
||||
{
|
||||
m_whiskerLinePen.setColor(__value);
|
||||
}
|
||||
|
||||
QColor JKQTPGraphViolinplotStyleMixin::getWhiskerLineColor() const
|
||||
{
|
||||
return m_whiskerLinePen.color();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerLineDashOffset(qreal offset)
|
||||
{
|
||||
m_whiskerLinePen.setDashOffset(offset);
|
||||
}
|
||||
|
||||
qreal JKQTPGraphViolinplotStyleMixin::getWhiskerLineDashOffset() const
|
||||
{
|
||||
return m_whiskerLinePen.dashOffset();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerLineDashPattern(const QVector<qreal> &pattern)
|
||||
{
|
||||
m_whiskerLinePen.setDashPattern(pattern);
|
||||
m_whiskerLinePen.setStyle(Qt::CustomDashLine);
|
||||
}
|
||||
|
||||
QVector<qreal> JKQTPGraphViolinplotStyleMixin::getWhiskerLineDashPattern() const
|
||||
{
|
||||
return m_whiskerLinePen.dashPattern();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerLineJoinStyle(Qt::PenJoinStyle style)
|
||||
{
|
||||
m_whiskerLinePen.setJoinStyle(style);
|
||||
}
|
||||
|
||||
Qt::PenJoinStyle JKQTPGraphViolinplotStyleMixin::getWhiskerLineJoinStyle() const
|
||||
{
|
||||
return m_whiskerLinePen.joinStyle();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerLineCapStyle(Qt::PenCapStyle style)
|
||||
{
|
||||
m_whiskerLinePen.setCapStyle(style);
|
||||
}
|
||||
|
||||
Qt::PenCapStyle JKQTPGraphViolinplotStyleMixin::getWhiskerLineCapStyle() const
|
||||
{
|
||||
return m_whiskerLinePen.capStyle();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerLineBrush(const QBrush &style)
|
||||
{
|
||||
m_whiskerLinePen.setBrush(style);
|
||||
}
|
||||
|
||||
QBrush JKQTPGraphViolinplotStyleMixin::getWhiskerLineBrush() const
|
||||
{
|
||||
return m_whiskerLinePen.brush();
|
||||
}
|
||||
|
||||
QPen JKQTPGraphViolinplotStyleMixin::getWhiskerPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
|
||||
{
|
||||
QPen pw=m_whiskerLinePen;
|
||||
pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerLineWidth)));
|
||||
pw.setJoinStyle(Qt::MiterJoin);
|
||||
pw.setCapStyle(Qt::FlatCap);
|
||||
return pw;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineStyle(Qt::PenStyle __value)
|
||||
{
|
||||
this->m_whiskerCapLinePen.setStyle(__value);
|
||||
}
|
||||
|
||||
Qt::PenStyle JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineStyle() const
|
||||
{
|
||||
return this->m_whiskerCapLinePen.style();
|
||||
}
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineWidth(double __value)
|
||||
{
|
||||
whiskerCapLineWidth=__value;
|
||||
}
|
||||
|
||||
double JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineWidth() const
|
||||
{
|
||||
return whiskerCapLineWidth;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineColor(QColor __value)
|
||||
{
|
||||
m_whiskerCapLinePen.setColor(__value);
|
||||
}
|
||||
|
||||
QColor JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineColor() const
|
||||
{
|
||||
return m_whiskerCapLinePen.color();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineDashOffset(qreal offset)
|
||||
{
|
||||
m_whiskerCapLinePen.setDashOffset(offset);
|
||||
}
|
||||
|
||||
qreal JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineDashOffset() const
|
||||
{
|
||||
return m_whiskerCapLinePen.dashOffset();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineDashPattern(const QVector<qreal> &pattern)
|
||||
{
|
||||
m_whiskerCapLinePen.setDashPattern(pattern);
|
||||
m_whiskerCapLinePen.setStyle(Qt::CustomDashLine);
|
||||
}
|
||||
|
||||
QVector<qreal> JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineDashPattern() const
|
||||
{
|
||||
return m_whiskerCapLinePen.dashPattern();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineJoinStyle(Qt::PenJoinStyle style)
|
||||
{
|
||||
m_whiskerCapLinePen.setJoinStyle(style);
|
||||
}
|
||||
|
||||
Qt::PenJoinStyle JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineJoinStyle() const
|
||||
{
|
||||
return m_whiskerCapLinePen.joinStyle();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineCapStyle(Qt::PenCapStyle style)
|
||||
{
|
||||
m_whiskerCapLinePen.setCapStyle(style);
|
||||
}
|
||||
|
||||
Qt::PenCapStyle JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineCapStyle() const
|
||||
{
|
||||
return m_whiskerCapLinePen.capStyle();
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineBrush(const QBrush &style)
|
||||
{
|
||||
m_whiskerCapLinePen.setBrush(style);
|
||||
}
|
||||
|
||||
QBrush JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineBrush() const
|
||||
{
|
||||
return m_whiskerCapLinePen.brush();
|
||||
}
|
||||
|
||||
QPen JKQTPGraphViolinplotStyleMixin::getWhiskerCapPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
|
||||
{
|
||||
QPen pw=m_whiskerCapLinePen;
|
||||
pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerCapLineWidth)));
|
||||
pw.setJoinStyle(Qt::MiterJoin);
|
||||
return pw;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QPen JKQTPGraphViolinplotStyleMixin::getMedianPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
|
||||
{
|
||||
QPen pw=m_medianLinePen;
|
||||
pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*medianLineWidth)));
|
||||
pw.setJoinStyle(Qt::MiterJoin);
|
||||
pw.setCapStyle(Qt::FlatCap);
|
||||
return pw;
|
||||
}
|
||||
|
||||
QPen JKQTPGraphViolinplotStyleMixin::getMeanSymbolPen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
|
||||
QPen p=m_meanSymbolLinePen;
|
||||
p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth)));
|
||||
p.setStyle(Qt::SolidLine);
|
||||
p.setJoinStyle(Qt::RoundJoin);
|
||||
p.setCapStyle(Qt::RoundCap);
|
||||
return p;
|
||||
}
|
||||
|
||||
QPen JKQTPGraphViolinplotStyleMixin::getMeanLinePen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
|
||||
QPen p=m_meanSymbolLinePen;
|
||||
p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth)));
|
||||
p.setJoinStyle(Qt::MiterJoin);
|
||||
p.setCapStyle(Qt::FlatCap);
|
||||
return p;
|
||||
}
|
||||
|
||||
QBrush JKQTPGraphViolinplotStyleMixin::getMeanSymbolBrush(JKQTPEnhancedPainter& /*painter*/, JKQTBasePlotter* /*parent*/) const {
|
||||
QBrush b;
|
||||
b.setColor(m_meanSymbolFillColor);
|
||||
return b;
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::plotStyledMeanSymbol(JKQTBasePlotter *parent, JKQTPEnhancedPainter &painter, double x, double y) const
|
||||
{
|
||||
JKQTPPlotSymbol(painter, x, y,m_meanSymbolType, parent->pt2px(painter, m_meanSymbolSize), parent->pt2px(painter, m_meanSymbolLineWidth*parent->getLineWidthMultiplier()), m_meanSymbolLinePen.color(), m_meanSymbolFillColor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::plotVerticalViolinplot(JKQTBasePlotter *parent, JKQTPEnhancedPainter &painter, double xp, double xpleft, double xpright, const QVector<double> &violin_cat, const QVector<double> &violin_freq, double minp, double medianp, double maxp, double meanp) const
|
||||
{
|
||||
if (JKQTPIsOKFloat(xp) ) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
|
||||
|
||||
double minstop=medianp;
|
||||
double maxstop=medianp;
|
||||
if (!JKQTPIsOKFloat(minstop) && JKQTPIsOKFloat(meanp)) minstop=meanp;
|
||||
else if (!JKQTPIsOKFloat(minstop) && JKQTPIsOKFloat(maxp)) minstop=maxp;
|
||||
if (!JKQTPIsOKFloat(maxstop) && JKQTPIsOKFloat(meanp)) maxstop=meanp;
|
||||
else if (!JKQTPIsOKFloat(maxstop) && JKQTPIsOKFloat(minp)) maxstop=minp;
|
||||
const double wl=fabs(xpright-xp);
|
||||
const double wr=fabs(xpleft-xp);
|
||||
const double xprightWhisker=xp+wr*getRelativeWhiskerWidth();
|
||||
const double xpleftWhisker=xp-wl*getRelativeWhiskerWidth();
|
||||
|
||||
|
||||
// draw violin
|
||||
const int NViol=std::min(violin_cat.size(), violin_freq.size());
|
||||
double medianMin=xpleft;
|
||||
double medianMax=xpright;
|
||||
if (NViol>0) {
|
||||
double fmin=violin_freq[0], fmax=violin_freq[0];
|
||||
for (int i=1; i<NViol; i++) {
|
||||
fmin=std::min(fmin, violin_freq[i]);
|
||||
fmax=std::max(fmax, violin_freq[i]);
|
||||
}
|
||||
|
||||
const double freqFactorr=1.0/fmax*fabs(xpright-xp);
|
||||
const double freqFactorl=1.0/fmax*fabs(xpleft-xp);
|
||||
|
||||
if (m_violinStyle==ViolinStyle::BoxViolin && NViol>1) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(getLinePen(painter, parent));
|
||||
painter.setBrush(getFillBrush(painter, parent));
|
||||
|
||||
for (int i=0; i<NViol; i++) {
|
||||
if (i==0) {
|
||||
const double hl=(violin_cat[1]-violin_cat[0]);
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
painter.drawRect(QRectF(QPointF(xp-violin_freq[i]*freqFactorl, violin_cat.first()), QPointF(xp+violin_freq[i]*freqFactorr, violin_cat.first()+hl/2.0)));
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawRect(QRectF(QPointF(xp-violin_freq[i]*freqFactorl, violin_cat.first()), QPointF(xp, violin_cat.first()+hl/2.0)));
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawRect(QRectF(QPointF(xp, violin_cat.first()), QPointF(xp+violin_freq[i]*freqFactorr, violin_cat.first()+hl/2.0)));
|
||||
}
|
||||
|
||||
} else if (i>0 && i<NViol-1) {
|
||||
const double hl=(violin_cat[i]-violin_cat[i-1]);
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
painter.drawRect(QRectF(QPointF(xp-violin_freq[i]*freqFactorl, violin_cat[i]-hl/2.0), QPointF(xp+violin_freq[i]*freqFactorr, violin_cat[i]+hl/2.0)));
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawRect(QRectF(QPointF(xp-violin_freq[i]*freqFactorl, violin_cat[i]-hl/2.0), QPointF(xp, violin_cat[i]+hl/2.0)));
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawRect(QRectF(QPointF(xp, violin_cat[i]-hl/2.0), QPointF(xp+violin_freq[i]*freqFactorr, violin_cat[i]+hl/2.0)));
|
||||
}
|
||||
} else if (i==NViol-1) {
|
||||
const double hl=(violin_cat[i]-violin_cat[i-1]);
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
painter.drawRect(QRectF(QPointF(xp-violin_freq[i]*freqFactorl, violin_cat[i]-hl/2.0), QPointF(xp+violin_freq[i]*freqFactorr, violin_cat[i])));
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawRect(QRectF(QPointF(xp-violin_freq[i]*freqFactorl, violin_cat[i]-hl/2.0), QPointF(xp, violin_cat[i])));
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawRect(QRectF(QPointF(xp, violin_cat[i]-hl/2.0), QPointF(xp+violin_freq[i]*freqFactorr, violin_cat[i])));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} else if (m_violinStyle==ViolinStyle::SmoothViolin && NViol>1) {
|
||||
QPolygonF pleft, pright;
|
||||
pleft<<QPointF(xp, violin_cat.first());
|
||||
pright<<QPointF(xp, violin_cat.last());
|
||||
for (int i=0; i<NViol; i++) {
|
||||
pleft<<QPointF(xp-violin_freq[i]*freqFactorl, violin_cat[i]);
|
||||
pright<<QPointF(xp+violin_freq[NViol-1-i]*freqFactorr, violin_cat[NViol-1-i]);
|
||||
}
|
||||
pleft<<QPointF(xp, violin_cat.last());
|
||||
pright<<QPointF(xp, violin_cat.first());
|
||||
|
||||
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(getLinePen(painter, parent));
|
||||
painter.setBrush(getFillBrush(painter, parent));
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
pleft.append(pright);
|
||||
painter.drawPolygon(pleft);
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawPolygon(pleft);
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawPolygon(pright);
|
||||
}
|
||||
} else if (m_violinStyle==ViolinStyle::StepViolin && NViol>1) {
|
||||
QPolygonF pleft, pright;
|
||||
for (int i=0; i<NViol; i++) {
|
||||
if (i==0) {
|
||||
const double hl=(violin_cat[1]-violin_cat[0]);
|
||||
pleft<<QPointF(xp, violin_cat.first())
|
||||
<<QPointF(xp-violin_freq[i]*freqFactorl, violin_cat.first())
|
||||
<<QPointF(xp-violin_freq[i]*freqFactorl, violin_cat.first()+hl/2.0);
|
||||
} else if (i>0 && i<NViol-1) {
|
||||
const double hl=(violin_cat[i]-violin_cat[i-1]);
|
||||
pleft<<QPointF(xp-violin_freq[i]*freqFactorl, violin_cat[i]-hl/2.0)
|
||||
<<QPointF(xp-violin_freq[i]*freqFactorl, violin_cat[i]+hl/2.0);
|
||||
} else if (i==NViol-1) {
|
||||
const double hl=(violin_cat[i]-violin_cat[i-1]);
|
||||
pleft<<QPointF(xp-violin_freq[i]*freqFactorl, violin_cat[i]-hl/2.0)
|
||||
<<QPointF(xp-violin_freq[i]*freqFactorl, violin_cat[i])
|
||||
<<QPointF(xp, violin_cat[i]);
|
||||
|
||||
}
|
||||
if (i==0) {
|
||||
const double hr=fabs(violin_cat[NViol-1]-violin_cat[NViol-2]);
|
||||
pright<<QPointF(xp, violin_cat.last())
|
||||
<<QPointF(xp+violin_freq.last()*freqFactorr, violin_cat.last())
|
||||
<<QPointF(xp+violin_freq.last()*freqFactorr, violin_cat.last()+hr/2.0);
|
||||
} else if (i>0 && i<NViol-1) {
|
||||
const double hr=fabs(violin_cat[NViol-1-i]-violin_cat[NViol-1-i-1]);
|
||||
pright<<QPointF(xp+violin_freq[NViol-1-i]*freqFactorr, violin_cat[NViol-1-i]-hr/2.0)
|
||||
<<QPointF(xp+violin_freq[NViol-1-i]*freqFactorr, violin_cat[NViol-1-i]+hr/2.0);
|
||||
} else if (i==NViol-1) {
|
||||
const double hr=fabs(violin_cat[1]-violin_cat[0]);
|
||||
pright<<QPointF(xp+violin_freq[0]*freqFactorr, violin_cat[0]-hr/2.0)
|
||||
<<QPointF(xp+violin_freq[0]*freqFactorr, violin_cat[0])
|
||||
<<QPointF(xp, violin_cat[0]);
|
||||
}
|
||||
}
|
||||
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(getLinePen(painter, parent));
|
||||
painter.setBrush(getFillBrush(painter, parent));
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
pleft.append(pright);
|
||||
painter.drawPolygon(pleft);
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawPolygon(pleft);
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawPolygon(pright);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// whisker lines
|
||||
painter.setPen(getWhiskerPen(painter, parent));
|
||||
if (JKQTPIsOKFloat(minp) && JKQTPIsOKFloat(minstop)) {
|
||||
painter.drawLine(QLineF(xp, minp, xp, minstop));
|
||||
}
|
||||
if (JKQTPIsOKFloat(maxp) && JKQTPIsOKFloat(maxstop)) {
|
||||
painter.drawLine(QLineF(xp, maxp, xp, maxstop));
|
||||
}
|
||||
|
||||
// whisker caps
|
||||
if (JKQTPIsOKFloat(xpleftWhisker) && JKQTPIsOKFloat(xprightWhisker)){
|
||||
painter.setPen(getWhiskerCapPen(painter, parent));
|
||||
if (JKQTPIsOKFloat(minp)) {
|
||||
painter.drawLine(QLineF(xpleftWhisker, minp, xprightWhisker, minp));
|
||||
}
|
||||
if (JKQTPIsOKFloat(maxp)) {
|
||||
painter.drawLine(QLineF(xpleftWhisker, maxp, xprightWhisker, maxp));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// draw median
|
||||
if (JKQTPIsOKFloat(medianp)) {
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.setPen(getMedianPen(painter, parent));
|
||||
painter.drawLine(QLineF(medianMin, medianp, medianMax, medianp));
|
||||
}
|
||||
|
||||
// draw mean
|
||||
if (JKQTPIsOKFloat(meanp)) {
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
plotStyledMeanSymbol(parent, painter,xp,meanp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::plotHorizontalViolinplot(JKQTBasePlotter *parent, JKQTPEnhancedPainter &painter, double yp, double ypbottom, double yptop, const QVector<double> &violin_cat, const QVector<double> &violin_freq, double minp, double medianp, double maxp, double meanp) const
|
||||
{
|
||||
if (JKQTPIsOKFloat(yp) ) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
|
||||
|
||||
double minstop=medianp;
|
||||
double maxstop=medianp;
|
||||
if (!JKQTPIsOKFloat(minstop) && JKQTPIsOKFloat(meanp)) minstop=meanp;
|
||||
else if (!JKQTPIsOKFloat(minstop) && JKQTPIsOKFloat(maxp)) minstop=maxp;
|
||||
if (!JKQTPIsOKFloat(maxstop) && JKQTPIsOKFloat(meanp)) maxstop=meanp;
|
||||
else if (!JKQTPIsOKFloat(maxstop) && JKQTPIsOKFloat(minp)) maxstop=minp;
|
||||
const double wbot=fabs(ypbottom-yp);
|
||||
const double wtop=fabs(yptop-yp);
|
||||
const double xbottomWhisker=yp+wbot*getRelativeWhiskerWidth();
|
||||
const double xptopWhisker=yp-wtop*getRelativeWhiskerWidth();
|
||||
|
||||
|
||||
|
||||
// draw violin
|
||||
const int NViol=std::min(violin_cat.size(), violin_freq.size());
|
||||
double medianMin=ypbottom;
|
||||
double medianMax=yptop;
|
||||
if (NViol>0) {
|
||||
double fmin=violin_freq[0], fmax=violin_freq[0];
|
||||
for (int i=1; i<NViol; i++) {
|
||||
fmin=std::min(fmin, violin_freq[i]);
|
||||
fmax=std::max(fmax, violin_freq[i]);
|
||||
}
|
||||
|
||||
const double freqFactorr=1.0/fmax*fabs(yptop-yp);
|
||||
const double freqFactorl=1.0/fmax*fabs(ypbottom-yp);
|
||||
|
||||
if (m_violinStyle==ViolinStyle::BoxViolin && NViol>1) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(getLinePen(painter, parent));
|
||||
painter.setBrush(getFillBrush(painter, parent));
|
||||
|
||||
for (int i=0; i<NViol; i++) {
|
||||
if (i==0) {
|
||||
const double hl=(violin_cat[1]-violin_cat[0]);
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
painter.drawRect(QRectF(QPointF(violin_cat.first(), yp+violin_freq[i]*freqFactorl), QPointF(violin_cat.first()+hl/2.0, yp-violin_freq[i]*freqFactorr)));
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawRect(QRectF(QPointF(violin_cat.first(), yp+violin_freq[i]*freqFactorl), QPointF(violin_cat.first()+hl/2.0, yp)));
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawRect(QRectF(QPointF(violin_cat.first(), yp), QPointF(violin_cat.first()+hl/2.0, yp-violin_freq[i]*freqFactorr)));
|
||||
}
|
||||
|
||||
} else if (i>0 && i<NViol-1) {
|
||||
const double hl=(violin_cat[i]-violin_cat[i-1]);
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
painter.drawRect(QRectF(QPointF(violin_cat[i]-hl/2.0, yp+violin_freq[i]*freqFactorl), QPointF(violin_cat[i]+hl/2.0, yp-violin_freq[i]*freqFactorr)));
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawRect(QRectF(QPointF(violin_cat[i]-hl/2.0, yp+violin_freq[i]*freqFactorl), QPointF(violin_cat[i]+hl/2.0, yp)));
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawRect(QRectF(QPointF(violin_cat[i]-hl/2.0, yp), QPointF(violin_cat[i]+hl/2.0, yp-violin_freq[i]*freqFactorr)));
|
||||
}
|
||||
} else if (i==NViol-1) {
|
||||
const double hl=(violin_cat[i]-violin_cat[i-1]);
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
painter.drawRect(QRectF(QPointF(violin_cat[i]-hl/2.0, yp+violin_freq[i]*freqFactorl), QPointF(violin_cat[i], yp-violin_freq[i]*freqFactorr)));
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawRect(QRectF(QPointF(violin_cat[i]-hl/2.0, yp+violin_freq[i]*freqFactorl), QPointF(violin_cat[i], yp)));
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawRect(QRectF(QPointF(violin_cat[i]-hl/2.0, yp), QPointF(violin_cat[i], yp-violin_freq[i]*freqFactorr)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} else if (m_violinStyle==ViolinStyle::SmoothViolin && NViol>1) {
|
||||
QPolygonF pleft, pright;
|
||||
pleft<<QPointF(violin_cat.first(), yp);
|
||||
pright<<QPointF(violin_cat.last(), yp);
|
||||
for (int i=0; i<NViol; i++) {
|
||||
pleft<<QPointF(violin_cat[i], yp+violin_freq[i]*freqFactorl);
|
||||
pright<<QPointF(violin_cat[NViol-1-i], yp-violin_freq[NViol-1-i]*freqFactorr);
|
||||
}
|
||||
pleft<<QPointF(violin_cat.last(), yp);
|
||||
pright<<QPointF(violin_cat.first(), yp);
|
||||
|
||||
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(getLinePen(painter, parent));
|
||||
painter.setBrush(getFillBrush(painter, parent));
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
pleft.append(pright);
|
||||
painter.drawPolygon(pleft);
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawPolygon(pleft);
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawPolygon(pright);
|
||||
}
|
||||
} else if (m_violinStyle==ViolinStyle::StepViolin && NViol>1) {
|
||||
QPolygonF pleft, pright;
|
||||
for (int i=0; i<NViol; i++) {
|
||||
if (i==0) {
|
||||
const double hl=(violin_cat[1]-violin_cat[0]);
|
||||
pleft<<QPointF(violin_cat.first(), yp)
|
||||
<<QPointF(violin_cat.first(), yp+violin_freq[i]*freqFactorl)
|
||||
<<QPointF(violin_cat.first()+hl/2.0, yp+violin_freq[i]*freqFactorl);
|
||||
} else if (i>0 && i<NViol-1) {
|
||||
const double hl=(violin_cat[i]-violin_cat[i-1]);
|
||||
pleft<<QPointF(violin_cat[i]-hl/2.0, yp+violin_freq[i]*freqFactorl)
|
||||
<<QPointF(violin_cat[i]+hl/2.0, yp+violin_freq[i]*freqFactorl);
|
||||
} else if (i==NViol-1) {
|
||||
const double hl=(violin_cat[i]-violin_cat[i-1]);
|
||||
pleft<<QPointF(violin_cat[i]-hl/2.0, yp+violin_freq[i]*freqFactorl)
|
||||
<<QPointF(violin_cat[i], yp+violin_freq[i]*freqFactorl)
|
||||
<<QPointF(violin_cat[i], yp);
|
||||
|
||||
}
|
||||
if (i==0) {
|
||||
const double hr=-fabs(violin_cat[NViol-1]-violin_cat[NViol-2]);
|
||||
pright<<QPointF(violin_cat.last(), yp)
|
||||
<<QPointF(violin_cat.last(), yp-violin_freq.last()*freqFactorr)
|
||||
<<QPointF(violin_cat.last()+hr/2.0, yp-violin_freq.last()*freqFactorr);
|
||||
} else if (i>0 && i<NViol-1) {
|
||||
const double hr=-fabs(violin_cat[NViol-1-i]-violin_cat[NViol-1-i-1]);
|
||||
pright<<QPointF(violin_cat[NViol-1-i]-hr/2.0, yp-violin_freq[NViol-1-i]*freqFactorr)
|
||||
<<QPointF(violin_cat[NViol-1-i]+hr/2.0, yp-violin_freq[NViol-1-i]*freqFactorr);
|
||||
} else if (i==NViol-1) {
|
||||
const double hr=-fabs(violin_cat[1]-violin_cat[0]);
|
||||
pright<<QPointF(violin_cat[0]-hr/2.0, yp-violin_freq[0]*freqFactorr)
|
||||
<<QPointF(violin_cat[0], yp-violin_freq[0]*freqFactorr)
|
||||
<<QPointF(violin_cat[0], yp);
|
||||
}
|
||||
}
|
||||
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(getLinePen(painter, parent));
|
||||
painter.setBrush(getFillBrush(painter, parent));
|
||||
if (m_violinPositionMode==ViolinBoth) {
|
||||
pleft.append(pright);
|
||||
painter.drawPolygon(pleft);
|
||||
} else if (m_violinPositionMode==ViolinLeft) {
|
||||
painter.drawPolygon(pleft);
|
||||
} else if (m_violinPositionMode==ViolinRight) {
|
||||
painter.drawPolygon(pright);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// whisker lines
|
||||
painter.setPen(getWhiskerPen(painter, parent));
|
||||
if (JKQTPIsOKFloat(minp) && JKQTPIsOKFloat(minstop)) {
|
||||
painter.drawLine(QLineF(minp, yp, minstop, yp));
|
||||
}
|
||||
if (JKQTPIsOKFloat(maxp) && JKQTPIsOKFloat(maxstop)) {
|
||||
painter.drawLine(QLineF(maxp, yp, maxstop, yp));
|
||||
}
|
||||
|
||||
// whisker caps
|
||||
if (JKQTPIsOKFloat(xptopWhisker) && JKQTPIsOKFloat(xbottomWhisker)){
|
||||
painter.setPen(getWhiskerCapPen(painter, parent));
|
||||
if (JKQTPIsOKFloat(minp)) {
|
||||
painter.drawLine(QLineF(minp, xptopWhisker, minp, xbottomWhisker));
|
||||
}
|
||||
if (JKQTPIsOKFloat(maxp)) {
|
||||
painter.drawLine(QLineF(maxp, xptopWhisker, maxp, xbottomWhisker));
|
||||
}
|
||||
}
|
||||
|
||||
// draw median
|
||||
if (JKQTPIsOKFloat(medianp)) {
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.setPen(getMedianPen(painter, parent));
|
||||
painter.drawLine(QLineF(medianp, medianMin, medianp, medianMax));
|
||||
}
|
||||
|
||||
// draw mean
|
||||
if (JKQTPIsOKFloat(meanp)) {
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
plotStyledMeanSymbol(parent, painter,meanp,yp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::plotVerticalKeyMarker(JKQTBasePlotter *parent, JKQTPEnhancedPainter &painter, const QRectF &rect)
|
||||
{
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
QPen p=getLinePenForRects(painter, parent);
|
||||
QPen pw=getWhiskerPen(painter, parent);
|
||||
QPen pm=getMedianPen(painter, parent);
|
||||
QPen np(Qt::NoPen);
|
||||
QBrush b=getFillBrush(painter, parent);
|
||||
|
||||
p.setWidthF(qMin(0.5, p.widthF()));
|
||||
p.setStyle(Qt::SolidLine);
|
||||
pw.setWidthF(qMin(0.5, pw.widthF()));
|
||||
pw.setStyle(Qt::SolidLine);
|
||||
pm.setWidthF(qMin(0.5, pm.widthF()));
|
||||
pm.setStyle(Qt::SolidLine);
|
||||
|
||||
const double x=rect.left()+rect.width()/2.0;
|
||||
const double xma=x+rect.width()/2.5;
|
||||
const double xmi=x-rect.width()/2.5;
|
||||
const double min=rect.bottom();
|
||||
const double max=rect.top();
|
||||
const double median=max+rect.height()/2.0;
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
path.moveTo(x,max);
|
||||
path.cubicTo(x,max+rect.height()/4.0,xma,median-rect.height()/4.0,xma,median);
|
||||
path.cubicTo(xma,median+rect.height()/4.0,x,min-rect.height()/4.0,x,min);
|
||||
path.cubicTo(x,min-rect.height()/4.0,xmi,median+rect.height()/4.0,xmi,median);
|
||||
path.cubicTo(xmi,median-rect.height()/4.0,x,max+rect.height()/4.0,x,max);
|
||||
|
||||
|
||||
painter.setPen(p);
|
||||
{
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setBrush(b);
|
||||
painter.drawPath(path);
|
||||
}
|
||||
|
||||
painter.setPen(pm);
|
||||
painter.drawLine(QLineF(xmi, median, xma, median));
|
||||
painter.setPen(pw);
|
||||
painter.drawLine(QLineF(x, max, x, min));
|
||||
}
|
||||
|
||||
|
||||
void JKQTPGraphViolinplotStyleMixin::plotHorizontalKeyMarker(JKQTBasePlotter *parent, JKQTPEnhancedPainter &painter, const QRectF &rect)
|
||||
{
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
|
||||
painter.translate(rect.center());
|
||||
painter.rotate(90);
|
||||
painter.translate(-1.0*rect.height()/2.0, -1.0*rect.width()/2.0);
|
||||
plotVerticalKeyMarker(parent, painter, QRectF(0,0,rect.height(),rect.width()));
|
||||
}
|
427
lib/jkqtplotter/jkqtpgraphsviolinplotstylingmixins.h
Normal file
@ -0,0 +1,427 @@
|
||||
/*
|
||||
Copyright (c) 2008-2019 Jan W. Krieger (<jan@jkrieger.de>)
|
||||
|
||||
|
||||
|
||||
This software is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License (LGPL) as published by
|
||||
the Free Software Foundation, either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License (LGPL) for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License (LGPL)
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <QString>
|
||||
#include <QPainter>
|
||||
#include "jkqtplotter/jkqtptools.h"
|
||||
#include "jkqtcommon/jkqtp_imexport.h"
|
||||
#include "jkqtplotter/jkqtpgraphsbase.h"
|
||||
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
|
||||
|
||||
#ifndef jkqtpgraphsviolinplotstylingmixins_H
|
||||
#define jkqtpgraphsviolinplotstylingmixins_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Styling Mix-In for Violinplots
|
||||
\ingroup jkqtplotter_basegraphs_stylemixins
|
||||
|
||||
|
||||
\image html JKQTPViolinplotHorizontalElement_elements.png
|
||||
|
||||
*/
|
||||
class JKQTP_LIB_EXPORT JKQTPGraphViolinplotStyleMixin: public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin {
|
||||
Q_GADGET
|
||||
public:
|
||||
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPGraphViolinplotStyleMixin();
|
||||
|
||||
void initViolinplotStyle(JKQTBasePlotter* parent, int &parentPlotStyle);
|
||||
/*! \copydoc violinWidthAbsolute */
|
||||
void setViolinWidthAbsolute(double __value);
|
||||
/*! \copydoc violinWidthAbsolute */
|
||||
double getViolinWidthAbsolute() const;
|
||||
|
||||
/*! \copydoc relativeWhiskerWidth */
|
||||
void setRelativeWhiskerWidth(double __value);
|
||||
/*! \copydoc relativeWhiskerWidth */
|
||||
double getRelativeWhiskerWidth() const;
|
||||
|
||||
|
||||
/*! \brief set the line style of whisker lines */
|
||||
void setWhiskerLineStyle(Qt::PenStyle __value);
|
||||
/*! \brief get the line style of whisker lines */
|
||||
Qt::PenStyle getWhiskerLineStyle() const;
|
||||
|
||||
/*! \brief set the width [pt] of whisker lines */
|
||||
void setWhiskerLineWidth(double __value);
|
||||
/*! \brief get the width [pt] of whisker lines */
|
||||
double getWhiskerLineWidth() const;
|
||||
|
||||
/*! \brief set the color of whisker lines */
|
||||
void setWhiskerLineColor(QColor __value);
|
||||
/*! \brief get the color of whisker lines */
|
||||
QColor getWhiskerLineColor() const;
|
||||
|
||||
|
||||
/** \brief sets the dash offset for a custom dash style of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashOffset
|
||||
*/
|
||||
void setWhiskerLineDashOffset(qreal offset);
|
||||
/** \brief returns the dash offset for a custom dash style of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashOffset
|
||||
*/
|
||||
qreal getWhiskerLineDashOffset() const;
|
||||
/** \brief sets the dash pattern for a custom dash style of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashPattern
|
||||
*/
|
||||
void setWhiskerLineDashPattern(const QVector<qreal> &pattern);
|
||||
/** \brief gets the dash pattern for a custom dash style of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashPattern
|
||||
*/
|
||||
QVector<qreal> getWhiskerLineDashPattern() const;
|
||||
/** \brief sets the join style of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setJoinStyle
|
||||
*/
|
||||
void setWhiskerLineJoinStyle(Qt::PenJoinStyle style);
|
||||
/** \brief returns the join style of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setJoinStyle
|
||||
*/
|
||||
Qt::PenJoinStyle getWhiskerLineJoinStyle() const;
|
||||
/** \brief sets the cap style of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setCapStyle
|
||||
*/
|
||||
void setWhiskerLineCapStyle(Qt::PenCapStyle style);
|
||||
/** \brief gets the cap style of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setCapStyle
|
||||
*/
|
||||
Qt::PenCapStyle getWhiskerLineCapStyle() const;
|
||||
/** \brief sets the brush used to fill the line area of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setBrush
|
||||
*/
|
||||
void setWhiskerLineBrush(const QBrush& style);
|
||||
/** \brief gets the brush used to fill the line area of whisker lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setBrush
|
||||
*/
|
||||
QBrush getWhiskerLineBrush() const;
|
||||
|
||||
/** \brief build a pen to be used for drawing whiskers */
|
||||
QPen getWhiskerPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const;
|
||||
|
||||
|
||||
|
||||
/*! \brief set the line style of whisker cap lines */
|
||||
void setWhiskerCapLineStyle(Qt::PenStyle __value);
|
||||
/*! \brief get the line style of whisker cap lines */
|
||||
Qt::PenStyle getWhiskerCapLineStyle() const;
|
||||
|
||||
/*! \brief set the width [pt] of whisker cap lines */
|
||||
void setWhiskerCapLineWidth(double __value);
|
||||
/*! \brief get the width [pt] of whisker cap lines */
|
||||
double getWhiskerCapLineWidth() const;
|
||||
|
||||
/*! \brief set the color of whisker cap lines */
|
||||
void setWhiskerCapLineColor(QColor __value);
|
||||
/*! \brief get the color of whisker cap lines */
|
||||
QColor getWhiskerCapLineColor() const;
|
||||
|
||||
|
||||
/** \brief sets the dash offset for a custom dash style of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashOffset
|
||||
*/
|
||||
void setWhiskerCapLineDashOffset(qreal offset);
|
||||
/** \brief returns the dash offset for a custom dash style of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashOffset
|
||||
*/
|
||||
qreal getWhiskerCapLineDashOffset() const;
|
||||
/** \brief sets the dash pattern for a custom dash style of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashPattern
|
||||
*/
|
||||
void setWhiskerCapLineDashPattern(const QVector<qreal> &pattern);
|
||||
/** \brief gets the dash pattern for a custom dash style of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashPattern
|
||||
*/
|
||||
QVector<qreal> getWhiskerCapLineDashPattern() const;
|
||||
/** \brief sets the join style of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setJoinStyle
|
||||
*/
|
||||
void setWhiskerCapLineJoinStyle(Qt::PenJoinStyle style);
|
||||
/** \brief returns the join style of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setJoinStyle
|
||||
*/
|
||||
Qt::PenJoinStyle getWhiskerCapLineJoinStyle() const;
|
||||
/** \brief sets the cap style of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setCapStyle
|
||||
*/
|
||||
void setWhiskerCapLineCapStyle(Qt::PenCapStyle style);
|
||||
/** \brief gets the cap style of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setCapStyle
|
||||
*/
|
||||
Qt::PenCapStyle getWhiskerCapLineCapStyle() const;
|
||||
/** \brief sets the brush used to fill the line area of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setBrush
|
||||
*/
|
||||
void setWhiskerCapLineBrush(const QBrush& style);
|
||||
/** \brief gets the brush used to fill the line area of whisker cap lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setBrush
|
||||
*/
|
||||
QBrush getWhiskerCapLineBrush() const;
|
||||
|
||||
/** \brief build a pen to be used for drawing whisker caps */
|
||||
QPen getWhiskerCapPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const;
|
||||
|
||||
|
||||
|
||||
/*! \brief set the line style of median lines */
|
||||
void setMedianLineStyle(Qt::PenStyle __value);
|
||||
/*! \brief get the line style of median lines */
|
||||
Qt::PenStyle getMedianLineStyle() const;
|
||||
|
||||
/*! \brief set the width [pt] of median lines */
|
||||
void setMedianLineWidth(double __value);
|
||||
/*! \brief get the width [pt] of median lines */
|
||||
double getMedianLineWidth() const;
|
||||
|
||||
/*! \brief set the color of median lines */
|
||||
void setMedianLineColor(QColor __value);
|
||||
/*! \brief get the color of median lines */
|
||||
QColor getMedianLineColor() const;
|
||||
|
||||
|
||||
/** \brief sets the dash offset for a custom dash style of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashOffset
|
||||
*/
|
||||
void setMedianLineDashOffset(qreal offset);
|
||||
/** \brief returns the dash offset for a custom dash style of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashOffset
|
||||
*/
|
||||
qreal getMedianLineDashOffset() const;
|
||||
/** \brief sets the dash pattern for a custom dash style of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashPattern
|
||||
*/
|
||||
void setMedianLineDashPattern(const QVector<qreal> &pattern);
|
||||
/** \brief gets the dash pattern for a custom dash style of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashPattern
|
||||
*/
|
||||
QVector<qreal> getMedianLineDashPattern() const;
|
||||
/** \brief sets the join style of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setJoinStyle
|
||||
*/
|
||||
void setMedianLineJoinStyle(Qt::PenJoinStyle style);
|
||||
/** \brief returns the join style of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setJoinStyle
|
||||
*/
|
||||
Qt::PenJoinStyle getMedianLineJoinStyle() const;
|
||||
/** \brief sets the cap style of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setCapStyle
|
||||
*/
|
||||
void setMedianLineCapStyle(Qt::PenCapStyle style);
|
||||
/** \brief gets the cap style of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setCapStyle
|
||||
*/
|
||||
Qt::PenCapStyle getMedianLineCapStyle() const;
|
||||
/** \brief sets the brush used to fill the line area of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setBrush
|
||||
*/
|
||||
void setMedianLineBrush(const QBrush& style);
|
||||
/** \brief gets the brush used to fill the line area of median lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setBrush
|
||||
*/
|
||||
QBrush getMedianLineBrush() const;
|
||||
|
||||
/** \brief build a pen to be used for drawing medians */
|
||||
QPen getMedianPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief set the line style of Mean lines */
|
||||
void setMeanLineStyle(Qt::PenStyle __value);
|
||||
/*! \brief get the line style of Mean lines */
|
||||
Qt::PenStyle getMeanLineStyle() const;
|
||||
/** \brief sets the dash offset for a custom dash style of Mean lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashOffset
|
||||
*/
|
||||
void setMeanLineDashOffset(qreal offset);
|
||||
/** \brief returns the dash offset for a custom dash style of Mean lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashOffset
|
||||
*/
|
||||
qreal getMeanLineDashOffset() const;
|
||||
/** \brief sets the dash pattern for a custom dash style of Mean lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashPattern
|
||||
*/
|
||||
void setMeanLineDashPattern(const QVector<qreal> &pattern);
|
||||
/** \brief gets the dash pattern for a custom dash style of Mean lines
|
||||
* \see https://doc.qt.io/qt-5/qpen.html#setDashPattern
|
||||
*/
|
||||
QVector<qreal> getMeanLineDashPattern() const;
|
||||
/** \brief set the type of the symbol for the mean */
|
||||
void setMeanSymbolType(JKQTPGraphSymbols __value);
|
||||
/** \brief get the type of the symbol for the mean */
|
||||
JKQTPGraphSymbols getMeanSymbolType() const;
|
||||
|
||||
/** \brief set the size (=diameter in pt) of the symbol for the mean (in pt) */
|
||||
void setMeanSize(double __value);
|
||||
/** \brief get the size (=diameter in pt) of the symbol for the mean (in pt) */
|
||||
double getMeanSize() const;
|
||||
|
||||
/** \brief set the color of the symbol for the mean, or mean line */
|
||||
void setMeanColor(const QColor & __value);
|
||||
/** \brief set the color of the symbol for the mean, or mean line */
|
||||
QColor getMeanColor() const;
|
||||
|
||||
/** \brief set the color of filling of the symbol for the mean */
|
||||
void setMeanFillColor(const QColor & __value);
|
||||
/** \brief set the color of filling of the symbol for the mean */
|
||||
QColor getMeanFillColor() const;
|
||||
|
||||
/** \brief set the line width of the symbol for the mean outline, or mean line (in pt) */
|
||||
void setMeanLineWidth(double __value);
|
||||
/** \brief get the line width of the symbol for the mean outline, or mean line (in pt) */
|
||||
double getMeanLineWidth() const;
|
||||
|
||||
/** \brief defines how to draw the violin graph */
|
||||
enum ViolinStyle {
|
||||
SmoothViolin, /*!< \brief connect all violin points by lines, resulting in a (nearly) smooth curve \image html JKQTPGraphViolinplot_SmoothViolin.png */
|
||||
StepViolin, /*!< \brief connect violin points by a steped line, but fully filled \image html JKQTPGraphViolinplot_StepViolin.png */
|
||||
BoxViolin, /*!< \brief violin datapoints are drawn like a boxplot \image html JKQTPGraphViolinplot_BoxViolin.png */
|
||||
};
|
||||
|
||||
/** \brief returns the style of the violin plot */
|
||||
ViolinStyle getViolinStyle() const;
|
||||
/** \brief set the style of the violin plot */
|
||||
void setViolinStyle(ViolinStyle style);
|
||||
|
||||
/** \brief defines where to draw the violin graph with respect to the violin center position */
|
||||
enum ViolinPositionMode {
|
||||
ViolinLeft, /*!< \brief draw violin on the left hand side only (for vertical violins) \image html JKQTPGraphViolinplot_ViolinLeft.png */
|
||||
ViolinBottom=ViolinLeft, /*!< \brief draw violin on the bottom side only (for horizontal violins) \image html JKQTPGraphViolinplot_ViolinBottom.png */
|
||||
ViolinRight, /*!< \brief draw violin on the right hand side only (for vertical violins) \image html JKQTPGraphViolinplot_ViolinRight.png */
|
||||
ViolinTop=ViolinRight, /*!< \brief draw violin on the top side only (for horizontal violins) \image html JKQTPGraphViolinplot_ViolinTop.png */
|
||||
ViolinBoth /*!< \brief draw violin on the left+right or top+bottom side \image html JKQTPGraphViolinplot_ViolinBoth.png \image html JKQTPGraphViolinplot_ViolinHBoth.png */
|
||||
};
|
||||
|
||||
/** \brief returns the position mode of the violin plot */
|
||||
ViolinPositionMode getViolinPositionMode() const;
|
||||
/** \brief set the position mode of the violin plot */
|
||||
void setViolinPositionMode(ViolinPositionMode positionMode);
|
||||
|
||||
|
||||
/** \brief constructs a QPen from the line styling properties to draw the mean line */
|
||||
QPen getMeanLinePen(JKQTPEnhancedPainter &painter, JKQTBasePlotter* parent) const;
|
||||
/** \brief constructs a QPen from the line styling properties to draw the mean symbol */
|
||||
QPen getMeanSymbolPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter* parent) const;
|
||||
/** \brief constructs a QPen from the line styling properties */
|
||||
QBrush getMeanSymbolBrush(JKQTPEnhancedPainter &painter, JKQTBasePlotter* parent) const;
|
||||
|
||||
/*! \brief set the color of the graph (colors all elements, based on the given color \a c )*/
|
||||
void setViolinplotColor(QColor c, JKQTBasePlotter *parent);
|
||||
|
||||
/*! \brief set the color of the graph (colors all elements, based on the given color \a c , sets background colors from \a bc )*/
|
||||
void setViolinplotColor(QColor c, QColor bc, JKQTBasePlotter *parent);
|
||||
protected:
|
||||
/*! \brief plot a symbol at location x,y (in painter coordinates), using the current style
|
||||
|
||||
\param parent parent JKQTBasePlotter of the graph that uses this mix-in (used e.g. for line-width transformation)
|
||||
\param painter the <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a> to draw to
|
||||
\param x x-coordinate of the symbol center
|
||||
\param y y-coordinate of the symbol center
|
||||
*/
|
||||
void plotStyledMeanSymbol(JKQTBasePlotter* parent, JKQTPEnhancedPainter &painter, double x, double y) const;
|
||||
/** \brief draws a vertical boxplot, with all coordinates/sizes given in coordinates of the given painter,
|
||||
* using the style properties declared in this class. Provide a parameter with \c JKQTP_NAN of you
|
||||
* don't want it to be drawn, or don't know its value
|
||||
*
|
||||
* \param parent parent JKQTBasePlotter of the graph that uses this mix-in (used e.g. for line-width transformation)
|
||||
* \param painter the <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a> to draw to
|
||||
* \param xp x-coordinate of the boxplot center
|
||||
* \param xpleft x-coordinate of the boxplot box left edge
|
||||
* \param xpright x-coordinate of the boxplot box right edge
|
||||
* \param violin_cat category-dataset for the violin (y-values of KDE/histogram/...)
|
||||
* \param violin_freq frequency/count-dataset for the violin (y-values/frequencies of KDE/histogram/...)
|
||||
* \param minp y-coordinate of the minimum (lower whisker)
|
||||
* \param medianp y-coordinate the median
|
||||
* \param maxp y-coordinate of the maximum (upper whisker)
|
||||
* \param meanp y-coordinate of the mean (symbol or line)
|
||||
*/
|
||||
void plotVerticalViolinplot(JKQTBasePlotter* parent, JKQTPEnhancedPainter &painter, double xp, double xpleft, double xpright, const QVector<double> &violin_cat, const QVector<double>& violin_freq, double minp, double medianp, double maxp, double meanp=JKQTP_NAN) const;
|
||||
|
||||
/** \brief draws a horizontal boxplot, with all coordinates/sizes given in coordinates of the given painter,
|
||||
* using the style properties declared in this class. Provide a parameter with \c JKQTP_NAN of you
|
||||
* don't want it to be drawn, or don't know its value
|
||||
*
|
||||
* \param parent parent JKQTBasePlotter of the graph that uses this mix-in (used e.g. for line-width transformation)
|
||||
* \param painter the <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a> to draw to
|
||||
* \param yp y-coordinate of the boxplot center
|
||||
* \param ypbottom y-coordinate of the boxplot box bottom edge
|
||||
* \param yptop y-coordinate of the boxplot box top edge
|
||||
* \param violin_cat category-dataset for the violin (x-values of KDE/histogram/...)
|
||||
* \param violin_freq frequency/count-dataset for the violin (y-values/frequencies of KDE/histogram/...)
|
||||
* \param minp x-coordinate of the minimum (lower whisker)
|
||||
* \param medianp x-coordinate the median
|
||||
* \param maxp x-coordinate of the maximum (upper whisker)
|
||||
* \param meanp x-coordinate of the mean (symbol or line)
|
||||
*/
|
||||
void plotHorizontalViolinplot(JKQTBasePlotter* parent, JKQTPEnhancedPainter &painter, double yp, double ypbottom, double yptop, const QVector<double>& violin_cat, const QVector<double>& violin_freq, double minp, double medianp, double maxp, double meanp=JKQTP_NAN) const;
|
||||
|
||||
/** \brief draw a small, stylized, vertical symbol into \a rect that symbolizes a boxplot, e.g. in a plot legend */
|
||||
void plotVerticalKeyMarker(JKQTBasePlotter* parent, JKQTPEnhancedPainter &painter, const QRectF& rect);
|
||||
|
||||
/** \brief draw a small, stylized, horizontal symbol into \a rect that symbolizes a boxplot, e.g. in a plot legend */
|
||||
void plotHorizontalKeyMarker(JKQTBasePlotter* parent, JKQTPEnhancedPainter &painter, const QRectF& rect);
|
||||
private:
|
||||
/** \brief which symbol to use for the datapoints */
|
||||
JKQTPGraphSymbols m_meanSymbolType;
|
||||
/** \brief size (diameter in pt) of the symbol for the data points, given in pt */
|
||||
double m_meanSymbolSize;
|
||||
/** \brief outline color of the symbol or line pen of the mean-line */
|
||||
QPen m_meanSymbolLinePen;
|
||||
/** \brief color of the symbol filling */
|
||||
QColor m_meanSymbolFillColor;
|
||||
/** \brief width (in pt) of the lines used to plot the symbol for the data points, given in pt */
|
||||
double m_meanSymbolLineWidth;
|
||||
/** \brief line style of the whisker lines */
|
||||
QPen m_whiskerLinePen;
|
||||
/** \brief line width (in pt) of the whisker lines */
|
||||
double whiskerLineWidth;
|
||||
/** \brief line style of the whisker cap lines */
|
||||
QPen m_whiskerCapLinePen;
|
||||
/** \brief line width (in pt) of the whisker cap lines */
|
||||
double whiskerCapLineWidth;
|
||||
/** \brief line style of the median lines */
|
||||
QPen m_medianLinePen;
|
||||
/** \brief line width (in pt) of the median lines */
|
||||
double medianLineWidth;
|
||||
/** \brief width of box in pt.
|
||||
*
|
||||
* \note If several boxplots are drawn, the width is typically calculated,
|
||||
* based on a relative width and the position distances, see JKQTPBoxplotVerticalGraph::boxWidthRelative */
|
||||
double violinWidthAbsolute;
|
||||
/** \brief width of the whiskers, relative to the box width (default: 0.5) */
|
||||
double relativeWhiskerWidth;
|
||||
|
||||
/** \brief the style of the violin plot */
|
||||
ViolinStyle m_violinStyle;
|
||||
|
||||
/** \brief the position mode of the violin plot */
|
||||
ViolinPositionMode m_violinPositionMode;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // jkqtpgraphsviolinplotstylingmixins_H
|
BIN
screenshots/jkqtplotter_simpletest_violinplot_hor.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
screenshots/jkqtplotter_simpletest_violinplot_small.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
screenshots/jkqtplotter_simpletest_violinplot_vert.png
Normal file
After Width: | Height: | Size: 38 KiB |