CTL  0.6.1
Computed Tomography Library
Public Types | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
CTL::IntervalDataSeries Class Reference

The IntervalDataSeries class is a container for a series of values sampled in equidistant steps (i.e. intervals with equal bin width). More...

#include <intervaldataseries.h>

Inheritance diagram for CTL::IntervalDataSeries:
Inheritance graph
[legend]
Collaboration diagram for CTL::IntervalDataSeries:
Collaboration graph
[legend]

Public Types

enum  ValueType { BinIntegral, MeanValue }
 

Public Member Functions

 IntervalDataSeries (float binWidth, float firstBinStart=0.0f, ValueType valueType=BinIntegral)
 Constructs an empty IntervalDataSeries object for a series with bin width binWidth. More...
 
 IntervalDataSeries (float binWidth, float firstBinStart, const std::vector< float > &values, ValueType valueType=BinIntegral)
 Constructs an IntervalDataSeries object and directly sets its data to values. More...
 
void append (float value)
 Appends value to the series. More...
 
void append (const std::vector< float > &values)
 Appends all values in values to the series. More...
 
void clampToRange (const SamplingRange &range)
 Clamps all values in this series to the interval specified by range. More...
 
void normalizeByIntegral ()
 Normalizes the values in the series such that the integral will be one afterwards.
 
void setValue (uint sampleNb, float value)
 
void setValues (const std::vector< float > &values)
 Sets the values passed by values as bin values for this series. More...
 
SamplingRange binBounds (uint binNb) const
 Returns the boundaries of the interval covered by the bin with index binNb. More...
 
float binWidth () const
 Returns the bin width (or x distance between two consecutive sampling points).
 
float centroid () const
 Returns the centroid of the series. More...
 
float integral () const
 Returns the integral over the series. More...
 
float integral (const std::vector< float > &weights) const
 Returns the integral over the series with each bin value being weighted by the corresponding factor in weights. More...
 
IntervalDataSeries normalizedByIntegral () const
 Returns a copy of the series in which the values have been normalized such that the integral will be one.
 
SamplingRange samplingRange () const
 Returns the range (of x-values) covered by all bins of this series. More...
 
ValueType valueType () const
 Returns the type of the values in the series, i.e. whether they represent bin integrals or mean values. More...
 
void normalizeByMaxAbsVal ()
 
void normalizeByMaxVal ()
 
void scaleValues (float factor)
 
- Public Member Functions inherited from CTL::PointSeriesBase
const QList< QPointF > & data () const
 
float max () const
 
float min () const
 
uint nbSamples () const
 
uint size () const
 
float sum () const
 
float sum (const std::vector< float > &weights) const
 
float weightedSum (const std::vector< float > &weights) const
 
float samplingPoint (uint sampleNb) const
 
std::vector< float > samplingPoints () const
 
Range< float > samplingRange () const
 
float value (uint sampleNb) const
 
std::vector< float > values () const
 
Range< float > valueRange () const
 

Static Public Member Functions

static IntervalDataSeries sampledFromModel (const AbstractIntegrableDataModel &dataModel, float from, float to, uint nbSamples, ValueType samples=BinIntegral)
 Return a series of nbSamples values sampled from dataModel within the specified interval [ from, to ]. More...
 
static IntervalDataSeries sampledFromModel (std::shared_ptr< AbstractIntegrableDataModel > dataModel, float from, float to, uint nbSamples, ValueType samples=BinIntegral)
 Overload for std::shared_ptr input.
 

Private Member Functions

std::vector< float > samplingPointsForIndices (uint startIdx, uint endIdx) const
 Computes the sampling points for bins with indices between startIdx and endIdx. More...
 

Private Attributes

float _binWidth
 
float _firstBinStart
 
ValueType _valueType
 

Additional Inherited Members

- Protected Member Functions inherited from CTL::PointSeriesBase
 PointSeriesBase (const QList< QPointF > &pointSeries)
 
 PointSeriesBase (QList< QPointF > &&pointSeries)
 
void normalizeByMaxAbsVal ()
 
void normalizeByMaxVal ()
 
void scaleValues (float factor)
 
- Protected Attributes inherited from CTL::PointSeriesBase
QList< QPointF > _data
 

Detailed Description

The IntervalDataSeries class is a container for a series of values sampled in equidistant steps (i.e. intervals with equal bin width).

This class is a specialization of PointSeriesBase to manage equidistantly-sampled data points. Although data is managed as a series of x and y pairs internally, only y-values might be manipulated, in order to ensure that the actual sampling points (i.e. x-values) are kept on the equidistant 'grid'.

There are two main ways of creating an IntervalDataSeries object:

  1. Sample data from an AbstractIntegrableDataModel subclass, and
  2. Individually add (consecutive) values to the series.

For 1., the sampledFromModel() factory method can be used. These take a data model and return a series of values sampled within the specified interval. You can choose whether the sampled values shall be data integrated over the entire bin or mean values within the individual intervals.

Example:

// create a step function (steps from 0 to 1 at x=0)
auto dataModel = StepFunctionModel();
// sample the interval [-5, 5] with 5 values, i.e. bin width is 2.0
auto series = IntervalDataSeries::sampledFromModel(dataModel, -5.0f, 5.0f, 5);
// print values
for(const auto& pt : series.data())
qInfo() << pt.x() << pt.y();
// output: (bin center, value)-pairs
// -4 0
// -2 0
// 0 1
// 2 2
// 4 2
// Note that the sampled values represent bin integrals!

When manually filling a series (method 2.), you need to decide on the distance between sampling points (i.e. bin width) used in the series to create an IntervalDataSeries using its constructor. Besides the bin width, you might also set the beginning of the first interval (i.e. lower edge of the first bin) and specify the type of data, your sampled values will represent (i.e. either bin integrals of mean values). Note that all these properties may not be changed afterwards. After creating the series object, data points can be appended to the series with append(). The sampling point (i.e. x-value or bin position) is determined automatically, based on the bin width and the specified beginning of the first bin.

IntervalDataSeries offers the possibility to compute both the sum as well as the integral over all values in the series; see sum() and integral() for details. Further convenience provided includes normalization of the values in the series by the integral (see normalizeByIntegral()), computation of the centroid ('center-of-mass', see centroid()), and the possibility to clamp the sampled series to a specific range of x-values (see clampToRange()).

Constructor & Destructor Documentation

◆ IntervalDataSeries() [1/2]

CTL::IntervalDataSeries::IntervalDataSeries ( float  binWidth,
float  firstBinStart = 0.0f,
IntervalDataSeries::ValueType  valueType = BinIntegral 
)
explicit

Constructs an empty IntervalDataSeries object for a series with bin width binWidth.

If required, set the beginning of the first interval (i.e. lower edge of the first bin) with firstBinStart and specify the type of data, your sampled values will represent (i.e. either bin integrals or mean values) by valueType. Note that none of these properties may be changed afterwards. If unspecified, the first bin will start at 0.0 and the value type will default to BinIntegral.

Data points can be added to the series with append().

Example: we create a series that contains values with bin width 1.0, with its first bin starting at x=-2.5 and representing mean values. We then fill in the values 1, 2, 3, and 4.

auto series = IntervalDataSeries(1.0f, -2.5f, IntervalDataSeries::MeanValue);
series.append(1.0f); // series: (-2.0, 1.0)
series.append(2.0f); // series: (-2.0, 1.0), (-1.0, 2.0)
series.append(3.0f); // series: (-2.0, 1.0), (-1.0, 2.0), (0.0, 3.0)
series.append(4.0f); // series: (-2.0, 1.0), (-1.0, 2.0), (0.0, 3.0), (1.0, 4.0)

Note that the sampling points (i.e. bin centers) are computed automatically based on the bin width and starting point of the first bin.

◆ IntervalDataSeries() [2/2]

CTL::IntervalDataSeries::IntervalDataSeries ( float  binWidth,
float  firstBinStart,
const std::vector< float > &  values,
IntervalDataSeries::ValueType  valueType = BinIntegral 
)

Constructs an IntervalDataSeries object and directly sets its data to values.

The series is created with a bin width of binWidth and its first bin starting at firstBinStart. The type of data that is represented by the values in the series (i.e. either bin integrals or mean values) can be set by valueType. Note that none of these properties may be changed afterwards. If unspecified, the first bin will start at 0.0 and the value type will default to BinIntegral.

Data passed by values will be added to the series, defining the first values.size() samples. Additional data points can later be added to the series with append().

Example: we create a series that contains the following samples: (-2.0, 1.0), (-1.0, 2.0), (0.0, 3.0), (1.0, 4.0), which shall represent mean values. For that, we need a bin width of 1.0 and a first bin starting point of -2.5f.

auto series = IntervalDataSeries(1.0f, -2.5f, { 1.0f, 2.0f, 3.0f, 4.0f }, IntervalDataSeries::MeanValue);

Note that the sampling points (i.e. bin centers) are computed automatically based on the bin width and starting point of the first bin.

Member Function Documentation

◆ append() [1/2]

void CTL::IntervalDataSeries::append ( float  value)

Appends value to the series.

Automatically computes the corresponding sampling point (i.e. bin center coordinate).

Example:

auto series = IntervalDataSeries(1.0f, -1.5f);
series.append(1.0f); // series: (-1.0, 1.0)
series.append(2.0f); // series: (-1.0, 1.0), (0.0, 1.0)
series.append(3.0f); // series: (-1.0, 1.0), (0.0, 1.0), (1.0, 2.0)

◆ append() [2/2]

void CTL::IntervalDataSeries::append ( const std::vector< float > &  values)

Appends all values in values to the series.

Automatically computes the corresponding sampling points (i.e. bin center coordinates).

Example:

auto series = IntervalDataSeries(1.0f, -1.5f);
series.append({ 1.0f, 2.0f, 3.0f }); // series: (-1.0, 1.0), (0.0, 1.0), (1.0, 2.0)

◆ binBounds()

SamplingRange CTL::IntervalDataSeries::binBounds ( uint  binNb) const

Returns the boundaries of the interval covered by the bin with index binNb.

This returns the lower and upper boundary of the interval covered by the bin with index binNb as a SamplingRange.

Example:

IntervalDataSeries series(10.0f);
series.append(13.37f);
series.append(42.0f);
series.append(6.66f);
const auto bounds = series.binBounds(1);
qInfo() << QString("Bin [%1, %2] has value: %3").arg(bounds.start())
.arg(bounds.end())
.arg(series.value(1));
// output: "Bin [10, 20] has value: 42"

◆ centroid()

float CTL::IntervalDataSeries::centroid ( ) const

Returns the centroid of the series.

Example:

// create an IntervalDataSeries with bin width 1 starting at 0.0 (default value)
IntervalDataSeries series(1.0f);
series.append(0.0f);
series.append(1.0f);
series.append(2.0f);
series.append(3.0f);
series.append(4.0f);
qInfo() << series.centroid(); // output: 3.5

◆ clampToRange()

void CTL::IntervalDataSeries::clampToRange ( const SamplingRange range)

Clamps all values in this series to the interval specified by range.

This means that all values smaller than range.start() and values larger than range.end() will be set to zero.

Note that a series that used to be normalized beforehand might no longer be normalized after the clamp operation.

Example:

// vector: 0, 1, 2, ...
std::vector<float> vec(5);
std::iota(vec.begin(), vec.end(), 0.0f);
// Interval series with bin width 1, starting at 0.0, with values from vec
IntervalDataSeries series(1.0f, 0.0f, vec);
qInfo() << series.data();
// output: (QPointF(0.5,0), QPointF(1.5,1), QPointF(2.5,2), QPointF(3.5,3), QPointF(4.5,4))
// clamp samples to interval [1.5 4.0]
series.clampToRange({1.5, 4.0});
qInfo() << series.data();
// output: (QPointF(0.5,0), QPointF(1.5,0.5), QPointF(2.5,2), QPointF(3.5,3), QPointF(4.5,0))

◆ integral() [1/2]

float CTL::IntervalDataSeries::integral ( ) const

Returns the integral over the series.

If valueType() == IntervalDataSeries::BinIntegral, this is the same as sum().

◆ integral() [2/2]

float CTL::IntervalDataSeries::integral ( const std::vector< float > &  weights) const

Returns the integral over the series with each bin value being weighted by the corresponding factor in weights.

The weight vector must contain at least as many elements as there are samples in the series.

If valueType() == IntervalDataSeries::BinIntegral, this is the same as the weighted sum.

◆ sampledFromModel()

IntervalDataSeries CTL::IntervalDataSeries::sampledFromModel ( const AbstractIntegrableDataModel dataModel,
float  from,
float  to,
uint  nbSamples,
ValueType  samples = BinIntegral 
)
static

Return a series of nbSamples values sampled from dataModel within the specified interval [ from, to ].

You can choose whether the sampled values shall be data integrated over the entire bin or mean values within the individual intervals, by passing the corresponding flag to samples (default: IntervalDataSeries::BinIntegral).

