diff --git a/external/TimeSeries b/external/TimeSeries index 772f732..3e1b5eb 160000 --- a/external/TimeSeries +++ b/external/TimeSeries @@ -1 +1 @@ -Subproject commit 772f73227be2003fda7309a27d11cd0e248663ad +Subproject commit 3e1b5ebf191a92c416fb1f51ab071875008f0ff4 diff --git a/include/Data/DataSeriesType.h b/include/Data/DataSeriesType.h index b255c52..1f79846 100644 --- a/include/Data/DataSeriesType.h +++ b/include/Data/DataSeriesType.h @@ -1,6 +1,9 @@ #ifndef SCIQLOP_DATASERIESTYPE_H #define SCIQLOP_DATASERIESTYPE_H +#include +#include +#include #include enum class DataSeriesType @@ -30,6 +33,15 @@ struct DataSeriesTypeUtils return DataSeriesType::NONE; } } + static DataSeriesType type(TimeSeries::ITimeSerie* ts) + { + if(!ts) return DataSeriesType::NONE; + if(dynamic_cast(ts)) return DataSeriesType::SCALAR; + if(dynamic_cast(ts)) return DataSeriesType::VECTOR; + if(dynamic_cast(ts)) + return DataSeriesType::SPECTROGRAM; + return DataSeriesType::NONE; + } }; #endif // SCIQLOP_DATASERIESTYPE_H diff --git a/include/Data/DateTimeRange.h b/include/Data/DateTimeRange.h index 44c9fe0..2edc1f3 100644 --- a/include/Data/DateTimeRange.h +++ b/include/Data/DateTimeRange.h @@ -49,6 +49,9 @@ struct DateTimeRange { DateTimeRange() : m_TStart(std::nan("")), m_TEnd(std::nan("")) {} DateTimeRange(double TStart, double TEnd) : m_TStart(TStart), m_TEnd(TEnd) {} + DateTimeRange(const std::pair& range) + : m_TStart(range.first), m_TEnd(range.second) + {} /// Creates SqpRange from dates and times static DateTimeRange fromDateTime(const QDate& startDate, const QTime& startTime, diff --git a/include/Variable/Variable2.h b/include/Variable/Variable2.h index 7930d07..999c267 100644 --- a/include/Variable/Variable2.h +++ b/include/Variable/Variable2.h @@ -19,11 +19,6 @@ #include #include -using AnyTimeSerie = - variant_w_base>; - class SCIQLOP_CORE_EXPORT Variable2 : public QObject { Q_OBJECT @@ -45,7 +40,7 @@ public: std::size_t nbPoints(); /// @return the data of the variable, nullptr if there is no data - AnyTimeSerie* data(); + std::shared_ptr data(); /// @return the type of data that the variable holds DataSeriesType type(); diff --git a/include/Variable/private/VCTransaction.h b/include/Variable/private/VCTransaction.h index 4f4e24d..0087df8 100644 --- a/include/Variable/private/VCTransaction.h +++ b/include/Variable/private/VCTransaction.h @@ -71,7 +71,7 @@ public: _variable->setData(data, _range, true); else { - data.push_back(_variable->data()->base()); + data.push_back(_variable->data().get()); _variable->setData(data, _range, true); } emit transactionComplete(); diff --git a/src/Variable/Variable2.cpp b/src/Variable/Variable2.cpp index a3d7c52..fdd5fdf 100644 --- a/src/Variable/Variable2.cpp +++ b/src/Variable/Variable2.cpp @@ -43,6 +43,18 @@ static DataSeriesType findDataSeriesType(const QVariantHash& metadata) return dataSeriesType; } +std::shared_ptr +clone_ts(const std::shared_ptr& ts) +{ + if(auto scal_ts = std::dynamic_pointer_cast(ts)) + return std::make_shared(*scal_ts); + if(auto scal_ts = std::dynamic_pointer_cast(ts)) + return std::make_shared(*scal_ts); + if(auto scal_ts = std::dynamic_pointer_cast(ts)) + return std::make_shared(*scal_ts); + return nullptr; +} + struct Variable2::VariablePrivate { VariablePrivate(const QString& name, const QVariantHash& metadata) @@ -52,51 +64,52 @@ struct Variable2::VariablePrivate switch(findDataSeriesType(metadata)) { case DataSeriesType::SCALAR: - m_TimeSerie = std::make_unique(ScalarTimeSerie{}); + m_TimeSerie = std::make_shared(ScalarTimeSerie{}); break; case DataSeriesType::VECTOR: - m_TimeSerie = std::make_unique(VectorTimeSerie{}); + m_TimeSerie = std::make_shared(VectorTimeSerie{}); break; case DataSeriesType::SPECTROGRAM: - m_TimeSerie = std::make_unique(SpectrogramTimeSerie{}); + m_TimeSerie = + std::make_shared(SpectrogramTimeSerie{}); break; default: break; } } - VariablePrivate(const VariablePrivate& other) {} + VariablePrivate(const VariablePrivate& other) + : m_Name{other.m_Name}, m_Range{other.m_Range}, + m_Metadata{other.m_Metadata}, m_RealRange{other.m_RealRange} + { + m_TimeSerie = clone_ts(other.m_TimeSerie); + } + std::size_t nbPoints() { - if(m_TimeSerie) return m_TimeSerie->base()->size(); + if(m_TimeSerie) return m_TimeSerie->size(); return 0; } DataSeriesType type() const { - if(m_TimeSerie) return DataSeriesType(m_TimeSerie->index()); - return DataSeriesType::NONE; + return DataSeriesTypeUtils::type(m_TimeSerie.get()); } PROPERTY_(m_Name, name, setName, QString) PROPERTY_(m_Range, range, setRange, DateTimeRange) PROPERTY_(m_Metadata, metadata, setMetadata, QVariantHash) PROPERTY_(m_RealRange, realRange, setRealRange, std::optional) - AnyTimeSerie* dataSeries() { return m_TimeSerie.get(); } - void setDataSeries(std::unique_ptr&& timeSerie) + std::shared_ptr dataSeries() { return m_TimeSerie; } + void setDataSeries(std::shared_ptr&& timeSerie) { QWriteLocker lock{&m_Lock}; - m_TimeSerie = std::move(timeSerie); - if(m_TimeSerie->index() != 0) - { - setRealRange(DateTimeRange( - m_TimeSerie->base()->t(0), - m_TimeSerie->base()->t(m_TimeSerie->base()->size() - 1))); - } + m_TimeSerie = timeSerie; + if(m_TimeSerie) { setRealRange(DateTimeRange(m_TimeSerie->axis_range(0))); } else { setRealRange(std::nullopt); } } - std::unique_ptr m_TimeSerie; + std::shared_ptr m_TimeSerie; QReadWriteLock m_Lock{QReadWriteLock::Recursive}; }; @@ -133,7 +146,10 @@ std::optional Variable2::realRange() std::size_t Variable2::nbPoints() { return impl->nbPoints(); } -AnyTimeSerie* Variable2::data() { return impl->dataSeries(); } +std::shared_ptr Variable2::data() +{ + return impl->dataSeries(); +} DataSeriesType Variable2::type() { @@ -143,81 +159,47 @@ DataSeriesType Variable2::type() QVariantHash Variable2::metadata() const noexcept { return QVariantHash{}; } -// template -// std::unique_ptr _merge(std::vector source) -//{ -// std::unique_ptr dest = std::make_unique(); -// std::sort(std::begin(source), std::end(source), -// [](AnyTimeSerie* a, AnyTimeSerie* b) { -// return a->get().front().t() < b->get().front().t(); -// }); -// *dest = std::move(*source.front()); -// std::for_each( -// std::begin(source) + 1, std::end(source), [&dest](AnyTimeSerie* serie) { -// std::copy(std::begin(serie->get()), std::end(serie->get()), -// std::back_inserter(dest->get())); -// }); -// return dest; -//} - template -std::unique_ptr -_merge(std::vector source) +std::shared_ptr +_merge(std::vector source, const DateTimeRange& range) { - std::unique_ptr dest = std::make_unique(); std::sort(std::begin(source), std::end(source), [](TimeSeries::ITimeSerie* a, TimeSeries::ITimeSerie* b) { if(a->size() && b->size()) return a->t(0) < b->t(0); return false; }); - *dest = std::move(*static_cast(source.front())); - std::for_each(std::begin(source) + 1, std::end(source), - [&dest](TimeSeries::ITimeSerie* serie) { - // TODO -> remove overlap ! - std::copy(std::begin(*static_cast(serie)), - std::end(*static_cast(serie)), - std::back_inserter(dest->get())); - }); + std::shared_ptr dest = std::make_shared(); + std::for_each( + std::begin(source), std::end(source), + [&dest, &range](TimeSeries::ITimeSerie* serie) { + auto& ts = *static_cast(serie); + auto last_t = range.m_TStart; + if(dest->size()) last_t = dest->axis(0).back(); + + std::copy(std::upper_bound( + std::begin(ts), std::end(ts), last_t, + [](const auto& a, const auto& b) { return a < b.t(); }), + std::lower_bound( + std::begin(ts), std::end(ts), range.m_TEnd, + [](const auto& a, const auto& b) { return a.t() < b; }), + std::back_inserter(*std::dynamic_pointer_cast(dest))); + }); return dest; } -// std::unique_ptr -// merge(const std::vector& dataSeries) -//{ -// switch(DataSeriesType(dataSeries.front()->index())) -// { -// case DataSeriesType::NONE: break; -// case DataSeriesType::SCALAR: return _merge(dataSeries); -// case DataSeriesType::VECTOR: return _merge(dataSeries); -// case DataSeriesType::SPECTROGRAM: -// return _merge(dataSeries); -// } -// return std::unique_ptr{}; -//} - -std::unique_ptr -merge(const std::vector& dataSeries) +std::shared_ptr +merge(const std::vector& dataSeries, + const DateTimeRange& range) { if(dynamic_cast(dataSeries.front())) - return _merge(dataSeries); + return _merge(dataSeries, range); if(dynamic_cast(dataSeries.front())) - return _merge(dataSeries); + return _merge(dataSeries, range); if(dynamic_cast(dataSeries.front())) - return _merge(dataSeries); - return std::unique_ptr{}; + return _merge(dataSeries, range); + return std::shared_ptr{}; } -// void Variable2::setData(const std::vector& dataSeries, -// const DateTimeRange& range, bool notify) -//{ -// if(dataSeries.size()) -// { -// impl->setDataSeries(merge(dataSeries)); -// impl->setRange(range); -// if(notify) emit this->updated(this->ID()); -// } -//} - void Variable2::setData(const std::vector& dataSeries, const DateTimeRange& range, bool notify) { @@ -225,7 +207,7 @@ void Variable2::setData(const std::vector& dataSeries, { { QWriteLocker lock{&m_lock}; - impl->setDataSeries(merge(dataSeries)); + impl->setDataSeries(merge(dataSeries, range)); impl->setRange(range); } if(notify) emit this->updated(this->ID()); diff --git a/src/Variable/VariableController2.cpp b/src/Variable/VariableController2.cpp index 15d6e02..1bc410f 100644 --- a/src/Variable/VariableController2.cpp +++ b/src/Variable/VariableController2.cpp @@ -264,7 +264,7 @@ class VariableController2::VariableController2Private data.push_back( provider->getData(DataProviderParameters{{range}, var->metadata()})); } - data.push_back(var->data()->base()); // might be smarter + data.push_back(var->data().get()); // might be smarter var->setData(data, r, true); } diff --git a/src/pybind11_wrappers/CoreWrappers.cpp b/src/pybind11_wrappers/CoreWrappers.cpp index ba528e7..988015a 100644 --- a/src/pybind11_wrappers/CoreWrappers.cpp +++ b/src/pybind11_wrappers/CoreWrappers.cpp @@ -209,7 +209,8 @@ PYBIND11_MODULE(pysciqlopcore, m) }) .def("__repr__", __repr__); - py::class_(m, "ITimeSerie") + py::class_>( + m, "ITimeSerie") .def_property_readonly( "size", [](const TimeSeries::ITimeSerie& ts) { return ts.size(); }) .def("__len__", @@ -309,12 +310,11 @@ PYBIND11_MODULE(pysciqlopcore, m) .def_property("name", &Variable2::name, &Variable2::setName) .def_property_readonly("range", &Variable2::range) .def_property_readonly("nbPoints", &Variable2::nbPoints) - .def_property_readonly("data", - [](Variable2& var) -> TimeSeries::ITimeSerie* { - auto data = var.data(); - if(data) return data->base(); - return nullptr; - }) + .def_property_readonly( + "data", + [](Variable2& var) -> std::shared_ptr { + return var.data(); + }) .def("set_data", [](Variable2& var, std::vector ts_list, const DateTimeRange& range) { var.setData(ts_list, range); }) diff --git a/tests/TestUtils/TestProviders.h b/tests/TestUtils/TestProviders.h index 65a6efa..bfe70ca 100644 --- a/tests/TestUtils/TestProviders.h +++ b/tests/TestUtils/TestProviders.h @@ -37,8 +37,7 @@ public: auto serie = new ScalarTimeSerie(size); std::generate(std::begin(*serie), std::end(*serie), [i = ceil(parameters.m_Range.m_TStart)]() mutable { - return std::pair{i, i * slope}; - i++; + return std::pair{i, i++ * slope}; }); return serie; } @@ -63,8 +62,9 @@ template struct RangeType template void check_variable_state(std::shared_ptr v, DateTimeRange r) { - QVERIFY(v->data()->base()->t(0) >= r.m_TStart); - QVERIFY(v->data()->base()->t(v->data()->base()->size() - 1) <= r.m_TEnd); + auto range = v->data()->axis_range(0); + QVERIFY(range.first >= r.m_TStart); + QVERIFY(range.second <= r.m_TEnd); T::check_properties(v, r); }