Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d03ab1b
Add new request model. Rename response models.
jwasikpsnc Apr 17, 2026
5a1db85
Data smoothing (WIP)
jwasikpsnc Apr 24, 2026
a52b06a
Update docs
jwasikpsnc Apr 28, 2026
b1c3327
Add interpolation without data creation. Update docstrings.
jwasikpsnc May 4, 2026
279c759
Fix interpolation bugs. Update tests.
jwasikpsnc May 5, 2026
d1a410d
Update interpolation docs.
jwasikpsnc May 5, 2026
66018e2
Merge branch 'iterorganization:develop' into feature/data-smoothing-d…
jwasikpsnc May 8, 2026
7807d59
Merge data-smoothing-denoising into data-smoothing
jwasikpsnc May 11, 2026
8dfe769
Merge data-smoothing-denoising into data-smoothing
jwasikpsnc May 12, 2026
c2352ef
Merge branch 'develop' into feature/interpolation-without-new-values
olivhoenen May 12, 2026
d0959d0
Add models for data manipulation
jwasikpsnc May 12, 2026
9f0a1b8
Add missing interface def. Delete old, unused argument.
jwasikpsnc May 15, 2026
ad14563
Commit of shame - run linter
jwasikpsnc May 15, 2026
782d1d8
Delete missed argument
jwasikpsnc May 15, 2026
e4ddaf9
Merge branch 'feature/interpolation-without-new-values' into feature/…
jwasikpsnc May 15, 2026
ed502cb
Pass query object down to data source layer
jwasikpsnc May 18, 2026
4c30996
Add data smoothing
jwasikpsnc May 19, 2026
4cab041
Merge remote-tracking branch 'refs/remotes/origin/develop' into featu…
jwasikpsnc May 19, 2026
2e8bb56
Merge branch 'iterorganization:develop' into feature/data-smoothing
jwasikpsnc May 20, 2026
53958af
Update data manipulation docs
jwasikpsnc May 20, 2026
b9702f6
Delete unused models
jwasikpsnc May 20, 2026
7ac0dad
Add more underlines in adding_new_data_manipulation_method.rst
jwasikpsnc May 25, 2026
2368381
char encoding issue
olivhoenen May 29, 2026
03148dd
Set smoothing_method to None when interpolating
jwasikpsnc Jun 1, 2026
cc73e6a
Allow only time-based smoothing
jwasikpsnc Jun 2, 2026
394118a
Allow 2D smoothing with "time" coordinate
jwasikpsnc Jun 5, 2026
88dcc50
Apply linter
jwasikpsnc Jun 5, 2026
050b612
Apply linter --again
jwasikpsnc Jun 5, 2026
9e85057
Add missing uri.strip()
jwasikpsnc Jun 5, 2026
9fb50d8
Merge branch 'develop' into feature/data-smoothing
jwasikpsnc Jun 5, 2026
06e0c42
Merge branch 'refs/heads/develop' into feature/data-smoothing
jwasikpsnc Jun 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 172 additions & 0 deletions backend/ibex/core/data_manipulation_methods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
from typing import Optional
from enum import Enum
from pydantic import BaseModel


class InterpolationMethod(str, Enum):
EXACT_VALUE = "exact_value"
LINEAR = "linear"
NEAREST = "nearest"


class SmoothingMethod(str, Enum):
GAUSSIAN_FILTER = "gaussian_filter"
SAVITZKY_GOLAY_FILTER = "savitzky-golay_filter"


class AdditionalParameter(BaseModel):
"""
Parameters for specific data manipulation methods. E.g. sigma -> for Gaussian smoothing
"""

name: str
human_readable_name: str
description: str
possible_values: Optional[list[str]] = None


class PossibleValue(BaseModel):
"""
Possible value for data manipulation method parameter. E.g. Gaussian smoothing
"""

value: str
description: str
additional_parameters: Optional[list[AdditionalParameter]] = None


class DataManipulationParameter(BaseModel):
"""
E.g. interpolate_over, type of filtering, binary operation
"""

human_readable_name: str
name: str
description: str
possible_values: Optional[list[PossibleValue]] = None


class DataManipulationOperation(BaseModel):
"""
Type of data manipulation method. E.g. data-smoothing, data-interpolation, binary-operation
"""

name: str
description: str
method_parameters: list[DataManipulationParameter]


class DataManipulationMethodsResponse(BaseModel):
data_manipulation_methods: list[DataManipulationOperation]


available_methods = DataManipulationMethodsResponse(data_manipulation_methods=[])

# ====================== DATA INTERPOLATION ======================

data_interpolation_description = DataManipulationOperation(
name="Data interpolation",
description="Operation performed in order to represent dataset over different set of coordinates",
method_parameters=[],
)

# ====================== DATA INTERPOLATION PARAMETERS ======================

data_interpolation_interpolate_over_parameter = DataManipulationParameter(
human_readable_name="Interpolate over",
name="interpolate_over",
description="List of URIs to gather coordinates from, for interpolation",
)

data_interpolation_method_parameter = DataManipulationParameter(
human_readable_name="Interpolation method",
name="interpolation_method",
description="List of URIs to gather coordinates from, for interpolation",
possible_values=[
PossibleValue(
value=InterpolationMethod.EXACT_VALUE,
description="values are present only on data points where they were originally. Rest of the data grid is filled with NaNs",
),
PossibleValue(
value=InterpolationMethod.LINEAR,
description="see scipy.interpolate.RegularGridInterpolator documentation",
),
PossibleValue(
value=InterpolationMethod.NEAREST,
description="see scipy.interpolate.RegularGridInterpolator documentation",
),
],
)

data_interpolation_description.method_parameters.append(data_interpolation_interpolate_over_parameter)
data_interpolation_description.method_parameters.append(data_interpolation_method_parameter)
available_methods.data_manipulation_methods.append(data_interpolation_description)

# ====================== DATA SMOOTHING ======================

data_smoothing_description = DataManipulationOperation(
name="Data smoothing/denoising",
description="Operation performed in order to eliminate noise from data",
method_parameters=[],
)

# ====================== DATA SMOOTHING PARAMETERS ======================

data_smoothing_method_parameter = DataManipulationParameter(
human_readable_name="Smoothing method",
name="smoothing_method",
description="Method to be used in data smoothing process",
possible_values=[
PossibleValue(
value=SmoothingMethod.GAUSSIAN_FILTER,
description="see scipy.ndimage.gaussian_filter documentation",
additional_parameters=[
AdditionalParameter(
name="gaussian_smoothing_sigma",
human_readable_name="Sigma",
description="Standard deviation for Gaussian kernel.",
)
],
),
PossibleValue(
value=SmoothingMethod.SAVITZKY_GOLAY_FILTER,
description="see scipy.signal.savgol_filter documentation",
additional_parameters=[
AdditionalParameter(
name="savgol_smoothing_window_length",
human_readable_name="Window length",
description="The length of the filter window (i.e., the number of coefficients). If mode is ‘interp’, window_length must be less than or equal to the size of x.",
),
AdditionalParameter(
name="savgol_smoothing_polyorder",
human_readable_name="Polyorder",
description="The order of the polynomial used to fit the samples. polyorder must be less than window_length.",
),
AdditionalParameter(
name="savgol_smoothing_deriv",
human_readable_name="Deriv",
description="The order of the derivative to compute. This must be a nonnegative integer. The default is 0, which means to filter the data without differentiating.",
),
AdditionalParameter(
name="savgol_smoothing_delta",
human_readable_name="Window delta",
description="The spacing of the samples to which the filter will be applied. This is only used if deriv > 0. Default is 1.0.",
),
AdditionalParameter(
name="savgol_smoothing_mode",
human_readable_name="Mode",
description="This determines the type of extension to use for the padded signal to which the filter is applied.",
possible_values=["mirror", "constant", "nearest", "wrap", "interp"],
),
AdditionalParameter(
name="savgol_smoothing_cval",
human_readable_name="C-Val",
description="Value to fill past the edges of the input if mode is ‘constant’. Default is 0.0.",
),
],
),
],
)

data_smoothing_description.method_parameters.append(data_smoothing_method_parameter)
available_methods.data_manipulation_methods.append(data_smoothing_description)
23 changes: 4 additions & 19 deletions backend/ibex/core/ibex_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import time
from pathlib import Path
from functools import wraps # for measure_execution_time()
from typing import Any, Callable, Optional, Sequence, List
from typing import Any, Callable, Optional, Sequence

from ibex.data_source.imas_python_source import IMASPythonSource
from ibex.data_source.exception import CannotGenerateUriException
from ibex.core.utils import IMAS_URI
from ibex.endpoints.schemas.request_data_schemas import PlotDataRequestModel


# helper decorator used during development
Expand Down Expand Up @@ -116,21 +117,5 @@ def get_multiple_node_data(uri: str) -> dict:
)


def get_plot_data(
uri: str,
interpolate_over: List[str] | None,
interpolation_method: str | None,
downsampling_method: str | None,
downsampled_size: int,
) -> dict:
uri_obj = IMAS_URI(uri)
return data_source.get_plot_data(
uri=uri_obj.uri_entry_identifiers,
ids=uri_obj.ids_name,
node_path=uri_obj.node_path,
occurrence=uri_obj.occurrence,
interpolate_over=interpolate_over,
interpolation_method=interpolation_method,
downsampling_method=downsampling_method,
downsampled_size=downsampled_size,
)
def get_plot_data(plot_data_query: PlotDataRequestModel) -> dict:
return data_source.get_plot_data(plot_data_query)
25 changes: 5 additions & 20 deletions backend/ibex/data_source/data_source_interface.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Interface for all data sources"""

from abc import ABC, abstractmethod
from typing import Sequence, Optional, List
from typing import Sequence, Optional
from ibex.endpoints.schemas.request_data_schemas import PlotDataRequestModel


class DataSourceInterface(ABC):
Expand Down Expand Up @@ -123,28 +124,12 @@ def list_db_entries(
"""
...

def get_plot_data(
self,
uri: str,
ids: str,
node_path: str,
occurrence: int = 0,
interpolate_over: List[str] | None = None,
interpolation_method: str | None = None,
downsampling_method: str | None = None,
downsampled_size: int = 1000,
) -> dict:
def get_plot_data(self, plot_data_query: PlotDataRequestModel) -> dict:
"""
Returns all data used to plot selected quantity. Result contains data values, metadata and coordinates.

:param uri: imas URI
:param ids: name of ids e.g. core_profiles
:param node_path: path to ids node e.g. ids_properties/version_put
:param occurrence: ids occurrence number
:param interpolate_over: list of uris used in interpolation
:param interpolation_method: method to be used in data interpolation; one from scipy.interpolate.RegularGridInterpolator or 'exact_value'
:param downsampling_method: one of the downsampling metods returend by :func:`~ibex.endpoints.info.downsampling_methods` endpoint, or None
:param downsampled_size: target size of downsampled data
:param plot_data_query: See :class:`ibex.endpoints.schemas.request_data_schemas.PlotDataRequestModel`
:type plot_data_query: :class:`ibex.endpoints.schemas.request_data_schemas.PlotDataRequestModel`
:return: Dictionary containing data values, metadata and coordinates.
"""
...
Loading
Loading