##// END OF EJS Templates
Removes title and close button from graph widget...
Removes title and close button from graph widget Title and button will be added directly as items in plot overlay

File last commit:

r660:3f8156a1a068
r665:6a98c66c04c4
Show More
DataSeries.h
400 lines | 13.2 KiB | text/x-c | CLexer
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 #ifndef SCIQLOP_DATASERIES_H
#define SCIQLOP_DATASERIES_H
Alexandre Leroux
Updates declaration of logger to avoid multiple definitions
r529 #include "CoreGlobal.h"
Alexandre Leroux
Makes a Data series be sorted (2)...
r416 #include <Common/SortUtils.h>
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 #include <Data/ArrayData.h>
Alexandre Leroux
Updates merge() method (1)...
r622 #include <Data/DataSeriesMergeHelper.h>
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 #include <Data/IDataSeries.h>
Correction for pull request
r227 #include <QLoggingCategory>
Add current progression for thread fix
r336 #include <QReadLocker>
#include <QReadWriteLock>
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 #include <memory>
Alexandre Leroux
Updates declaration of logger to avoid multiple definitions
r529 // We don't use the Qt macro since the log is used in the header file, which causes multiple log
// definitions with inheritance. Inline method is used instead
inline const QLoggingCategory &LOG_DataSeries()
{
static const QLoggingCategory category{"DataSeries"};
return category;
}
Correction for pull request
r227
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 template <int Dim>
class DataSeries;
namespace dataseries_detail {
Alexandre Leroux
Adapts SqpIterator to make non-const iterators
r626 template <int Dim, bool IsConst>
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 class IteratorValue : public DataSeriesIteratorValue::Impl {
public:
Alexandre Leroux
Adapts SqpIterator to make non-const iterators
r626 friend class DataSeries<Dim>;
template <bool IC = IsConst, typename = std::enable_if_t<IC == false> >
explicit IteratorValue(DataSeries<Dim> &dataSeries, bool begin)
: m_XIt(begin ? dataSeries.xAxisData()->begin() : dataSeries.xAxisData()->end()),
m_ValuesIt(begin ? dataSeries.valuesData()->begin() : dataSeries.valuesData()->end())
{
}
template <bool IC = IsConst, typename = std::enable_if_t<IC == true> >
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 explicit IteratorValue(const DataSeries<Dim> &dataSeries, bool begin)
: m_XIt(begin ? dataSeries.xAxisData()->cbegin() : dataSeries.xAxisData()->cend()),
m_ValuesIt(begin ? dataSeries.valuesData()->cbegin()
: dataSeries.valuesData()->cend())
{
}
Alexandre Leroux
Adapts SqpIterator to make non-const iterators
r626
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 IteratorValue(const IteratorValue &other) = default;
std::unique_ptr<DataSeriesIteratorValue::Impl> clone() const override
{
Alexandre Leroux
Adapts SqpIterator to make non-const iterators
r626 return std::make_unique<IteratorValue<Dim, IsConst> >(*this);
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 }
Alexandre Leroux
Makes random access iterators...
r640 int distance(const DataSeriesIteratorValue::Impl &other) const override try {
const auto &otherImpl = dynamic_cast<const IteratorValue &>(other);
return m_XIt->distance(*otherImpl.m_XIt);
}
catch (const std::bad_cast &) {
return 0;
}
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 bool equals(const DataSeriesIteratorValue::Impl &other) const override try {
const auto &otherImpl = dynamic_cast<const IteratorValue &>(other);
return std::tie(m_XIt, m_ValuesIt) == std::tie(otherImpl.m_XIt, otherImpl.m_ValuesIt);
}
catch (const std::bad_cast &) {
return false;
}
Alexandre Leroux
Makes random access iterators...
r640 bool lowerThan(const DataSeriesIteratorValue::Impl &other) const override try {
const auto &otherImpl = dynamic_cast<const IteratorValue &>(other);
return m_XIt->lowerThan(*otherImpl.m_XIt);
}
catch (const std::bad_cast &) {
return false;
}
std::unique_ptr<DataSeriesIteratorValue::Impl> advance(int offset) const override
{
auto result = clone();
Alexandre Leroux
Improves random access iterator performance
r647 result->next(offset);
Alexandre Leroux
Makes random access iterators...
r640 return result;
}
Alexandre Leroux
Improves random access iterator performance
r647 void next(int offset) override
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 {
Alexandre Leroux
Improves random access iterator performance
r647 m_XIt->next(offset);
m_ValuesIt->next(offset);
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 }
void prev() override
{
--m_XIt;
--m_ValuesIt;
}
double x() const override { return m_XIt->at(0); }
double value() const override { return m_ValuesIt->at(0); }
double value(int componentIndex) const override { return m_ValuesIt->at(componentIndex); }
Alexandre Leroux
Implements method to get min/max values of a dataseries giving a range (2)
r570 double minValue() const override { return m_ValuesIt->min(); }
double maxValue() const override { return m_ValuesIt->max(); }
Alexandre Leroux
Adds method into ArrayData and DataSeries iterator to get all values
r621 QVector<double> values() const override { return m_ValuesIt->values(); }
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558
Alexandre Leroux
Adapts iterator to be MoveAssignable...
r627 void swap(DataSeriesIteratorValue::Impl &other) override
{
auto &otherImpl = dynamic_cast<IteratorValue &>(other);
m_XIt->impl()->swap(*otherImpl.m_XIt->impl());
m_ValuesIt->impl()->swap(*otherImpl.m_ValuesIt->impl());
}
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 private:
Alexandre Leroux
Replaces current iterator of ArrayData by the previous iterator created
r598 ArrayDataIterator m_XIt;
ArrayDataIterator m_ValuesIt;
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 };
} // namespace dataseries_detail
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 /**
* @brief The DataSeries class is the base (abstract) implementation of IDataSeries.
*
Alexandre Leroux
Makes a Data series be sorted (1)
r415 * It proposes to set a dimension for the values ​​data.
*
* A DataSeries is always sorted on its x-axis data.
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 *
* @tparam Dim The dimension of the values data
*
*/
template <int Dim>
Alexandre Leroux
Updates declaration of logger to avoid multiple definitions
r529 class SCIQLOP_CORE_EXPORT DataSeries : public IDataSeries {
Alexandre Leroux
Updates merge() method (1)...
r622 friend class DataSeriesMergeHelper;
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 public:
/// @sa IDataSeries::xAxisData()
std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
Alexandre Leroux
Use std::shared_ptr in CosinusProvider
r287 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117
/// @sa IDataSeries::xAxisUnit()
Alexandre Leroux
Replaces QString unit by a new struct...
r164 Unit xAxisUnit() const override { return m_XAxisUnit; }
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117
/// @return the values dataset
Alexandre Leroux
Use std::shared_ptr in CosinusProvider
r287 std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; }
const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117
/// @sa IDataSeries::valuesUnit()
Alexandre Leroux
Replaces QString unit by a new struct...
r164 Unit valuesUnit() const override { return m_ValuesUnit; }
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117
Alexandre Leroux
Creates method to retrieve nb points of a data series
r660 int nbPoints() const override { return m_XAxisData->totalSize() + m_ValuesData->totalSize(); }
Implementation of V5 acquisition
r510
SqpRange range() const override
{
Alexandre Leroux
Uses std::vector instead of QVector in ArrayData (1)...
r644 if (!m_XAxisData->cdata().empty()) {
return SqpRange{m_XAxisData->cdata().front(), m_XAxisData->cdata().back()};
Implementation of V5 acquisition
r510 }
return SqpRange{};
}
Add current progression for thread fix
r336 void clear()
{
m_XAxisData->clear();
m_ValuesData->clear();
}
Alexandre Leroux
Updates merge() method (1)...
r622 bool isEmpty() const noexcept { return m_XAxisData->size() == 0; }
Alexandre Leroux
Handles merge of two data series
r417 /// Merges into the data series an other data series
/// @remarks the data series to merge with is cleared after the operation
Add merge API and implement it for the DataSeries
r217 void merge(IDataSeries *dataSeries) override
{
Alexandre Leroux
Handles merge of two data series
r417 dataSeries->lockWrite();
lockWrite();
if (auto other = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
Alexandre Leroux
Updates merge() method (1)...
r622 DataSeriesMergeHelper::merge(*other, *this);
Add merge API and implement it for the DataSeries
r217 }
Correction for pull request
r227 else {
qCWarning(LOG_DataSeries())
Alexandre Leroux
Handles merge of two data series
r417 << QObject::tr("Detection of a type of IDataSeries we cannot merge with !");
Correction for pull request
r227 }
Alexandre Leroux
Handles merge of two data series
r417 unlock();
dataSeries->unlock();
Add merge API and implement it for the DataSeries
r217 }
Alexandre Leroux
Implements purge() method for DataSeries
r629 void purge(double min, double max) override
{
Alexandre Leroux
Improves purge method
r641 // Nothing to purge if series is empty
if (isEmpty()) {
return;
}
Alexandre Leroux
Implements purge() method for DataSeries
r629 if (min > max) {
std::swap(min, max);
}
Alexandre Leroux
Improves purge method
r641 // Nothing to purge if series min/max are inside purge range
auto xMin = cbegin()->x();
auto xMax = (--cend())->x();
if (xMin >= min && xMax <= max) {
return;
}
Alexandre Leroux
Implements purge() method for DataSeries
r629
Alexandre Leroux
Improves purge method
r641 auto lowerIt = std::lower_bound(
begin(), end(), min, [](const auto &it, const auto &val) { return it.x() < val; });
erase(begin(), lowerIt);
auto upperIt = std::upper_bound(
begin(), end(), max, [](const auto &val, const auto &it) { return val < it.x(); });
erase(upperIt, end());
Alexandre Leroux
Implements purge() method for DataSeries
r629 }
Alexandre Leroux
Creates iterator for DataSeries
r524 // ///////// //
// Iterators //
// ///////// //
Alexandre Leroux
Adapts SqpIterator to make non-const iterators
r626 DataSeriesIterator begin() override
{
return DataSeriesIterator{DataSeriesIteratorValue{
std::make_unique<dataseries_detail::IteratorValue<Dim, false> >(*this, true)}};
}
DataSeriesIterator end() override
{
return DataSeriesIterator{DataSeriesIteratorValue{
std::make_unique<dataseries_detail::IteratorValue<Dim, false> >(*this, false)}};
}
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 DataSeriesIterator cbegin() const override
{
return DataSeriesIterator{DataSeriesIteratorValue{
Alexandre Leroux
Adapts SqpIterator to make non-const iterators
r626 std::make_unique<dataseries_detail::IteratorValue<Dim, true> >(*this, true)}};
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 }
Alexandre Leroux
Creates iterator for DataSeries
r524
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 DataSeriesIterator cend() const override
{
return DataSeriesIterator{DataSeriesIteratorValue{
Alexandre Leroux
Adapts SqpIterator to make non-const iterators
r626 std::make_unique<dataseries_detail::IteratorValue<Dim, true> >(*this, false)}};
Alexandre Leroux
Uses new iterator in DataSeries.cpp...
r558 }
Alexandre Leroux
Creates iterator for DataSeries
r524
Alexandre Leroux
Adds erase() method for ArrayData and DataSeries
r628 void erase(DataSeriesIterator first, DataSeriesIterator last)
{
auto firstImpl
= dynamic_cast<dataseries_detail::IteratorValue<Dim, false> *>(first->impl());
auto lastImpl = dynamic_cast<dataseries_detail::IteratorValue<Dim, false> *>(last->impl());
if (firstImpl && lastImpl) {
m_XAxisData->erase(firstImpl->m_XIt, lastImpl->m_XIt);
m_ValuesData->erase(firstImpl->m_ValuesIt, lastImpl->m_ValuesIt);
}
}
Alexandre Leroux
Updates merge method...
r646 void insert(DataSeriesIterator first, DataSeriesIterator last, bool prepend = false)
{
auto firstImpl = dynamic_cast<dataseries_detail::IteratorValue<Dim, true> *>(first->impl());
auto lastImpl = dynamic_cast<dataseries_detail::IteratorValue<Dim, true> *>(last->impl());
if (firstImpl && lastImpl) {
m_XAxisData->insert(firstImpl->m_XIt, lastImpl->m_XIt, prepend);
m_ValuesData->insert(firstImpl->m_ValuesIt, lastImpl->m_ValuesIt, prepend);
}
}
Alexandre Leroux
(Refactoring) Renames IDataSeries::minData() and IDataSeries::maxData()
r565 /// @sa IDataSeries::minXAxisData()
DataSeriesIterator minXAxisData(double minXAxisData) const override
Alexandre Leroux
Shows min x-axis data in Variable widget (1)...
r561 {
return std::lower_bound(
cbegin(), cend(), minXAxisData,
[](const auto &itValue, const auto &value) { return itValue.x() < value; });
}
Alexandre Leroux
(Refactoring) Renames IDataSeries::minData() and IDataSeries::maxData()
r565 /// @sa IDataSeries::maxXAxisData()
DataSeriesIterator maxXAxisData(double maxXAxisData) const override
Alexandre Leroux
Shows min/max x-axis data in Variable widget (2)...
r562 {
// Gets the first element that greater than max value
auto it = std::upper_bound(
cbegin(), cend(), maxXAxisData,
[](const auto &value, const auto &itValue) { return value < itValue.x(); });
return it == cbegin() ? cend() : --it;
}
Alexandre Leroux
(Refactoring) Renames IDataSeries::subData()
r566 std::pair<DataSeriesIterator, DataSeriesIterator> xAxisRange(double minXAxisData,
double maxXAxisData) const override
Alexandre Leroux
Adds subData() method
r525 {
Alexandre Leroux
(Refactoring) Renames IDataSeries::subData()
r566 if (minXAxisData > maxXAxisData) {
std::swap(minXAxisData, maxXAxisData);
Alexandre Leroux
Adds subData() method
r525 }
auto begin = cbegin();
auto end = cend();
Alexandre Leroux
(Refactoring) Renames IDataSeries::subData()
r566 auto lowerIt = std::lower_bound(
begin, end, minXAxisData,
[](const auto &itValue, const auto &value) { return itValue.x() < value; });
auto upperIt = std::upper_bound(
Alexandre Leroux
Updates merge method...
r646 lowerIt, end, maxXAxisData,
Alexandre Leroux
(Refactoring) Renames IDataSeries::subData()
r566 [](const auto &value, const auto &itValue) { return value < itValue.x(); });
Alexandre Leroux
Adds subData() method
r525
return std::make_pair(lowerIt, upperIt);
}
Alexandre Leroux
Implements method to get min/max values of a dataseries giving a range (1)
r569 std::pair<DataSeriesIterator, DataSeriesIterator>
valuesBounds(double minXAxisData, double maxXAxisData) const override
{
// Places iterators to the correct x-axis range
auto xAxisRangeIts = xAxisRange(minXAxisData, maxXAxisData);
// Returns end iterators if the range is empty
if (xAxisRangeIts.first == xAxisRangeIts.second) {
return std::make_pair(cend(), cend());
}
Alexandre Leroux
Implements method to get min/max values of a dataseries giving a range (2)
r570 // Gets the iterator on the min of all values data
auto minIt = std::min_element(
xAxisRangeIts.first, xAxisRangeIts.second, [](const auto &it1, const auto &it2) {
return SortUtils::minCompareWithNaN(it1.minValue(), it2.minValue());
});
Alexandre Leroux
Implements method to get min/max values of a dataseries giving a range (1)
r569
Alexandre Leroux
Implements method to get min/max values of a dataseries giving a range (2)
r570 // Gets the iterator on the max of all values data
auto maxIt = std::max_element(
xAxisRangeIts.first, xAxisRangeIts.second, [](const auto &it1, const auto &it2) {
return SortUtils::maxCompareWithNaN(it1.maxValue(), it2.maxValue());
});
return std::make_pair(minIt, maxIt);
Alexandre Leroux
Implements method to get min/max values of a dataseries giving a range (1)
r569 }
Alexandre Leroux
Creates iterator for DataSeries
r524 // /////// //
// Mutexes //
// /////// //
Add current progression for thread fix
r336 virtual void lockRead() { m_Lock.lockForRead(); }
virtual void lockWrite() { m_Lock.lockForWrite(); }
virtual void unlock() { m_Lock.unlock(); }
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 protected:
Alexandre Leroux
Makes a Data series be sorted (1)
r415 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
/// DataSeries with no values will be created.
/// @remarks data series is automatically sorted on its x-axis data
Alexandre Leroux
Fixes after review
r175 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 : m_XAxisData{xAxisData},
Alexandre Leroux
Fixes after review
r175 m_XAxisUnit{xAxisUnit},
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 m_ValuesData{valuesData},
Alexandre Leroux
Fixes after review
r175 m_ValuesUnit{valuesUnit}
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 {
Alexandre Leroux
Makes a Data series be sorted (1)
r415 if (m_XAxisData->size() != m_ValuesData->size()) {
clear();
}
// Sorts data if it's not the case
const auto &xAxisCData = m_XAxisData->cdata();
if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) {
sort();
}
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 }
Alexandre Leroux
Use std::shared_ptr in CosinusProvider
r287 /// Copy ctor
explicit DataSeries(const DataSeries<Dim> &other)
: m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)},
m_XAxisUnit{other.m_XAxisUnit},
m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)},
m_ValuesUnit{other.m_ValuesUnit}
{
Alexandre Leroux
Makes a Data series be sorted (1)
r415 // Since a series is ordered from its construction and is always ordered, it is not
// necessary to call the sort method here ('other' is sorted)
Alexandre Leroux
Use std::shared_ptr in CosinusProvider
r287 }
/// Assignment operator
template <int D>
DataSeries &operator=(DataSeries<D> other)
{
std::swap(m_XAxisData, other.m_XAxisData);
std::swap(m_XAxisUnit, other.m_XAxisUnit);
std::swap(m_ValuesData, other.m_ValuesData);
std::swap(m_ValuesUnit, other.m_ValuesUnit);
return *this;
}
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 private:
Alexandre Leroux
Makes a Data series be sorted (1)
r415 /**
* Sorts data series on its x-axis data
*/
void sort() noexcept
{
Alexandre Leroux
Makes a Data series be sorted (2)...
r416 auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>());
m_XAxisData = m_XAxisData->sort(permutation);
m_ValuesData = m_ValuesData->sort(permutation);
Alexandre Leroux
Makes a Data series be sorted (1)
r415 }
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 std::shared_ptr<ArrayData<1> > m_XAxisData;
Alexandre Leroux
Replaces QString unit by a new struct...
r164 Unit m_XAxisUnit;
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
Alexandre Leroux
Replaces QString unit by a new struct...
r164 Unit m_ValuesUnit;
Add current progression for thread fix
r336
QReadWriteLock m_Lock;
Alexandre Leroux
Creates IDataSeries interface and its default implementation
r117 };
#endif // SCIQLOP_DATASERIES_H