diff --git a/core b/core index 483146a..1e3f92d 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 483146a07a5ffeec8f0a2d61459e94d95e851572 +Subproject commit 1e3f92d40b0ec24443e067aaa9e7bca385ec27b2 diff --git a/gui/src/TimeWidget/TimeWidget.cpp b/gui/src/TimeWidget/TimeWidget.cpp index 08fd810..9b3e69d 100644 --- a/gui/src/TimeWidget/TimeWidget.cpp +++ b/gui/src/TimeWidget/TimeWidget.cpp @@ -74,7 +74,7 @@ DateTimeRange TimeWidget::timeRange() const void TimeWidget::onTimeUpdateRequested() { auto dateTime = timeRange(); - emit timeUpdated(std::move(dateTime)); + emit timeUpdated(dateTime); sqpApp->timeController().setDateTimeRange(dateTime); } diff --git a/gui/src/Visualization/VisualizationGraphHelper.cpp b/gui/src/Visualization/VisualizationGraphHelper.cpp index 94dad1d..1540a6e 100644 --- a/gui/src/Visualization/VisualizationGraphHelper.cpp +++ b/gui/src/Visualization/VisualizationGraphHelper.cpp @@ -9,6 +9,7 @@ #include #include #include +#include Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper") @@ -272,11 +273,10 @@ struct PlottablesUpdater(&dataSeries)) { - std::for_each( - std::begin(*serie), std::end(*serie), [&minValue, &maxValue](const auto& v) { - minValue = std::min(minValue, std::min_element(v.begin(), v.end())->v()); - maxValue = std::max(maxValue, std::max_element(v.begin(), v.end())->v()); - }); + std::for_each(std::begin(*serie), std::end(*serie), [&minValue, &maxValue](auto& v) { + minValue = std::min(minValue, std::min_element(v.begin(), v.end())->v()); + maxValue = std::max(maxValue, std::max_element(v.begin(), v.end())->v()); + }); } plot.yAxis->setRange(QCPRange { minValue, maxValue }); } @@ -314,6 +314,46 @@ struct PlottablesUpdater(xAxisProperties.range / xAxisProperties.max_resolution)); + int colormap_v_size = static_cast(yAxisProperties.range / yAxisProperties.max_resolution); + double colormap_h_resolution = xAxisProperties.range / static_cast(colormap_h_size); + double colormap_v_resolution = yAxisProperties.range / static_cast(colormap_v_size); + return ColomapProperties { colormap_h_size, colormap_v_size, colormap_h_resolution, + colormap_v_resolution }; +} + +inline std::vector> build_access_pattern(const std::vector& axis, + const TimeSeriesUtils::axis_properties& axisProperties, + const ColomapProperties& colormap_properties) +{ + std::vector> access_pattern; + for (int index = 0, cel_index = 0; index < colormap_properties.v_size_px; index++) + { + double current_y = pow(10., (axisProperties.max_resolution * index) + axisProperties.min); + if (current_y > axis[cel_index]) + cel_index++; + access_pattern.push_back({ index, axis.size() - 1 - cel_index }); + } + return access_pattern; +} + +/*=============================================================*/ + /** * Specialization of PlottablesUpdater for spectrograms * @sa SpectrogramSeries @@ -354,57 +394,75 @@ struct PlottablesUpdateraxis(1); // copy for in place reverse order std::reverse(std::begin(yAxis), std::end(yAxis)); auto xAxisProperties = TimeSeriesUtils::axis_analysis(xAxis); + TimeSeriesUtils::CheckMedian>(xAxis, serie->min_sampling); auto yAxisProperties = TimeSeriesUtils::axis_analysis(yAxis); + auto colormap_properties = CMAxisAnalysis(xAxisProperties, yAxisProperties); - int colormap_h_size = std::min(32000, - static_cast(xAxisProperties.range / xAxisProperties.max_resolution)); - auto colormap_v_size - = static_cast(yAxisProperties.range / yAxisProperties.max_resolution); - - colormap->data()->setSize(colormap_h_size, colormap_v_size); + colormap->data()->setSize( + colormap_properties.h_size_px, colormap_properties.v_size_px); colormap->data()->setRange( - QCPRange { serie->begin()->t(), (serie->end() - 1)->t() }, - { minValue, maxValue }); + QCPRange { xAxisProperties.min, xAxisProperties.max }, { minValue, maxValue }); - std::vector> y_access_pattern; - for (int y_index = 0, cel_index = 0; y_index < colormap_v_size; y_index++) - { - double current_y = pow( - 10., (yAxisProperties.max_resolution * y_index) + std::log10(minValue)); - if (current_y > yAxis[cel_index]) - cel_index++; - y_access_pattern.push_back({ y_index, yAxis.size() - 1 - cel_index }); - } + auto y_access_pattern + = build_access_pattern(yAxis, yAxisProperties, colormap_properties); auto line = serie->begin(); - double current_time = xAxis[0]; + auto next_line = line + 1; + double current_time = xAxisProperties.min; int x_index = 0; - - while (x_index < colormap_h_size) + auto x_min_resolution + = std::fmin(2. * serie->max_sampling, xAxisProperties.max_resolution * 100.); + std::vector line_values(serie->size(1)); + double avg_coef = 0.; + bool has_nan = false; + while (x_index < colormap_properties.h_size_px) { - if (current_time > (line + 1)->t()) + if (next_line != std::end(*serie) and current_time >= next_line->t()) { - line++; + line = next_line; + next_line++; } - if ((current_time - xAxis[0]) - > (x_index * xAxisProperties.range / colormap_h_size)) + if ((current_time - xAxisProperties.min) + > (static_cast(x_index + 1) * colormap_properties.h_resolutuon)) { + std::for_each(std::cbegin(y_access_pattern), std::cend(y_access_pattern), + [&colormap, &line_values, x_index, avg_coef](const auto& acc) { + colormap->data()->setCell( + x_index, acc.first, line_values[acc.second] / avg_coef); + }); + std::fill(std::begin(line_values), std::end(line_values), 0.); x_index++; + avg_coef = 0.; + has_nan = false; } - if (line->t() <= (current_time + xAxisProperties.max_resolution)) + if (line->t() + x_min_resolution > current_time) { - std::for_each(std::cbegin(y_access_pattern), std::cend(y_access_pattern), - [&colormap, &line, x_index](const auto& acc) { - colormap->data()->setCell(x_index, acc.first, (*line)[acc.second]); - }); + if (has_nan) + { + std::transform(std::begin(*line), std::end(*line), + std::begin(line_values), + [](const auto& input) { return input.v(); }); + has_nan = false; + } + else + { + std::transform(std::begin(*line), std::end(*line), + std::cbegin(line_values), std::begin(line_values), + [](const auto& input, auto output) { return input.v() + output; }); + } + avg_coef += 1.; } else { - for (int y_index = 0; y_index < colormap_v_size; y_index++) + for (int y_index = 0; y_index < colormap_properties.v_size_px; y_index++) { - colormap->data()->setCell(x_index, y_index, std::nan("")); + if (avg_coef > 0.) + { + has_nan = true; + std::fill( + std::begin(line_values), std::end(line_values), std::nan("")); + } } } current_time += xAxisProperties.max_resolution; diff --git a/plugins/python_providers/resources/amda.py b/plugins/python_providers/resources/amda.py index 1f85f70..838b276 100644 --- a/plugins/python_providers/resources/amda.py +++ b/plugins/python_providers/resources/amda.py @@ -32,6 +32,8 @@ def amda_make_spectro(var=None): if var is None: return pysciqlopcore.SpectrogramTimeSerie((0,2)) else: + min_sampling = float(var.meta.get("DATASET_MIN_SAMPLING","nan")) + max_sampling = float(var.meta.get("DATASET_MAX_SAMPLING","nan")) if "PARAMETER_TABLE_MIN_VALUES[1]" in var.meta: min_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MIN_VALUES[1]"].split(',') ]) max_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MAX_VALUES[1]"].split(',') ]) @@ -42,7 +44,7 @@ def amda_make_spectro(var=None): y = (max_v + min_v)/2. else: y = np.logspace(1,3,var.data.shape[1])[::-1] - return pysciqlopcore.SpectrogramTimeSerie(var.time,y,var.data) + return pysciqlopcore.SpectrogramTimeSerie(var.time,y,var.data,min_sampling,max_sampling) def amda_get_sample(metadata,start,stop): ts_type = amda_make_scalar diff --git a/plugins/python_providers/resources/test.py b/plugins/python_providers/resources/test.py index 53a0c55..ff687e3 100644 --- a/plugins/python_providers/resources/test.py +++ b/plugins/python_providers/resources/test.py @@ -64,7 +64,7 @@ def get_data(metadata,start,stop): ts_type = pysciqlopcore.MultiComponentTimeSerie default_ctor_args = (0,2) elif value == 'spectrogram': - ts_type = lambda t,values: pysciqlopcore.SpectrogramTimeSerie(t,np.logspace(1,3,32)[::-1],values) + ts_type = lambda t,values: pysciqlopcore.SpectrogramTimeSerie(t,np.logspace(1,3,32)[::-1],values,np.nan,np.nan) default_ctor_args = (0,2) if key == 'cache' and value == 'true': use_cache = True