improved/breaking change: reworked class hierarchy of boxplots

This commit is contained in:
jkriege2 2020-09-21 13:40:38 +02:00
parent f368855076
commit 40e4b30c45
7 changed files with 758 additions and 552 deletions

View File

@ -32,6 +32,7 @@ Changes, compared to \ref page_whatsnew_V2019_11 "v2019.11" include:
<li>improved/breaking change: reworked class hierarchy of special line (step) graphs.</li>
<li>improved/breaking change: reworked class hierarchy of filled line graphs.</li>
<li>improved/breaking change: reworked class hierarchy of range plot elements (JKQTPVerticalRange and JKQTPHorizontalRange).</li>
<li>improved/breaking change: reworked class hierarchy of boxplots.</li>
<li>improved/breaking change: reworked graph Base-Classes (promoted several setters to slots, added Q_PROPERTY- and Q_ENUM-declarations...)</li>
<li>improved/breaking change: made more functions and function parameters const</li>
<li>bugfixed/improved: aspect ratio handling in JKQTPlotter.</li>

View File

@ -25,6 +25,7 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
$$PWD/jkqtplotter/jkqtpcoordinateaxesstyle.h \
$$PWD/jkqtplotter/jkqtpimagetools.h \
$$PWD/jkqtplotter/graphs/jkqtpboxplot.h \
$$PWD/jkqtplotter/graphs/jkqtpboxplotbase.h \
$$PWD/jkqtplotter/graphs/jkqtpboxplotstylingmixins.h \
$$PWD/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.h \
$$PWD/jkqtplotter/graphs/jkqtpevaluatedfunction.h \
@ -75,6 +76,7 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
$$PWD/jkqtplotter/jkqtpcoordinateaxes.cpp \
$$PWD/jkqtplotter/jkqtpcoordinateaxesstyle.cpp \
$$PWD/jkqtplotter/graphs/jkqtpboxplot.cpp \
$$PWD/jkqtplotter/graphs/jkqtpboxplotbase.cpp \
$$PWD/jkqtplotter/graphs/jkqtpboxplotstylingmixins.cpp \
$$PWD/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.cpp \
$$PWD/jkqtplotter/graphs/jkqtpevaluatedfunction.cpp \

View File

@ -43,6 +43,7 @@ set(SOURCES_GRAPHS
graphs/jkqtpbarchartbase.cpp
graphs/jkqtpbarchart.cpp
graphs/jkqtpboxplot.cpp
graphs/jkqtpboxplotbase.cpp
graphs/jkqtpboxplotstylingmixins.cpp
graphs/jkqtpevaluatedfunctionbase.cpp
graphs/jkqtpevaluatedfunction.cpp
@ -93,6 +94,7 @@ set(HEADERS
)
set(HEADERS_GRAPHS
graphs/jkqtpboxplot.h
graphs/jkqtpboxplotbase.h
graphs/jkqtpboxplotstylingmixins.h
graphs/jkqtpevaluatedfunctionbase.h
graphs/jkqtpevaluatedfunction.h

View File

@ -34,7 +34,7 @@
JKQTPBoxplotVerticalGraph::JKQTPBoxplotVerticalGraph(JKQTBasePlotter* parent):
JKQTPGraph(parent)
JKQTPBoxplotGraphBase(parent)
{
boxWidthRelative=0.4;
useRelativeBoxWidth=true;
@ -296,171 +296,22 @@ bool JKQTPBoxplotVerticalGraph::getYMinMax(double& miny, double& maxy, double& s
return !start;
}
bool JKQTPBoxplotVerticalGraph::usesColumn(int c) const
{
return (c==meanColumn)||(c==posColumn)||(c==medianColumn)||(c==minColumn)||(c==maxColumn)||(c==percentile25Column)||(c==percentile75Column);
}
void JKQTPBoxplotVerticalGraph::setDataSortOrder(JKQTPBoxplotVerticalGraph::DataSortOrder __value)
{
this->sortData = __value;
}
JKQTPBoxplotVerticalGraph::DataSortOrder JKQTPBoxplotVerticalGraph::getDataSortOrder() const
{
return this->sortData;
}
void JKQTPBoxplotVerticalGraph::setDataSortOrder(int __value) {
sortData=static_cast<DataSortOrder>(__value);
if (__value>0) sortData=Sorted;
}
void JKQTPBoxplotVerticalGraph::setPositionColumn(int __value)
{
this->posColumn = __value;
}
int JKQTPBoxplotVerticalGraph::getPositionColumn() const
{
return this->posColumn;
}
void JKQTPBoxplotVerticalGraph::setPositionColumn(size_t __value) {
this->posColumn = static_cast<int>(__value);
}
void JKQTPBoxplotVerticalGraph::setMedianColumn(int __value)
{
this->medianColumn = __value;
}
int JKQTPBoxplotVerticalGraph::getMedianColumn() const
{
return this->medianColumn;
}
void JKQTPBoxplotVerticalGraph::setMedianColumn(size_t __value) {
this->medianColumn = static_cast<int>(__value);
}
void JKQTPBoxplotVerticalGraph::setMeanColumn(int __value)
{
this->meanColumn = __value;
}
int JKQTPBoxplotVerticalGraph::getMeanColumn() const
{
return this->meanColumn;
}
void JKQTPBoxplotVerticalGraph::setMeanColumn(size_t __value) {
this->meanColumn = static_cast<int>(__value);
}
void JKQTPBoxplotVerticalGraph::setMinColumn(int __value)
{
this->minColumn = __value;
}
int JKQTPBoxplotVerticalGraph::getMinColumn() const
{
return this->minColumn;
}
void JKQTPBoxplotVerticalGraph::setMinColumn(size_t __value) {
this->minColumn = static_cast<int>(__value);
}
void JKQTPBoxplotVerticalGraph::setMaxColumn(int __value)
{
this->maxColumn = __value;
}
int JKQTPBoxplotVerticalGraph::getMaxColumn() const
{
return this->maxColumn;
}
void JKQTPBoxplotVerticalGraph::setMaxColumn(size_t __value) {
this->maxColumn = static_cast<int>(__value);
}
void JKQTPBoxplotVerticalGraph::setPercentile25Column(int __value)
{
this->percentile25Column = __value;
}
int JKQTPBoxplotVerticalGraph::getPercentile25Column() const
{
return this->percentile25Column;
}
void JKQTPBoxplotVerticalGraph::setPercentile25Column(size_t __value) {
this->percentile25Column = static_cast<int>(__value);
}
void JKQTPBoxplotVerticalGraph::setPercentile75Column(int __value)
{
this->percentile75Column = __value;
}
int JKQTPBoxplotVerticalGraph::getPercentile75Column() const
{
return this->percentile75Column;
}
void JKQTPBoxplotVerticalGraph::setPercentile75Column(size_t __value) {
this->percentile75Column = static_cast<int>(__value);
}
int JKQTPBoxplotVerticalGraph::getMedianConfidenceColumn() const
{
return medianConfidenceColumn;
}
void JKQTPBoxplotVerticalGraph::setMedianConfidenceColumn(size_t __value)
{
medianConfidenceColumn=static_cast<int>(__value);
}
void JKQTPBoxplotVerticalGraph::setBoxWidthRelative(double __value)
{
this->boxWidthRelative = __value;
}
double JKQTPBoxplotVerticalGraph::getBoxWidthRelative() const
{
return this->boxWidthRelative;
}
void JKQTPBoxplotVerticalGraph::setUseRelativeBoxWidth(bool __value)
{
useRelativeBoxWidth=__value;
}
bool JKQTPBoxplotVerticalGraph::getUseRelativeBoxWidth() const
{
return useRelativeBoxWidth;
}
void JKQTPBoxplotVerticalGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
plotVerticalKeyMarker(parent, painter, rect);
}
QColor JKQTPBoxplotVerticalGraph::getKeyLabelColor() const {
return getLineColor();
}
void JKQTPBoxplotVerticalGraph::setColor(QColor c)
JKQTPBoxplotHorizontalGraph::JKQTPBoxplotHorizontalGraph(JKQTBasePlotter *parent):
JKQTPBoxplotGraphBase(parent)
{
setBoxplotColor(c, getParent());
}
JKQTPBoxplotHorizontalGraph::JKQTPBoxplotHorizontalGraph(JKQTPlotter *parent):
JKQTPBoxplotHorizontalGraph(parent->getPlotter())
{
}
void JKQTPBoxplotHorizontalGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
plotHorizontalKeyMarker(parent, painter, rect);
@ -558,15 +409,6 @@ bool JKQTPBoxplotHorizontalGraph::getYMinMax(double& minx, double& maxx, double&
return !start;
}
JKQTPBoxplotHorizontalGraph::JKQTPBoxplotHorizontalGraph(JKQTBasePlotter *parent):
JKQTPBoxplotVerticalGraph(parent)
{
}
JKQTPBoxplotHorizontalGraph::JKQTPBoxplotHorizontalGraph(JKQTPlotter *parent):
JKQTPBoxplotHorizontalGraph(parent->getPlotter())
{
}
void JKQTPBoxplotHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
#ifdef JKQTBP_AUTOTIMER
@ -730,7 +572,7 @@ void JKQTPBoxplotHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
JKQTPBoxplotVerticalElement::JKQTPBoxplotVerticalElement(JKQTBasePlotter* parent):
JKQTPGeometricPlotElement(DrawAsGraphicElement, parent)
JKQTPBoxplotElementBase(parent)
{
pos=JKQTP_NAN;
median=JKQTP_NAN;
@ -921,157 +763,23 @@ bool JKQTPBoxplotVerticalElement::getYMinMax(double& miny, double& maxy, double&
return true;
}
void JKQTPBoxplotVerticalElement::setPos(double __value)
{
this->pos = __value;
}
double JKQTPBoxplotVerticalElement::getPos() const
{
return this->pos;
}
void JKQTPBoxplotVerticalElement::setMedian(double __value)
{
if (this->median != __value) {
this->median = __value;
drawMedian=true;
}
}
double JKQTPBoxplotVerticalElement::getMedian() const
{
return this->median;
}
void JKQTPBoxplotVerticalElement::setMedianConfidenceIntervalWidth(double __value)
{
if (this->medianConfidenceIntervalWidth != __value) {
this->medianConfidenceIntervalWidth = __value;
drawNotch=true;
}
}
double JKQTPBoxplotVerticalElement::getMedianConfidenceIntervalWidth() const
{
return this->medianConfidenceIntervalWidth;
}
void JKQTPBoxplotVerticalElement::setMean(double __value)
{
if (this->mean != __value) {
this->mean = __value;
drawMean=true;
}
}
double JKQTPBoxplotVerticalElement::getMean() const
{
return this->mean;
}
void JKQTPBoxplotVerticalElement::setMin(double __value)
{
if (this->min != __value) {
this->min = __value;
drawMinMax=true;
}
}
double JKQTPBoxplotVerticalElement::getMin() const
{
return this->min;
}
void JKQTPBoxplotVerticalElement::setMax(double __value)
{
if (this->max != __value) {
this->max = __value;
drawMinMax=true;
}
}
double JKQTPBoxplotVerticalElement::getMax() const
{
return this->max;
}
void JKQTPBoxplotVerticalElement::setPercentile25(double __value)
{
this->percentile25 = __value;
}
double JKQTPBoxplotVerticalElement::getPercentile25() const
{
return this->percentile25;
}
void JKQTPBoxplotVerticalElement::setPercentile75(double __value)
{
this->percentile75 = __value;
}
double JKQTPBoxplotVerticalElement::getPercentile75() const
{
return this->percentile75;
}
void JKQTPBoxplotVerticalElement::setDrawMean(bool __value)
{
this->drawMean = __value;
}
bool JKQTPBoxplotVerticalElement::getDrawMean() const
{
return this->drawMean;
}
void JKQTPBoxplotVerticalElement::setDrawMedian(bool __value)
{
this->drawMedian = __value;
}
bool JKQTPBoxplotVerticalElement::getDrawMedian() const
{
return this->drawMedian;
}
void JKQTPBoxplotVerticalElement::setDrawMinMax(bool __value)
{
this->drawMinMax = __value;
}
bool JKQTPBoxplotVerticalElement::getDrawMinMax() const
{
return this->drawMinMax;
}
void JKQTPBoxplotVerticalElement::setDrawNotch(bool __value)
{
drawNotch=__value;
}
bool JKQTPBoxplotVerticalElement::getDrawNotch() const
{
return drawNotch;
}
void JKQTPBoxplotVerticalElement::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
plotVerticalKeyMarker(parent, painter, rect);
}
QColor JKQTPBoxplotVerticalElement::getKeyLabelColor() const {
return getLineColor();
}
void JKQTPBoxplotVerticalElement::setColor(QColor c)
JKQTPBoxplotHorizontalElement::JKQTPBoxplotHorizontalElement(JKQTBasePlotter *parent):
JKQTPBoxplotElementBase(parent)
{
setBoxplotColor(c, getParent());
}
JKQTPBoxplotHorizontalElement::JKQTPBoxplotHorizontalElement(JKQTPlotter *parent):
JKQTPBoxplotHorizontalElement(parent->getPlotter())
{
}
void JKQTPBoxplotHorizontalElement::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
plotHorizontalKeyMarker(parent, painter, rect);
@ -1132,16 +840,6 @@ bool JKQTPBoxplotHorizontalElement::getYMinMax(double& miny, double& maxy, doubl
}
JKQTPBoxplotHorizontalElement::JKQTPBoxplotHorizontalElement(JKQTBasePlotter *parent):
JKQTPBoxplotVerticalElement(parent)
{
}
JKQTPBoxplotHorizontalElement::JKQTPBoxplotHorizontalElement(JKQTPlotter *parent):
JKQTPBoxplotHorizontalElement(parent->getPlotter())
{
}
void JKQTPBoxplotHorizontalElement::draw(JKQTPEnhancedPainter& painter) {
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaaot("JKQTPBoxplotHorizontalElement::draw");
@ -1254,39 +952,3 @@ void JKQTPBoxplotHorizontalElement::draw(JKQTPEnhancedPainter& painter) {
void JKQTPBoxplotVerticalGraph::intSortData()
{
sortedIndices.clear();
if (parent==nullptr) return ;
JKQTPDatastore* datastore=parent->getDatastore();
int imin=0;
int imax=static_cast<int>(datastore->getRows(static_cast<size_t>(posColumn)));
if (imax<imin) {
int h=imin;
imin=imax;
imax=h;
}
if (imin<0) imin=0;
if (imax<0) imax=0;
QVector<double> datas;
if (sortData==JKQTPBoxplotVerticalGraph::Sorted) {
for (int i=0; i<imax; i++) {
double xv=datastore->get(posColumn,static_cast<size_t>(i));
sortedIndices<<i;
datas<<xv;
}
jkqtpQuicksortDual(datas.data(), sortedIndices.data(), datas.size());
}
}

View File

@ -25,6 +25,7 @@
#include "jkqtplotter/jkqtplotter_imexport.h"
#include "jkqtplotter/jkqtpimagetools.h"
#include "jkqtplotter/jkqtpgraphsbase.h"
#include "jkqtplotter/graphs/jkqtpboxplotbase.h"
#include "jkqtplotter/graphs/jkqtpboxplotstylingmixins.h"
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
@ -98,17 +99,10 @@
\see \ref JKQTPlotterBoxplotsGraphs, jkqtpstatVAddBoxplots(),\ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat, \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotStyling
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPGraph, public JKQTPGraphBoxplotStyleMixin {
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPBoxplotGraphBase {
Q_OBJECT
public:
/** \brief Sort order in a JKQTPBoxplotVerticalGraph (or one of its child classes) */
enum DataSortOrder {
Unsorted=0,
Sorted=1
};
/** \brief class constructor */
JKQTPBoxplotVerticalGraph(JKQTBasePlotter* parent=nullptr);
@ -119,11 +113,6 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPGraph, publi
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
*
@ -136,108 +125,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPGraph, publi
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
/** \copydoc JKQTPGraph::usesColumn() */
virtual bool usesColumn(int c) const override;
/*! \copydoc sortData */
void setDataSortOrder(DataSortOrder __value);
/*! \copydoc sortData */
DataSortOrder getDataSortOrder() const;
/*! \copydoc sortData */
void setDataSortOrder(int __value);
/*! \copydoc posColumn */
void setPositionColumn(int __value);
/*! \copydoc posColumn */
int getPositionColumn() const;
/*! \copydoc posColumn */
void setPositionColumn (size_t __value);
/*! \copydoc medianColumn */
void setMedianColumn(int __value);
/*! \copydoc medianColumn */
int getMedianColumn() const;
/*! \copydoc medianColumn */
void setMedianColumn (size_t __value);
/*! \copydoc meanColumn */
void setMeanColumn(int __value);
/*! \copydoc meanColumn */
int getMeanColumn() const;
/*! \copydoc meanColumn */
void setMeanColumn (size_t __value);
/*! \copydoc minColumn */
void setMinColumn(int __value);
/*! \copydoc minColumn */
int getMinColumn() const;
/*! \copydoc minColumn */
void setMinColumn( size_t __value);
/*! \copydoc maxColumn */
void setMaxColumn(int __value);
/*! \copydoc maxColumn */
int getMaxColumn() const;
/*! \copydoc maxColumn */
void setMaxColumn (size_t __value);
/*! \copydoc percentile25Column */
void setPercentile25Column(int __value);
/*! \copydoc percentile25Column */
int getPercentile25Column() const;
/*! \copydoc percentile25Column */
void setPercentile25Column (size_t __value);
/*! \copydoc percentile75Column */
void setPercentile75Column(int __value);
/*! \copydoc percentile75Column */
int getPercentile75Column() const;
/*! \copydoc percentile75Column */
void setPercentile75Column (size_t __value);
/*! \copydoc medianConfidenceColumn */
int getMedianConfidenceColumn() const;
/*! \copydoc medianConfidenceColumn */
void setMedianConfidenceColumn (size_t __value);
/*! \copydoc boxWidthRelative */
void setBoxWidthRelative(double __value);
/*! \copydoc boxWidthRelative */
double getBoxWidthRelative() const;
/*! \copydoc useRelativeBoxWidth */
void setUseRelativeBoxWidth(bool __value);
/*! \copydoc useRelativeBoxWidth */
bool getUseRelativeBoxWidth() const;
protected:
/** \brief width of box in percent of distance between the current two posColumn values
* if we only plot one box&whiskers then JKQTPGraphBoxplotStyleMixin::boxWidthAbsolute in pt is used */
double boxWidthRelative;
/** \brief if set \c true, boxplot widths are calculated automatically, based on boxWidthRelative,
* otherwise JKQTPGraphBoxplotStyleMixin::boxWidthAbsolute is used. */
bool useRelativeBoxWidth;
/** \brief the column that contains the x-component of the datapoints */
int posColumn;
/** \brief the column that contains the median-component of the datapoints */
int medianColumn;
/** \brief the column that contains the confidence interval width of the median (e.g. 1.57*IQR/sqrt(n) ). This is used to draw a notch in the plot (if set) */
int medianConfidenceColumn;
/** \brief the column that contains the median-component of the datapoints. \note This column is strictly optional. */
int meanColumn;
/** \brief the column that contains the minimum-component of the datapoints */
int minColumn;
/** \brief the column that contains the maximum-component of the datapoints */
int maxColumn;
/** \brief the column that contains the 25% percentile-component of the datapoints */
int percentile25Column;
/** \brief the column that contains the 75% percentile-component of the datapoints */
int percentile75Column;
/** \brief if \c !=Unsorted, the data is sorted before plotting */
DataSortOrder sortData;
/** \brief this array contains the order of indices, in which to access the data in the data columns */
QVector<int> sortedIndices;
virtual void intSortData() ;
inline int getDataIndex(int i) {
if (sortData==Unsorted) return i;
return sortedIndices.value(i,i);
}
};
@ -255,7 +143,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPGraph, publi
\see JKQTPBoxplotVerticalGraph \ref JKQTPlotterBoxplotsGraphs, jkqtpstatHAddBoxplots(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat, \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotStyling
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotHorizontalGraph: public JKQTPBoxplotVerticalGraph {
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotHorizontalGraph: public JKQTPBoxplotGraphBase {
Q_OBJECT
public:
/** \brief class constructor */
@ -309,7 +197,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotHorizontalGraph: public JKQTPBoxplotVer
\see jkqtpstatVAddBoxplot(), \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotsGraphs, \ref JKQTPlotterBoxplotStyling, jkqtpstatAddVBoxplotAndOutliers()
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalElement: public JKQTPGeometricPlotElement, public JKQTPGraphBoxplotStyleMixin {
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalElement: public JKQTPBoxplotElementBase {
Q_OBJECT
public:
/** \brief class constructor */
@ -321,10 +209,6 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalElement: public JKQTPGeometricP
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
@ -339,82 +223,9 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalElement: public JKQTPGeometricP
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 percentile25 */
void setPercentile25(double __value);
/*! \copydoc percentile25 */
double getPercentile25() const;
/*! \copydoc percentile75 */
void setPercentile75(double __value);
/*! \copydoc percentile75 */
double getPercentile75() 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 drawNotch */
void setDrawNotch(bool __value);
/*! \copydoc drawNotch */
bool getDrawNotch() const;
/*! \copydoc medianConfidenceIntervalWidth */
double getMedianConfidenceIntervalWidth() const;
/*! \copydoc medianConfidenceIntervalWidth */
void setMedianConfidenceIntervalWidth(double __value);
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 width of the confidence interval around the median */
double medianConfidenceIntervalWidth;
/** \brief indicates whether to draw a notch with width medianConfidenceIntervalWidth */
bool drawNotch;
/** \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 the 25% percentile value to be used for the boxplot */
double percentile25;
/** \brief the 75% percentile value to be used for the boxplot */
double percentile75;
};
@ -433,7 +244,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalElement: public JKQTPGeometricP
\see JKQTPBoxplotVerticalElement, jkqtpstatHAddBoxplot(), \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotsGraphs, \ref JKQTPlotterBoxplotStyling, jkqtpstatAddHBoxplotAndOutliers()
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotHorizontalElement: public JKQTPBoxplotVerticalElement {
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotHorizontalElement: public JKQTPBoxplotElementBase {
Q_OBJECT
public:
/** \brief class constructor */

View File

@ -0,0 +1,440 @@
/*
Copyright (c) 2008-2020 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/graphs/jkqtpboxplotbase.h"
#include "jkqtplotter/jkqtpbaseplotter.h"
#include <stdlib.h>
#include <QDebug>
#include <iostream>
#include "jkqtplotter/jkqtptools.h"
#include "jkqtplotter/graphs/jkqtpimage.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;
JKQTPBoxplotGraphBase::JKQTPBoxplotGraphBase(JKQTBasePlotter* parent):
JKQTPGraph(parent)
{
boxWidthRelative=0.4;
useRelativeBoxWidth=true;
posColumn=-1;
medianColumn=-1;
meanColumn=-1;
minColumn=-1;
maxColumn=-1;
percentile25Column=-1;
percentile75Column=-1;
medianConfidenceColumn=-1;
sortData=Unsorted;
initBoxplotStyle(parent, parentPlotStyle);
setMeanSymbolType(JKQTPPlus);
}
bool JKQTPBoxplotGraphBase::usesColumn(int c) const
{
return (c==meanColumn)||(c==posColumn)||(c==medianColumn)||(c==minColumn)||(c==maxColumn)||(c==percentile25Column)||(c==percentile75Column);
}
void JKQTPBoxplotGraphBase::setDataSortOrder(JKQTPBoxplotGraphBase::DataSortOrder __value)
{
this->sortData = __value;
}
JKQTPBoxplotGraphBase::DataSortOrder JKQTPBoxplotGraphBase::getDataSortOrder() const
{
return this->sortData;
}
void JKQTPBoxplotGraphBase::setDataSortOrder(int __value) {
sortData=static_cast<DataSortOrder>(__value);
if (__value>0) sortData=Sorted;
}
void JKQTPBoxplotGraphBase::setPositionColumn(int __value)
{
this->posColumn = __value;
}
int JKQTPBoxplotGraphBase::getPositionColumn() const
{
return this->posColumn;
}
void JKQTPBoxplotGraphBase::setPositionColumn(size_t __value) {
this->posColumn = static_cast<int>(__value);
}
void JKQTPBoxplotGraphBase::setMedianColumn(int __value)
{
this->medianColumn = __value;
}
int JKQTPBoxplotGraphBase::getMedianColumn() const
{
return this->medianColumn;
}
void JKQTPBoxplotGraphBase::setMedianColumn(size_t __value) {
this->medianColumn = static_cast<int>(__value);
}
void JKQTPBoxplotGraphBase::setMeanColumn(int __value)
{
this->meanColumn = __value;
}
int JKQTPBoxplotGraphBase::getMeanColumn() const
{
return this->meanColumn;
}
void JKQTPBoxplotGraphBase::setMeanColumn(size_t __value) {
this->meanColumn = static_cast<int>(__value);
}
void JKQTPBoxplotGraphBase::setMinColumn(int __value)
{
this->minColumn = __value;
}
int JKQTPBoxplotGraphBase::getMinColumn() const
{
return this->minColumn;
}
void JKQTPBoxplotGraphBase::setMinColumn(size_t __value) {
this->minColumn = static_cast<int>(__value);
}
void JKQTPBoxplotGraphBase::setMaxColumn(int __value)
{
this->maxColumn = __value;
}
int JKQTPBoxplotGraphBase::getMaxColumn() const
{
return this->maxColumn;
}
void JKQTPBoxplotGraphBase::setMaxColumn(size_t __value) {
this->maxColumn = static_cast<int>(__value);
}
void JKQTPBoxplotGraphBase::setPercentile25Column(int __value)
{
this->percentile25Column = __value;
}
int JKQTPBoxplotGraphBase::getPercentile25Column() const
{
return this->percentile25Column;
}
void JKQTPBoxplotGraphBase::setPercentile25Column(size_t __value) {
this->percentile25Column = static_cast<int>(__value);
}
void JKQTPBoxplotGraphBase::setPercentile75Column(int __value)
{
this->percentile75Column = __value;
}
int JKQTPBoxplotGraphBase::getPercentile75Column() const
{
return this->percentile75Column;
}
void JKQTPBoxplotGraphBase::setPercentile75Column(size_t __value) {
this->percentile75Column = static_cast<int>(__value);
}
int JKQTPBoxplotGraphBase::getMedianConfidenceColumn() const
{
return medianConfidenceColumn;
}
void JKQTPBoxplotGraphBase::setMedianConfidenceColumn(size_t __value)
{
medianConfidenceColumn=static_cast<int>(__value);
}
void JKQTPBoxplotGraphBase::setBoxWidthRelative(double __value)
{
this->boxWidthRelative = __value;
}
double JKQTPBoxplotGraphBase::getBoxWidthRelative() const
{
return this->boxWidthRelative;
}
void JKQTPBoxplotGraphBase::setUseRelativeBoxWidth(bool __value)
{
useRelativeBoxWidth=__value;
}
bool JKQTPBoxplotGraphBase::getUseRelativeBoxWidth() const
{
return useRelativeBoxWidth;
}
QColor JKQTPBoxplotGraphBase::getKeyLabelColor() const {
return getLineColor();
}
void JKQTPBoxplotGraphBase::setColor(QColor c)
{
setBoxplotColor(c, getParent());
}
void JKQTPBoxplotGraphBase::intSortData()
{
sortedIndices.clear();
if (parent==nullptr) return ;
JKQTPDatastore* datastore=parent->getDatastore();
int imin=0;
int imax=static_cast<int>(datastore->getRows(static_cast<size_t>(posColumn)));
if (imax<imin) {
int h=imin;
imin=imax;
imax=h;
}
if (imin<0) imin=0;
if (imax<0) imax=0;
QVector<double> datas;
if (sortData==JKQTPBoxplotGraphBase::Sorted) {
for (int i=0; i<imax; i++) {
double xv=datastore->get(posColumn,static_cast<size_t>(i));
sortedIndices<<i;
datas<<xv;
}
jkqtpQuicksortDual(datas.data(), sortedIndices.data(), datas.size());
}
}
JKQTPBoxplotElementBase::JKQTPBoxplotElementBase(JKQTBasePlotter* parent):
JKQTPPlotElement(parent)
{
pos=JKQTP_NAN;
median=JKQTP_NAN;
mean=JKQTP_NAN;
min=JKQTP_NAN;
max=JKQTP_NAN;
drawMean=false;
drawMinMax=false;
percentile25=JKQTP_NAN;
percentile75=JKQTP_NAN;
medianConfidenceIntervalWidth=JKQTP_NAN;
drawNotch=false;
initBoxplotStyle(parent, parentPlotStyle);
setMeanSymbolType(JKQTPPlus);
}
JKQTPBoxplotElementBase::JKQTPBoxplotElementBase(JKQTPlotter* parent):
JKQTPBoxplotElementBase(parent->getPlotter())
{
}
void JKQTPBoxplotElementBase::setPos(double __value)
{
this->pos = __value;
}
double JKQTPBoxplotElementBase::getPos() const
{
return this->pos;
}
void JKQTPBoxplotElementBase::setMedian(double __value)
{
if (this->median != __value) {
this->median = __value;
drawMedian=true;
}
}
double JKQTPBoxplotElementBase::getMedian() const
{
return this->median;
}
void JKQTPBoxplotElementBase::setMedianConfidenceIntervalWidth(double __value)
{
if (this->medianConfidenceIntervalWidth != __value) {
this->medianConfidenceIntervalWidth = __value;
drawNotch=true;
}
}
double JKQTPBoxplotElementBase::getMedianConfidenceIntervalWidth() const
{
return this->medianConfidenceIntervalWidth;
}
void JKQTPBoxplotElementBase::setMean(double __value)
{
if (this->mean != __value) {
this->mean = __value;
drawMean=true;
}
}
double JKQTPBoxplotElementBase::getMean() const
{
return this->mean;
}
void JKQTPBoxplotElementBase::setMin(double __value)
{
if (this->min != __value) {
this->min = __value;
drawMinMax=true;
}
}
double JKQTPBoxplotElementBase::getMin() const
{
return this->min;
}
void JKQTPBoxplotElementBase::setMax(double __value)
{
if (this->max != __value) {
this->max = __value;
drawMinMax=true;
}
}
double JKQTPBoxplotElementBase::getMax() const
{
return this->max;
}
void JKQTPBoxplotElementBase::setPercentile25(double __value)
{
this->percentile25 = __value;
}
double JKQTPBoxplotElementBase::getPercentile25() const
{
return this->percentile25;
}
void JKQTPBoxplotElementBase::setPercentile75(double __value)
{
this->percentile75 = __value;
}
double JKQTPBoxplotElementBase::getPercentile75() const
{
return this->percentile75;
}
void JKQTPBoxplotElementBase::setDrawMean(bool __value)
{
this->drawMean = __value;
}
bool JKQTPBoxplotElementBase::getDrawMean() const
{
return this->drawMean;
}
void JKQTPBoxplotElementBase::setDrawMedian(bool __value)
{
this->drawMedian = __value;
}
bool JKQTPBoxplotElementBase::getDrawMedian() const
{
return this->drawMedian;
}
void JKQTPBoxplotElementBase::setDrawMinMax(bool __value)
{
this->drawMinMax = __value;
}
bool JKQTPBoxplotElementBase::getDrawMinMax() const
{
return this->drawMinMax;
}
void JKQTPBoxplotElementBase::setDrawNotch(bool __value)
{
drawNotch=__value;
}
bool JKQTPBoxplotElementBase::getDrawNotch() const
{
return drawNotch;
}
QColor JKQTPBoxplotElementBase::getKeyLabelColor() const {
return getLineColor();
}
void JKQTPBoxplotElementBase::setColor(QColor c)
{
setBoxplotColor(c, getParent());
}

View File

@ -0,0 +1,288 @@
/*
Copyright (c) 2008-2020 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 "jkqtplotter/jkqtplotter_imexport.h"
#include "jkqtplotter/jkqtpimagetools.h"
#include "jkqtplotter/jkqtpgraphsbase.h"
#include "jkqtplotter/graphs/jkqtpboxplotstylingmixins.h"
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
#ifndef jkqtpgraphsboxplotbase_H
#define jkqtpgraphsboxplotbase_H
/** \brief Base class for graphs representing a series of <a href="http://en.wikipedia.org/wiki/Box_plot">boxplot</a>, elements
* \ingroup jkqtplotter_statgraphs
*
* \image html plot_boxplotvertical.png
*
*
* The different features of a boxplot are:
*
* \image html plot_boxplotverticalelement.png
*
* \see JKQTPBoxplotVerticalGraph, JKQTPBoxplotHorizontalGraph, JKQTPBoxplotElementBase
*
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotGraphBase: public JKQTPGraph, public JKQTPGraphBoxplotStyleMixin {
Q_OBJECT
public:
/** \brief Sort order in a JKQTPBoxplotVerticalGraph (or one of its child classes) */
enum DataSortOrder {
Unsorted=0,
Sorted=1
};
/** \brief class constructor */
JKQTPBoxplotGraphBase(JKQTBasePlotter* parent=nullptr);
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor() const override;
/** \copydoc JKQTPGraph::usesColumn() */
virtual bool usesColumn(int c) const override;
/*! \copydoc sortData */
DataSortOrder getDataSortOrder() const;
/*! \copydoc posColumn */
int getPositionColumn() const;
/*! \copydoc medianColumn */
int getMedianColumn() const;
/*! \copydoc meanColumn */
int getMeanColumn() const;
/*! \copydoc minColumn */
int getMinColumn() const;
/*! \copydoc maxColumn */
int getMaxColumn() const;
/*! \copydoc percentile25Column */
int getPercentile25Column() const;
/*! \copydoc percentile75Column */
int getPercentile75Column() const;
/*! \copydoc medianConfidenceColumn */
int getMedianConfidenceColumn() const;
/*! \copydoc boxWidthRelative */
double getBoxWidthRelative() const;
/*! \copydoc useRelativeBoxWidth */
bool getUseRelativeBoxWidth() const;
public slots:
/*! \brief set the color of the graph (colors all elements, based on the given color \a c )*/
virtual void setColor(QColor c);
/*! \copydoc sortData */
void setDataSortOrder(DataSortOrder __value);
/*! \copydoc sortData */
void setDataSortOrder(int __value);
/*! \copydoc posColumn */
void setPositionColumn(int __value);
/*! \copydoc posColumn */
void setPositionColumn (size_t __value);
/*! \copydoc medianColumn */
void setMedianColumn(int __value);
/*! \copydoc medianColumn */
void setMedianColumn (size_t __value);
/*! \copydoc meanColumn */
void setMeanColumn(int __value);
/*! \copydoc meanColumn */
void setMeanColumn (size_t __value);
/*! \copydoc minColumn */
void setMinColumn(int __value);
/*! \copydoc minColumn */
void setMinColumn( size_t __value);
/*! \copydoc maxColumn */
void setMaxColumn(int __value);
/*! \copydoc maxColumn */
void setMaxColumn (size_t __value);
/*! \copydoc percentile25Column */
void setPercentile25Column(int __value);
/*! \copydoc percentile25Column */
void setPercentile25Column (size_t __value);
/*! \copydoc percentile75Column */
void setPercentile75Column(int __value);
/*! \copydoc percentile75Column */
void setPercentile75Column (size_t __value);
/*! \copydoc medianConfidenceColumn */
void setMedianConfidenceColumn (size_t __value);
/*! \copydoc boxWidthRelative */
void setBoxWidthRelative(double __value);
/*! \copydoc useRelativeBoxWidth */
void setUseRelativeBoxWidth(bool __value);
protected:
/** \brief width of box in percent of distance between the current two posColumn values
* if we only plot one box&whiskers then JKQTPGraphBoxplotStyleMixin::boxWidthAbsolute in pt is used */
double boxWidthRelative;
/** \brief if set \c true, boxplot widths are calculated automatically, based on boxWidthRelative,
* otherwise JKQTPGraphBoxplotStyleMixin::boxWidthAbsolute is used. */
bool useRelativeBoxWidth;
/** \brief the column that contains the x-component of the datapoints */
int posColumn;
/** \brief the column that contains the median-component of the datapoints */
int medianColumn;
/** \brief the column that contains the confidence interval width of the median (e.g. 1.57*IQR/sqrt(n) ). This is used to draw a notch in the plot (if set) */
int medianConfidenceColumn;
/** \brief the column that contains the median-component of the datapoints. \note This column is strictly optional. */
int meanColumn;
/** \brief the column that contains the minimum-component of the datapoints */
int minColumn;
/** \brief the column that contains the maximum-component of the datapoints */
int maxColumn;
/** \brief the column that contains the 25% percentile-component of the datapoints */
int percentile25Column;
/** \brief the column that contains the 75% percentile-component of the datapoints */
int percentile75Column;
/** \brief if \c !=Unsorted, the data is sorted before plotting */
DataSortOrder sortData;
/** \brief this array contains the order of indices, in which to access the data in the data columns */
QVector<int> sortedIndices;
/** \brief generates a map from unsorted to sorted data \see getDataIndex() */
virtual void intSortData() ;
/** \brief retrieves the index of the i-th element when data is sorted (after calling intSortData(), which generates a map from unsorted to sorted data */
inline int getDataIndex(int i) const {
if (sortData==Unsorted) return i;
return sortedIndices.value(i,i);
}
};
/** \brief Tbaseclass for a single <a href="http://en.wikipedia.org/wiki/Box_plot">(notched) boxplot</a> as a "geometric element",
* where the data is directly given to the object and not stored in a column, as in JKQTPBoxplotGraphBase
* \ingroup jkqtplotter_statgraphs
* \ingroup jkqtplotter_diverse
*
* The different features of a boxplot are:
*
* \image html plot_boxplotverticalelement.png
*
* \see JKQTPBoxplotElementBase, JKQTPBoxplotHorizontalElement, JKQTPBoxplotGraphBase
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotElementBase: public JKQTPPlotElement, public JKQTPGraphBoxplotStyleMixin {
Q_OBJECT
public:
/** \brief class constructor */
JKQTPBoxplotElementBase(JKQTBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPBoxplotElementBase(JKQTPlotter* parent);
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor() const override;
/*! \copydoc pos */
double getPos() const;
/*! \copydoc median */
double getMedian() const;
/*! \copydoc mean */
double getMean() const;
/*! \copydoc min */
double getMin() const;
/*! \copydoc max */
double getMax() const;
/*! \copydoc percentile25 */
double getPercentile25() const;
/*! \copydoc percentile75 */
double getPercentile75() const;
/*! \copydoc drawMean */
void setDrawMean(bool __value);
/*! \copydoc drawMean */
bool getDrawMean() const;
/*! \copydoc drawMedian */
bool getDrawMedian() const;
/*! \copydoc drawMinMax */
bool getDrawMinMax() const;
/*! \copydoc drawNotch */
bool getDrawNotch() const;
/*! \copydoc medianConfidenceIntervalWidth */
double getMedianConfidenceIntervalWidth() const;
public slots:
/*! \brief set the color of the graph (colors all elements, based on the given color \a c )*/
virtual void setColor(QColor c);
/*! \copydoc pos */
void setPos(double __value);
/*! \copydoc median */
void setMedian(double __value);
/*! \copydoc min */
void setMin(double __value);
/*! \copydoc mean */
void setMean(double __value);
/*! \copydoc max */
void setMax(double __value);
/*! \copydoc percentile25 */
void setPercentile25(double __value);
/*! \copydoc percentile75 */
void setPercentile75(double __value);
/*! \copydoc drawMedian */
void setDrawMedian(bool __value);
/*! \copydoc drawMinMax */
void setDrawMinMax(bool __value);
/*! \copydoc drawNotch */
void setDrawNotch(bool __value);
/*! \copydoc medianConfidenceIntervalWidth */
void setMedianConfidenceIntervalWidth(double __value);
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 width of the confidence interval around the median */
double medianConfidenceIntervalWidth;
/** \brief indicates whether to draw a notch with width medianConfidenceIntervalWidth */
bool drawNotch;
/** \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 the 25% percentile value to be used for the boxplot */
double percentile25;
/** \brief the 75% percentile value to be used for the boxplot */
double percentile75;
};
#endif // jkqtpgraphsboxplotbase_H