new: rework/extension of the JKQTPDatastore interface (WIP)

new: Example simpletest_datastore, which demonstrates the extended interface of JKQTPDatastore
This commit is contained in:
jkriege2 2019-05-12 22:22:48 +02:00
parent 34366a42a0
commit 56e54baee9
43 changed files with 1409 additions and 260 deletions

View File

@ -77,6 +77,7 @@ addSimpleTest(ui)
addSimpleTest(boxplot) addSimpleTest(boxplot)
addSimpleTest(advancedlineandfillstyling) addSimpleTest(advancedlineandfillstyling)
addSimpleTest(imageplot_nodatastore) addSimpleTest(imageplot_nodatastore)
addSimpleTest(datastore)
#addSimpleTest(rgbimageplot_opencv) #addSimpleTest(rgbimageplot_opencv)
#addSimpleTest(imageplot_opencv) #addSimpleTest(imageplot_opencv)

View File

@ -143,6 +143,16 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
</table> </table>
\subsection jkqtp_extut_datamanagement Data Management
<table>
<tr><th> Screenshot <th> Description <th> Notes
<tr><td> \image html simpletest_datastore_small.png
<td> \subpage JKQTPlotterAdvancedJKQTPDatastore
<td> Advanced Data Management with JKQTPDatastore
</table>
\subsection jkqtp_extut_complexexamples More Complex Examples \subsection jkqtp_extut_complexexamples More Complex Examples

View File

@ -44,6 +44,8 @@ data sources (internal or external memory arrays. Later on it is simply possible
using the column number and the not a link to the actual data array, as the link is stored in these using the column number and the not a link to the actual data array, as the link is stored in these
classes. classes.
\see \ref JKQTPlotterAdvancedJKQTPDatastore for a detailed description of how to use this class for data management!
\defgroup jkqtpopencvinterface OpenCV Interfaceing Tools \defgroup jkqtpopencvinterface OpenCV Interfaceing Tools
\ingroup jkqtpdatastorage \ingroup jkqtpdatastorage

View File

@ -59,12 +59,21 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
## Plot Layout & Styling ## Data Management
| Screenshot | Description | Notes |
|:-------------:| ------------- | ------------- |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore) | [Advanced Usage of JKQTPDatastore](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore) | Advanced Data Management with JKQTPDatastore |
## More Complex Examples
| Screenshot | Description | Notes | | Screenshot | Description | Notes |
|:-------------:| ------------- | ------------- | |:-------------:| ------------- | ------------- |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/test_multiplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_multiplot) | [Layouting Several Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_multiplot) | Combining plots in Qt Layouts <br> linking plot axes <br> copy data from a `std::map` int the datastore <br> print plots/print preview | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/test_multiplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_multiplot) | [Layouting Several Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_multiplot) | Combining plots in Qt Layouts <br> linking plot axes <br> copy data from a `std::map` int the datastore <br> print plots/print preview |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/test_styling_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_styling) | [Styling of JKQTPlotter](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_styling) | Modifying different Aspects of the Styling of JKQTPlotter | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/test_distributionplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_distributionplot) | [Plotting a Statistical Distribution of Data](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_distributionplot) | Combines several different graphs to draw random values, their distribution and some statistical properties |

View File