nbSamples must be greater than 0. The resulting series has a bin width of \((\to - from) / nbSamples\).

Example:

// create a step function (steps from 0 to 1 at x=0)
auto dataModel = StepFunctionModel();
// sample the interval [-5, 5] with 5 values, i.e. bin width is 2.0
// we create two series: series1 containing bin integrals (default) and series2 with mean values
auto series1 = IntervalDataSeries::sampledFromModel(dataModel, -5.0f, 5.0f, 5);
auto series2 = IntervalDataSeries::sampledFromModel(dataModel, -5.0f, 5.0f, 5, IntervalDataSeries::MeanValue);
// print results
for(const auto& pt : series1.data())
qInfo() << pt.x() << pt.y();
// output: (bin center, value)-pairs
// -4 0
// -2 0
// 0 1
// 2 2
// 4 2
for(const auto& pt : series2.data())
qInfo() << pt.x() << pt.y();
// output: (bin center, value)-pairs
// -4 0
// -2 0
// 0 0.5
// 2 1
// 4 1

◆ samplingPointsForIndices()

std::vector< float > CTL::IntervalDataSeries::samplingPointsForIndices ( uint  startIdx,
uint  endIdx 
) const
private

Computes the sampling points for bins with indices between startIdx and endIdx.

Uses computation scheme that is safe even for small bin widths.

◆ samplingRange()

SamplingRange CTL::IntervalDataSeries::samplingRange ( ) const

Returns the range (of x-values) covered by all bins of this series.

Example:

// create an IntervalDataSeries with bin width 1 starting at 0.0 (default value)
IntervalDataSeries series(1.0f);
series.append(32.5f); // this is bin [0, 1]
series.append(2.6f); // this is bin [1, 2]
series.append(456.9f); // this is bin [2, 3]
qInfo() << series.samplingRange().toPair(); // output: std::pair(0,3)

◆ scaleValues()

void CTL::PointSeriesBase::scaleValues

Normalizes the series by dividing all values (i.e. 'y' part) by the maximum absolute value.

Example:

auto x = std::vector<float>(6);
std::iota(x.begin(), x.end(), 0.0f);
auto y = std::vector<float>(6);
std::iota(y.begin(), y.end(), -3.0f);
auto series = XYDataSeries(x, y);
qInfo() << series.values();
// output: std::vector(-3, -2, -1, 0, 1, 2)
series.normalizeByMaxAbsVal();
qInfo() << series.values();
// output: std::vector(-1, -0.666667, -0.333333, 0, 0.333333, 0.666667)
/
void PointSeriesBase::normalizeByMaxAbsVal()
{
auto maxEl = std::max_element(_data.begin(), _data.end(),
[] (const QPointF& a, const QPointF& b) {
return qAbs(a.y()) < qAbs(b.y()); });
scaleValues(1.0f / qAbs(maxEl->y()));
}

.

Example:

auto x = std::vector<float>(6);
std::iota(x.begin(), x.end(), 0.0f);
auto y = std::vector<float>(6);
std::iota(y.begin(), y.end(), -3.0f);
auto series = XYDataSeries(x, y);
qInfo() << series.values();
// output: std::vector(-3, -2, -1, 0, 1, 2)
series.normalizeByMaxVal();
qInfo() << series.values();
// output: std::vector(-1.5, -1, -0.5, 0, 0.5, 1)
/
void PointSeriesBase::normalizeByMaxVal()
{
scaleValues(1.0f / max());
}

◆ setValues()

void CTL::IntervalDataSeries::setValues ( const std::vector< float > &  values)

Sets the values passed by values as bin values for this series.

This replaces any previous data.

auto series = IntervalDataSeries(1.0f, -1.5f);
series.append(1.0f); // series: (-1.0, 1.0)
series.append(2.0f); // series: (-1.0, 1.0), (0.0, 1.0)
series.setValues({ 42.0f, 66.6f, 133.7f }); // series: (-1.0, 42.0), (0.0, 66.6), (1.0, 133.7)

◆ valueType()

IntervalDataSeries::ValueType CTL::IntervalDataSeries::valueType ( ) const

Returns the type of the values in the series, i.e. whether they represent bin integrals or mean values.

This will be BinIntegral in most cases. However, if specified explicitely during creation of an IntervalDataSeries, series can be created with ValueType MeanValue; so consider checking for the actual type with this method if that is of concern for your specific use case.


The documentation for this class was generated from the following files: