diff --git a/JKQtPlotterBuildAllExamples.pro b/JKQtPlotterBuildAllExamples.pro
index c9dffb0628..47119df0c4 100644
--- a/JKQtPlotterBuildAllExamples.pro
+++ b/JKQtPlotterBuildAllExamples.pro
@@ -86,6 +86,7 @@ addSimpleTest(datastore_statistics_2d)
addSimpleTest(datastore_regression)
addSimpleTest(datastore_groupedstat)
addSimpleTest(contourplot)
+addSimpleTest(violinplot)
#addSimpleTest(rgbimageplot_opencv)
#addSimpleTest(imageplot_opencv)
diff --git a/doc/dox/examples_and_tutorials.dox b/doc/dox/examples_and_tutorials.dox
index 0d2a421b2b..81674e058b 100644
--- a/doc/dox/examples_and_tutorials.dox
+++ b/doc/dox/examples_and_tutorials.dox
@@ -62,6 +62,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
+ \image html JKQTPViolinplotVerticalElement.png
+ | JKQTPViolinplotVerticalElement, JKQTPViolinplotHorizontalElement
Examples:
diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox
index dd8a64fda7..3282888a0a 100644
--- a/doc/dox/whatsnew.dox
+++ b/doc/dox/whatsnew.dox
@@ -26,7 +26,7 @@ Changes, compared to \ref page_whatsnew_V2018_08 "v2018.08" include:
changed: using static const variables instead of #define for fixed default values (e.g. JKQTPImageTools::LUTSIZE, JKQTPImageTools::PALETTE_ICON_WIDTH, JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, JKQTMathText::ABS_MIN_LINEWIDTH ...)
Updates to JKQTPlotter:
- - new: added JKQTPSingleColumnSymbolsGraph for single-column data, e.g. drawn as (random) scatter or bee-swar plots
+ - new: added JKQTPSingleColumnSymbolsGraph for single-column data, e.g. drawn as (random) scatter or bee-swarm or rug plots
- new: stacked barcharts with JKQTPBarVerticalStackableGraph, JKQTPBarHorizontalStackableGraph
- new: use/support of C++11 features (e.g. \c std::function<> and lambda functions in JKQTPXFunctionLineGraph / JKQTPYFunctionLineGraph )
- new: \ref jkqtpopencvinterface "optional OpenCV interface"
@@ -46,6 +46,7 @@ Changes, compared to \ref page_whatsnew_V2018_08 "v2018.08" include:
- new: several new plot symbols, see: JKQTPGraphSymbols
- new: Statistics library with functions to calculate histograms, regression, kernel density estimates, ... see: \ref jkqtptools_math_statistics
- new: iterator interface and improved documentation for JKQTPDatastore
+ - new: violin plots (see \ref JKQTPlotterViolinplotGraphs )
- changed: removed old selection-code and replaced by general highlighting feature
- changed: JKQTPStepHorizontalGraph has been renamed to JKQTPSpecialLineHorizontalGraph (vertical variants also) and have gained additional features (baseline for filling and drawing of symbols)
- changed: filled curve graphs (e.g. JKQTPSpecialLineHorizontalGraph) are now merely a specializedly initialized JKQTPSpecialLineHorizontalGraph
diff --git a/doc/images/JKQTPGraphViolinplot_BoxViolin.png b/doc/images/JKQTPGraphViolinplot_BoxViolin.png
new file mode 100644
index 0000000000..806c2afd16
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_BoxViolin.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_HBoxViolin.png b/doc/images/JKQTPGraphViolinplot_HBoxViolin.png
new file mode 100644
index 0000000000..2276849be6
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_HBoxViolin.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_HSmoothViolin.png b/doc/images/JKQTPGraphViolinplot_HSmoothViolin.png
new file mode 100644
index 0000000000..bc00845036
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_HSmoothViolin.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_HStepViolin.png b/doc/images/JKQTPGraphViolinplot_HStepViolin.png
new file mode 100644
index 0000000000..eb1cae7c20
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_HStepViolin.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_SmoothViolin.png b/doc/images/JKQTPGraphViolinplot_SmoothViolin.png
new file mode 100644
index 0000000000..ed9022029e
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_SmoothViolin.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_StepViolin.png b/doc/images/JKQTPGraphViolinplot_StepViolin.png
new file mode 100644
index 0000000000..d5709383ef
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_StepViolin.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_ViolinBoth.png b/doc/images/JKQTPGraphViolinplot_ViolinBoth.png
new file mode 100644
index 0000000000..dad8ffdac7
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_ViolinBoth.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_ViolinBottom.png b/doc/images/JKQTPGraphViolinplot_ViolinBottom.png
new file mode 100644
index 0000000000..2f964f8ff4
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_ViolinBottom.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_ViolinHBoth.png b/doc/images/JKQTPGraphViolinplot_ViolinHBoth.png
new file mode 100644
index 0000000000..449e90005a
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_ViolinHBoth.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_ViolinLeft.png b/doc/images/JKQTPGraphViolinplot_ViolinLeft.png
new file mode 100644
index 0000000000..035c00e0b9
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_ViolinLeft.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_ViolinRight.png b/doc/images/JKQTPGraphViolinplot_ViolinRight.png
new file mode 100644
index 0000000000..f7f07c3e52
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_ViolinRight.png differ
diff --git a/doc/images/JKQTPGraphViolinplot_ViolinTop.png b/doc/images/JKQTPGraphViolinplot_ViolinTop.png
new file mode 100644
index 0000000000..ef2ca1f0c1
Binary files /dev/null and b/doc/images/JKQTPGraphViolinplot_ViolinTop.png differ
diff --git a/doc/images/JKQTPViolinplotHorizontalElement_elements.png b/doc/images/JKQTPViolinplotHorizontalElement_elements.png
new file mode 100644
index 0000000000..b281c47d27
Binary files /dev/null and b/doc/images/JKQTPViolinplotHorizontalElement_elements.png differ
diff --git a/doc/images/JKQTPViolinplotVerticalElement.png b/doc/images/JKQTPViolinplotVerticalElement.png
new file mode 100644
index 0000000000..9c3bc69657
Binary files /dev/null and b/doc/images/JKQTPViolinplotVerticalElement.png differ
diff --git a/examples/README.md b/examples/README.md
index 79b9240699..dfb1e9cd40 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -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` 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, ...
diff --git a/examples/simpletest_violinplot/README.md b/examples/simpletest_violinplot/README.md
new file mode 100644
index 0000000000..5741663f82
--- /dev/null
+++ b/examples/simpletest_violinplot/README.md
@@ -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 violin plots 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)
+
+
+
+
diff --git a/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.cpp b/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.cpp
new file mode 100644
index 0000000000..7810d9882f
--- /dev/null
+++ b/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.cpp
@@ -0,0 +1,159 @@
+/** \example jkqtplotter_simpletest_violinplot->cpp
+ * Shows how to draw Violin-Plot with JKQTPlotter
+ *
+ * \ref JKQTPlotterViolinplotGraphs
+ */
+
+#include
+#include "jkqtplotter/jkqtplotter.h"
+#include "jkqtplotter/jkqtpgraphsviolinplot.h"
+#include "jkqtplotter/jkqtpgraphssinglecolumnsymbols.h"
+#include "jkqtplotter/jkqtpgraphsstatisticsadaptors.h"
+#include "jkqtcommon/jkqtpstatisticstools.h"
+#include
+#include
+
+template
+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();
+ showPlot();
+
+ return app.exec();
+}
diff --git a/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.pro b/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.pro
new file mode 100644
index 0000000000..abf2985c3c
--- /dev/null
+++ b/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.pro
@@ -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
+
+
diff --git a/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot_and_lib.pro b/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot_and_lib.pro
new file mode 100644
index 0000000000..ee47d6ed2a
--- /dev/null
+++ b/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot_and_lib.pro
@@ -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
diff --git a/lib/jkqtplotter.pri b/lib/jkqtplotter.pri
index d95c3e53df..b1a570af09 100644
--- a/lib/jkqtplotter.pri
+++ b/lib/jkqtplotter.pri
@@ -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 \
@@ -76,7 +78,9 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
$$PWD/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp \
$$PWD/jkqtplotter/jkqtpgraphsimageoverlays.cpp \
$$PWD/jkqtplotter/jkqtpgraphscontour.cpp \
- $$PWD/jkqtplotter/jkqtpgraphsimagergb.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 \
diff --git a/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h b/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h
index 11855908e7..c409eced39 100644
--- a/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h
+++ b/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h
@@ -41,12 +41,13 @@
The second coordinate is:
- if positionScatterStyle==NoScatter it is simply the value of position, e.g. \image html JKQTPSingleColumnSymbolsGraph_NoScatter.png
+ - if positionScatterStyle==RugPlot is like a NoScatter-plot, but with lines instead of symbols (see https://en.wikipedia.org/wiki/Rug_plot) \image html JKQTPSingleColumnSymbolsGraph_RugPlot.png
- if positionScatterStyle==RandomScatter it scatters around position in the range [position-width/2 ... position+width/2], e.g. \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. \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. https://en.wikipedia.org/wiki/Rug_plot). \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. https://www.r-statistics.com/2011/03/beeswarm-boxplot-and-plotting-it-with-r/). 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. https://en.wikipedia.org/wiki/Rug_plot). \image html JKQTPSingleColumnSymbolsGraph_RugPlot.png */
};
/** \brief class constructor */
diff --git a/lib/jkqtplotter/jkqtpgraphsviolinplot.cpp b/lib/jkqtplotter/jkqtpgraphsviolinplot.cpp
new file mode 100644
index 0000000000..23bd07cb44
--- /dev/null
+++ b/lib/jkqtplotter/jkqtpgraphsviolinplot.cpp
@@ -0,0 +1,490 @@
+/*
+ Copyright (c) 2008-2019 Jan W. Krieger ()
+
+
+
+ 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 .
+*/
+
+
+
+#include "jkqtplotter/jkqtpgraphsviolinplot.h"
+#include "jkqtplotter/jkqtpbaseplotter.h"
+#include
+#include
+#include
+#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) || (xvsgzgetPlotter())
+{
+}
+
+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) = ( "<pt2px(painter,getViolinWidthAbsolute());
+ double xma=x+w/2.0;
+ double xmi=x-w/2.0;
+
+ QVector violPos;
+ if (violinPositionColumn>=0) violPos=transformY(getParent()->getDatastore()->getData(static_cast(violinPositionColumn)));
+ QVector violFreq;
+ if (violinFrequencyColumn>=0) violFreq=getParent()->getDatastore()->getData(static_cast(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 && (minmaxy)) maxy=max;
+ if (drawMinMax && (maxpos = __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(__value);
+}
+
+int JKQTPViolinplotVerticalElement::getViolinPositionColumn() const
+{
+ return violinPositionColumn;
+}
+
+void JKQTPViolinplotVerticalElement::setViolinFrequencyColumn(int __value)
+{
+ violinFrequencyColumn=__value;
+}
+
+void JKQTPViolinplotVerticalElement::setViolinFrequencyColumn(size_t __value)
+{
+ violinFrequencyColumn=static_cast(__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 && (minmaxx)) maxx=max;
+ if (drawMinMax && (maxpt2px(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) = ( "<pt2px(painter,getViolinWidthAbsolute());
+ double yma=y+w/2.0;
+ double ymi=y-w/2.0;
+
+ QVector violPos;
+ if (violinPositionColumn>=0) violPos=transformX(getParent()->getDatastore()->getData(static_cast(violinPositionColumn)));
+ QVector violFreq;
+ if (violinFrequencyColumn>=0) violFreq=getParent()->getDatastore()->getData(static_cast(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);
+}
+
+
+
+
diff --git a/lib/jkqtplotter/jkqtpgraphsviolinplot.h b/lib/jkqtplotter/jkqtpgraphsviolinplot.h
new file mode 100644
index 0000000000..692a67045c
--- /dev/null
+++ b/lib/jkqtplotter/jkqtpgraphsviolinplot.h
@@ -0,0 +1,222 @@
+/*
+ Copyright (c) 2008-2019 Jan W. Krieger ()
+
+
+
+ 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 .
+*/
+
+
+#include
+#include
+#include
+#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 Violin Plot 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 Violin Plot 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
diff --git a/lib/jkqtplotter/jkqtpgraphsviolinplotstylingmixins.cpp b/lib/jkqtplotter/jkqtpgraphsviolinplotstylingmixins.cpp
new file mode 100644
index 0000000000..04341f7155
--- /dev/null
+++ b/lib/jkqtplotter/jkqtpgraphsviolinplotstylingmixins.cpp
@@ -0,0 +1,978 @@
+/*
+ Copyright (c) 2008-2019 Jan W. Krieger ()
+
+
+
+ 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 .
+*/
+
+
+
+#include "jkqtplotter/jkqtpgraphsviolinplotstylingmixins.h"
+#include "jkqtplotter/jkqtpbaseplotter.h"
+#include
+#include
+#include
+#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 &pattern)
+{
+ m_meanSymbolLinePen.setDashPattern(pattern);
+ m_meanSymbolLinePen.setStyle(Qt::CustomDashLine);
+}
+
+QVector 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 &pattern)
+{
+ m_medianLinePen.setDashPattern(pattern);
+ m_medianLinePen.setStyle(Qt::CustomDashLine);
+}
+
+QVector 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 &pattern)
+{
+ m_whiskerLinePen.setDashPattern(pattern);
+ m_whiskerLinePen.setStyle(Qt::CustomDashLine);
+}
+
+QVector 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 &pattern)
+{
+ m_whiskerCapLinePen.setDashPattern(pattern);
+ m_whiskerCapLinePen.setStyle(Qt::CustomDashLine);
+}
+
+QVector 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 &violin_cat, const QVector &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; i1) {
+ painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
+ painter.setPen(getLinePen(painter, parent));
+ painter.setBrush(getFillBrush(painter, parent));
+
+ for (int i=0; i0 && i1) {
+ QPolygonF pleft, pright;
+ pleft<1) {
+ QPolygonF pleft, pright;
+ for (int i=0; i0 && i0 && i &violin_cat, const QVector &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; i1) {
+ painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
+ painter.setPen(getLinePen(painter, parent));
+ painter.setBrush(getFillBrush(painter, parent));
+
+ for (int i=0; i0 && i1) {
+ QPolygonF pleft, pright;
+ pleft<1) {
+ QPolygonF pleft, pright;
+ for (int i=0; i0 && i0 && i)
+
+
+
+ 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 .
+*/
+
+
+#include
+#include
+#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 &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 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 &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 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 &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 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 &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 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 QPainter 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 QPainter 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 &violin_cat, const QVector& 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 QPainter 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& violin_cat, const QVector& 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
diff --git a/screenshots/jkqtplotter_simpletest_violinplot_hor.png b/screenshots/jkqtplotter_simpletest_violinplot_hor.png
new file mode 100644
index 0000000000..dcb0ac1475
Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_violinplot_hor.png differ
diff --git a/screenshots/jkqtplotter_simpletest_violinplot_small.png b/screenshots/jkqtplotter_simpletest_violinplot_small.png
new file mode 100644
index 0000000000..4389f9bce6
Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_violinplot_small.png differ
diff --git a/screenshots/jkqtplotter_simpletest_violinplot_vert.png b/screenshots/jkqtplotter_simpletest_violinplot_vert.png
new file mode 100644
index 0000000000..9dd2a34115
Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_violinplot_vert.png differ
|