@ -0,0 +1,282 @@
# Example (JKQTPlotter): Advanced Usage of JKQTPDatastore {#JKQTPlotterAdvancedJKQTPDatastore}
This project (see `./examples/simpletest_datastore/`) explains several advanced options of JKQTPDatastore, which is the class used to centrally store the data for (most) graphs on a JKQTPlotter widget.
The source code of the main application can be found in [`jkqtplotter_simpletest_datastore.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore/jkqtplotter_simpletest_datastore.cpp).
This tutorial cites parts of this code to demonstrate different ways of working with data for the graphs.
In every code-segment below, we will use these two declarations from the code to access the internal datastore of the JKQTPlotter instance:
```.cpp
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPlotter plot;
JKQTPDatastore* datastore=plot.getDatastore();
```
## Copy Data from different data structures into JKQTPDatastore
### Copy Data from a Vector into a column of the JKQTPDatastore
First we fill data into a QVector for a simple plot (a sine curve) and add a plot using this data:
```.cpp
QVector<double> X, Y;
const int Ndata=100;
for (int i=0; i<Ndata; i++) {
const double x=double(i)/double(Ndata)*8.0*M_PI;
X<<x;
Y<<sin(x);
}
```
Now the contents of the vector is copied into the datastore using `JKQTPDatastore::addCopiedColumn()`. After this operation, the contents of the vectors `X` and `Y` can be altered, as the `JKQTPDatastore` inside the `JKQTPlotter` now hosts its own copy of the data.
```.cpp
plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
linegraph->setXColumn(ds->addCopiedColumn(X, "x"));
linegraph->setYColumn(ds->addCopiedColumn(Y, "y"));
linegraph->setTitle(QObject::tr("sine graph"));
```
Note that you could also use a `std::vector` instead, as `JKQTPDatastore::addCopiedColumn()` is a template function that only requires the container to support C++ standard iterations (with `begin()` and `end()`), as well as the function `size()` to determine the number of items in the container. Also other datatypes than `double` are possible, as long as they can be converted to `double` (the function `jkqtp_todouble()` is used to perform the conversion, notably all integer and floating-point types, as well as `bool` are supported out of the box).
The plot from the code above looks like this:
![simpletest_datastore_sine](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_sine.png)
### Copy Data from a C-array into a column of the JKQTPDatastore
Of course if you have your data in a C-array, you can use the same syntax:
```.cpp
#define NDATA 5
double X[NDATA]= { 1, 2, 3, 4, 5 };
double Y[NDATA]= { 1, 0, 1, 0, 1 };
linegraph->setXColumn(datastore->addCopiedColumn(X, NDATA, "x"));
linegraph->setYColumn(datastore->addCopiedColumn(Y, NDATA, "Y"));
```
The plot from the code above looks like this:
![simpletest_datastore_linkedcarray](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_linkedcarray.png)
### Copy Data from a Map into a JKQTPDatastore
Since graphs often display (x,y)-pairs, it may make sense to store them in a map (e.g. for histograms). There there are also functions that copy the contents of a map into a JKQTPDatastore, resulting in two columns beeing added:
```.cpp
std::map<int, double> datamap;
datamap[1]=1.1;
datamap[2]=1.4;
datamap[4]=1.2;
datamap[5]=1.8;
datamap[7]=0.9;
plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
linegraph->setXYColumns(datastore->addCopiedMap(datamap, "map_x", "map_y"));
linegraph->setTitle(QObject::tr("copied map"));
```
This code results in a graph like this:
![simpletest_datastore_map](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_map.png)
## Reference External Data in a column of the JKQTPDatastore
### Referencing without transfer of ownership
As an alternative to the method of copying data (see above), you could also just link the data. For this to work, the data has to reside in a C-array of type `double`, as this is the internal datatype of the `JKQTPDatastore`. You can simply replace the two lines with `JKQTPDatastore::addCopiedColumn()` in the example above by (we exploit the fact that `QVector<double>::data()` returns a pointer to the internal C-array of the vector):
```.cpp
linegraph->setXColumn(datastore->addColumn(X.data(), X.size(), "x"));
linegraph->setYColumn(datastore->addColumn(Y.data(), Y.size(), "Y"));
```
Of course if you have your data in a C-array, you can use the same syntax:
```.cpp
#define NDATA 5
double XCA[NDATA]= { 1, 2, 3, 4, 5 };
double YCA[NDATA]= { 1, 0, 1, 0, 1 };
linegraph->setXColumn(datastore->addColumn(XCA, NDATA, "x"));
linegraph->setYColumn(datastore->addColumn(YCA, NDATA, "Y"));
```
This method is especially useful, when you have large datasets (e.g. images) that you don't want to copy around.
Note however that the ownership of the data is not transfered to the JKQTPDatastore, i.e. you have to ensure that the data behind the pointer exists, as long as the column references the array and you have to ensure that the data is freed, when you don't need it any more.
The plot from the code above looks like this:
![simpletest_datastore_linkedcarray](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_linkedcarray.png)
### Referencing with transfer of ownership
In addition to the variants of `JKQTPDatastore::addColumn()`, that do not transfer ownership of the data to the `JKQTPDatastore`, you can also use `JKQTPDatastore::addInternalColumn()`, which tells the `JKQTPDatastore` to use the external data array and also take over its owner-ship. This implies that the array is freed when the `JKQTPDatastore` is destroyed, by calling `free()` in the array. Therefor data for this method needs to be allocated by using `malloc()` or `calloc()`:
```.cpp
#define NDATA 5
double* XCA=(double*)malloc(NDATA, sizeof(double));
...
linegraph->setXColumn(datastore->addInternalColumn(XCA, NDATA, "x"));
```
## JKQTPDatastore-internal Data Management
It is also possible to leave the data mangement completely to the JKQTPDatastore and just edit the data with access functions from JKQTPDatastore.
### Generating Columns Non-Initialized Columns and Filling Them
The most basic way to generate data for a plot is to generate two non-initialized columns for the x- and y-coordinates of the graph points
```.cpp
const int Ndata=100;
size_t colX=datastore->addColumn(Ndata, "x");
size_t colY=datastore->addColumn(Ndata, "y");
```
These calls to JKQTPDatastore::addColumn() will generate a column each with with `ndata` uninitialized entries.
Then use JKQTPDatastore::set() to fill them with data:
```.cpp
for (int i=0; i<Ndata; i++) {
const double x=double(i)/double(Ndata)*8.0*M_PI;
datastore->set(colX, i, x);
datastore->set(colY, i, sin(x));
}
```
Plotting these two columns versus each other results in a simple sine graph:
![simpletest_datastore_sine](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_sine.png)
### Generating Columns Preinitialized Columns
For your convenience there are also function that simply create such a linear vector with one call:
```.cpp
size_t colLinX=datastore->addLinearColumn(count, 0, 20, "x_lin");
```
This call is equivalent to
```.cpp
for (size_t i=0; i<count; i++) {
datastore->set(colLinX, i, 0.0+static_cast<double>(i)/static_cast<double>(count-1)*20.0);
}
```
In both cases the column `colLinX` will contain these numbers afterwards:
```
0, 0.512821, 1.02564, 1.53846, 2.05128, 2.5641, 3.07692, ..., 18.9744, 19.4872, 20
```
Comparable functions exist for logarithmically spaced columns (`JKQTPDatastore::addLogColumn()` and `JKQTPDatastore::addDecadeLogColumn()` which only differ in the way the start and end values are specified):
```.cpp
size_t colLogX=datastore->addLogColumn(30, 1, 1000, "x_log");
```
This call results in a column with these 30 values spanning the range between 1 and 1000:
```
1, 1.26896, 1.61026, 2.04336, ..., 8.53168, 10.8264, 13.7382, ..., 72.7895, 92.3671, ..., 788.046, 1000
```
### Using Data from one Column to Calculate Another
After generating columns, as shown above, you can also use the data in these columns to calculate a second column based on the values in the first. You can do this explicitly:
```.cpp
size_t colLinX=datastore->addLinearColumn(40, 0, 20, "x_lin");
size_t colFunc1=datastore->addColumn(datastore->getRows(colLinX), "cos(x_lin)*x_lin/20.0");
for (size_t i=0; i<datastore->getRows(colLinX); i++) {
double x=datastore->get(colLinX, i);
datastore->set(colFunc1, i, cos(x)*x/20.0);
}
```
In this example the function JKQTPDatastore::get() is used to retrieve a value from a column and then JKQTPDatastore::set() is used to store a new value calculated from the read values into another column.
Or use a special function that gets a column with values and a functor f: double->double as parameters:
```.cpp
size_t colLinX=datastore->addLinearColumn(40, 0, 20, "x_lin");
size_t colFunc1=datastore->addColumnCalculatedFromColumn(colLinX, [](double x)->double { return cos(x)*x/20.0; }, "cos(x_lin)*x_lin/20.0");
```
Plotting these two columns versus each other
```.cpp
plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
linegraph->setXColumn(colLinX);
linegraph->setYColumn(colFunc1);
linegraph->setTitle(QObject::tr("calculated column(s)"));
```
results in:
![simpletest_datastore_calccolumns](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_calccolumns.png)
### 2D-Datasets and Images
There is also a function `JKQTPDatastore::addLinearGridColumns(size_t width, double startX, double endX, size_t height, double startY, double endY, const QString &nameX, const QString &nameY)` that generate two columns simultaneously that conatin the x- and y-coordinates of the points on a rectangular grid, in a column-major order:
```.cpp
std::pair<size_t,size_t> colLinXY=datastore->addLinearGridColumns(10, 10, 20, 10, 1.5, 3);
```
This call will generate these columns with x-values scaling between 10 and 20 (in 10 steps) and y-values between 1.5 and 3 (also in 10 steps):
```
x y
----------------------
10, 1.5
11.1111, 1.5
12.2222, 1.5
13.3333, 1.5
14.4444, 1.5
15.5556, 1.5
16.6667, 1.5
17.7778, 1.5
18.8889, 1.5
20, 1.5
10, 1.66667
11.1111, 1.66667
12.2222, 1.66667
13.3333, 1.66667
14.4444, 1.66667
15.5556, 1.66667
16.6667, 1.66667
17.7778, 1.66667
18.8889, 1.66667
20, 1.66667
10, 1.83333
11.1111, 1.83333
... ...
... ...
18.8889, 3
20, 3
```
Such x-y-coordinate columns are especially usefull when calculating data for an image (plotted by `JKQTPColumnMathImage`), or for a parametrized scatter plot (plotted by `JKQTPXYParametrizedScatterGraph`). To demonstrate this, we can can add another column with 10*10=100 entries and fill it with some values calculated from the the x and y-values in colLinXY:
```.cpp
size_t imgColumn=datastore->addImageColumn(10, 10, "image values");
for (size_t i=0; i<datastore->getRows(imgColumn); i++) {
double x=datastore->get(colLinXY.first, i);
double y=datastore->get(colLinXY.second, i);
datastore->set(imgColumn, i, cos((x-15.0))/(x-15.0)*cos((y-2.0))/(x-2.0));
}
```
Note that we used `JKQTPDatastore::addImageColumn(width,height,name)` here, which generates a column with `width*height` entries that are meant to be interpreted as a 2D image with width columns and height rows. This function therefore also save this image size in the column metadata and graphs can later extract this dimension and use it to set them up internally (e.g. JKQTPColumnMathImage::setImageColumn() does just that).
In the example above we used the simple JKQTPDatastore::set() store values into our image column. This function treats the column as linearized in row-major order. Alternatively you can also use code like this to access the imageColumn as a real image or matrix:
```.cpp
for (int iy=0; iy<10; iy++) {
for (int ix=0; ix<10; ix++) {
datastore->setPixel(imgColumn, ix, iy, sin(ix*iy));
}
}
```
Drawing this column as an image (using JKQTPColumnMathImage) will look like this:
![simpletest_datastore_sineimg](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_sineimg.png)
In these examples, the iteration and calculation is written out with an explicit for-loop. JKQTPDatastore also offers a shortcut function for this that accepts a functor with the calculation only:
```.cpp
imgColumn=datastore->addColumnCalculatedFromColumn(colLinXY.first, colLinXY.second,
[](double x, double y)->double {
return cos((x-15.0))/(x-15.0)*cos((y-2.0))/(x-2.0);
},
"image value");
```
Then you can plot these as a parametrized scatter graph (`JKQTPXYParametrizedScatterGraph`) using:
```.cpp
plot.addGraph(paramscattergraph=new JKQTPXYParametrizedScatterGraph(&plot));
paramscattergraph->setXYColumns(colLinXY);
paramscattergraph->setColorColumn(imgColumn);
paramscattergraph->setTitle(QObject::tr("parametrized scatter"));
```
... or alternatively you can only use the column imgColumn in a `JKQTPColumnMathImage`
```.cpp
plot.addGraph(imggraph=new JKQTPColumnMathImage(&plot));
imggraph->setImageColumn(imgColumn);
imggraph->setX(21);
imggraph->setY(1.5);
imggraph->setWidth(10);
imggraph->setHeight(1.5);
imggraph->setTitle(QObject::tr("imgColumn"));
```
The result will look like this:
![simpletest_datastore_image](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_image.png)

View File

@ -0,0 +1,140 @@
/** \example jkqtplotter_simpletest_datastore.cpp
* A very basic example for the usage of JKQTPlotter
*
* \ref JKQTPlottersimpletest_datastore
*/
#include <QApplication>
#include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/jkqtpgraphsscatter.h"
#include "jkqtplotter/jkqtpgraphsimage.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPlotter plot;
JKQTPDatastore* datastore=plot.getDatastore();
JKQTPXYLineGraph* linegraph;
JKQTPColumnMathImage* imggraph;
JKQTPXYParametrizedScatterGraph* paramscattergraph;
// 2. first we create data inside a QVector for a simple plot (a sine curve) ... and add the plot
// note that you could use a std::vector equally well
QVector<double> X, Y;
const int Ndata=100;
for (int i=0; i<Ndata; i++) {
const double x=double(i)/double(Ndata)*8.0*M_PI;
X<<x;
Y<<sin(x);
}
plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
// by calling JKQTPDatastore::addCopiedColumn() the data is COPIED from the vector into the datastore
linegraph->setXColumn(datastore->addCopiedColumn(X, "x"));
linegraph->setYColumn(datastore->addCopiedColumn(Y, "y"));
// alternatively you can also tell JKQTPDatastore to just reference an external array:
//linegraph->setXColumn(datastore->addColumn(X.data(), X.size(), "x"));
//linegraph->setYColumn(datastore->addColumn(Y.data(), Y.size(), "Y"));
linegraph->setTitle(QObject::tr("sine graph"));
// 3. Now we generate a plot from data in a C-array, just reference in the JKQTPDatastore
#define NDATA 5
double XCA[NDATA]= { 1, 2, 3, 4, 5 };
double YCA[NDATA]= { 1, 0, 1, 0, 1 };
plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
linegraph->setXColumn(datastore->addColumn(XCA, NDATA, "xca (C-array)"));
linegraph->setYColumn(datastore->addColumn(YCA, NDATA, "yca (C-array)"));
// of course you could also simply copy the data with a comparable syntax:
//linegraph->setXColumn(datastore->addCopiedColumn(XCA, NDATA, "xca (C-array)"));
//linegraph->setYColumn(datastore->addCopiedColumn(YCA, NDATA, "yca (C-array)"));
linegraph->setTitle(QObject::tr("linked C-array data"));
// 4. Since graphs often display (x,y)-pairs, it may make sense to store them in a map (e.g. for histograms)
// There there are also functions that copy the contents of a map into a JKQTPDatastore, resulting in
// two columns beeing added:
std::map<int, double> datamap;
datamap[1]=1.1;
datamap[2]=1.4;
datamap[4]=1.2;
datamap[5]=1.8;
datamap[7]=0.9;
plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
linegraph->setXYColumns(datastore->addCopiedMap(datamap, "map_x", "map_y"));
linegraph->setTitle(QObject::tr("copied map"));
// 5. It is also possible to leave the data mangement completely to the JKQTPDatastore
// and just edit the data with access functions from JKQTPDatastore:
plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
// 5.1 this adds a column with 40 values, linearly spaced between 0 and 20 (inclusive).
size_t colLinX=datastore->addLinearColumn(40, 0, 20, "x_lin");
// 5.2 this adds a column with one entry for every entry x in the column colLinX, where
// the entry is calculated by applying a function cos(x)*x/20.0
size_t colFunc1=datastore->addColumnCalculatedFromColumn(colLinX, [](double x)->double { return cos(x)*x/20.0; }, "cos(x_lin)*x_lin/20.0");
// the same can be done by this code explicitly:
// 5.2.1 add a column with as many rows as column colLinX
//size_t colFunc1=datastore->addColumn(datastore->getRows(colLinX), "cos(x_lin)*x_lin/20.0");
// 5.2.2 iterate over the data in column colLinX and set a newly calculated value into a row of column colFunc1
//for (size_t i=0; i<datastore->getRows(colLinX); i++) {
// double x=datastore->get(colLinX, i);
// datastore->set(colFunc1, i, cos(x)*x/20.0);
//}
linegraph->setXColumn(colLinX);
linegraph->setYColumn(colFunc1);
linegraph->setTitle(QObject::tr("calculated column(s)"));
// 6. The function addLinearGridColumns() generates a rectangular 2D grid of coordinates
// in row-major order. Here we generate a 10x10 grid with x-coordinates between 10 and 20 (inclusive)
// and y-coordinates between 1.5 and 3:
std::pair<size_t,size_t> colLinXY=datastore->addLinearGridColumns(10, 10, 20, 10, 1.5, 3);
// now we can add another column with 10*10=100 entries and fill it with some values
// calculated from the the x and y-values in colLinXY:
size_t imgColumn=datastore->addImageColumn(10, 10, "image values");
for (size_t i=0; i<datastore->getRows(imgColumn); i++) {
double x=datastore->get(colLinXY.first, i);
double y=datastore->get(colLinXY.second, i);
datastore->set(imgColumn, i, cos((x-15.0))/(x-15.0)*cos((y-2.0))/(x-2.0));
}
// alternatively you can access image pixels with setPixel():
//for (int iy=0; iy<10; iy++) {
// for (int ix=0; ix<10; ix++) {
// datastore->setPixel(imgColumn, ix, iy, sin(ix*iy/30.0));
// }
//}
// the loop above can be written more compact using addColumnCalculatedFromColumn():
//imgColumn=datastore->addColumnCalculatedFromColumn(colLinXY.first, colLinXY.second, [](double x, double y)->double { return cos((x-15.0))/(x-15.0)*cos((y-2.0))/(x-2.0); }, "image value");
// finally we can use a JKQTPXYParametrizedScatterGraph to display the data from our three columns
// by using colLinXY->first and colLinXY->second as positions for symbols that are colored, based
// on the respective value in imgColumn:
plot.addGraph(paramscattergraph=new JKQTPXYParametrizedScatterGraph(&plot));
paramscattergraph->setXYColumns(colLinXY);
paramscattergraph->setColorColumn(imgColumn);
paramscattergraph->setTitle(QObject::tr("parametrized scatter"));
// alternatively you can only use the column imgColumn in a JKQTPColumnMathImage
plot.addGraph(imggraph=new JKQTPColumnMathImage(&plot));
imggraph->setImageColumn(imgColumn);
imggraph->setX(21);
imggraph->setY(1.5);
imggraph->setWidth(10);
imggraph->setHeight(1.5);
imggraph->setTitle(QObject::tr("imgColumn"));
// 6. autoscale the plot so the graph is contained
plot.zoomToFit();
// show plotter and make it a decent size
plot.show();
plot.resize(600,400);
return app.exec();
}

View File

@ -0,0 +1,26 @@
# source code for this simple demo
SOURCES = jkqtplotter_simpletest_datastore.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_datastore
# include JKQTPlotter source headers and link against library
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

View File

@ -0,0 +1,8 @@
TEMPLATE = subdirs
SUBDIRS += jkqtplotterlib jkqtplotter_simpletest_datastore
jkqtplotterlib.file = ../../staticlib/jkqtplotterlib/jkqtplotterlib.pro
jkqtplotter_simpletest_datastore.file=$$PWD/jkqtplotter_simpletest_datastore.pro
jkqtplotter_simpletest_datastore.depends = jkqtplotterlib

View File

@ -15,20 +15,12 @@ And three columns with 256 entries each, which will be filled with the R-, G- an
size_t columnB=ds->addColumn(256, "historam_B"); size_t columnB=ds->addColumn(256, "historam_B");
``` ```
In this example we will access the data in the internal datastore directly. This access is possible through objects of type JKQTPColumn, which is a proxy to the data in one of the columns in a `JKQTdatastore`:
```.cpp
JKQTPColumn cG=ds->getColumn(columnG);
JKQTPColumn cR=ds->getColumn(columnR);
JKQTPColumn cB=ds->getColumn(columnB);
```
In order to calculate the histograms, first all enries in the columns are set to 0: In order to calculate the histograms, first all enries in the columns are set to 0:
```.cpp ```.cpp
cR.setAll(0); ds->setAll(columnG, 0);
cG.setAll(0); ds->setAll(columnR, 0);
cB.setAll(0); ds->setAll(columnB, 0);
``` ```
Finally the histogram is calculated: Finally the histogram is calculated:
@ -38,14 +30,14 @@ Finally the histogram is calculated:
for (int y=0; y<image.height(); y++) { for (int y=0; y<image.height(); y++) {
for (int x=0; x<image.width(); x++) { for (int x=0; x<image.width(); x++) {
QRgb pix=image.pixel(x,y); QRgb pix=image.pixel(x,y);
cR.incValue(qRed(pix), 1); ds->inc(columnR, qRed(pix), 1);
cG.incValue(qGreen(pix), 1); ds->inc(columnG, qGreen(pix), 1);
cB.incValue(qBlue(pix), 1); ds->inc(columnB, qBlue(pix), 1);
} }
} }
cR.scale(100.0/static_cast<double>(image.width()*image.height())); ds->scaleColumnValues(columnR, 100.0/static_cast<double>(image.width()*image.height()));
cG.scale(100.0/static_cast<double>(image.width()*image.height())); ds->scaleColumnValues(columnG, 100.0/static_cast<double>(image.width()*image.height()));
cB.scale(100.0/static_cast<double>(image.width()*image.height())); ds->scaleColumnValues(columnB, 100.0/static_cast<double>(image.width()*image.height()));
``` ```
Finally three `JKQTPFilledCurveXGraph` objects are generated and added to the plot (here we show the code for the R-channel only): Finally three `JKQTPFilledCurveXGraph` objects are generated and added to the plot (here we show the code for the R-channel only):

View File

@ -25,15 +25,10 @@ int main(int argc, char* argv[])
size_t columnR=ds->addColumn(256, "historam_R"); size_t columnR=ds->addColumn(256, "historam_R");
size_t columnG=ds->addColumn(256, "historam_G"); size_t columnG=ds->addColumn(256, "historam_G");
size_t columnB=ds->addColumn(256, "historam_B"); size_t columnB=ds->addColumn(256, "historam_B");
// - in addition JKQTPColumn objects are generated, which can be used to access
// the data in the columns
JKQTPColumn cG=ds->getColumn(columnG);
JKQTPColumn cR=ds->getColumn(columnR);
JKQTPColumn cB=ds->getColumn(columnB);
// - now all columns for RGB are initialized to 0 // - now all columns for RGB are initialized to 0
cR.setAll(0); ds->setAll(columnG, 0);
cG.setAll(0); ds->setAll(columnR, 0);
cB.setAll(0); ds->setAll(columnB, 0);
// 3. now we open a BMP-file and load it into a QImage // 3. now we open a BMP-file and load it into a QImage
QImage image(":/example.bmp"); QImage image(":/example.bmp");
@ -41,15 +36,15 @@ int main(int argc, char* argv[])
for (int y=0; y<image.height(); y++) { for (int y=0; y<image.height(); y++) {
for (int x=0; x<image.width(); x++) { for (int x=0; x<image.width(); x++) {
QRgb pix=image.pixel(x,y); QRgb pix=image.pixel(x,y);
cR.incValue(qRed(pix), 1); ds->inc(columnR, qRed(pix), 1);
cG.incValue(qGreen(pix), 1); ds->inc(columnG, qGreen(pix), 1);
cB.incValue(qBlue(pix), 1); ds->inc(columnB, qBlue(pix), 1);
} }
} }
// ... and normalize histograms // ... and normalize histograms
cR.scale(100.0/static_cast<double>(image.width()*image.height())); ds->scaleColumnValues(columnR, 100.0/static_cast<double>(image.width()*image.height()));
cG.scale(100.0/static_cast<double>(image.width()*image.height())); ds->scaleColumnValues(columnG, 100.0/static_cast<double>(image.width()*image.height()));
cB.scale(100.0/static_cast<double>(image.width()*image.height())); ds->scaleColumnValues(columnB, 100.0/static_cast<double>(image.width()*image.height()));
// 4. now we add three semi-transparent, filled curve plots, one for each histogram // 4. now we add three semi-transparent, filled curve plots, one for each histogram

View File

@ -957,11 +957,11 @@ JKQTBasePlotter::JKQTPPen JKQTBasePlotter::getPlotStyle(int i) const{
p.setFillColor(JKQTPGetDerivedColor(plotterStyle.graphFillColorDerivationMode, p.color())); p.setFillColor(JKQTPGetDerivedColor(plotterStyle.graphFillColorDerivationMode, p.color()));
p.setErrorLineColor(JKQTPGetDerivedColor(plotterStyle.graphErrorColorDerivationMode, p.color())); p.setErrorLineColor(JKQTPGetDerivedColor(plotterStyle.graphErrorColorDerivationMode, p.color()));
p.setErrorFillColor(JKQTPGetDerivedColor(plotterStyle.graphErrorFillColorDerivationMode, p.errorColor())); p.setErrorFillColor(JKQTPGetDerivedColor(plotterStyle.graphErrorFillColorDerivationMode, p.errorColor()));
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphWidth)); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphWidth));
p.setErrorLineWidth(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphWidth)); p.setErrorLineWidth(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphWidth));
p.setSymbolSize(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphSymbolSize)); p.setSymbolSize(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphSymbolSize));
p.setSymbolFillColor(JKQTPGetDerivedColor(plotterStyle.graphFillColorDerivationMode, p.color())); p.setSymbolFillColor(JKQTPGetDerivedColor(plotterStyle.graphFillColorDerivationMode, p.color()));
p.setSymbolLineWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphSymbolLineWidth)); p.setSymbolLineWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphSymbolLineWidth));
p.setStyle(plotterStyle.defaultGraphPenStyles[styleI]); p.setStyle(plotterStyle.defaultGraphPenStyles[styleI]);
p.setSymbolType(plotterStyle.defaultGraphSymbols[symbolI]); p.setSymbolType(plotterStyle.defaultGraphSymbols[symbolI]);
p.setFillStyle(plotterStyle.defaultGraphFillStyles[brushI]); p.setFillStyle(plotterStyle.defaultGraphFillStyles[brushI]);
@ -1088,7 +1088,7 @@ void JKQTBasePlotter::drawKey(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pf=painter.pen(); QPen pf=painter.pen();
pf.setColor(plotterStyle.keyStyle.frameColor); pf.setColor(plotterStyle.keyStyle.frameColor);
pf.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, pt2px(painter, plotterStyle.keyStyle.frameWidth*lineWidthMultiplier))); pf.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, pt2px(painter, plotterStyle.keyStyle.frameWidth*lineWidthMultiplier)));
pf.setStyle(Qt::SolidLine); pf.setStyle(Qt::SolidLine);
painter.setBrush(plotterStyle.keyStyle.backgroundBrush); painter.setBrush(plotterStyle.keyStyle.backgroundBrush);
@ -1162,7 +1162,7 @@ void JKQTBasePlotter::drawPlot(JKQTPEnhancedPainter& painter, bool showOverlays)
if (plotterStyle.plotFrameVisible) { if (plotterStyle.plotFrameVisible) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen p(plotterStyle.plotFrameColor); QPen p(plotterStyle.plotFrameColor);
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, pt2px(painter, plotterStyle.plotFrameWidth*lineWidthMultiplier))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, pt2px(painter, plotterStyle.plotFrameWidth*lineWidthMultiplier)));
painter.setPen(p); painter.setPen(p);
painter.setBrush(plotterStyle.plotBackgroundBrush); painter.setBrush(plotterStyle.plotBackgroundBrush);
if (plotterStyle.plotFrameRounding<=0) { if (plotterStyle.plotFrameRounding<=0) {

View File

@ -1148,11 +1148,11 @@ void JKQTPVerticalAxis::drawGrids(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pg=painter.pen(); QPen pg=painter.pen();
pg.setColor(axisStyle.gridColor); pg.setColor(axisStyle.gridColor);
pg.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.gridWidth*parent->getLineWidthMultiplier()))); pg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.gridWidth*parent->getLineWidthMultiplier())));
pg.setStyle(axisStyle.gridStyle); pg.setStyle(axisStyle.gridStyle);
QPen pmg=painter.pen(); QPen pmg=painter.pen();
pmg.setColor(axisStyle.minorGridColor); pmg.setColor(axisStyle.minorGridColor);
pmg.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, axisStyle.minorGridWidth*parent->getLineWidthMultiplier()))); pmg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, axisStyle.minorGridWidth*parent->getLineWidthMultiplier())));
pmg.setStyle(axisStyle.minorGridStyle); pmg.setStyle(axisStyle.minorGridStyle);
//double top=x2p(axismax); //double top=x2p(axismax);
//double bottom=x2p(axismin); //double bottom=x2p(axismin);
@ -1343,14 +1343,14 @@ void JKQTPVerticalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pmain=painter.pen(); QPen pmain=painter.pen();
pmain.setColor(axisStyle.axisColor); pmain.setColor(axisStyle.axisColor);
pmain.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidth*parent->getLineWidthMultiplier()))); pmain.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidth*parent->getLineWidthMultiplier())));
pmain.setStyle(Qt::SolidLine); pmain.setStyle(Qt::SolidLine);
QPen ptick=pmain; QPen ptick=pmain;
ptick.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.tickWidth*parent->getLineWidthMultiplier()))); ptick.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.tickWidth*parent->getLineWidthMultiplier())));
QPen pmtick=ptick; QPen pmtick=ptick;
pmtick.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorTickWidth*parent->getLineWidthMultiplier()))); pmtick.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorTickWidth*parent->getLineWidthMultiplier())));
getParentMathText()->setFontSize(this->axisStyle.tickLabelFontSize*parent->getFontSizeMultiplier()); getParentMathText()->setFontSize(this->axisStyle.tickLabelFontSize*parent->getFontSizeMultiplier());
getParentMathText()->setFontRomanOrSpecial(getParent()->getCurrentPlotterStyle().defaultFontName); getParentMathText()->setFontRomanOrSpecial(getParent()->getCurrentPlotterStyle().defaultFontName);
@ -1364,7 +1364,7 @@ void JKQTPVerticalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
JKQTPAutoOutputTimer jkaat(QString("JKQTPEnhancedPainter[%1]::drawAxes(): 0Axis").arg(objectName())); JKQTPAutoOutputTimer jkaat(QString("JKQTPEnhancedPainter[%1]::drawAxes(): 0Axis").arg(objectName()));
#endif #endif
QPen pmain1=pmain; QPen pmain1=pmain;
pmain1.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidthZeroAxis*parent->getLineWidthMultiplier()))); pmain1.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidthZeroAxis*parent->getLineWidthMultiplier())));
pmain1.setColor(axisStyle.colorZeroAxis); pmain1.setColor(axisStyle.colorZeroAxis);
pmain1.setStyle(axisStyle.styleZeroAxis); pmain1.setStyle(axisStyle.styleZeroAxis);
painter.setPen(pmain1); painter.setPen(pmain1);
@ -1771,11 +1771,11 @@ void JKQTPHorizontalAxis::drawGrids(JKQTPEnhancedPainter& painter) {
} }
QPen pg=painter.pen(); QPen pg=painter.pen();
pg.setColor(axisStyle.gridColor); pg.setColor(axisStyle.gridColor);
pg.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.gridWidth*parent->getFontSizeMultiplier()))); pg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.gridWidth*parent->getFontSizeMultiplier())));
pg.setStyle(axisStyle.gridStyle); pg.setStyle(axisStyle.gridStyle);
QPen pmg=painter.pen(); QPen pmg=painter.pen();
pmg.setColor(axisStyle.minorGridColor); pmg.setColor(axisStyle.minorGridColor);
pmg.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorGridWidth*parent->getLineWidthMultiplier()))); pmg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorGridWidth*parent->getLineWidthMultiplier())));
pmg.setStyle(axisStyle.minorGridStyle); pmg.setStyle(axisStyle.minorGridStyle);
double x=tickStart; double x=tickStart;
@ -1926,14 +1926,14 @@ void JKQTPHorizontalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
QPen pmain=painter.pen(); QPen pmain=painter.pen();
pmain.setColor(axisStyle.axisColor); pmain.setColor(axisStyle.axisColor);
pmain.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidth*parent->getLineWidthMultiplier()))); pmain.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidth*parent->getLineWidthMultiplier())));
pmain.setStyle(Qt::SolidLine); pmain.setStyle(Qt::SolidLine);
QPen ptick=pmain; QPen ptick=pmain;
ptick.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.tickWidth*parent->getLineWidthMultiplier()))); ptick.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.tickWidth*parent->getLineWidthMultiplier())));
QPen pmtick=ptick; QPen pmtick=ptick;
pmtick.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorTickWidth*parent->getLineWidthMultiplier()))); pmtick.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorTickWidth*parent->getLineWidthMultiplier())));
getParentMathText()->setFontSize(this->axisStyle.tickLabelFontSize*parent->getFontSizeMultiplier()); getParentMathText()->setFontSize(this->axisStyle.tickLabelFontSize*parent->getFontSizeMultiplier());
getParentMathText()->setFontRomanOrSpecial(getParent()->getCurrentPlotterStyle().defaultFontName); getParentMathText()->setFontRomanOrSpecial(getParent()->getCurrentPlotterStyle().defaultFontName);
@ -1947,7 +1947,7 @@ void JKQTPHorizontalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
JKQTPAutoOutputTimer jkaat(QString("JKQTPHorizontalAxis[%1]::drawAxes(): 0Axis").arg(objectName())); JKQTPAutoOutputTimer jkaat(QString("JKQTPHorizontalAxis[%1]::drawAxes(): 0Axis").arg(objectName()));
#endif #endif
QPen pmain1=pmain; QPen pmain1=pmain;
pmain1.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidthZeroAxis*parent->getLineWidthMultiplier()))); pmain1.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidthZeroAxis*parent->getLineWidthMultiplier())));
pmain1.setColor(axisStyle.colorZeroAxis); pmain1.setColor(axisStyle.colorZeroAxis);
pmain1.setStyle(axisStyle.styleZeroAxis); pmain1.setStyle(axisStyle.styleZeroAxis);
painter.setPen(pmain1); painter.setPen(pmain1);

View File

@ -22,7 +22,7 @@
#include "jkqtplotter/jkqtpdatastorage.h" #include "jkqtplotter/jkqtpdatastorage.h"
#include <QDebug> #include <QDebug>
#include <QtGlobal> #include <QtGlobal>
#include <cmath>
/************************************************************************************************************************** /**************************************************************************************************************************
* JKQTPColumn * JKQTPColumn
@ -34,23 +34,39 @@ JKQTPColumn::JKQTPColumn()
name=""; name="";
datastoreItem=0; datastoreItem=0;
datastoreOffset=0; datastoreOffset=0;
imageColumns=1;
valid=false; valid=false;
} }
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
JKQTPColumn::JKQTPColumn(JKQTPDatastore *datastore, const QString &name, size_t datastoreItem, size_t datastoreOffset) JKQTPColumn::JKQTPColumn(JKQTPDatastore *datastore, const QString &name, size_t datastoreItem, size_t datastoreOffset, size_t imageColumns)
{ {
this->datastore=datastore; this->datastore=datastore;
this->datastoreItem=datastoreItem; this->datastoreItem=datastoreItem;
this->datastoreOffset=datastoreOffset; this->datastoreOffset=datastoreOffset;
this->imageColumns=imageColumns;
this->name=name; this->name=name;
valid=true; valid=true;
} }
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
JKQTPColumn::~JKQTPColumn() void JKQTPColumn::setName(const QString &__value)
= default; {
this->name = __value;
}
////////////////////////////////////////////////////////////////////////////////////////////////
QString JKQTPColumn::getName() const
{
return this->name;
}
////////////////////////////////////////////////////////////////////////////////////////////////
void JKQTPColumn::setImageColumns(size_t __value)
{
imageColumns=__value;
}
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPColumn::getRows() const { size_t JKQTPColumn::getRows() const {
@ -261,6 +277,11 @@ JKQTPDatastore::JKQTPDatastore()
clear(); clear();
} }
////////////////////////////////////////////////////////////////////////////////////////////////
JKQTPDatastore::~JKQTPDatastore() {
clear();
}
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
void JKQTPDatastore::clear(){ void JKQTPDatastore::clear(){
maxItemID=0; maxItemID=0;
@ -310,6 +331,7 @@ void JKQTPDatastore::deleteAllPrefixedColumns(QString prefix, bool removeItems)
} }
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
void JKQTPDatastore::deleteColumn(size_t column, bool removeItems) { void JKQTPDatastore::deleteColumn(size_t column, bool removeItems) {
if (removeItems) { if (removeItems) {
@ -475,7 +497,31 @@ size_t JKQTPDatastore::addInternalColumn(double* data, size_t rows, const QStrin
//std::cout<<"adding column\n"; //std::cout<<"adding column\n";
size_t it=addItem(new JKQTPDatastoreItem(JKQTPSingleColumn, data, 1, rows,true)); size_t it=addItem(new JKQTPDatastoreItem(JKQTPSingleColumn, data, 1, rows,true));
return addColumnForItem(it, 0, name); return addColumnForItem(it, 0, name);
}; }
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::addImageColumn(size_t width, size_t height, const QString &name)
{
size_t col= addColumn(width*height, name);
columns[col].setImageColumns(width);
return col;
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::addImageColumn(double *data, size_t width, size_t height, const QString &name)
{
size_t col= addColumn(data, width*height, name);
columns[col].setImageColumns(width);
return col;
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::addInternalImageColumn(double *data, size_t width, size_t height, const QString &name)
{
size_t col= addInternalColumn(data, width*height, name);
columns[col].setImageColumns(width);
return col;
}
@ -524,6 +570,102 @@ size_t JKQTPDatastore::addLinearColumn(size_t rows, double start, double end, co
return addColumnForItem(itemid, 0, name); return addColumnForItem(itemid, 0, name);
} }
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::addLogColumn(size_t rows, double start, double end, const QString &name)
{
JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, rows);
const double x0=log(start)/log(10.0);
const double x1=log(end)/log(10.0);
for (size_t i=0; i<rows; i++) {
it->set(0, i, pow(10.0, x0+static_cast<double>(i)/static_cast<double>(rows-1)*(x1-x0)));
}
size_t itemid= addItem(it);
return addColumnForItem(itemid, 0, name);
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::addDecadeLogColumn(size_t rows, double startDecade, double endDecade, const QString &name)
{
JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, rows);
const double x0=startDecade;
const double x1=endDecade;
for (size_t i=0; i<rows; i++) {
it->set(0, i, pow(10.0, x0+static_cast<double>(i)/static_cast<double>(rows-1)*(x1-x0)));
}
size_t itemid= addItem(it);
return addColumnForItem(itemid, 0, name);
}
////////////////////////////////////////////////////////////////////////////////////////////////
std::pair<size_t, size_t> JKQTPDatastore::addLinearGridColumns(size_t width, double startX, double endX, size_t height, double startY, double endY, const QString &nameX, const QString &nameY)
{
const double decX=(endX-startX)/static_cast<double>(width-1);
const double decY=(endY-startY)/static_cast<double>(height-1);
double y=startY;
size_t cx=addColumn(width*height, nameX);
size_t cy=addColumn(width*height, nameY);
size_t i=0;
for (size_t iy=0; iy<height; iy++) {
double x=startX;
for (size_t ix=0; ix<width; ix++) {
set(cx, i, x);
set(cy, i, y);
x+=decX;
i++;
}
y+=decY;
}
return std::make_pair(cx,cy);
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::addCalculatedColumn(size_t rows, const std::function<double (size_t, JKQTPDatastore *)> &f, const QString &name)
{
JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, rows);
for (size_t i=0; i<rows; i++) {
it->set(0, i, f(i, this));
}
size_t itemid= addItem(it);
return addColumnForItem(itemid, 0, name);
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::addCalculatedColumn(size_t rows, const std::function<double (size_t)> &f, const QString &name)
{
JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, rows);
for (size_t i=0; i<rows; i++) {
it->set(0, i, f(i));
}
size_t itemid= addItem(it);
return addColumnForItem(itemid, 0, name);
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::addColumnCalculatedFromColumn(size_t otherColumn, const std::function<double (double)> &f, const QString &name)
{
const JKQTPColumn& oc=columns.value(otherColumn);
JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, oc.getRows());
for (size_t i=0; i<oc.getRows(); i++) {
it->set(0, i, f(oc.getValue(i)));
}
size_t itemid= addItem(it);
return addColumnForItem(itemid, 0, name);
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::addColumnCalculatedFromColumn(size_t otherColumnX, size_t otherColumnY, const std::function<double (double, double)> &f, const QString &name)
{
const JKQTPColumn& ocx=columns.value(otherColumnX);
const JKQTPColumn& ocy=columns.value(otherColumnY);
const size_t N= qMin(ocx.getRows(), ocy.getRows());
JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, N);
for (size_t i=0; i<N; i++) {
it->set(0, i, f(ocx.getValue(i), ocy.getValue(i)));
}
size_t itemid= addItem(it);
return addColumnForItem(itemid, 0, name);
}
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
int JKQTPDatastore::getNextLowerIndex(size_t column, size_t row, int start, int end) const int JKQTPDatastore::getNextLowerIndex(size_t column, size_t row, int start, int end) const
@ -938,7 +1080,7 @@ QVariant JKQTPDatastoreModel::data(const QModelIndex &index, int role) const {
if (datastore) { if (datastore) {
if (role==Qt::DisplayRole || role==Qt::EditRole) { if (role==Qt::DisplayRole || role==Qt::EditRole) {
int col=static_cast<int>(datastore->getColumnIDs().value(column, -1)); int col=static_cast<int>(datastore->getColumnIDs().value(column, -1));
if (col>-1 && row>=0 && row<static_cast<int>(datastore->getColumn(col).getRows())) { if (col>-1 && row>=0 && row<static_cast<int>(datastore->getRows(col))) {
return datastore->get(col, static_cast<size_t>(row)); return datastore->get(col, static_cast<size_t>(row));
} }
} }

View File

@ -82,6 +82,8 @@ enum JKQTPDatastoreItemFormat {
/** \brief This class manages chunks of memory that are used for column data in JKQTBasePlotter descendents /** \brief This class manages chunks of memory that are used for column data in JKQTBasePlotter descendents
* \ingroup jkqtpdatastorage * \ingroup jkqtpdatastorage
* *
* \see \ref JKQTPlotterAdvancedJKQTPDatastore for a detailed description of how to use this class for data management!
*
* This class manages a list if JKQTPDatastoreItem onjects that may each contain a chunk of memory, containig * This class manages a list if JKQTPDatastoreItem onjects that may each contain a chunk of memory, containig
* one or more columns of data. Each item can be accessed with get() by a specific ID which is returned by add(). * one or more columns of data. Each item can be accessed with get() by a specific ID which is returned by add().
* JKQTPColumn. You may only clear all chunks of memory/items. If you no longer need some of the data, but still want * JKQTPColumn. You may only clear all chunks of memory/items. If you no longer need some of the data, but still want
@ -135,17 +137,37 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief add a new column to the datastore and return its ID */ /** \brief add a new column to the datastore and return its ID */
size_t addColumn(JKQTPColumn col); size_t addColumn(JKQTPColumn col);
/** \brief add a new item to the datastore and return its ID
* This function retuns an item ID (which can be used with getItem() ), not a column ID! */
size_t addItem(JKQTPDatastoreItem* item);
public:
/** \brief class constructor, generates an empty datastore */
JKQTPDatastore();
/** \brief class destructor, destroys all subordered JKQTPDatastoreItem objects */
~JKQTPDatastore() {
clear();
}
/** \brief deletes all items from the datastore and possibly frees the memory they manage */ /** \brief add a new columns/item with \a rows rows to the datastore and return its ID. The item uses internal memory management.
void clear(); * This function retuns an item ID (which can be used with getItem() ), not a column ID! */
size_t addItem(size_t rows);
/** \brief add a new item with \a rows rows and \a columns columns to the datastore and return its ID. The item uses internal memory management.
* This function retuns an item ID (which can be used with getItem() ), not a column ID! */
size_t addItem(size_t columns, size_t rows);
/** \brief add one external column to the datastore. It contains \a rows rows.
* This function retuns an item ID (which can be used with getItem() ), not a column ID! */
size_t addItem(double* data, size_t rows);
/** \brief add one internal column to the datastore. It contains \a rows rows.
* This function retuns an item ID (which can be used with getItem() ), not a column ID! */
size_t addInternalItem(double* data, size_t rows);
/** \brief add one external column to the datastore. It contains \a rows rows. The data is copied and the copy managed internally
* This function retuns an item ID (which can be used with getItem() ), not a column ID! */
size_t addCopiedItem(const double *data, size_t rows);
/** \brief add an external memory block to the datastore. It contains \a rows rows and \a columns columns. \a dataformat determined the memory layout.
* This function retuns an item ID (which can be used with getItem() ), not a column ID! */
size_t addItem(JKQTPDatastoreItemFormat dataformat, double* data, size_t columns, size_t rows);
/** \brief add one external data block to the datastore. It contains \a rows rows and \a columns columns. The data is copied and the copy managed internally
* This function retuns an item ID (which can be used with getItem() ), not a column ID! */
size_t addCopiedItem(JKQTPDatastoreItemFormat dataformat, double* data, size_t columns, size_t rows);
/** \brief returns the JKQTPDatastoreItem object for the \a i -th item in the store */ /** \brief returns the JKQTPDatastoreItem object for the \a i -th item in the store */
inline JKQTPDatastoreItem* getItem(size_t i) { inline JKQTPDatastoreItem* getItem(size_t i) {
@ -157,12 +179,38 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
return items.value(i, nullptr); return items.value(i, nullptr);
} }
/** \brief add a new item to the datastore and return its ID */ /** \brief add a new columns which references a specified item and a specified column therein.
size_t addItem(JKQTPDatastoreItem* item); * \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addColumnForItem(size_t itemID, size_t columnInItem, const QString& name=QString(""));
/** \brief returns the JKQTPColumn object for the \a i -th column in the store
*
* \warning This function copies the pointers/references to the internal data into a new object.
* Therefore you should delete it as soon as possible and not store the return value over long durations,
* as the data may get moved in the meantime and then the object gets invalid, but is not informed of this fact!
*/
JKQTPColumn getColumn(size_t i) const;
/** \brief add a new columns/item with \a rows rows to the datastore and return its ID. The item uses internal memory management. */ /** \brief returns the JKQTPColumn object for the \a i -th column in the store
size_t addItem(size_t rows); *
* \warning This function copies the pointers/references to the internal data into a new object.
* Therefore you should delete it as soon as possible and not store the return value over long durations,
* as the data may get moved in the meantime and then the object gets invalid, but is not informed of this fact!
*/
JKQTPColumn getColumn(int i) const;
public:
/** \brief class constructor, generates an empty datastore */
JKQTPDatastore();
/** \brief class destructor, destroys all subordered JKQTPDatastoreItem objects */
~JKQTPDatastore();
/** \brief deletes all items from the datastore and possibly frees the memory they manage */
void clear();
/** \brief delete the given column, if no other columns points to the datastore item of the column and \a removeItems is \c true, the item will be removed */ /** \brief delete the given column, if no other columns points to the datastore item of the column and \a removeItems is \c true, the item will be removed */
void deleteColumn(size_t column, bool removeItems=true); void deleteColumn(size_t column, bool removeItems=true);
@ -173,24 +221,24 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief delete all columns where the name starts with a given prefix, if no other columns points to the datastore item of the column and \a removeItems is \c true, the item will be removed */ /** \brief delete all columns where the name starts with a given prefix, if no other columns points to the datastore item of the column and \a removeItems is \c true, the item will be removed */
void deleteAllPrefixedColumns(QString prefix, bool removeItems=true); void deleteAllPrefixedColumns(QString prefix, bool removeItems=true);
/** \brief add a new item with \a rows rows and \a columns columns to the datastore and return its ID. The item uses internal memory management. */
size_t addItem(size_t columns, size_t rows);
/** \brief add one external column to the datastore. It contains \a rows rows.*/
size_t addItem(double* data, size_t rows);
/** \brief add one internal column to the datastore. It contains \a rows rows.*/
size_t addInternalItem(double* data, size_t rows);
/** \brief add an external memory block to the datastore. It contains \a rows rows and \a columns columns. \a dataformat determined the memory layout*/
size_t addItem(JKQTPDatastoreItemFormat dataformat, double* data, size_t columns, size_t rows);
/** \brief add one external column to the datastore. It contains \a rows rows. The data is copied and the copy managed internally */
size_t addCopiedItem(const double *data, size_t rows);
/** \brief add one external data block to the datastore. It contains \a rows rows and \a columns columns. The data is copied and the copy managed internally */
size_t addCopiedItem(JKQTPDatastoreItemFormat dataformat, double* data, size_t columns, size_t rows);
/** \brief returns the number of rows in the column \a column */
inline size_t getRows(size_t column) const;
/** \brief returns a pointer to the data in column \a column, starting ar row \a row */
inline const double* getColumnPointer(size_t column, size_t row=0) const;
/** \brief returns a pointer to the data in column \a column, starting ar row \a row */
inline double* getColumnPointer(size_t column, size_t row=0);
/** \brief returns the number of rows in the column \a column */
inline size_t getRows(int column) const;
/** \brief returns a pointer to the data in column \a column, starting ar row \a row */
inline const double* getColumnPointer(int column, size_t row=0) const;
/** \brief returns a pointer to the data in column \a column, starting ar row \a row */
inline double* getColumnPointer(int column, size_t row=0);
/** \brief returns the width of the image, represented by \a column (in row-major ordering).
* Internally this returns the imageColumns or image width, if set in the column */
inline size_t getColumnImageWidth(int column);
/** \brief returns the height of the image, represented by \a column (in row-major ordering) */
inline size_t getColumnImageHeight(int column);
/** \brief returns the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */ /** \brief returns the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
inline double get(size_t column, size_t row) const ; inline double get(size_t column, size_t row) const ;
@ -209,11 +257,6 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
int getNextHigherIndex(size_t column, size_t row, int start, int end) const; int getNextHigherIndex(size_t column, size_t row, int start, int end) const;
/** \brief gets the index of the datapoint with the nearest, but higher value in the column */ /** \brief gets the index of the datapoint with the nearest, but higher value in the column */
int getNextHigherIndex(size_t column, size_t row) const; int getNextHigherIndex(size_t column, size_t row) const;
/** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
inline void set(size_t column, size_t row, double value);
/** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
inline void set(int column, size_t row, double value);
/** \brief gets the index of the datapoint with the nearest, but lower value in the column (in a given inclusive row range [start ... end] values of -1 for the ranges are "wildcards", i.e. start/end of column)*/ /** \brief gets the index of the datapoint with the nearest, but lower value in the column (in a given inclusive row range [start ... end] values of -1 for the ranges are "wildcards", i.e. start/end of column)*/
int getNextLowerIndex(int column, size_t row, int start, int end) const; int getNextLowerIndex(int column, size_t row, int start, int end) const;
/** \brief gets the index of the datapoint with the nearest, but lower value in the column */ /** \brief gets the index of the datapoint with the nearest, but lower value in the column */
@ -223,24 +266,153 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief gets the index of the datapoint with the nearest, but higher value in the column */ /** \brief gets the index of the datapoint with the nearest, but higher value in the column */
int getNextHigherIndex(int column, size_t row) const; int getNextHigherIndex(int column, size_t row) const;
/** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
inline void set(size_t column, size_t row, double value);
/** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
inline void set(int column, size_t row, double value);
/** \brief returns the value at position (\c x, \c y) in the \a column-th column, which is interpreted with the imageWidth stored in that column */
inline double getPixel(size_t column, size_t x, size_t y) const ;
/** \brief returns the value at position (\c x, \c y) in the \a column-th column, which is interpreted with the imageWidth stored in that column */
inline void setPixel(size_t column, size_t x, size_t y, double value) ;
/** \brief sets all entries in column \a column to \a value
*
* \see \ref JKQTPlotterFilledGraphs
*/
inline void setAll(size_t column, double value);
/** \brief scales (multiplies) all entries in column \a column by \a factor
*
* \see \ref JKQTPlotterFilledGraphs
*/
inline void scaleColumnValues(size_t column, double factor);
/** \brief increases entry in row \a row of column \a column by \a increment
*
* \see \ref JKQTPlotterFilledGraphs
*/
inline void inc(size_t column, size_t row, double increment=1);
/** \brief decrements entry in row \a row of column \a column by \a decrement
*
* \see \ref JKQTPlotterFilledGraphs
*/
inline void dec(size_t column, size_t row, double decrement=1);
/** \brief add a new columns which references a specified item and a specified column therein. */
size_t addColumnForItem(size_t itemID, size_t columnInItem, const QString& name=QString(""));
/** \brief add a new columns with \a rows rows to the datastore and return its column ID. The new item uses internal memory management. */ /** \brief add a new columns with \a rows rows to the datastore and return its column ID. The new item uses internal memory management.
* \param rows number of rows in the data array
* \param name name for the column
* \return the ID of the newly created column
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addColumn(size_t rows, const QString& name=QString("")); size_t addColumn(size_t rows, const QString& name=QString(""));
/** \brief add one external column to the datastore. It contains \a rows rows. This returns its logical column ID.*/ /** \brief add one external column to the datastore. It contains \a rows rows. This returns its logical column ID.
* Data is not owned by the JKQTPDatastore!
*
* \param data data array to be copied
* \param rows number of rows in the data array
* \param name name for the column
* \return the ID of the newly created column
*
* \code
* #define NDATA 5
* double XCA[NDATA]= { 1, 2, 3, 4, 5 };
* double YCA[NDATA]= { 1, 0, 1, 0, 1 };
* plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
* linegraph->setXColumn(datastore->addColumn(XCA, NDATA, "xca (C-array)"));
* linegraph->setYColumn(datastore->addColumn(YCA, NDATA, "yca (C-array)"));
* \endcode
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addColumn(double* data, size_t rows, const QString& name=QString("")); size_t addColumn(double* data, size_t rows, const QString& name=QString(""));
/** \brief add a column with \a rows entries from the array \a data,
* ownership of the memory behind \a data is transfered to the datastore
*
* \param data data array to be copied
* \param rows number of rows in the data array
* \param name name for the column
* \return the ID of the newly created column
*
* \code
* #define NDATA 5
* double* XCA=(double*)malloc(NDATA, sizeof(double));
* double* YCA=(double*)malloc(NDATA, sizeof(double));
* ...
* plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
* linegraph->setXColumn(datastore->addInternalColumn(XCA, NDATA, "x"));
* linegraph->setXColumn(datastore->addInternalColumn(YCA, NDATA, "y"));
* \endcode
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addInternalColumn(double *data, size_t rows, const QString& name);
/** \brief add a new columns with \a width * \a height rows to the datastore and return its column ID. The new item uses internal memory management.
* The column is meant to represent an image in row-major order with x-dimention \a width and y-dimension \a height .
*
* \param width width of the image represented by the data array
* \param height height of the image represented by the data array
* \param name name for the column
* \return the ID of the newly created column
* \see addImageColumn(), addInternalImageColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addImageColumn(size_t width, size_t height, const QString& name=QString(""));
/** \brief add one external column to the datastore. It contains \a width * \a height rows. This returns its logical column ID.
* Data is not owned by the JKQTPDatastore!
* The column is meant to represent an image in row-major order with x-dimention \a width and y-dimension \a height .
*
*
* \param data data array to be copied
* \param width width of the image represented by the data array
* \param height height of the image represented by the data array
* \param name name for the column
* \return the ID of the newly created column
*
* \see addColumn(), addImageColumn(), addInternalImageColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addImageColumn(double* data, size_t width, size_t height, const QString& name=QString(""));
/** \brief add a column with \a width * \a height entries from the array \a data,
* ownership of the memory behind \a data is transfered to the datastore
* The column is meant to represent an image in row-major order with x-dimention \a width and y-dimension \a height .
*
*
* \param data data array to be copied
* \param width width of the image represented by the data array
* \param height height of the image represented by the data array
* \param name name for the column
* \return the ID of the newly created column
*
* \see addInternalColumn(), addImageColumn(), addInternalImageColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addInternalImageColumn(double *data, size_t width, size_t height, const QString& name);
/** \brief copies the given \a old_column into a new one, reading the data with the given start column and stride
*
/** \brief copies the given \a old_column into a new one, reading the data with the given start column and stride */ * \param old_column the column to be duplicated
* \param start for row in column \a old_column to copy
* \param stride stride for iterating through \a old_column when copying
* \param name name for the new column
* \return ID of the newly created column
*
* Pseuo-Code:
* \code
* newColumn=addColumn(rowcount(old_column), name)
* forall ( r: rows(old_column)) {
* set(newColumn, r, get(old_column, r))
* }
* return newColumn;
* \endcode
*/
size_t copyColumn(size_t old_column, size_t start, size_t stride, const QString& name=QString("")); size_t copyColumn(size_t old_column, size_t start, size_t stride, const QString& name=QString(""));
/** \brief copies the given \a old_column into a new one */ /** \brief copies the given \a old_column into a new one
*
* \param old_column the column to be duplicated
* \param name name for the new column
* \return ID of the newly created column
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t copyColumn(size_t old_column, const QString& name=QString("")); size_t copyColumn(size_t old_column, const QString& name=QString(""));
@ -250,6 +422,22 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
* \param data data vector to be copied * \param data data vector to be copied
* \param name name for the column * \param name name for the column
* \return the ID of the newly created column * \return the ID of the newly created column
*
* \code
* QVector<double> X, Y;
* const int Ndata=100;
* for (int i=0; i<Ndata; i++) {
* const double x=double(i)/double(Ndata)*8.0*M_PI;
* X<<x;
* Y<<sin(x);
* }
* plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
* // by calling JKQTPDatastore::addCopiedColumn() the data is COPIED from the vector into the datastore
* linegraph->setXColumn(datastore->addCopiedColumn(X, "x"));
* linegraph->setYColumn(datastore->addCopiedColumn(Y, "y"));
* \endcode
*
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/ */
template <typename TContainer> template <typename TContainer>
size_t addCopiedColumn(const TContainer& data, const QString& name=QString("")) { size_t addCopiedColumn(const TContainer& data, const QString& name=QString("")) {
@ -270,11 +458,24 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief add one external column to the datastore. It will be filled with the contents of vector \a data. /** \brief add one external column to the datastore. It will be filled with the contents of vector \a data.
* *
* \tparam TContainer datatype of the container, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to double. * \tparam TContainer datatype of the container, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to double.
* The iterator of TContainer needs to support \c ++ and \c +=
* \param data data vector to be copied * \param data data vector to be copied
* \param name name for the column * \param name name for the column
* \param stride strides through the container \a data with the given stride * \param stride strides through the container \a data with the given stride
* \param start starts copying from \a data with the element \a start * \param start starts copying from \a data with the element \a start
* \return the ID of the newly created column * \return the ID of the newly created column
*
* Pseudocode:
* \code
* it=data.begin();
* it += start; // shift by start items
* while (it!=data.end()) {
* newColumn.push_back(jkqtp_todouble(*it));
* it += stride;
* }
* \endcode
*
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/ */
template <typename TContainer> template <typename TContainer>
size_t addCopiedColumn(const TContainer& data, const QString& name, size_t stride, size_t start=0) { size_t addCopiedColumn(const TContainer& data, const QString& name, size_t stride, size_t start=0) {
@ -304,6 +505,7 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
* \return the ID of the newly created column * \return the ID of the newly created column
* *
* \note This function converts the input array \a data into an array of double! * \note This function converts the input array \a data into an array of double!
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/ */
template<typename T> template<typename T>
size_t addCopiedColumn(const T* data, size_t rows, const QString& name=QString("")){ size_t addCopiedColumn(const T* data, size_t rows, const QString& name=QString("")){
@ -328,7 +530,15 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
* \param name name for the column * \param name name for the column
* \return the ID of the newly created column * \return the ID of the newly created column
* *
* Pseudocode:
* \code
* for (i=start; i<rows; i+=stride) {
* newColumn.push_back(jkqtp_todouble(data[i]));
* }
* \endcode
* \note This function converts the input array \a data into an array of double! * \note This function converts the input array \a data into an array of double!
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/ */
template<typename T> template<typename T>
size_t addCopiedColumn(const T* data, size_t rows, size_t stride, int start, const QString& name) { size_t addCopiedColumn(const T* data, size_t rows, size_t stride, int start, const QString& name) {
@ -351,7 +561,16 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
* \param stride when copying, this function steps throught the data with the given stride, so only eleemnts <code>[0, stride, 2*stride, ... (rows-1)*stride]</code> are copied! * \param stride when copying, this function steps throught the data with the given stride, so only eleemnts <code>[0, stride, 2*stride, ... (rows-1)*stride]</code> are copied!
* \return the ID of the newly created column * \return the ID of the newly created column
* *
*
* Pseudocode:
* \code
* for (i=0; i<rows; i+=stride) {
* newColumn.push_back(jkqtp_todouble(data[i]));
* }
* \endcode
* \note This function converts the input array \a data into an array of double! * \note This function converts the input array \a data into an array of double!
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/ */
template<typename T> template<typename T>
size_t addCopiedColumn(const T* data, size_t rows, size_t stride, const QString& name) { size_t addCopiedColumn(const T* data, size_t rows, size_t stride, const QString& name) {
@ -362,49 +581,60 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief add one external column to the datastore. It contains \a width * \a height rows. The external data is assumed to be organized as a row-major image and is copied as such. The external data is copied to an internal array, so /** \brief add one external column to the datastore. It contains \a width * \a height rows. The external data is assumed to be organized as a row-major image and is copied as such. The external data is copied to an internal array, so
* afterwards you can delete the external arrayThis returns its logical column ID.*/ * afterwards you can delete the external arrayThis returns its logical column ID.*/
template <typename T> template <typename T>
inline size_t addCopiedImageAsColumn(const T* data, size_t width, size_t height, const QString& name=QString(""), size_t stride=1, size_t start=0){ inline size_t addCopiedImageAsColumn(const T* data, size_t width, size_t height, const QString& name=QString(""), size_t stride=1, size_t start=0);
return addCopiedColumn<T>(data, width*height, stride, start, name);
}
/** \brief add one external column to the datastore. It contains \a width * \a height rows. The external data is assumed to be organized as a row-major image and is copied as such. The external data is copied to an internal array, so /** \brief add one external column to the datastore. It contains \a width * \a height rows. The external data is assumed to be organized as a row-major image and is copied as such. The external data is copied to an internal array, so
* afterwards you can delete the external arrayThis returns its logical column ID.*/ * afterwards you can delete the external arrayThis returns its logical column ID.
*
* \tparam TContainer datatype of the container, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to double.
* \param data data vector to be copied
* \param width width of the image, stored in \a data
* \param name name for the column
* \return the ID of the newly created column
*/
template <typename TContainer> template <typename TContainer>
inline size_t addCopiedImageAsColumn(const TContainer& data, const QString& name=QString("")){ inline size_t addCopiedImageAsColumn(const TContainer& data, size_t width, const QString& name=QString(""));
return addCopiedColumn<TContainer>(data, name);
}
/** \brief add one external column to the datastore. It contains \a width * \a height rows. The external data is assumed to be organized as a column-major image and is copied as row-major (i.e. is transposed). The external data is copied to an internal array, so /** \brief add a new column to the datastore, which is filled from the transposed column-major array \a data with
* afterwards you can delete the external arrayThis returns its logical column ID.*/ * the given \a width and \a height.
*
* The external data is assumed to be organized as a column-major image and is copied as row-major (i.e. is transposed).
* The external data is copied to an internal array, so afterwards you can delete the external arrayThis returns its logical column ID.
*
* \tparam T data type of the array \a data, needs to be convertible to \c double by jkqtp_todouble()
* \param data a column major image
* \param width width of \a data
* \param height height of \a data
* \param name name of the new column
* \param stride stride to use, when reading \a data. Use this to e.g. read one channel from a packed RGB-image (\c stride=3, \c start=0/1/2 )
* \param start first entry from \a data top copy \a data. Use this to e.g. read one channel from a packed RGB-image (\c stride=3, \c start=0/1/2 )
* \return ID of the newly added column
*/
template <typename T> template <typename T>
size_t addCopiedImageAsColumnTranspose(const T* data, size_t width, size_t height, const QString& name=QString(""), size_t stride=1, size_t start=0){ size_t addCopiedImageAsColumnTranspose(const T* data, size_t width, size_t height, const QString& name=QString(""), size_t stride=1, size_t start=0);
double* temp=static_cast<T*>(malloc(width*height*sizeof(T)));
for (size_t x=0; x<width; x++) {
for (size_t y=0; y<height; y++) {
temp[x*height+y]=data[start+(y*width+x)*stride];
}
}
size_t idx=addCopiedColumn(temp, width*height, name);
free(temp);
return idx;
}
/** \brief add one external column to the datastore. It contains \a width * \a height rows. The external data is assumed to be organized as a column-major image and is copied as row-major (i.e. is transposed). The external data is copied to an internal array, so /** \brief add one external column to the datastore. It contains \a width * \a height rows.
* afterwards you can delete the external arrayThis returns its logical column ID.*/ *
* The external data is assumed to be organized as a column-major image and is copied as row-major (i.e. is transposed).
* The external data is copied to an internal array, so afterwards you can delete the external array This returns its
* logical column ID.
*
* \tparam T data type of the array \a data, needs to be convertible to \c double by jkqtp_todouble()
* \param data data vector to be copied
* \param width width of the image, stored in \a data
* \param name name for the column
* \return the ID of the newly created column
*/
template <typename T> template <typename T>
inline size_t addCopiedImageAsColumnTranspose(const QVector<T>& data, size_t width, const QString& name=QString("")){ inline size_t addCopiedImageAsColumnTranspose(const QVector<T>& data, size_t width, const QString& name=QString(""));
return addCopiedImageAsColumnTranspose<T>(data.data(), width, static_cast<size_t>(data.size())/width, name);
}
/** \brief add one external column to the datastore. It contains \a rows rows. The external data is copied to an internal array, so /** \brief add one external column to the datastore. It contains \a rows rows. The external data is copied to an internal array, so
* afterwards you can delete the external arrayThis returns its logical column ID. * afterwards you can delete the external arrayThis returns its logical column ID.
* *
* \note This function converts the input array \a data into an array of double! * \note This function converts the input array \a data into an array of double!
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/ */
template <typename T> template <typename T>
size_t addCopiedColumnMasked(const T* data, const bool* mask, size_t rows, const QString& name=QString(""), bool useIfMaskEquals=false) { size_t addCopiedColumnMasked(const T* data, const bool* mask, size_t rows, const QString& name=QString(""), bool useIfMaskEquals=false) {
@ -420,19 +650,31 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
} }
size_t col= addCopiedColumn(d, rrs, name); size_t col= addInternalColumn(d, rrs, name);
free(d);
return col; return col;
} }
/** \brief add one external column to the datastore. It will be filled with the contents of vector \a data. /** \brief add one external column to the datastore. It will be filled with the contents of vector \a data.
* *
* \tparam TContainer datatype of the container, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to double. * \tparam TContainer datatype of the container \a data, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to double.
* \tparam TContainerMask datatype of the container \a mask, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to bool.
* \param data data vector to be copied * \param data data vector to be copied
* \param mask data vector to be copied
* \param name name for the column * \param name name for the column
* \param stride strides through the container \a data with the given stride * \param stride strides through the container \a data with the given stride
* \param start starts copying from \a data with the element \a start * \param start starts copying from \a data with the element \a start
* \return the ID of the newly created column * \return the ID of the newly created column
* \see \ref JKQTPlotterAdvancedJKQTPDatastore
*
* Pseudocode:
* \code
* for (i=0; i<data.size(); i++) {
* if (static_cast<bool>(mask[i])==useIfMaskEquals) {
* newColumn.push_back(jkqtp_todouble(data[i]));
* }
* }
* return newColumn;
* \endcode
*/ */
template <typename TContainer, typename TContainerMask> template <typename TContainer, typename TContainerMask>
size_t addCopiedColumnMasked(const TContainer& data, const TContainerMask& mask, const QString& name=QString(""), bool useIfMaskEquals=false) { size_t addCopiedColumnMasked(const TContainer& data, const TContainerMask& mask, const QString& name=QString(""), bool useIfMaskEquals=false) {
@ -443,7 +685,7 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
auto itmask=mask.begin(); auto itmask=mask.begin();
auto itdata=data.begin(); auto itdata=data.begin();
for (size_t r=0; r<N; r++) { for (size_t r=0; r<N; r++) {
if ((*itmask)==useIfMaskEquals) { if (static_cast<bool>(*itmask)==useIfMaskEquals) {
d[rrs]=jkqtp_todouble(*itdata); d[rrs]=jkqtp_todouble(*itdata);
rrs++; rrs++;
} }
@ -451,42 +693,149 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
++itdata; ++itdata;
} }
} }
size_t col= addInternalColumn(d, rrs, name);
size_t col= addCopiedColumn(d, rrs, name);
free(d);
return col; return col;
} }
/** \brief copies the contents of the map-like container \a c into two columns of the datastore, /** \brief copies the contents of the map-like container \a c into two columns of the datastore,
* returns the two IDs of the items as a std::pair */ * returns the two IDs of the items as a std::pair
* \see \ref JKQTPlotterAdvancedJKQTPDatastore, jkqtp_todouble()
*
* \tparam TContainer datatype of the map-typed container (e.g. \c std::map or \c QMap ) The requiremen to this container is
* that it supports standard iterators with \c begin() and \c end() .
* \param c the map to copy to the datastore
* \param nameKey name for the column with the map keys
* \param nameValue name for the column with the map values
* \return a pair of IDs to the newly created columns (IDkeyColumn, IDvalueColumn)
* Example of usage:
* \code
* std::map<int, double> datamap;
* datamap[1]=1.1;
* datamap[2]=1.4;
* datamap[4]=1.2;
* datamap[5]=1.8;
* datamap[7]=0.9;
* plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
* linegraph->setXYColumns(datastore->addCopiedMap(datamap, "map_x", "map_y"));
* linegraph->setTitle(QObject::tr("copied map"));
* \endcode
*/
template <typename TContainer> template <typename TContainer>
std::pair<size_t, size_t> addCopiedMap(const TContainer& c, const QString& nameKey=QString("map_key"), const QString& nameValue=QString("map_value")) { std::pair<size_t, size_t> addCopiedMap(const TContainer& c, const QString& nameKey=QString("map_key"), const QString& nameValue=QString("map_value")) {
std::vector<double> xvals; const size_t N=std::distance(c.begin(), c.end());
std::vector<double> yvals; double* xvals=static_cast<double*>(malloc(N*sizeof(double)));
double* yvals=static_cast<double*>(malloc(N*sizeof(double)));
size_t i=0;
for (auto it=c.begin(); it!=c.end(); ++it) { for (auto it=c.begin(); it!=c.end(); ++it) {
xvals.push_back(jkqtp_todouble(it->first)); xvals[i]=(jkqtp_todouble(it->first));
yvals.push_back(jkqtp_todouble(it->second)); yvals[i]=(jkqtp_todouble(it->second));
i++;
} }
return std::make_pair<size_t, size_t>( const size_t cx=addInternalColumn(xvals, N, nameKey);
addCopiedColumn(xvals, nameKey), const size_t cy=addInternalColumn(yvals, N, nameValue);
addCopiedColumn(yvals, nameValue) return std::pair<size_t, size_t>(cx,cy);
);
} }
/** \brief add a column to the datastore that contains \a rows rows with increasing value starting at \a start and ending at \a end. /** \brief add a column to the datastore that contains \a rows rows with monotonely increasing value starting at \a start and ending at \a end.
* the values are equidistant between \a start end \a end */ * the values are equidistant between \a start end \a end
* \see addLogColumn(), addDecadeLogColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addLinearColumn(size_t rows, double start, double end, const QString& name=QString("")); size_t addLinearColumn(size_t rows, double start, double end, const QString& name=QString(""));
/** \brief add a column to the datastore that contains \a rows rows with monotonely increasing value starting at \a start and ending at \a end.
* the values are logarithmically spaced between \a start end \a end
* \see addLinearColumn(), addDecadeLogColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addLogColumn(size_t rows, double start, double end, const QString& name=QString(""));
/** \brief add a column to the datastore that contains \a rows rows with monotonely increasing value starting at 10^start and ending at 10^end.
* the values are logarithmically spaced between 10^start end 10^end
* \see addLinearColumn(), addLogColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addDecadeLogColumn(size_t rows, double startDecade, double endDecade, const QString& name=QString(""));
/** \brief add two columns to the datastore that contains the x- and y- coordinates of a rectangular grid with \a width points in x- and \a height
* points in y-direction.
*
* \param width number of columns in the mesh grid
* \param startX x-coordinate of the first column of the mesh grid
* \param endX x-coordinate of the last column of the mesh grid
* \param height number of rows in the mesh grid
* \param startY y-coordinate of the first row of the mesh grid
* \param endY y-coordinate of the last row of the mesh grid
* \param nameX name for the x-coordinate column
* \param nameY name for the y-coordinate column
* \return IDs of two column that contain the x- and y- coordinates od the mesh points (in row-major order), where the
* x-coordinates are linearly distributed between \a startX and \a endX and the x-coordinates are linearly
* distributed between \a startY and \a endY .
*
* \see addLogGridColumns(), addDecadeLogGridColumns(), addColumnCalculatedFromColumn(), JKQTPXYParametrizedScatterGraph, \ref JKQTPlotterAdvancedJKQTPDatastore
*/
std::pair<size_t,size_t> addLinearGridColumns(size_t width, double startX, double endX, size_t height, double startY, double endY, const QString& nameX=QString(""), const QString& nameY=QString(""));
/** \brief add a column with \a rows entries, that is calculated by calling \a f for each entry
*
* Pseudocode:
* \code
* for (i=0; i<rows; i++) {
* newColumn.push_back(f(i, this));
* }
* return newColumn;
* \endcode
*
* \see addColumnCalculatedFromColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addCalculatedColumn(size_t rows, const std::function<double(size_t, JKQTPDatastore*)>& f, const QString& name=QString(""));
/** \brief add a column with \a rows entries, that is calculated by calling \a f for each entry
*
* Pseudocode:
* \code
* for (i=0; i<rows; i++) {
* newColumn.push_back(f(i));
* }
* return newColumn;
* \endcode
*
* \see addColumnCalculatedFromColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addCalculatedColumn(size_t rows, const std::function<double(size_t)>& f, const QString& name=QString(""));
/** \brief add a column with the same number of entries, as in the other column \a otherColumn , that are calculated by calling \a f for each entry in \a otherColumn
*
* Pseudocode:
* \code
* for (i=0; i<rows(otherColumn); i++) {
* newColumn.push_back(f(getValue(otherColumn, i));
* }
* return newColumn;
* \endcode
*
* \see addCalculatedColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addColumnCalculatedFromColumn(size_t otherColumn, const std::function<double(double)>& f, const QString& name=QString(""));
/** \brief add a column with the same number of entries, as in the other column \a otherColumn , that are calculated by calling \a f for each pair of entries in \a otherColumnX and \a otherColumnY
*
* Pseudocode:
* \code
* for (i=0; i<min(rows(otherColumnX), rows(otherColumnY)); i++) {
* newColumn.push_back(f(getValue(otherColumnX, i), getValue(otherColumnY, i));
* }
* return newColumn;
* \endcode
*
* \see addCalculatedColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
*/
size_t addColumnCalculatedFromColumn(size_t otherColumnX, size_t otherColumnY, const std::function<double(double,double)>& f, const QString& name=QString(""));
/** \brief returns the number of (logical) columns currently managed by the datastore */ /** \brief returns the number of (logical) columns currently managed by the datastore */
inline size_t getColumnCount() { return static_cast<size_t>(columns.size()); } inline size_t getColumnCount() { return static_cast<size_t>(columns.size()); }
/** \brief returns a list with all available column IDs */
inline QList<size_t> getColumnIDs() { return columns.keys(); } inline QList<size_t> getColumnIDs() { return columns.keys(); }
/** \brief return the num of the first column with the given name, or -1 if none was found */ /** \brief return the num of the first column with the given name, or -1 if none was found */
@ -495,12 +844,6 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief return the num of the first column with the given name, if none was found this creates a new column with no rows and returns its num */ /** \brief return the num of the first column with the given name, if none was found this creates a new column with no rows and returns its num */
int ensureColumnNum(const QString& name); int ensureColumnNum(const QString& name);
/** \brief returns the JKQTPColumn object for the \a i -th column in the store */
JKQTPColumn getColumn(size_t i) const;
/** \brief returns the JKQTPColumn object for the \a i -th column in the store */
JKQTPColumn getColumn(int i) const;
/** \brief returns the maximum number of rows in all columns */ /** \brief returns the maximum number of rows in all columns */
size_t getMaxRows(); size_t getMaxRows();
@ -580,9 +923,10 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief return a list with all columns available in the datastore */ /** \brief return a list with all columns available in the datastore */
QStringList getColumnNames() const; QStringList getColumnNames() const;
/** \brief add a column with \a rows entries from the array \a data,
* ownership of the memory behind \a data is transfered to the datastore */ friend class JKQTPColumn;
size_t addInternalColumn(double *data, size_t rows, const QString& name); friend class JKQTPDatastoreItem;
friend class JKQTPDatastoreModel;
}; };
@ -603,8 +947,10 @@ class JKQTP_LIB_EXPORT JKQTPColumn {
QString name; QString name;
/** \brief pointer to the datastore object used to manage the data of the plot */ /** \brief pointer to the datastore object used to manage the data of the plot */
JKQTPDatastore* datastore; JKQTPDatastore* datastore;
/** \brief is this item valid?/usable? */
bool valid; bool valid;
/** \brief number of columns, if interpreted as a row-major image */
size_t imageColumns;
protected: protected:
inline JKQTPDatastore* getDatastore() { return datastore; } inline JKQTPDatastore* getDatastore() { return datastore; }
@ -616,23 +962,22 @@ class JKQTP_LIB_EXPORT JKQTPColumn {
* The use of this constructor is mandatory. The default constructor (no arguments) is hidden. Also note * The use of this constructor is mandatory. The default constructor (no arguments) is hidden. Also note
* that you cannot change the binding of a column to a datastore object after creation of the column. * that you cannot change the binding of a column to a datastore object after creation of the column.
*/ */
JKQTPColumn(JKQTPDatastore* datastore, const QString& name=QString(""), size_t datastoreItem=0, size_t datastoreOffset=0); JKQTPColumn(JKQTPDatastore* datastore, const QString& name=QString(""), size_t datastoreItem=0, size_t datastoreOffset=0, size_t imageColumns=1);
inline bool isValid() const { return valid; } inline bool isValid() const { return valid; }
/** \brief class destructor */ /** \brief class destructor */
~JKQTPColumn() ; ~JKQTPColumn() =default;
/*! \brief sets the property name ( \copybrief name ) to the specified \a __value. \details Description of the parameter name is: <BLOCKQUOTE>\copydoc JKQTPColumn::name </BLOCKQUOTE> \see JKQTPColumn::name for more information */ /*! \brief sets the property name ( \copybrief name ) to the specified \a __value. \details Description of the parameter name is: <BLOCKQUOTE>\copydoc JKQTPColumn::name </BLOCKQUOTE> \see JKQTPColumn::name for more information */
inline void setName (const QString& __value) void setName (const QString& __value);
{
this->name = __value;
}
/*! \brief returns the property name ( \copybrief name ). \see name for more information */ /*! \brief returns the property name ( \copybrief name ). \see name for more information */
inline QString getName () const QString getName () const;
{
return this->name; /*! \copydoc imageColumns */
} void setImageColumns (size_t __value);
/*! \copydoc imageColumns */
inline size_t getImageColumns () const { return imageColumns; }
/** \brief returns the number of rows in this column (accesses the datastore) */ /** \brief returns the number of rows in this column (accesses the datastore) */
size_t getRows() const; size_t getRows() const;
@ -681,13 +1026,32 @@ class JKQTP_LIB_EXPORT JKQTPColumn {
/** \brief sets the element at (x,y) in the column, where the data is interpreted as a row-major ordered Matrix of the given width /** \brief sets the element at (x,y) in the column, where the data is interpreted as a row-major ordered Matrix of the given width
* *
* This method accesses the datastore and returns the double value stored in the \a n'th row of the according * This method accesses the datastore and returns the double value stored in the \c (y*width+x)'th row of the according
* column. * column.
*/ */
inline void setPixelValue(size_t x, size_t y, size_t width, double val) { inline void setPixelValue(size_t x, size_t y, size_t width, double val) {
setValue(y*width+x, val); setValue(y*width+x, val);
} }
/** \brief sets the element at (x,y) in the column, where the data is interpreted as a row-major ordered Matrix of the width imageWidth
*
* This method accesses the datastore and returns the double value stored in the \c (y*imageColumns+x)'th row of the according
* column.
*/
inline void setPixelValue(size_t x, size_t y, double val) {
setValue(y*imageColumns+x, val);
}
/** \brief returns the element at (x,y) in the column, where the data is interpreted as a row-major ordered Matrix of the width imageWidth
*
* This method accesses the datastore and returns the double value stored in the \c (y*imageColumns+x)'th row of the according
* column.
*/
inline double getPixelValue(size_t x, size_t y) const {
return getValue(y*imageColumns+x);
}
/** \brief returns a pointer to the datastore item representing this column */ /** \brief returns a pointer to the datastore item representing this column */
inline JKQTPDatastoreItem* getDatastoreItem() const { return datastore->getItem(datastoreItem); } inline JKQTPDatastoreItem* getDatastoreItem() const { return datastore->getItem(datastoreItem); }
@ -893,6 +1257,57 @@ inline double JKQTPColumn::getValue(int n) const {
return datastore->getItem(datastoreItem)->get(datastoreOffset, static_cast<size_t>(n)); return datastore->getItem(datastoreItem)->get(datastoreOffset, static_cast<size_t>(n));
} }
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::getRows(size_t column) const {
return columns.value(column).getRows();
}
////////////////////////////////////////////////////////////////////////////////////////////////
const double *JKQTPDatastore::getColumnPointer(int column, size_t row) const
{
if (column<0) return nullptr;
return columns.value(static_cast<size_t>(column)).getPointer(row);
}
////////////////////////////////////////////////////////////////////////////////////////////////
double *JKQTPDatastore::getColumnPointer(int column, size_t row)
{
if (column<0) return nullptr;
return columns[static_cast<size_t>(column)].getPointer(row);
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::getColumnImageWidth(int column)
{
if (column<0) return 0;
return columns[static_cast<size_t>(column)].getImageColumns();
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::getColumnImageHeight(int column)
{
if (column<0) return 0;
return columns[static_cast<size_t>(column)].getRows()/columns[static_cast<size_t>(column)].getImageColumns();
}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPDatastore::getRows(int column) const {
if (column<0) return 0;
return columns.value(static_cast<size_t>(column)).getRows();
}
////////////////////////////////////////////////////////////////////////////////////////////////
const double *JKQTPDatastore::getColumnPointer(size_t column, size_t row) const
{
return columns.value(column).getPointer(row);
}
////////////////////////////////////////////////////////////////////////////////////////////////
double *JKQTPDatastore::getColumnPointer(size_t column, size_t row)
{
return columns[column].getPointer(row);
}
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
inline double JKQTPDatastore::get(size_t column, size_t row) const { inline double JKQTPDatastore::get(size_t column, size_t row) const {
return columns[column].getValue(row); return columns[column].getValue(row);
@ -928,6 +1343,80 @@ inline void JKQTPDatastore::set(int column, size_t row, double value) {
set(static_cast<size_t>(column), static_cast<size_t>(row), value); set(static_cast<size_t>(column), static_cast<size_t>(row), value);
} }
////////////////////////////////////////////////////////////////////////////////////////////////
inline double JKQTPDatastore::getPixel(size_t column, size_t x, size_t y) const {
return columns.value(column).getPixelValue(x, y);
}
////////////////////////////////////////////////////////////////////////////////////////////////
inline void JKQTPDatastore::setPixel(size_t column, size_t x, size_t y, double value) {
return columns[column].setPixelValue(x, y, value);
}
////////////////////////////////////////////////////////////////////////////////////////////////
void JKQTPDatastore::setAll(size_t column, double value)
{
columns[column].setAll(value);
}
////////////////////////////////////////////////////////////////////////////////////////////////
void JKQTPDatastore::scaleColumnValues(size_t column, double factor)
{
columns[column].scale(factor);
}
////////////////////////////////////////////////////////////////////////////////////////////////
void JKQTPDatastore::inc(size_t column, size_t row, double increment)
{
columns[column].incValue(row, increment);
}
////////////////////////////////////////////////////////////////////////////////////////////////
void JKQTPDatastore::dec(size_t column, size_t row, double decrement)
{
columns[column].decValue(row, decrement);
}
////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
inline size_t JKQTPDatastore::addCopiedImageAsColumn(const T* data, size_t width, size_t height, const QString& name, size_t stride, size_t start){
size_t col=addCopiedColumn<T>(data, width*height, stride, start, name);
columns[col].setImageColumns(width);
return col;
}
////////////////////////////////////////////////////////////////////////////////////////////////
template <typename TContainer>
inline size_t JKQTPDatastore::addCopiedImageAsColumn(const TContainer& data, size_t width, const QString& name){
size_t col= addCopiedColumn<TContainer>(data, name);
columns[col].setImageColumns(width);
return col;
}
////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
size_t JKQTPDatastore::addCopiedImageAsColumnTranspose(const T* data, size_t width, size_t height, const QString& name, size_t stride, size_t start){
double* temp=static_cast<double*>(malloc(width*height*sizeof(double)));
for (size_t x=0; x<width; x++) {
for (size_t y=0; y<height; y++) {
temp[x*height+y]=jkqtp_todouble<T>(data[start+(y*width+x)*stride]);
}
}
size_t idx=addInternalColumn(temp, width*height, name);
columns[idx].setImageColumns(height);
return idx;
}
////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
inline size_t JKQTPDatastore::addCopiedImageAsColumnTranspose(const QVector<T>& data, size_t width, const QString& name) {
return addCopiedImageAsColumnTranspose<T>(data.data(), width, static_cast<size_t>(data.size())/width, name);
}
#endif // JKQTPDATASTORAGE_H #endif // JKQTPDATASTORAGE_H

View File

@ -84,7 +84,7 @@ void JKQTPBarVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
QBrush b=getFillBrush(painter, parent); QBrush b=getFillBrush(painter, parent);
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
@ -167,7 +167,7 @@ bool JKQTPBarVerticalGraph::getXMinMax(double& minx, double& maxx, double& small
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -222,7 +222,7 @@ bool JKQTPBarVerticalGraph::getYMinMax(double& miny, double& maxy, double& small
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -328,7 +328,7 @@ void JKQTPBarHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
QBrush b=getFillBrush(painter, parent); QBrush b=getFillBrush(painter, parent);
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -414,7 +414,7 @@ bool JKQTPBarHorizontalGraph::getXMinMax(double& minx, double& maxx, double& sma
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(xColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(xColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -457,7 +457,7 @@ bool JKQTPBarHorizontalGraph::getYMinMax(double& miny, double& maxy, double& sma
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -607,7 +607,7 @@ bool JKQTPBarHorizontalErrorGraph::getXMinMax(double &minx, double &maxx, double
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -676,7 +676,7 @@ bool JKQTPBarVerticalErrorGraph::getYMinMax(double &miny, double &maxy, double &
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -717,7 +717,7 @@ bool JKQTPBarVerticalErrorGraph::getYMinMax(double &miny, double &maxy, double &
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;

View File

@ -131,7 +131,7 @@ bool JKQTPGraph::getDataMinMax(int column, double &minx, double &maxx, double &s
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=static_cast<int>(datastore->getColumn(column).getRows()); int imax=static_cast<int>(datastore->getRows(column));
if (imin<0) imin=0; if (imin<0) imin=0;
if (imax<0) imax=0; if (imax<0) imax=0;
@ -402,6 +402,42 @@ void JKQTPXYGraph::setDataSortOrder(int __value) {
sortData=static_cast<DataSortOrder>(__value); sortData=static_cast<DataSortOrder>(__value);
} }
void JKQTPXYGraph::setXYColumns(size_t xCol, size_t yCol)
{
setXColumn(xCol);
setYColumn(yCol);
}
void JKQTPXYGraph::setXYColumns(int xCol, int yCol)
{
setXColumn(xCol);
setYColumn(yCol);
}
void JKQTPXYGraph::setXYColumns(std::pair<int, int> xyColPair)
{
setXColumn(xyColPair.first);
setYColumn(xyColPair.second);
}
void JKQTPXYGraph::setXYColumns(std::pair<size_t, size_t> xyColPair)
{
setXColumn(xyColPair.first);
setYColumn(xyColPair.second);
}
void JKQTPXYGraph::setXYColumns(QPair<int, int> xyColPair)
{
setXColumn(xyColPair.first);
setYColumn(xyColPair.second);
}
void JKQTPXYGraph::setXYColumns(QPair<size_t, size_t> xyColPair)
{
setXColumn(xyColPair.first);
setYColumn(xyColPair.second);
}
double JKQTPXYGraph::hitTest(const QPointF &posSystem, QPointF *closestSpotSystem, QString *label, HitTestMode mode) const double JKQTPXYGraph::hitTest(const QPointF &posSystem, QPointF *closestSpotSystem, QString *label, HitTestMode mode) const
{ {
@ -547,7 +583,7 @@ bool JKQTPSingleColumnGraph::getIndexRange(int &imin, int &imax) const
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
imin=0; imin=0;
imax=static_cast<int>(datastore->getColumn(static_cast<size_t>(dataColumn)).getRows()); imax=static_cast<int>(datastore->getRows(static_cast<size_t>(dataColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -617,7 +653,7 @@ bool JKQTPXYGraph::getIndexRange(int& imin, int& imax) const
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
imin=0; imin=0;
imax=static_cast<int>(qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows())); imax=static_cast<int>(qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn))));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;

View File

@ -531,6 +531,19 @@ class JKQTP_LIB_EXPORT JKQTPXYGraph: public JKQTPGraph {
/*! \brief sets the property sortData ( \copybrief sortData ) to the specified \a __value. \details Description of the parameter sortData is: <BLOCKQUOTE>\copydoc sortData </BLOCKQUOTE> \see sortData for more information */ /*! \brief sets the property sortData ( \copybrief sortData ) to the specified \a __value. \details Description of the parameter sortData is: <BLOCKQUOTE>\copydoc sortData </BLOCKQUOTE> \see sortData for more information */
void setDataSortOrder(int __value); void setDataSortOrder(int __value);
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns(size_t xCol, size_t yCol);
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns(int xCol, int yCol);
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns(std::pair<int,int> xyColPair);
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns(std::pair<size_t,size_t> xyColPair);
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns(QPair<int,int> xyColPair);
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns(QPair<size_t,size_t> xyColPair);
/** \brief Implmentation of JKQTPPlotElement::hitTest(), which searches through all graph points defined by xColumn and yColumn /** \brief Implmentation of JKQTPPlotElement::hitTest(), which searches through all graph points defined by xColumn and yColumn
* and returns a general x/y-label, also taking into account possibly known errors to the graphs (if it is derived * and returns a general x/y-label, also taking into account possibly known errors to the graphs (if it is derived

View File

@ -82,7 +82,7 @@ void JKQTPGraphErrorStyleMixin::setErrorColorFromGraphColor(QColor graphColor)
QPen JKQTPGraphErrorStyleMixin::getErrorLinePen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const QPen JKQTPGraphErrorStyleMixin::getErrorLinePen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
{ {
QPen p=m_errorLinePen; QPen p=m_errorLinePen;
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_errorLineWidth))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_errorLineWidth)));
return p; return p;
} }
@ -282,8 +282,8 @@ void JKQTPGraphErrorStyleMixin::intPlotXYErrorIndicators(JKQTPEnhancedPainter& p
painter.setPen(p); painter.setPen(p);
size_t imaxx=0, imaxy=0; size_t imaxx=0, imaxy=0;
if (xColumn>=0) imaxx=datastore->getColumn(static_cast<size_t>(xColumn)).getRows(); if (xColumn>=0) imaxx=datastore->getRows(static_cast<size_t>(xColumn));
if (yColumn>=0) imaxy=datastore->getColumn(static_cast<size_t>(yColumn)).getRows(); if (yColumn>=0) imaxy=datastore->getRows(static_cast<size_t>(yColumn));
size_t imax=qMin(imaxx, imaxy); size_t imax=qMin(imaxx, imaxy);
size_t imin=0; size_t imin=0;
if (imax<imin) { if (imax<imin) {
@ -630,7 +630,7 @@ void JKQTPXGraphErrorData::setXErrorColumnLower(int __value) {
double JKQTPXGraphErrorData::getXErrorU(int i, JKQTPDatastore *ds) const double JKQTPXGraphErrorData::getXErrorU(int i, JKQTPDatastore *ds) const
{ {
if (ds && xErrorColumn>=0 && i>=0 && i<static_cast<int>(ds->getColumn(xErrorColumn).getRows())) { if (ds && xErrorColumn>=0 && i>=0 && i<static_cast<int>(ds->getRows(xErrorColumn))) {
return ds->get(xErrorColumn, static_cast<size_t>(i)); return ds->get(xErrorColumn, static_cast<size_t>(i));
} }
return 0.0; return 0.0;
@ -640,9 +640,9 @@ double JKQTPXGraphErrorData::getXErrorL(int i, JKQTPDatastore *ds) const
{ {
if (ds) { if (ds) {
if (xErrorSymmetric) { if (xErrorSymmetric) {
if (xErrorColumn>=0 && i>=0 && i<static_cast<int>(ds->getColumn(xErrorColumn).getRows())) return ds->get(xErrorColumn, static_cast<size_t>(i)); if (xErrorColumn>=0 && i>=0 && i<static_cast<int>(ds->getRows(xErrorColumn))) return ds->get(xErrorColumn, static_cast<size_t>(i));
} else { } else {
if (xErrorColumnLower>=0 && i>=0 && i<static_cast<int>(ds->getColumn(xErrorColumnLower).getRows())) return ds->get(xErrorColumnLower, static_cast<size_t>(i)); if (xErrorColumnLower>=0 && i>=0 && i<static_cast<int>(ds->getRows(xErrorColumnLower))) return ds->get(xErrorColumnLower, static_cast<size_t>(i));
} }
} }
return 0.0; return 0.0;
@ -706,7 +706,7 @@ void JKQTPYGraphErrorData::setYErrorColumnLower(int __value) {
double JKQTPYGraphErrorData::getYErrorU(int i, JKQTPDatastore *ds) const double JKQTPYGraphErrorData::getYErrorU(int i, JKQTPDatastore *ds) const
{ {
if (ds && yErrorColumn>=0 && i>=0 && i<static_cast<int>(ds->getColumn(yErrorColumn).getRows())) { if (ds && yErrorColumn>=0 && i>=0 && i<static_cast<int>(ds->getRows(yErrorColumn))) {
return ds->get(yErrorColumn, static_cast<size_t>(i)); return ds->get(yErrorColumn, static_cast<size_t>(i));
} }
return 0.0; return 0.0;
@ -716,9 +716,9 @@ double JKQTPYGraphErrorData::getYErrorL(int i, JKQTPDatastore *ds) const
{ {
if (ds) { if (ds) {
if (yErrorSymmetric) { if (yErrorSymmetric) {
if (yErrorColumn>=0 && i>=0 && i<static_cast<int>(ds->getColumn(yErrorColumn).getRows())) return ds->get(yErrorColumn, static_cast<size_t>(i)); if (yErrorColumn>=0 && i>=0 && i<static_cast<int>(ds->getRows(yErrorColumn))) return ds->get(yErrorColumn, static_cast<size_t>(i));
} else { } else {
if (yErrorColumnLower>=0 && i>=0 && i<static_cast<int>(ds->getColumn(yErrorColumnLower).getRows())) return ds->get(yErrorColumnLower, static_cast<size_t>(i)); if (yErrorColumnLower>=0 && i>=0 && i<static_cast<int>(ds->getRows(yErrorColumnLower))) return ds->get(yErrorColumnLower, static_cast<size_t>(i));
} }
} }
return 0.0; return 0.0;

View File

@ -135,7 +135,7 @@ QBrush JKQTPGraphLineStyleMixin::getLineBrush() const
QPen JKQTPGraphLineStyleMixin::getLinePen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const { QPen JKQTPGraphLineStyleMixin::getLinePen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
QPen p=m_linePen; QPen p=m_linePen;
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_lineWidth))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_lineWidth)));
return p; return p;
} }
@ -239,7 +239,7 @@ double JKQTPGraphSymbolStyleMixin::getSymbolLineWidth() const
QPen JKQTPGraphSymbolStyleMixin::getSymbolPen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const { QPen JKQTPGraphSymbolStyleMixin::getSymbolPen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
QPen p; QPen p;
p.setColor(m_symbolColor); p.setColor(m_symbolColor);
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_symbolLineWidth))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_symbolLineWidth)));
p.setStyle(Qt::SolidLine); p.setStyle(Qt::SolidLine);
p.setJoinStyle(Qt::RoundJoin); p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap); p.setCapStyle(Qt::RoundCap);

View File

@ -71,7 +71,7 @@ void JKQTPBoxplotVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
drawErrorsBefore(painter); drawErrorsBefore(painter);
int imax=static_cast<int>(datastore->getColumn(static_cast<size_t>(posColumn)).getRows()); int imax=static_cast<int>(datastore->getRows(static_cast<size_t>(posColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -213,7 +213,7 @@ bool JKQTPBoxplotVerticalGraph::getXMinMax(double& minx, double& maxx, double& s
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=static_cast<int>(datastore->getColumn(static_cast<size_t>(posColumn)).getRows()); int imax=static_cast<int>(datastore->getRows(static_cast<size_t>(posColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -256,7 +256,7 @@ bool JKQTPBoxplotVerticalGraph::getYMinMax(double& miny, double& maxy, double& s
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=datastore->getColumn(medianColumn).getRows(); int imax=datastore->getRows(medianColumn);
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -477,7 +477,7 @@ bool JKQTPBoxplotHorizontalGraph::getXMinMax(double& miny, double& maxy, double&
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=datastore->getColumn(medianColumn).getRows(); int imax=datastore->getRows(medianColumn);
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -526,7 +526,7 @@ bool JKQTPBoxplotHorizontalGraph::getYMinMax(double& minx, double& maxx, double&
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=static_cast<int>(datastore->getColumn(static_cast<size_t>(posColumn)).getRows()); int imax=static_cast<int>(datastore->getRows(static_cast<size_t>(posColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -578,7 +578,7 @@ void JKQTPBoxplotHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
drawErrorsBefore(painter); drawErrorsBefore(painter);
int imax=static_cast<int>(datastore->getColumn(static_cast<size_t>(posColumn)).getRows()); int imax=static_cast<int>(datastore->getRows(static_cast<size_t>(posColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -1259,7 +1259,7 @@ void JKQTPBoxplotVerticalGraph::intSortData()
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=static_cast<int>(datastore->getColumn(static_cast<size_t>(posColumn)).getRows()); int imax=static_cast<int>(datastore->getRows(static_cast<size_t>(posColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;

View File

@ -415,7 +415,7 @@ QBrush JKQTPGraphBoxplotStyleMixin::getWhiskerLineBrush() const
QPen JKQTPGraphBoxplotStyleMixin::getWhiskerPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const QPen JKQTPGraphBoxplotStyleMixin::getWhiskerPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
{ {
QPen pw=m_whiskerLinePen; QPen pw=m_whiskerLinePen;
pw.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerLineWidth))); pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerLineWidth)));
pw.setJoinStyle(Qt::MiterJoin); pw.setJoinStyle(Qt::MiterJoin);
pw.setCapStyle(Qt::FlatCap); pw.setCapStyle(Qt::FlatCap);
return pw; return pw;
@ -513,7 +513,7 @@ QBrush JKQTPGraphBoxplotStyleMixin::getWhiskerCapLineBrush() const
QPen JKQTPGraphBoxplotStyleMixin::getWhiskerCapPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const QPen JKQTPGraphBoxplotStyleMixin::getWhiskerCapPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
{ {
QPen pw=m_whiskerCapLinePen; QPen pw=m_whiskerCapLinePen;
pw.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerCapLineWidth))); pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerCapLineWidth)));
pw.setJoinStyle(Qt::MiterJoin); pw.setJoinStyle(Qt::MiterJoin);
return pw; return pw;
} }
@ -529,7 +529,7 @@ QPen JKQTPGraphBoxplotStyleMixin::getWhiskerCapPen(JKQTPEnhancedPainter &painter
QPen JKQTPGraphBoxplotStyleMixin::getMedianPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const QPen JKQTPGraphBoxplotStyleMixin::getMedianPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
{ {
QPen pw=m_medianLinePen; QPen pw=m_medianLinePen;
pw.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*medianLineWidth))); pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*medianLineWidth)));
pw.setJoinStyle(Qt::MiterJoin); pw.setJoinStyle(Qt::MiterJoin);
pw.setCapStyle(Qt::FlatCap); pw.setCapStyle(Qt::FlatCap);
return pw; return pw;
@ -537,7 +537,7 @@ QPen JKQTPGraphBoxplotStyleMixin::getMedianPen(JKQTPEnhancedPainter &painter, JK
QPen JKQTPGraphBoxplotStyleMixin::getMeanSymbolPen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const { QPen JKQTPGraphBoxplotStyleMixin::getMeanSymbolPen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
QPen p=m_meanSymbolLinePen; QPen p=m_meanSymbolLinePen;
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth)));
p.setStyle(Qt::SolidLine); p.setStyle(Qt::SolidLine);
p.setJoinStyle(Qt::RoundJoin); p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap); p.setCapStyle(Qt::RoundCap);
@ -546,7 +546,7 @@ QPen JKQTPGraphBoxplotStyleMixin::getMeanSymbolPen(JKQTPEnhancedPainter& painter
QPen JKQTPGraphBoxplotStyleMixin::getMeanLinePen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const { QPen JKQTPGraphBoxplotStyleMixin::getMeanLinePen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
QPen p=m_meanSymbolLinePen; QPen p=m_meanSymbolLinePen;
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth)));
p.setJoinStyle(Qt::MiterJoin); p.setJoinStyle(Qt::MiterJoin);
p.setCapStyle(Qt::FlatCap); p.setCapStyle(Qt::FlatCap);
return p; return p;

View File

@ -216,7 +216,7 @@ bool JKQTPContour::getRelativeLevels() const
void JKQTPContour::setImageColumn(size_t columnID) void JKQTPContour::setImageColumn(size_t columnID)
{ {
datatype=JKQTPMathImageBase::DoubleArray; datatype=JKQTPMathImageBase::DoubleArray;
data=parent->getDatastore()->getColumn(columnID).getPointer(0); data=parent->getDatastore()->getColumnPointer(columnID,0);
} }

View File

@ -263,7 +263,7 @@ void JKQTPXFunctionLineGraph::collectParameters()
iparams.clear(); iparams.clear();
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=datastore->getColumn(parameterColumn).getRows(); int imax=datastore->getRows(parameterColumn);
for (int i=imin; i<imax; i++) { for (int i=imin; i<imax; i++) {
double xv=datastore->get(parameterColumn,i); double xv=datastore->get(parameterColumn,i);
@ -286,7 +286,7 @@ void JKQTPXFunctionLineGraph::collectParameters()
ierrorparams.clear(); ierrorparams.clear();
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=datastore->getColumn(errorParameterColumn).getRows(); int imax=datastore->getRows(errorParameterColumn);
for (int i=imin; i<imax; i++) { for (int i=imin; i<imax; i++) {
double xv=datastore->get(errorParameterColumn,i); double xv=datastore->get(errorParameterColumn,i);
@ -361,7 +361,7 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
QPen ep=painter.pen(); QPen ep=painter.pen();
ep.setColor(errorColor); ep.setColor(errorColor);
ep.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier()))); ep.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier())));
ep.setStyle(errorStyle); ep.setStyle(errorStyle);
ep.setJoinStyle(Qt::RoundJoin); ep.setJoinStyle(Qt::RoundJoin);
@ -540,7 +540,7 @@ void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
QPen ep=painter.pen(); QPen ep=painter.pen();
ep.setColor(errorColor); ep.setColor(errorColor);
ep.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier()))); ep.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier())));
ep.setStyle(errorStyle); ep.setStyle(errorStyle);
ep.setJoinStyle(Qt::RoundJoin); ep.setJoinStyle(Qt::RoundJoin);
@ -723,7 +723,7 @@ QBrush JKQTPXFunctionLineGraph::getErrorBrush(JKQTPEnhancedPainter& /*painter*/)
QPen JKQTPXFunctionLineGraph::getErrorLinePen(JKQTPEnhancedPainter& painter) const { QPen JKQTPXFunctionLineGraph::getErrorLinePen(JKQTPEnhancedPainter& painter) const {
QPen p; QPen p;
p.setColor(errorColor); p.setColor(errorColor);
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*errorLineWidth))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*errorLineWidth)));
p.setStyle(errorStyle); p.setStyle(errorStyle);
p.setJoinStyle(Qt::RoundJoin); p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap); p.setCapStyle(Qt::RoundCap);

View File

@ -148,7 +148,7 @@ bool JKQTPFilledVerticalRangeGraph::getYMinMax(double &miny, double &maxy, doubl
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=static_cast<int>(qMin(qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()), datastore->getColumn(static_cast<size_t>(yColumn2)).getRows())); int imax=static_cast<int>(qMin(qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn))), datastore->getRows(static_cast<size_t>(yColumn2))));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
imin=imax; imin=imax;
@ -202,7 +202,7 @@ void JKQTPFilledVerticalRangeGraph::draw(JKQTPEnhancedPainter &painter)
QBrush b=getFillBrush(painter, parent); QBrush b=getFillBrush(painter, parent);
int imax=static_cast<int>(qMin(qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()), datastore->getColumn(static_cast<size_t>(yColumn2)).getRows())); int imax=static_cast<int>(qMin(qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn))), datastore->getRows(static_cast<size_t>(yColumn2))));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;

View File

@ -1116,7 +1116,7 @@ void JKQTPMathImage::drawOutside(JKQTPEnhancedPainter& painter, QRect /*leftSpac
painter.drawImage(cb, b.mirrored(true, false)); painter.drawImage(cb, b.mirrored(true, false));
QPen p=painter.pen(); QPen p=painter.pen();
p.setColor(colorBarRightAxis->getAxisColor()); p.setColor(colorBarRightAxis->getAxisColor());
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, colorBarRightAxis->getLineWidth()*parent->getLineWidthMultiplier()))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, colorBarRightAxis->getLineWidth()*parent->getLineWidthMultiplier())));
painter.setPen(p); painter.setPen(p);
painter.drawRect(cb); painter.drawRect(cb);
@ -1171,7 +1171,7 @@ void JKQTPMathImage::drawOutside(JKQTPEnhancedPainter& painter, QRect /*leftSpac
painter.drawImage(cb, b.transformed(rm)); painter.drawImage(cb, b.transformed(rm));
QPen p=painter.pen(); QPen p=painter.pen();
p.setColor(colorBarTopAxis->getAxisColor()); p.setColor(colorBarTopAxis->getAxisColor());
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, colorBarTopAxis->getLineWidth()*parent->getLineWidthMultiplier()))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, colorBarTopAxis->getLineWidth()*parent->getLineWidthMultiplier())));
painter.setPen(p); painter.setPen(p);
painter.drawRect(cb); painter.drawRect(cb);
@ -1647,7 +1647,7 @@ QImage JKQTPMathImage::drawImage() {
void JKQTPMathImage::setPalette(int pal) { void JKQTPMathImage::setPalette(int pal) {
palette=(JKQTPMathImageColorPalette)pal; palette=static_cast<JKQTPMathImageColorPalette>(pal);
} }
@ -1727,6 +1727,10 @@ JKQTPColumnMathImage::JKQTPColumnMathImage(double x, double y, double width, dou
void JKQTPColumnMathImage::setImageColumn(int __value) void JKQTPColumnMathImage::setImageColumn(int __value)
{ {
this->imageColumn = __value; this->imageColumn = __value;
if (parent && __value>=0 && parent->getDatastore()) {
setNx(parent->getDatastore()->getColumnImageWidth(__value));
setNy(parent->getDatastore()->getColumnImageHeight(__value));
}
} }
int JKQTPColumnMathImage::getImageColumn() const int JKQTPColumnMathImage::getImageColumn() const
@ -1752,20 +1756,20 @@ bool JKQTPColumnMathImage::usesColumn(int c) const
void JKQTPColumnMathImage::ensureImageData() void JKQTPColumnMathImage::ensureImageData()
{ {
if (this->Nx==0 || imageColumn<0 || !parent->getDatastore()->getColumn(imageColumn).getPointer(0)) { if (this->Nx==0 || imageColumn<0 || !parent->getDatastore()->getColumnPointer(imageColumn,0)) {
this->Ny=0; this->Ny=0;
this->data=nullptr; this->data=nullptr;
this->datatype=JKQTPMathImageBase::DoubleArray; this->datatype=JKQTPMathImageBase::DoubleArray;
} else { } else {
this->datatype=JKQTPMathImageBase::DoubleArray; this->datatype=JKQTPMathImageBase::DoubleArray;
this->data=parent->getDatastore()->getColumn(imageColumn).getPointer(0); this->data=parent->getDatastore()->getColumnPointer(imageColumn,0);
this->Ny=parent->getDatastore()->getColumn(imageColumn).getRows()/this->Nx; this->Ny=parent->getDatastore()->getRows(imageColumn)/this->Nx;
} }
if (this->Nx==0 || modifierColumn<0 || !parent->getDatastore()->getColumn(modifierColumn).getPointer(0)) { if (this->Nx==0 || modifierColumn<0 || !parent->getDatastore()->getColumnPointer(modifierColumn,0)) {
this->dataModifier=nullptr; this->dataModifier=nullptr;
} else { } else {
this->datatypeModifier=JKQTPMathImageBase::DoubleArray; this->datatypeModifier=JKQTPMathImageBase::DoubleArray;
this->dataModifier=parent->getDatastore()->getColumn(modifierColumn).getPointer(0); this->dataModifier=parent->getDatastore()->getColumnPointer(modifierColumn,0);
} }
} }

View File

@ -352,8 +352,8 @@ int JKQTPColumnOverlayImageEnhanced::getImageColumn() const
return this->imageColumn; return this->imageColumn;
} }
void JKQTPColumnOverlayImageEnhanced::draw(JKQTPEnhancedPainter &painter) { void JKQTPColumnOverlayImageEnhanced::draw(JKQTPEnhancedPainter &painter) {
double* d=parent->getDatastore()->getColumn(imageColumn).getPointer(0); double* d=parent->getDatastore()->getColumnPointer(imageColumn,0);
size_t imgSize=parent->getDatastore()->getColumn(imageColumn).getRows(); size_t imgSize=parent->getDatastore()->getRows(imageColumn);
this->data=(bool*)malloc(imgSize*sizeof(bool)); this->data=(bool*)malloc(imgSize*sizeof(bool));
this->Ny=imgSize/this->Nx; this->Ny=imgSize/this->Nx;
for (size_t i=0; i<imgSize; i++) { for (size_t i=0; i<imgSize; i++) {

View File

@ -425,7 +425,7 @@ void JKQTPRGBMathImage::drawOutside(JKQTPEnhancedPainter& painter, QRect /*leftS
painter.drawImage(cb, l[li].paletteImage.mirrored(true, false)); painter.drawImage(cb, l[li].paletteImage.mirrored(true, false));
QPen p=painter.pen(); QPen p=painter.pen();
p.setColor(l[li].colorBarRightAxis->getAxisColor()); p.setColor(l[li].colorBarRightAxis->getAxisColor());
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, l[li].colorBarRightAxis->getLineWidth()*parent->getLineWidthMultiplier()))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, l[li].colorBarRightAxis->getLineWidth()*parent->getLineWidthMultiplier())));
painter.setPen(p); painter.setPen(p);
painter.drawRect(cb); painter.drawRect(cb);
@ -456,7 +456,7 @@ void JKQTPRGBMathImage::drawOutside(JKQTPEnhancedPainter& painter, QRect /*leftS
painter.drawImage(cb, l[li].paletteImage.transformed(mt)); painter.drawImage(cb, l[li].paletteImage.transformed(mt));
QPen p=painter.pen(); QPen p=painter.pen();
p.setColor(l[li].colorBarTopAxis->getAxisColor()); p.setColor(l[li].colorBarTopAxis->getAxisColor());
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, l[li].colorBarTopAxis->getLineWidth()*parent->getLineWidthMultiplier()))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, l[li].colorBarTopAxis->getLineWidth()*parent->getLineWidthMultiplier())));
painter.setPen(p); painter.setPen(p);
painter.drawRect(cb); painter.drawRect(cb);
@ -1250,19 +1250,19 @@ void JKQTPColumnRGBMathImage::ensureImageData()
this->datatype=JKQTPMathImageBase::DoubleArray; this->datatype=JKQTPMathImageBase::DoubleArray;
this->datatypeG=JKQTPMathImageBase::DoubleArray; this->datatypeG=JKQTPMathImageBase::DoubleArray;
this->datatypeB=JKQTPMathImageBase::DoubleArray; this->datatypeB=JKQTPMathImageBase::DoubleArray;
this->data=parent->getDatastore()->getColumn(imageRColumn).getPointer(0); this->data=parent->getDatastore()->getColumnPointer(imageRColumn,0);
this->dataG=parent->getDatastore()->getColumn(imageGColumn).getPointer(0); this->dataG=parent->getDatastore()->getColumnPointer(imageGColumn,0);
this->dataB=parent->getDatastore()->getColumn(imageBColumn).getPointer(0); this->dataB=parent->getDatastore()->getColumnPointer(imageBColumn,0);
/*if (Nx*Ny==0 || Nx*Ny>parent->getDatastore()->getColumn(imageRColumn).getRows()) { /*if (Nx*Ny==0 || Nx*Ny>parent->getDatastore()->getRows(imageRColumn)) {
if (Nx>0) { if (Nx>0) {
Ny=parent->getDatastore()->getColumn(imageRColumn).getRows()/this->Nx; Ny=parent->getDatastore()->getRows(imageRColumn)/this->Nx;
} else { } else {
Nx=parent->getDatastore()->getColumn(imageRColumn).getRows(); Nx=parent->getDatastore()->getRows(imageRColumn);
Ny=1; Ny=1;
} }
}*/ }*/
this->datatypeModifier=JKQTPMathImageBase::DoubleArray; this->datatypeModifier=JKQTPMathImageBase::DoubleArray;
this->dataModifier=parent->getDatastore()->getColumn(modifierColumn).getPointer(0); this->dataModifier=parent->getDatastore()->getColumnPointer(modifierColumn,0);
} }

View File

@ -64,7 +64,7 @@ void JKQTPImpulsesHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
QPen p=getLinePen(painter, parent); QPen p=getLinePen(painter, parent);
p.setCapStyle(Qt::FlatCap); p.setCapStyle(Qt::FlatCap);
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -201,7 +201,7 @@ void JKQTPImpulsesVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
QPen p=getLinePen(painter, parent); QPen p=getLinePen(painter, parent);
p.setCapStyle(Qt::FlatCap); p.setCapStyle(Qt::FlatCap);
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;

View File

@ -92,7 +92,7 @@ void JKQTPPeakStreamGraph::draw(JKQTPEnhancedPainter &painter)
QPen p=getLinePen(painter, parent); QPen p=getLinePen(painter, parent);
p.setCapStyle(Qt::FlatCap); p.setCapStyle(Qt::FlatCap);
int imax=static_cast<int>(datastore->getColumn(static_cast<size_t>(dataColumn)).getRows()); int imax=static_cast<int>(datastore->getRows(static_cast<size_t>(dataColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -147,7 +147,7 @@ void JKQTPPeakStreamGraph::drawKeyMarker(JKQTPEnhancedPainter &painter, QRectF &
QPen p=getLinePen(painter, parent); QPen p=getLinePen(painter, parent);
painter.setPen(p); painter.setPen(p);
if (yPeaks) { if (yPeaks) {
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,qMin(parent->pt2px(painter, p.widthF()), rect.width()/10.0))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,qMin(parent->pt2px(painter, p.widthF()), rect.width()/10.0)));
if (drawBaseline) { if (drawBaseline) {
if (peakHeight>=0) painter.drawLine(rect.bottomLeft(), rect.bottomRight()); if (peakHeight>=0) painter.drawLine(rect.bottomLeft(), rect.bottomRight());
else painter.drawLine(rect.topLeft(), rect.topRight()); else painter.drawLine(rect.topLeft(), rect.topRight());
@ -157,7 +157,7 @@ void JKQTPPeakStreamGraph::drawKeyMarker(JKQTPEnhancedPainter &painter, QRectF &
painter.drawLine(QPointF(rect.left()+rect.width()*0.75, rect.top()), QPointF(rect.left()+rect.width()*0.75, rect.bottom())); painter.drawLine(QPointF(rect.left()+rect.width()*0.75, rect.top()), QPointF(rect.left()+rect.width()*0.75, rect.bottom()));
painter.drawLine(QPointF(rect.left()+rect.width()*0.9, rect.top()), QPointF(rect.left()+rect.width()*0.9, rect.bottom())); painter.drawLine(QPointF(rect.left()+rect.width()*0.9, rect.top()), QPointF(rect.left()+rect.width()*0.9, rect.bottom()));
} else { } else {
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,qMin(parent->pt2px(painter, p.widthF()), rect.height()/15.0))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,qMin(parent->pt2px(painter, p.widthF()), rect.height()/15.0)));
if (drawBaseline) { if (drawBaseline) {
if (peakHeight>=0) painter.drawLine(rect.bottomLeft(), rect.topLeft()); if (peakHeight>=0) painter.drawLine(rect.bottomLeft(), rect.topLeft());
else painter.drawLine(rect.bottomRight(), rect.topRight()); else painter.drawLine(rect.bottomRight(), rect.topRight());

View File

@ -123,7 +123,7 @@ void JKQTPHorizontalRange::draw(JKQTPEnhancedPainter& painter) {
QPen p=painter.pen(); QPen p=painter.pen();
p.setColor(centerColor); p.setColor(centerColor);
p.setStyle(centerStyle); p.setStyle(centerStyle);
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, centerLineWidth*parent->getLineWidthMultiplier()))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, centerLineWidth*parent->getLineWidthMultiplier())));
painter.setPen(p); painter.setPen(p);
painter.drawLine(QLineF(mi, c, ma, c)); painter.drawLine(QLineF(mi, c, ma, c));
} }
@ -411,7 +411,7 @@ void JKQTPVerticalRange::draw(JKQTPEnhancedPainter& painter) {
QPen p=painter.pen(); QPen p=painter.pen();
p.setColor(centerColor); p.setColor(centerColor);
p.setStyle(centerStyle); p.setStyle(centerStyle);
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, centerLineWidth*parent->getLineWidthMultiplier()))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, centerLineWidth*parent->getLineWidthMultiplier())));
painter.setPen(p); painter.setPen(p);
painter.drawLine(QLineF(c, mi, c, ma)); painter.drawLine(QLineF(c, mi, c, ma));
} }

View File

@ -78,7 +78,7 @@ void JKQTPXYLineGraph::draw(JKQTPEnhancedPainter& painter) {
QPen penSelection=getHighlightingLinePen(painter, parent); QPen penSelection=getHighlightingLinePen(painter, parent);
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
@ -208,7 +208,7 @@ bool JKQTPXYLineErrorGraph::getXMinMax(double &minx, double &maxx, double &small
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -250,7 +250,7 @@ bool JKQTPXYLineErrorGraph::getYMinMax(double &miny, double &maxy, double &small
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -364,7 +364,7 @@ void JKQTPXYParametrizedScatterGraph::draw(JKQTPEnhancedPainter &painter)
QPen penSelection=getHighlightingLinePen(painter, parent); QPen penSelection=getHighlightingLinePen(painter, parent);
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -774,7 +774,7 @@ void JKQTPXYParametrizedScatterGraph::cbGetDataMinMax(double &dmin, double &dmax
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
if (datastore==nullptr) return; if (datastore==nullptr) return;
if (colorColumn<0) return; if (colorColumn<0) return;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -824,7 +824,7 @@ double JKQTPXYParametrizedScatterGraph::getLocalSymbolSize(int i)
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
if (datastore==nullptr) return getSymbolSize(); if (datastore==nullptr) return getSymbolSize();
if (sizeColumn<0) return getSymbolSize(); if (sizeColumn<0) return getSymbolSize();
if (i>=(int64_t)datastore->getColumn(sizeColumn).getRows()) return getSymbolSize(); if (i>=(int64_t)datastore->getRows(sizeColumn)) return getSymbolSize();
return m_toSizePtFunctor(datastore->get(xColumn,i), datastore->get(yColumn,i), datastore->get(sizeColumn,i)); return m_toSizePtFunctor(datastore->get(xColumn,i), datastore->get(yColumn,i), datastore->get(sizeColumn,i));
} }
@ -834,7 +834,7 @@ double JKQTPXYParametrizedScatterGraph::getLocalLineWidth(int i)
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
if (datastore==nullptr) return getLineWidth(); if (datastore==nullptr) return getLineWidth();
if (linewidthColumn<0) return getLineWidth(); if (linewidthColumn<0) return getLineWidth();
if (i>=(int64_t)datastore->getColumn(linewidthColumn).getRows()) return getLineWidth(); if (i>=(int64_t)datastore->getRows(linewidthColumn)) return getLineWidth();
return m_toWidthPtFunctor(datastore->get(xColumn,i), datastore->get(yColumn,i), datastore->get(linewidthColumn,i)); return m_toWidthPtFunctor(datastore->get(xColumn,i), datastore->get(yColumn,i), datastore->get(linewidthColumn,i));
} }
@ -845,18 +845,18 @@ QColor JKQTPXYParametrizedScatterGraph::getLocalColor(int i) const
if (datastore==nullptr) return getLineColor(); if (datastore==nullptr) return getLineColor();
if (colorColumn<0) return getLineColor(); if (colorColumn<0) return getLineColor();
if (colorColumnContainsRGB) { if (colorColumnContainsRGB) {
if (i<0 || i>=(int64_t)datastore->getColumn(colorColumn).getRows()) return getLineColor(); if (i<0 || i>=(int64_t)datastore->getRows(colorColumn)) return getLineColor();
//QRgb rgb= //QRgb rgb=
return QRgb(round(datastore->get(colorColumn,i))); return QRgb(round(datastore->get(colorColumn,i)));
} else { } else {
QImage img; QImage img;
double colorval=0; double colorval=0;
if (i>=0 && i<(int64_t)datastore->getColumn(colorColumn).getRows()) colorval=datastore->get(colorColumn,i); if (i>=0 && i<(int64_t)datastore->getRows(colorColumn)) colorval=datastore->get(colorColumn,i);
double colMin=0; double colMin=0;
double colMax=0; double colMax=0;
if (intColMin==intColMax) { if (intColMin==intColMax) {
colMin=0; colMin=0;
colMax=datastore->getColumn(colorColumn).getRows()-1; colMax=datastore->getRows(colorColumn)-1;
} else { } else {
colMin=intColMin; colMin=intColMin;
colMax=intColMax; colMax=intColMax;
@ -873,7 +873,7 @@ JKQTPGraphSymbols JKQTPXYParametrizedScatterGraph::getLocalSymbolType(int i)
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
if (datastore==nullptr) return getSymbolType(); if (datastore==nullptr) return getSymbolType();
if (symbolColumn<0) return getSymbolType(); if (symbolColumn<0) return getSymbolType();
if (i>=static_cast<int64_t>(datastore->getColumn(symbolColumn).getRows())) return getSymbolType(); if (i>=static_cast<int64_t>(datastore->getRows(symbolColumn))) return getSymbolType();
return m_toSymbolFunctor(datastore->get(xColumn,i), datastore->get(yColumn,i), datastore->get(symbolColumn,i)); return m_toSymbolFunctor(datastore->get(xColumn,i), datastore->get(yColumn,i), datastore->get(symbolColumn,i));
} }
@ -906,7 +906,7 @@ bool JKQTPXYParametrizedErrorScatterGraph::getXMinMax(double &minx, double &maxx
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;
@ -949,7 +949,7 @@ bool JKQTPXYParametrizedErrorScatterGraph::getYMinMax(double &miny, double &maxy
JKQTPDatastore* datastore=parent->getDatastore(); JKQTPDatastore* datastore=parent->getDatastore();
int imin=0; int imin=0;
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;

View File

@ -102,7 +102,7 @@ void JKQTPSingleColumnSymbolsGraph::draw(JKQTPEnhancedPainter &painter)
{ {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
int imax=static_cast<int>(datastore->getColumn(static_cast<size_t>(dataColumn)).getRows()); int imax=static_cast<int>(datastore->getRows(static_cast<size_t>(dataColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
int h=imin; int h=imin;

View File

@ -155,7 +155,7 @@ void JKQTPSpecialLineHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
QPen np(Qt::NoPen); QPen np(Qt::NoPen);
QBrush b=getFillBrush(painter, parent); QBrush b=getFillBrush(painter, parent);
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {
@ -353,7 +353,7 @@ void JKQTPSpecialLineVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
QPen np(Qt::NoPen); QPen np(Qt::NoPen);
QBrush b=getFillBrush(painter, parent); QBrush b=getFillBrush(painter, parent);
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows()); int imax=qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn)));
int imin=0; int imin=0;
if (imax<imin) { if (imax<imin) {

View File

@ -26,7 +26,7 @@ Copyright (c) 2008-2019 Jan W. Krieger (<jan@jkrieger.de>)
#include "jkqtplottertools/jkqtpdrawingtools.h" #include "jkqtplottertools/jkqtpdrawingtools.h"
#include "jkqtplottertools/jkqtpenhancedpainter.h" #include "jkqtplottertools/jkqtpenhancedpainter.h"
const double JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH= 0.02; const double JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH= 0.02;
void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor) { void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor) {
JKQTPEnhancedPainter p(&paintDevice); JKQTPEnhancedPainter p(&paintDevice);
@ -37,7 +37,7 @@ void JKQTPPlotSymbol(JKQTPEnhancedPainter& painter, double x, double y, JKQTPGra
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen p=painter.pen(); QPen p=painter.pen();
p.setColor(color); p.setColor(color);
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, symbolLineWidth)); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, symbolLineWidth));
p.setStyle(Qt::SolidLine); p.setStyle(Qt::SolidLine);
p.setCapStyle(Qt::FlatCap); p.setCapStyle(Qt::FlatCap);
painter.setPen(p); painter.setPen(p);

View File

@ -30,7 +30,7 @@ class JKQTPEnhancedPainter; // forward
/*! \brief tool class with static values used by JKQTPlotter/JKQTBasePlotter /*! \brief tool class with static values used by JKQTPlotter/JKQTBasePlotter
\ingroup jkqtptools_drawing \ingroup jkqtptools_drawing
*/ */
JKQTP_LIB_EXPORT struct JKQTPlotterDrawinTools { JKQTP_LIB_EXPORT struct JKQTPlotterDrawingTools {
/** \brief smallest linewidth any line in JKQTPlotter/JKQTBasePlotter may have /** \brief smallest linewidth any line in JKQTPlotter/JKQTBasePlotter may have
*/ */
static const double ABS_MIN_LINEWIDTH; static const double ABS_MIN_LINEWIDTH;

View File

@ -1942,7 +1942,7 @@ void JKQTPColorPaletteTools::cbDrawOutside(JKQTPEnhancedPainter& painter, QRect
painter.drawImage(cb, b.mirrored(true, false)); painter.drawImage(cb, b.mirrored(true, false));
QPen p=painter.pen(); QPen p=painter.pen();
p.setColor(colorBarRightAxis->getAxisColor()); p.setColor(colorBarRightAxis->getAxisColor());
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, cbParent->pt2px(painter, colorBarRightAxis->getLineWidth()*cbParent->getLineWidthMultiplier()))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, cbParent->pt2px(painter, colorBarRightAxis->getLineWidth()*cbParent->getLineWidthMultiplier())));
painter.setPen(p); painter.setPen(p);
painter.drawRect(cb); painter.drawRect(cb);
@ -1995,7 +1995,7 @@ void JKQTPColorPaletteTools::cbDrawOutside(JKQTPEnhancedPainter& painter, QRect
painter.drawImage(cb, b.transformed(rm)); painter.drawImage(cb, b.transformed(rm));
QPen p=painter.pen(); QPen p=painter.pen();
p.setColor(colorBarTopAxis->getAxisColor()); p.setColor(colorBarTopAxis->getAxisColor());
p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, cbParent->pt2px(painter, colorBarTopAxis->getLineWidth()*cbParent->getLineWidthMultiplier()))); p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, cbParent->pt2px(painter, colorBarTopAxis->getLineWidth()*cbParent->getLineWidthMultiplier())));
painter.setPen(p); painter.setPen(p);
painter.drawRect(cb); painter.drawRect(cb);

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB