Skip to content

Data

The main entry point for the data is the Measurement class. These can be loaded from a .pssession file or directly returned as a result from an expirement.

These classes are wrappers for the underlying .NET code. Each Python wrapper in this module holds a reference to the underlying .NET SDK object in an attribute named ._inner (e.g. Measurement._inner). These .NET classes are instantiated by the measurement or data loading code. These wrappers are intended to be used for data processing and exploration and not to be directly instantiated.

The raw data is stored in a DataSet under Measurement.dataset. A dataset in turn consist of a series of DataArray's. These would be analogous to the ’Data' tab in the PSTrace software. A data array would be the equivalent of a column, with a title, array type, and units.

The Curve objects (retrieved via Measurement.curves) are interpretations of the data, much like the plots in the PSTrace software. These can be used for plots or data processing like smoothing the data and peak finding.

pypalmsens.data

Define classes for interfacing with measurement data.

Classes:

  • CallbackData –

    Data returned by the new data callback.

  • CallbackDataEIS –

    Data returned by the EIS new data callback.

  • CurrentArray –

    Array of current values in μA.

  • CurrentReading –

    Current reading data class.

  • Curve –

    Curve class with X and Y data of a single curve.

  • DataArray –

    Array of data values.

  • DataSet –

    Dataset containing multiple data arrays.

  • DeviceInfo –

    Dataclass for device information.

  • EISData –

    Dataset containing impedance measurement results.

  • Measurement –

    Measurement class containing method parameters, curves, and raw data.

  • Peak –

    Contains the peak data of one peak in a curve.

  • PotentialArray –

    Array of potential values in V.

  • PotentialReading –

    Potential reading data class.

  • Status –

    Device Status class.

CallbackData dataclass

CallbackData(x_array: DataArray, y_array: DataArray, start: int, id: int = 0)

Data returned by the new data callback.

Methods:

Attributes:

id class-attribute instance-attribute

id: int = 0

Curve identifier.

index property

index: int

Index of last point.

last_x property

last_x: float

Return last measured x value.

last_y property

last_y: float

Return last measured y value.

start instance-attribute

start: int

Start index for the new data.

x_array instance-attribute

x_array: DataArray

Data array for the x variable.

y_array instance-attribute

y_array: DataArray

Data array for the y variable.

last_datapoint

last_datapoint() -> dict[str, Any]

Return last measured data point.

Source code in src/pypalmsens/_instruments/callback.py
48
49
50
51
52
53
54
def last_datapoint(self) -> dict[str, Any]:
    """Return last measured data point."""
    return {
        'index': self.index,
        'x': self.x_array[-1],
        'y': self.y_array[-1],
    }

new_datapoints

new_datapoints() -> Generator[dict[str, Any]]

Return new data points since last callback.

Source code in src/pypalmsens/_instruments/callback.py
66
67
68
69
70
71
72
73
def new_datapoints(self) -> Generator[dict[str, Any]]:
    """Return new data points since last callback."""
    for i in range(self.start, self.index + 1):
        yield {
            'x': self.x_array[i],
            'y': self.y_array[i],
            'index': i,
        }

CallbackDataEIS dataclass

CallbackDataEIS(data: DataSet, start: int, index: int, id: int = 0)

Data returned by the EIS new data callback.

Methods:

Attributes:

data instance-attribute

data: DataSet

EIS dataset.

id class-attribute instance-attribute

id: int = 0

EIS Data object id.

index instance-attribute

index: int

Index of last point.

start instance-attribute

start: int

Start index for the new data.

last_datapoint

last_datapoint() -> dict[str, float]

Return last measured data point.

Source code in src/pypalmsens/_instruments/callback.py
101
102
103
104
105
106
107
108
109
def last_datapoint(self) -> dict[str, float]:
    """Return last measured data point."""
    ret = {
        array.name: array[self.index]
        for array in self.data.arrays()
        if not array.is_derived
    }
    ret['index'] = self.index
    return ret

new_datapoints

new_datapoints() -> Generator[dict[str, float]]

Return new data points since last callback.

Source code in src/pypalmsens/_instruments/callback.py
111
112
113
114
115
116
def new_datapoints(self) -> Generator[dict[str, float]]:
    """Return new data points since last callback."""
    for i in range(self.start, self.index + 1):
        ret = {array.name: array[i] for array in self.data.values() if not array.is_derived}
        ret['index'] = i
        yield ret

CurrentArray

CurrentArray(values: Iterable[float], *, name: str | None = None)

Array of current values in μA.

Note that for (m)iDC in EIS measurements the array value is 'in range' instead of µA for backwards compatibility reasons. current() and current_in_range() return the correct values.

Parameters:

  • values

    (Iterable[float]) –

    Values to store in the array. Any iterable (list, tuple, generator, etc.) of floats is accepted.

  • name

    (str, default: None ) –

    Name of the array. Defaults to the value of array_type when not given. The name is used in __repr__ and for identification.

Methods:

  • copy –

    Return a copy of the array.

  • current –

    Current in µA.

  • current_in_range –

    Raw current value expressed in the active current range.

  • current_range –

    Return current range as list of strings.

  • current_reading –

    Return as list of potential reading objects.

  • max –

    Return max value.

  • min –

    Return min value.

  • normalize –

    Normalize values in array to the 0 - 1 range.

  • reading_status –

    Return reading status as list of strings.

  • savitsky_golay –

    Smooth the array using a Savitsky-Golay filter with the window size.

  • timing_status –

    Return timing status as list of strings.

  • to_dataframe –

    Return array as pandas DataFrome.

  • to_dict –

    Return array as key/value mapping.

  • to_list –

    Export data array to list.

  • to_numpy –

    Export data array to numpy.

  • update –

    Update all values in-place.

Attributes:

Source code in src/pypalmsens/_data/data_array.py
372
373
374
375
376
377
378
def __init__(
    self,
    values: Iterable[float],
    *,
    name: str | None = None,
):
    super().__init__(values, array_type='Current', name=name)

is_derived property

is_derived: bool

Return True for derived data arrays.

name property

name: str

Name of the array.

ocp_value property

ocp_value: float

OCP Value.

quantity property

quantity: str

Quantity for array.

type property

Array type as str.

unit property

unit: str

Unit for array.

copy

copy() -> DataArray

Return a copy of the array.

Source code in src/pypalmsens/_data/data_array.py
256
257
258
def copy(self) -> DataArray:
    """Return a copy of the array."""
    return DataArray._wrap(self._inner.Clone())

current

current() -> list[float]

Current in µA.

Source code in src/pypalmsens/_data/data_array.py
380
381
382
383
384
385
def current(self) -> list[float]:
    """Current in µA."""
    # Work-around for mIDC bug
    if self.type == 'miDC':
        return [implementation(val).Value for val in self._inner]
    return self.to_list()

current_in_range

current_in_range() -> list[float]

Raw current value expressed in the active current range.

current = current_in_range * CR, e.g. 0.2 * 100uA = 2.0 uA

Source code in src/pypalmsens/_data/data_array.py
387
388
389
390
391
392
def current_in_range(self) -> list[float]:
    """Raw current value expressed in the active current range.

    `current` = `current_in_range` * CR, e.g. 0.2 * 100uA = 2.0 uA
    """
    return [implementation(val).ValueInRange for val in self._inner]

current_range

current_range() -> list[AllowedCurrentRanges]

Return current range as list of strings.

Source code in src/pypalmsens/_data/data_array.py
398
399
400
def current_range(self) -> list[AllowedCurrentRanges]:
    """Return current range as list of strings."""
    return [cr_enum_to_string(implementation(val).CurrentRange) for val in self._inner]

current_reading

current_reading() -> list[CurrentReading]

Return as list of potential reading objects.

Source code in src/pypalmsens/_data/data_array.py
394
395
396
def current_reading(self) -> list[CurrentReading]:
    """Return as list of potential reading objects."""
    return [CurrentReading._from_psobject(implementation(val)) for val in self._inner]

max

max() -> float

Return max value.

Source code in src/pypalmsens/_data/data_array.py
264
265
266
def max(self) -> float:
    """Return max value."""
    return self._inner.MaxValue

min

min() -> float

Return min value.

Source code in src/pypalmsens/_data/data_array.py
260
261
262
def min(self) -> float:
    """Return min value."""
    return self._inner.MinValue

normalize

normalize() -> DataArray

Normalize values in array to the 0 - 1 range.

Values are scaled with (value - min) / (max - min), where min and max are the min and max values.

The unit of the returned array is inherited from the source array.

Returns:

  • new_array ( DataArray ) –

    Data array with normalized values.

Source code in src/pypalmsens/_data/data_array.py
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
def normalize(self) -> DataArray:
    """Normalize values in array to the 0 - 1 range.

    Values are scaled with ``(value - min) / (max - min)``,
    where min and max are the min and max values.

    The unit of the returned array is inherited from the source array.

    Returns
    -------
    new_array : DataArray
        Data array with normalized values.
    """
    new_values = PSMath.NormalizeArray(self._inner.GetValues(), self.min(), self.max())
    new_array = PSDataArray(
        self._inner.Description, self._inner.Unit, self._inner.ArrayType
    )
    new_array.AddRange(new_values)
    return type(self)._wrap(new_array)

reading_status

reading_status() -> list[AllowedReadingStatus]

Return reading status as list of strings.

Source code in src/pypalmsens/_data/data_array.py
402
403
404
def reading_status(self) -> list[AllowedReadingStatus]:
    """Return reading status as list of strings."""
    return [str(implementation(val).ReadingStatus) for val in self._inner]  # type:ignore

savitsky_golay

savitsky_golay(window_size: int = 3) -> DataArray

Smooth the array using a Savitsky-Golay filter with the window size.

(i.e. window size 2 will filter points based on the values of the next/previous 2 points)

Parameters:

  • window_size
    (int, default: 3 ) –

    Size of the window

Returns:

  • new_array ( DataArray ) –

    Smoothed DataArray

Source code in src/pypalmsens/_data/data_array.py
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
def savitsky_golay(self, window_size: int = 3) -> DataArray:
    """Smooth the array using a Savitsky-Golay filter with the window size.

    (i.e. window size 2 will filter points based on the values of the next/previous 2 points)

    Parameters
    ----------
    window_size : int
        Size of the window

    Returns
    -------
    new_array : DataArray
        Smoothed DataArray
    """
    new = self.copy()
    success = new._inner.Smooth(window_size, False)
    if not success:
        raise ValueError('Something went wrong.')
    return new

timing_status

timing_status() -> list[AllowedTimingStatus]

Return timing status as list of strings.

Source code in src/pypalmsens/_data/data_array.py
406
407
408
def timing_status(self) -> list[AllowedTimingStatus]:
    """Return timing status as list of strings."""
    return [str(implementation(val).TimingStatus) for val in self._inner]  # type:ignore

to_dataframe

to_dataframe() -> DataFrame

Return array as pandas DataFrome.

Requires pandas to be installed.

Returns:

  • df ( DataFrame ) –

    Dataframe with current readings

Source code in src/pypalmsens/_data/data_array.py
433
434
435
436
437
438
439
440
441
442
443
444
445
def to_dataframe(self) -> pd.DataFrame:
    """Return array as pandas DataFrome.

    Requires pandas to be installed.

    Returns
    -------
    df : pd.DataFrame
        Dataframe with current readings
    """
    import pandas as pd

    return pd.DataFrame(self.to_dict())

to_dict

to_dict() -> dict[str, list[Any]]

Return array as key/value mapping.

The mapping can be used to create a pandas or polars dataframe.

For example:

array = measurement.dataset['Current']
df = pd.DataFrame(array.to_dict())

Returns:

  • dict[str, list[float | str] –

    Dictionary with current readings

Source code in src/pypalmsens/_data/data_array.py
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
def to_dict(self) -> dict[str, list[Any]]:
    """Return array as key/value mapping.

    The mapping can be used to create a pandas or polars dataframe.

    For example:

        array = measurement.dataset['Current']
        df = pd.DataFrame(array.to_dict())

    Returns
    -------
    dict[str, list[float | str]
        Dictionary with current readings
    """
    return {
        'Current': self.current(),
        'CurrentInRange': self.current_in_range(),
        'CR': self.current_range(),
        'TimingStatus': self.timing_status(),
        'ReadingStatus': self.reading_status(),
    }

to_list

to_list() -> list[float]

Export data array to list.

Source code in src/pypalmsens/_data/data_array.py
320
321
322
def to_list(self) -> list[float]:
    """Export data array to list."""
    return list(self._inner.GetValues())

to_numpy

to_numpy() -> ndarray

Export data array to numpy.

Source code in src/pypalmsens/_data/data_array.py
316
317
318
def to_numpy(self) -> np.ndarray:
    """Export data array to numpy."""
    return np.array(self._inner.GetValues())

update

update(values: Sequence[float])

Update all values in-place.

Parameters:

Raises:

  • ValueError: –

    If data length differs from current length.

Source code in src/pypalmsens/_data/data_array.py
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
def update(self, values: Sequence[float]):
    """Update all values in-place.

    Parameters
    ----------
    values : Iterable[float]
        Values to store in the array.

    Raises
    ------
    ValueError:
        If `data` length differs from current length.
    """
    if len(values) != len(self._inner):
        raise ValueError(
            f'Replacement data must have same length ({len(self._inner)}), '
            f'got {len(values)}'
        )

    for val, new in zip(self._inner, values):
        val.Value = new

CurrentReading dataclass

CurrentReading(current_range: AllowedCurrentRanges, current: float, current_in_range: float, timing_status: AllowedTimingStatus, reading_status: AllowedReadingStatus)

Current reading data class.

Attributes:

current instance-attribute

current: float

Current in μA.

current_in_range instance-attribute

current_in_range: float

Raw current value expressed in the active current range.

current = current_in_range * CR, e.g. 0.2 * 100uA = 2.0 uA

current_range instance-attribute

current_range: AllowedCurrentRanges

Active current range (CR) for this data point.

reading_status instance-attribute

reading_status: AllowedReadingStatus

Status of the current reading.

timing_status instance-attribute

timing_status: AllowedTimingStatus

Status of the current timing.

Curve

Curve(x: DataArray, y: DataArray, *, title: str = 'Curve')

Curve class with X and Y data of a single curve.

Parameters:

  • x

    (DataArray) –

    Data values for the x axis

  • y

    (DataArray) –

    Data values for the y axis

  • title

    (str, default: 'Curve' ) –

    Title for the curve

Notes

Supports arithmetic between curves. curve_a + curve_b and curve_a - curve_b return new curves.

Methods:

  • clear_peaks –

    Clear peaks stored on object.

  • concat –

    Concatenate the x and y arrays of this curve with another curve.

  • copy –

    Return a copy of this curve.

  • find_peaks –

    Find peaks in a curve in all directions.

  • find_peaks_semiderivative –

    Find peaks in a curve using the semi-derivative algorithm.

  • linear_slope –

    Calculate linear line parameters for this curve between two indexes.

  • metadata –

    Generate curve metadata as dataclass.

  • metadata_json –

    Generate curve metadata as json.

  • plot –

    Generate simple plot for this curve using matplotlib.

  • remove_baseline –

    Perform the moving average baseline correction on a curve.

  • savitsky_golay –

    Smooth the .y_array using a Savitsky-Golay filter with the specified window

  • smooth –

    Smooth the .y_array using a Savitsky-Golay filter with the specified smooth

Attributes:

Source code in src/pypalmsens/_data/curve.py
57
58
def __init__(self, x: DataArray, y: DataArray, *, title: str = 'Curve'):
    self._inner = PSCurve(x._inner, y._inner, title)

id property

id: int

Unique identifier for curve object.

max_x property

max_x: float

Maximum X value found in this curve.

max_y property

max_y: float

Maximum Y value found in this curve.

min_x property

min_x: float

Minimum X value found in this curve.

min_y property

min_y: float

Minimum Y value found in this curve.

mux_channel property

mux_channel: int

The corresponding MUX channel number with the curve starting at 0. Return -1 when no MUX channel used.

n_points property

n_points: int

Number of points for this curve.

ocp_value property

ocp_value: float

OCP value for curve.

peaks property

peaks: list[Peak]

Return peaks stored on object.

title property writable

title: str

Title for the curve.

x_array property

x_array: DataArray

Y data for the curve.

x_label property

x_label: str

Label for X dimension.

x_unit property

x_unit: str

Units for X dimension.

y_array property

y_array: DataArray

Y data for the curve.

y_label property

y_label: str

Label for Y dimension.

y_unit property

y_unit: str

Units for Y dimension.

z_label property

z_label: None | str

Units for Z dimension. Returns None if not set.

z_unit property

z_unit: None | str

Units for Z dimension. Returns None if not set.

clear_peaks

clear_peaks()

Clear peaks stored on object.

Source code in src/pypalmsens/_data/curve.py
387
388
389
def clear_peaks(self):
    """Clear peaks stored on object."""
    self._inner.ClearPeaks()

concat

concat(other: Curve) -> Self

Concatenate the x and y arrays of this curve with another curve.

Parameters:

  • other
    (Curve) –

    Curve whose points are appended after this curve's points.

Returns:

  • Curve –

    New curve with the concatenated x and y arrays.

Source code in src/pypalmsens/_data/curve.py
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
def concat(self, other: Curve) -> Self:
    """Concatenate the x and y arrays of this curve with another curve.

    Parameters
    ----------
    other: Curve
        Curve whose points are appended after this curve's points.

    Returns
    -------
    Curve
        New curve with the concatenated x and y arrays.
    """
    new_curve = PSMath.AppendCurves(self._inner, other._inner)

    return type(self)._wrap(new_curve)

copy

copy() -> Curve

Return a copy of this curve.

Source code in src/pypalmsens/_data/curve.py
116
117
118
def copy(self) -> Curve:
    """Return a copy of this curve."""
    return Curve._wrap(PSCurve(self._inner, cloneData=True))

find_peaks

Find peaks in a curve in all directions.

CV can have 1 or 2 direction changes.

Parameters:

  • min_peak_width
    (float, default: 0.1 ) –

    Minimum width of the peak in V

  • min_peak_height
    (float, default: 0.0 ) –

    Minimum height of the peak in uA

  • peak_shoulders
    (bool, default: False ) –

    Use alternative peak search algorithm optimized for finding peaks on slopes

  • merge_overlapping_peaks
    (bool, default: True ) –

    Two or more peaks that overlap will be identified as a single base peak and as shoulder peaks on the base peak.

Returns:

Source code in src/pypalmsens/_data/curve.py
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
def find_peaks(
    self,
    min_peak_width: float = 0.1,
    min_peak_height: float = 0.0,
    peak_shoulders: bool = False,
    merge_overlapping_peaks: bool = True,
) -> list[Peak]:
    """Find peaks in a curve in all directions.

    CV can have 1 or 2 direction changes.

    Parameters
    ----------
    min_peak_width : float
        Minimum width of the peak in V
    min_peak_height : float
        Minimum height of the peak in uA
    peak_shoulders : bool, optional
        Use alternative peak search algorithm optimized for finding peaks on slopes
    merge_overlapping_peaks : bool, optional
        Two or more peaks that overlap will be identified as a single
        base peak and as shoulder peaks on the base peak.

    Returns
    -------
    peak_list : list[Peak]
    """
    pspeaks = self._inner.FindPeaks(
        minPeakWidth=min_peak_width,
        minPeakHeight=min_peak_height,
        peakShoulders=peak_shoulders,
        mergeOverlappingPeaks=merge_overlapping_peaks,
    )

    peaks_list = [Peak._wrap(peak) for peak in pspeaks]

    return peaks_list

find_peaks_semiderivative

find_peaks_semiderivative(min_peak_height: float = 0.0) -> list[Peak]

Find peaks in a curve using the semi-derivative algorithm.

Used for detecting non-overlapping peaks in LSV and CV curves. The peaks are also assigned to the curve, updating Curve.peaks. Existing peaks are overwritten.

For more info, see this Wikipedia page.

Parameters:

  • min_peak_height
    (float, default: 0.0 ) –

    Minimum height of the peak in uA

Returns:

Source code in src/pypalmsens/_data/curve.py
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
def find_peaks_semiderivative(
    self,
    min_peak_height: float = 0.0,
) -> list[Peak]:
    """
    Find peaks in a curve using the semi-derivative algorithm.

    Used for detecting non-overlapping peaks in LSV and CV curves.
    The peaks are also assigned to the curve, updating `Curve.peaks`.
    Existing peaks are overwritten.

    For more info, see this
    [Wikipedia page](https://en.wikipedia.org/wiki/Neopolarogram).

    Parameters
    ----------
    min_peak_height : float
        Minimum height of the peak in uA

    Returns
    -------
    peak_list : list[Peak]
    """
    dct = System.Collections.Generic.Dictionary[PSCurve, System.Double]()
    dct[self._inner] = min_peak_height

    pd = PSAnalysis.SemiDerivativePeakDetection()
    pd.GetNonOverlappingPeaks(dct)

    return self.peaks

linear_slope

linear_slope(start: None | int = None, stop: None | int = None) -> tuple[float, float, float]

Calculate linear line parameters for this curve between two indexes.

current = a + b * x

Parameters:

  • start
    (int, default: None ) –

    begin index

  • stop
    (int, default: None ) –

    end index

Returns:

  • a ( float ) –
  • b ( float ) –
  • coefdet ( float ) –

    Coefficient of determination (R2)

Source code in src/pypalmsens/_data/curve.py
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
def linear_slope(
    self, start: None | int = None, stop: None | int = None
) -> tuple[float, float, float]:
    """Calculate linear line parameters for this curve between two indexes.

    current = a + b * x

    Parameters
    ----------
    start : int, optional
        begin index
    stop : int, optional
        end index

    Returns
    -------
    a : float
    b : float
    coefdet : float
        Coefficient of determination (R2)
    """
    if start and stop:
        return self._inner.LLS(start, stop)
    else:
        return self._inner.LLS()

metadata

metadata() -> CurveMetadata

Generate curve metadata as dataclass.

Source code in src/pypalmsens/_data/curve.py
364
365
366
367
368
369
370
371
372
def metadata(self) -> CurveMetadata:
    """Generate curve metadata as dataclass."""
    return CurveMetadata(
        title=self.title,
        columns=['x', 'y'],
        units=[self.x_unit, self.y_unit],
        labels=[self.x_label, self.y_label],
        id=self.id,
    )

metadata_json

metadata_json() -> bytes

Generate curve metadata as json.

Source code in src/pypalmsens/_data/curve.py
374
375
376
def metadata_json(self) -> bytes:
    """Generate curve metadata as json."""
    return TypeAdapter(CurveMetadata).dump_json(self.metadata())

plot

plot(ax: None | Axes = None, legend: bool = True, **plot_kwargs) -> Figure | SubFigure

Generate simple plot for this curve using matplotlib.

Parameters:

  • ax
    (Optional[Axes], default: None ) –

    Add plot to this ax if specified.

  • legend
    (bool, default: True ) –

    If True, add legend.

  • plot_kwargs
    –

    These keyword arguments are passed to ax.plot.

Returns:

  • fig ( Figure ) –

    Matplotlib figure. Use fig.show() to render plot.

Source code in src/pypalmsens/_data/curve.py
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
def plot(
    self,
    ax: None | axes.Axes = None,
    legend: bool = True,
    **plot_kwargs,
) -> figure.Figure | figure.SubFigure:
    """Generate simple plot for this curve using matplotlib.

    Parameters
    ----------
    ax : Optional[axes.Axes]
        Add plot to this ax if specified.
    legend : bool
        If True, add legend.
    plot_kwargs
        These keyword arguments are passed to `ax.plot`.

    Returns
    -------
    fig : fig.Figure
        Matplotlib figure. Use `fig.show()` to render plot.
    """
    import matplotlib.pyplot as plt

    if not ax:
        _, ax = plt.subplots()

    _ = ax.plot(self.x_array, self.y_array, label=self.title, **plot_kwargs)
    _ = ax.set_xlabel(f'{self.x_label} ({self.x_unit})')
    _ = ax.set_ylabel(f'{self.y_label} ({self.y_unit})')

    if peaks := self.peaks:
        x, y = list(zip(*((peak.x, peak.y) for peak in peaks)))
        _ = ax.scatter(x, y, label='Peaks')

    if legend:
        _ = ax.legend()

    return ax.figure

remove_baseline

remove_baseline(max_sweeps: int = 1001, window_size: int = 2, mode: Literal['moving-average'] = 'moving-average') -> tuple[Curve, Curve]

Perform the moving average baseline correction on a curve.

This method calculates and applies a baseline correction using a specified moving average window size and a maximum number of sweeps allowed.

Parameters:

  • max_sweeps
    (int, default: 1001 ) –

    The maximum number of sweeps allowed during the baseline correction process. Defaults to 1001.

  • window_size
    (int, default: 2 ) –

    The size of the moving average window used for calculating the baseline. Defaults to 2.

  • mode
    (str, default: 'moving-average' ) –

    The method used for baseline correction (e.g., 'moving-average'). Defaults to 'moving-average'.

Returns:

  • BaselineResult –

    A named tuple containing:

    • corrected : The baseline-corrected curve.
    • baseline : The calculated baseline curve that was subtracted.

Examples:

Unpacking as a tuple:

>>> corrected, baseline = curve.remove_baseline(max_sweeps=500, window_size=2)

Attribute access:

>>> result = curve.remove_baseline(max_sweeps=500, window_size=2)
>>> result.corrected, result.baseline
Source code in src/pypalmsens/_data/curve.py
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
def remove_baseline(
    self,
    max_sweeps: int = 1001,
    window_size: int = 2,
    mode: Literal['moving-average'] = 'moving-average',
) -> tuple[Curve, Curve]:
    """Perform the moving average baseline correction on a curve.

    This method calculates and applies a baseline correction using a specified
    moving average window size and a maximum number of sweeps allowed.

    Parameters
    ----------
    max_sweeps : int, optional
        The maximum number of sweeps allowed during the baseline correction process.
        Defaults to 1001.
    window_size : int, optional
        The size of the moving average window used for calculating the baseline.
        Defaults to 2.
    mode : str, optional
        The method used for baseline correction (e.g., 'moving-average').
        Defaults to 'moving-average'.

    Returns
    -------
    BaselineResult
        A named tuple containing:

        - `corrected` : The baseline-corrected curve.
        - `baseline` : The calculated baseline curve that was subtracted.

    Examples
    --------
    Unpacking as a tuple:
    >>> corrected, baseline = curve.remove_baseline(max_sweeps=500, window_size=2)

    Attribute access:
    >>> result = curve.remove_baseline(max_sweeps=500, window_size=2)
    >>> result.corrected, result.baseline
    """

    assert mode == 'moving-average'

    class BaselineResult(NamedTuple):
        corrected: Curve
        baseline: Curve

    _corrected = PSAnalysis.BaselineCorrection.GetMovingAverageBaselineCorrected(
        self._inner, nWindowSize=window_size, maxNSweeps=max_sweeps, baseline=False
    )
    _corrected.Title = self.title + ' (corrected)'
    _baseline = PSAnalysis.BaselineCorrection.GetMovingAverageBaselineCorrected(
        self._inner, nWindowSize=window_size, maxNSweeps=max_sweeps, baseline=True
    )
    _baseline.Title = self.title + ' (baseline)'

    return BaselineResult(
        corrected=Curve._wrap(_corrected), baseline=Curve._wrap(_baseline)
    )

savitsky_golay

savitsky_golay(window_size: int = 3)

Smooth the .y_array using a Savitsky-Golay filter with the specified window size.

(i.e. window size 2 will filter points based on the values of the next/previous 2 points)

Parameters:

  • window_size
    (int, default: 3 ) –

    Size of the window

Source code in src/pypalmsens/_data/curve.py
134
135
136
137
138
139
140
141
142
143
144
145
def savitsky_golay(self, window_size: int = 3):
    """Smooth the .y_array using a Savitsky-Golay filter with the specified window
    size.

    (i.e. window size 2 will filter points based on the values of the next/previous 2 points)

    Parameters
    ----------
    window_size : int
        Size of the window
    """
    self._inner.SavitskyGolay(windowSize=window_size)

smooth

smooth(smooth_level: int = 0)

Smooth the .y_array using a Savitsky-Golay filter with the specified smooth level.

Parameters:

  • smooth_level
    (int, default: 0 ) –

    The smooth level to be used. -1 = none, 0 = no smooth (spike rejection only), 1 = 5 points, 2 = 9 points, 3 = 15 points, 4 = 25 points

Source code in src/pypalmsens/_data/curve.py
120
121
122
123
124
125
126
127
128
129
130
131
132
def smooth(self, smooth_level: int = 0):
    """Smooth the .y_array using a Savitsky-Golay filter with the specified smooth
    level.

    Parameters
    ----------
    smooth_level : int
        The smooth level to be used. -1 = none, 0 = no smooth (spike rejection only),
        1 = 5 points, 2 = 9 points, 3 = 15 points, 4 = 25 points
    """
    success = self._inner.Smooth(smoothLevel=smooth_level)
    if not success:
        raise ValueError('Something went wrong.')

DataArray

DataArray(values: Iterable[float], *, array_type: AllowedArrayTypes = 'Generic', name: str | None = None)

Array of data values.

A data array can be created from an iterable of values, or wrapped from an existing PSDataArray (see _wrap).

Parameters:

  • values

    (Iterable[float]) –

    Values to store in the array. Any iterable (list, tuple, generator, etc.) of floats is accepted.

  • array_type

    (AllowedArrayTypes, default: 'Generic' ) –

    Type of the array. Defaults to 'Generic'. Use e.g. 'Current' or 'Potential' when constructing arrays that represent measured quantities.

  • name

    (str, default: None ) –

    Name of the array. Defaults to the value of array_type when not given. The name is used in __repr__ and for identification.

Notes

Supports arithmetic between arrays of the same type. array_a + array_b, array_a - array_b and array_a * factor return new arrays.

Methods:

  • copy –

    Return a copy of the array.

  • max –

    Return max value.

  • min –

    Return min value.

  • normalize –

    Normalize values in array to the 0 - 1 range.

  • savitsky_golay –

    Smooth the array using a Savitsky-Golay filter with the window size.

  • to_list –

    Export data array to list.

  • to_numpy –

    Export data array to numpy.

  • update –

    Update all values in-place.

Attributes:

Source code in src/pypalmsens/_data/data_array.py
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def __init__(
    self,
    values: Iterable[float],
    *,
    array_type: AllowedArrayTypes = 'Generic',
    name: str | None = None,
):
    array_type_enum = array_str_to_enum(array_type)

    if name is None:
        name = array_type

    if isinstance(self, CurrentArray):
        inner = PSDataArrayCurrents(name, array_type_enum)
    elif isinstance(self, PotentialArray):
        inner = PSDataArrayPotentials(name, array_type_enum)
    else:
        try:
            unit = DEFAULT_UNIT_MAPPING[array_type]()
        except KeyError:
            unit = PSUnits.FixedUnit('Unknown', '', '')

        inner = self._ps_cls(name, unit, array_type_enum)

    inner.AddRange(values)

    self._inner = inner

is_derived property

is_derived: bool

Return True for derived data arrays.

name property

name: str

Name of the array.

ocp_value property

ocp_value: float

OCP Value.

quantity property

quantity: str

Quantity for array.

type property

Array type as str.

unit property

unit: str

Unit for array.

copy

copy() -> DataArray

Return a copy of the array.

Source code in src/pypalmsens/_data/data_array.py
256
257
258
def copy(self) -> DataArray:
    """Return a copy of the array."""
    return DataArray._wrap(self._inner.Clone())

max

max() -> float

Return max value.

Source code in src/pypalmsens/_data/data_array.py
264
265
266
def max(self) -> float:
    """Return max value."""
    return self._inner.MaxValue

min

min() -> float

Return min value.

Source code in src/pypalmsens/_data/data_array.py
260
261
262
def min(self) -> float:
    """Return min value."""
    return self._inner.MinValue

normalize

normalize() -> DataArray

Normalize values in array to the 0 - 1 range.

Values are scaled with (value - min) / (max - min), where min and max are the min and max values.

The unit of the returned array is inherited from the source array.

Returns:

  • new_array ( DataArray ) –

    Data array with normalized values.

Source code in src/pypalmsens/_data/data_array.py
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
def normalize(self) -> DataArray:
    """Normalize values in array to the 0 - 1 range.

    Values are scaled with ``(value - min) / (max - min)``,
    where min and max are the min and max values.

    The unit of the returned array is inherited from the source array.

    Returns
    -------
    new_array : DataArray
        Data array with normalized values.
    """
    new_values = PSMath.NormalizeArray(self._inner.GetValues(), self.min(), self.max())
    new_array = PSDataArray(
        self._inner.Description, self._inner.Unit, self._inner.ArrayType
    )
    new_array.AddRange(new_values)
    return type(self)._wrap(new_array)

savitsky_golay

savitsky_golay(window_size: int = 3) -> DataArray

Smooth the array using a Savitsky-Golay filter with the window size.

(i.e. window size 2 will filter points based on the values of the next/previous 2 points)

Parameters:

  • window_size
    (int, default: 3 ) –

    Size of the window

Returns:

  • new_array ( DataArray ) –

    Smoothed DataArray

Source code in src/pypalmsens/_data/data_array.py
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
def savitsky_golay(self, window_size: int = 3) -> DataArray:
    """Smooth the array using a Savitsky-Golay filter with the window size.

    (i.e. window size 2 will filter points based on the values of the next/previous 2 points)

    Parameters
    ----------
    window_size : int
        Size of the window

    Returns
    -------
    new_array : DataArray
        Smoothed DataArray
    """
    new = self.copy()
    success = new._inner.Smooth(window_size, False)
    if not success:
        raise ValueError('Something went wrong.')
    return new

to_list

to_list() -> list[float]

Export data array to list.

Source code in src/pypalmsens/_data/data_array.py
320
321
322
def to_list(self) -> list[float]:
    """Export data array to list."""
    return list(self._inner.GetValues())

to_numpy

to_numpy() -> ndarray

Export data array to numpy.

Source code in src/pypalmsens/_data/data_array.py
316
317
318
def to_numpy(self) -> np.ndarray:
    """Export data array to numpy."""
    return np.array(self._inner.GetValues())

update

update(values: Sequence[float])

Update all values in-place.

Parameters:

Raises:

  • ValueError: –

    If data length differs from current length.

Source code in src/pypalmsens/_data/data_array.py
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
def update(self, values: Sequence[float]):
    """Update all values in-place.

    Parameters
    ----------
    values : Iterable[float]
        Values to store in the array.

    Raises
    ------
    ValueError:
        If `data` length differs from current length.
    """
    if len(values) != len(self._inner):
        raise ValueError(
            f'Replacement data must have same length ({len(self._inner)}), '
            f'got {len(values)}'
        )

    for val, new in zip(self._inner, values):
        val.Value = new

DataSet

Dataset containing multiple data arrays.

All values are related by means of their indices. DataArrays in a DataSet should always have an equal amount of entries.

Parameters:

  • arrays

    (Iterable[DataArray]) –

    List of DataArray objects to include in the dataset.

Methods:

  • arrays –

    Return list of all arrays.

  • curve –

    Construct a custom curve from x and y keys.

  • to_dataframe –

    Return dataset as pandas DataFrame.

  • to_dict –

    Return dataset as key/value mapping.

Attributes:

Source code in src/pypalmsens/_data/dataset.py
60
61
62
63
64
65
66
def __init__(self, arrays: Iterable[DataArray]):
    inner = PSDataSetCommon()
    for array in arrays:
        _ = inner.AddDataArray(array._inner)

    self._inner = inner
    self._mapping = _dataset_to_mapping_with_unique_keys(inner)

array_names property

array_names: set[str]

Return unique set of names for arrays in dataset.

array_quantities property

array_quantities: set[str]

Return unique set of quantities for arrays in dataset.

array_types property

array_types: set[AllowedArrayTypes]

Return unique set of array types for arrays in dataset.

n_points property

n_points: int

Number of points in arrays.

arrays

arrays(type: AllowedArrayTypes | None = None, name: str | None = None, quantity: str | None = None, hidden: bool = False) -> Sequence[DataArray]

Return list of all arrays.

By default, return all arrays. Only one filter can be active at the time.

Parameters:

  • type
    (str, default: None ) –

    Get arrays by type of the array, e.g. 'Current', 'Frequency', 'AuxInput'. Use .array_types() to get a list of possible values.

  • name
    (str, default: None ) –

    Get arrays with given name, e.g. 'scan1', 'time'. Use .array_names() to get a list of possible values.

  • quantity
    (str, default: None ) –

    Get arrays by quantity, e.g. 'Charge', '-Phase'. Use .array_quantities() to get a list of possible values.

  • hidden
    (bool, default: False ) –

    Return hidden arrays used for debugging.

Returns:

Source code in src/pypalmsens/_data/dataset.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
def arrays(
    self,
    type: AllowedArrayTypes | None = None,
    name: str | None = None,
    quantity: str | None = None,
    hidden: bool = False,
) -> Sequence[DataArray]:
    """Return list of all arrays.

    By default, return all arrays.
    Only one filter can be active at the time.

    Parameters
    ----------
    type : str
        Get arrays by type of the array, e.g. 'Current', 'Frequency', 'AuxInput'.
        Use `.array_types()` to get a list of possible values.
    name : str
        Get arrays with given name, e.g. 'scan1', 'time'.
        Use `.array_names()` to get a list of possible values.
    quantity : str
        Get arrays by quantity, e.g. 'Charge', '-Phase'.
        Use `.array_quantities()` to get a list of possible values.
    hidden : bool
        Return hidden arrays used for debugging.

    Returns
    -------
    arrays : Sequence[DataArray]
        List of arrays.
    """
    if type:
        return self._filter(key=lambda array: array.type == type)
    elif name:
        return self._filter(key=lambda array: array.name == name)
    elif quantity:
        return self._filter(key=lambda array: array.quantity == quantity)
    elif hidden:
        return [DataArray._wrap(psarray) for psarray in self._inner if psarray.Hidden]
    else:
        return list(self.values())

curve

curve(x: str, y: str, title: str | None = None) -> Curve

Construct a custom curve from x and y keys.

Parameters:

  • x
    (str) –

    Key identifying the x array

  • y
    (str) –

    Key identifying the y array

  • title
    (str, default: None ) –

    Set the title. If None, use the $x-$y as title

Returns:

  • curve ( Curve ) –

    New Curve with plotting x against y

Source code in src/pypalmsens/_data/dataset.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
def curve(self, x: str, y: str, title: str | None = None) -> Curve:
    """Construct a custom curve from x and y keys.

    Parameters
    ----------
    x : str
        Key identifying the x array
    y : str
        Key identifying the y array
    title : str
        Set the title. If None, use the $x-$y as title

    Returns
    -------
    curve : Curve
        New Curve with plotting x against y
    """
    xarray = self[x]
    yarray = self[y]

    if not title:
        title = f'{x}-{y}'

    return Curve(xarray, yarray, title=title)

to_dataframe

to_dataframe() -> DataFrame

Return dataset as pandas DataFrame. Requires pandas to be installed.

Returns:

  • df ( DataFrame ) –

    Dataframe with all arrays in dataset.

Source code in src/pypalmsens/_data/dataset.py
212
213
214
215
216
217
218
219
220
221
222
223
224
def to_dataframe(self) -> pd.DataFrame:
    """Return dataset as pandas DataFrame.
    Requires pandas to be installed.

    Returns
    -------
    df : pd.DataFrame
        Dataframe with all arrays in dataset.
    """
    import pandas as pd

    dct = self.to_dict()
    return pd.DataFrame.from_dict(dct, orient='index').T

to_dict

to_dict() -> dict[str, list[Any]]

Return dataset as key/value mapping.

The mapping can be used to create a pandas or polars dataframe.

For example:

df = pd.DataFrame(dataset.to_dict())

Returns:

  • dct ( dict[str, list[Any]] ) –

    Dictionary with all arrays in dataset.

Source code in src/pypalmsens/_data/dataset.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
def to_dict(self) -> dict[str, list[Any]]:
    """Return dataset as key/value mapping.

    The mapping can be used to create a pandas or polars dataframe.

    For example:

        df = pd.DataFrame(dataset.to_dict())

    Returns
    -------
    dct : dict[str, list[Any]]
        Dictionary with all arrays in dataset.
    """
    dct: dict[str, Any] = {key: arr.to_list() for key, arr in self.items() if len(arr)}

    if 'Current' in self.array_types:
        *_, current = self.arrays(type='Current')

        if isinstance(current, CurrentArray):
            dct['CR'] = current.current_range()
            dct['ReadingStatus'] = current.reading_status()

    return dct

DeviceInfo dataclass

DeviceInfo(type: str, firmware: str, serial: str, id: int)

Dataclass for device information.

Attributes:

firmware instance-attribute

firmware: str

Firmware version.

id instance-attribute

id: int

Device ID.

serial instance-attribute

serial: str

Serial number.

type instance-attribute

type: str

Device type.

EISData

EISData()

Dataset containing impedance measurement results.

EISData cannot be instantiated directly. Obtain instances through measurements or io methods.

Methods:

Attributes:

Source code in src/pypalmsens/_data/eisdata.py
51
52
53
54
55
def __init__(self):
    raise TypeError(
        'EISData cannot be instantiated directly. '
        'Obtain instances through measurements or io methods.'
    )

cdc property

cdc: str

Gets the CDC circuit for fitting.

cdc_values property

cdc_values: list[float]

Return values for circuit description code (CDC).

dataset property

dataset: DataSet

Dataset which contains multiple arrays of values.

frequency_type property

frequency_type: AllowedFrequencyTypes

Frequency type.

has_subscans property

has_subscans: bool

Return True if data contains subscans.

id property

id: int

Unique identifier for curve object.

mux_channel property

mux_channel: int

Mux channel.

n_frequencies property

n_frequencies: int

Number of frequencies.

n_points property

n_points: int

Number of points (including subscans).

n_subscans property

n_subscans: int

Number of subscans.

ocp_value property

ocp_value: float

OCP Value.

scan_type property

scan_type: AllowedScanTypes

Scan type.

subscans property

subscans: list[EISData]

Get list of subscans.

title property

title: str

Tite for EIS data.

x_quantity property

x_quantity: str

Quantity for array.

x_unit property

x_unit: str

Unit for array.

arrays

arrays() -> list[DataArray]

Complete list of data arrays.

Source code in src/pypalmsens/_data/eisdata.py
164
165
166
def arrays(self) -> list[DataArray]:
    """Complete list of data arrays."""
    return list(self.dataset.values())

current_range

current_range() -> list[AllowedCurrentRanges]

Current ranges for the measurement.

Source code in src/pypalmsens/_data/eisdata.py
168
169
170
171
172
def current_range(self) -> list[AllowedCurrentRanges]:
    """Current ranges for the measurement."""
    return [
        cr_enum_to_string(self._inner.GetCurrentRange(val)) for val in range(self.n_points)
    ]

get_data_for_frequency

get_data_for_frequency(frequency: int) -> dict[str, DataArray]

Returns dictionary with data per frequency.

Parameters:

  • frequency
    (int) –

    Index of the frequency to retrieve the data for.

Returns:

  • dict[str, DataArray] –

    Data are returned as a dictionary keyed by the data type.

Source code in src/pypalmsens/_data/eisdata.py
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
def get_data_for_frequency(self, frequency: int) -> dict[str, DataArray]:
    """Returns dictionary with data per frequency.

    Parameters
    ----------
    frequency : int
        Index of the frequency to retrieve the data for.

    Returns
    -------
    dict[str, DataArray]
        Data are returned as a dictionary keyed by the data type.
    """
    if not (0 <= frequency < self.n_frequencies):
        raise ValueError(f'Frequency must be between 0 and {self.n_frequencies}')

    return {
        str(row.Key): DataArray._wrap(row.Value)
        for row in self._inner.GetDataArrayVsX(frequency)
    }

metadata

metadata() -> EISDataMetadata

Return eis data metadata as dataclass

Source code in src/pypalmsens/_data/eisdata.py
189
190
191
192
193
194
195
196
197
198
199
200
201
def metadata(self) -> EISDataMetadata:
    """Return eis data metadata as dataclass"""
    arrays = [array for array in self.dataset.values() if not array.is_derived]
    return EISDataMetadata(
        title=self.title,
        columns=[array.name for array in arrays],
        units=[array.unit for array in arrays],
        quantities=[array.quantity for array in arrays],
        n_frequencies=self.n_frequencies,
        frequency_type=self.frequency_type,
        scan_type=self.scan_type,
        id=self.id,
    )

metadata_json

metadata_json() -> bytes

Generate eis data metadata as json.

Source code in src/pypalmsens/_data/eisdata.py
203
204
205
206
def metadata_json(self) -> bytes:
    """Generate eis data metadata as json."""

    return TypeAdapter(EISDataMetadata).dump_json(self.metadata())

Measurement

Measurement(method: MethodTypeCompatible | None = None, dataset: DataSet | None = None)

Measurement class containing method parameters, curves, and raw data.

Instantiation via the constructor is limited. Obtain instances through measurements or io methods.

Parameters:

  • method

    (MethodTypeCompatible, default: None ) –

    The electrochemical method associated with this measurement. Defaults to None.

  • dataset

    (DataSet, default: None ) –

    The DataSet containing the raw data associated with this measurement. Defaults to None.

Methods:

  • metadata –

    Return measurement metadata as dataclass

  • metadata_json –

    Generate measurement metadata as json.

Attributes:

Source code in src/pypalmsens/_data/measurement.py
84
85
86
87
88
89
90
91
92
93
94
def __init__(
    self, method: MethodTypeCompatible | None = None, dataset: DataSet | None = None
):
    args = []

    if method:
        args.append(method._to_psmethod())
    if dataset:
        args.append(dataset._inner)

    self._inner = PSMeasurement(*args)

blank_curve property

blank_curve: Curve | None

Blank curve.

If the 'Use Blank' curve function was used in PSTrace, a new curve will be added after each measurement containing the result of the measured curve subtracted with the blank curve.

channel property

channel: float

Get the channel that the measurement was measured on.

curves property

curves: list[Curve]

Get all curves in measurement.

Returns:

dataset property

dataset: DataSet

Dataset containing multiple arrays of values.

All values are related by means of their indices. Data arrays in a dataset should always have an equal amount of entries.

device property

device: DeviceInfo

Return dataclass with measurement device information.

eis_data property

eis_data: list[EISData]

EIS data in measurement.

eis_fit property

eis_fit: list[FitResult]

Get all EIS fits from measurement

Returns:

  • eis_fits ( list[EISFitResults] ) –

    Return list of EIS fits

has_blank_subtracted_curves property

has_blank_subtracted_curves: bool

Return True if the curve collection contains a blank subtracted curve.

has_eis_data property

has_eis_data: bool

Return True if EIS data are is available.

method property

Method related with this Measurement.

The information from the Method is used when saving Curves.

n_curves property

n_curves: int

Number of curves that are part of the Measurement class.

n_eis_data property

n_eis_data: int

Number of EISdata curves (channels) that are part of the Measurement class.

ocp_value property

ocp_value: float

First OCP Value from either curves or EISData.

peaks property

peaks: list[Peak]

Get peaks from all curves.

Returns:

  • peaks ( list[Peak] ) –

    List of peaks

timestamp property

timestamp: datetime

Date and time of the start of this measurement.

Returns a timezone-naive datetime in local time, matching the format used by the SDK (e.g. 2017-07-12 14:28:58).

title property

title: str

Title for the measurement.

metadata

metadata() -> MeasurementMetadata

Return measurement metadata as dataclass

Source code in src/pypalmsens/_data/measurement.py
128
129
130
131
132
133
134
135
def metadata(self) -> MeasurementMetadata:
    """Return measurement metadata as dataclass"""
    return MeasurementMetadata(
        device=self.device,
        timestamp=self.timestamp,
        title=self.title,
        method=self.method,  # type:ignore
    )

metadata_json

metadata_json() -> bytes

Generate measurement metadata as json.

Source code in src/pypalmsens/_data/measurement.py
137
138
139
def metadata_json(self) -> bytes:
    """Generate measurement metadata as json."""
    return TypeAdapter(MeasurementMetadata).dump_json(self.metadata())

Peak

Peak()

Contains the peak data of one peak in a curve.

Attributes:

Source code in src/pypalmsens/_data/peak.py
22
23
24
25
def __init__(self):
    raise TypeError(
        'Peak cannot be instantiated directly. Obtain instances through the Curve methods.'
    )

analyte_name property writable

analyte_name: str

Name of analyte.

area property

area: float

Area of the peak.

curve property

curve: Curve

Parent curve associated with Peak.

index property

index: int

Location of the peak as index number of the curve.

label property

label: str

Formatted label for the peak value.

left_index property

left_index: int

Left side of the peaks baseline as index number of the curve.

left_x property

left_x: float

X of the left side of the peak baseline.

left_y property

left_y: float

Y of the left side of the peak baseline.

maximum_of_derivative_neg property

maximum_of_derivative_neg: float

Maximum derivative of the negative slope of the peak.

maximum_of_derivative_pos property

maximum_of_derivative_pos: float

Maximum derivative of the positive slope of the peak.

maximum_of_derivative_sum property

maximum_of_derivative_sum: float

Sum of the absolute values for both the positive and negative maximum derivative.

notes property

notes: str

User notes stored on this peak.

right_index property

right_index: int

Left side of the peaks baseline as index number of the curve.

right_x property

right_x: float

X of the right side of the peak baseline.

right_y property

right_y: float

Returns the Y of the right side of the peak baseline.

type property

type: str

Used to determine if a peak is auto found.

value property

value: float

Value of the peak in units of the curve. This is the value of the peak height relative to the baseline of the peak.

width property

width: float

Full width at half-height of the peak.

x property

x: float

X value of the peak.

y property

y: float

Y value of the peak.

y_offset property

y_offset: float

Offset of Y.

PotentialArray

PotentialArray(values: Iterable[float], *, name: str | None = None)

Array of potential values in V.

Parameters:

  • values

    (Iterable[float]) –

    Values to store in the array. Any iterable (list, tuple, generator, etc.) of floats is accepted.

  • name

    (str, default: None ) –

    Name of the array. Defaults to the value of array_type when not given. The name is used in __repr__ and for identification.

Methods:

  • copy –

    Return a copy of the array.

  • max –

    Return max value.

  • min –

    Return min value.

  • normalize –

    Normalize values in array to the 0 - 1 range.

  • potential –

    Return list of potential values in V.

  • potential_in_range –

    Return list of raw potential values expressed in the active potential range.

  • potential_range –

    Return potential range as list of strings.

  • potential_reading –

    Return as list of potential reading objects.

  • reading_status –

    Return reading status as list of strings.

  • savitsky_golay –

    Smooth the array using a Savitsky-Golay filter with the window size.

  • timing_status –

    Return timing status as list of strings.

  • to_dataframe –

    Return array as pandas DataFrome.

  • to_dict –

    Return array as key/value mapping.

  • to_list –

    Export data array to list.

  • to_numpy –

    Export data array to numpy.

  • update –

    Update all values in-place.

Attributes:

Source code in src/pypalmsens/_data/data_array.py
466
467
468
469
470
471
472
def __init__(
    self,
    values: Iterable[float],
    *,
    name: str | None = None,
):
    super().__init__(values, array_type='Potential', name=name)

is_derived property

is_derived: bool

Return True for derived data arrays.

name property

name: str

Name of the array.

ocp_value property

ocp_value: float

OCP Value.

quantity property

quantity: str

Quantity for array.

type property

Array type as str.

unit property

unit: str

Unit for array.

copy

copy() -> DataArray

Return a copy of the array.

Source code in src/pypalmsens/_data/data_array.py
256
257
258
def copy(self) -> DataArray:
    """Return a copy of the array."""
    return DataArray._wrap(self._inner.Clone())

max

max() -> float

Return max value.

Source code in src/pypalmsens/_data/data_array.py
264
265
266
def max(self) -> float:
    """Return max value."""
    return self._inner.MaxValue

min

min() -> float

Return min value.

Source code in src/pypalmsens/_data/data_array.py
260
261
262
def min(self) -> float:
    """Return min value."""
    return self._inner.MinValue

normalize

normalize() -> DataArray

Normalize values in array to the 0 - 1 range.

Values are scaled with (value - min) / (max - min), where min and max are the min and max values.

The unit of the returned array is inherited from the source array.

Returns:

  • new_array ( DataArray ) –

    Data array with normalized values.

Source code in src/pypalmsens/_data/data_array.py
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
def normalize(self) -> DataArray:
    """Normalize values in array to the 0 - 1 range.

    Values are scaled with ``(value - min) / (max - min)``,
    where min and max are the min and max values.

    The unit of the returned array is inherited from the source array.

    Returns
    -------
    new_array : DataArray
        Data array with normalized values.
    """
    new_values = PSMath.NormalizeArray(self._inner.GetValues(), self.min(), self.max())
    new_array = PSDataArray(
        self._inner.Description, self._inner.Unit, self._inner.ArrayType
    )
    new_array.AddRange(new_values)
    return type(self)._wrap(new_array)

potential

potential() -> list[float]

Return list of potential values in V.

Source code in src/pypalmsens/_data/data_array.py
474
475
476
def potential(self) -> list[float]:
    """Return list of potential values in V."""
    return self.to_list()

potential_in_range

potential_in_range() -> list[float]

Return list of raw potential values expressed in the active potential range.

potential = potential_in_range * PR, e.g. 2.0 * 100mV = 0.2V

Source code in src/pypalmsens/_data/data_array.py
478
479
480
481
482
483
def potential_in_range(self) -> list[float]:
    """Return list of raw potential values expressed in the active potential range.

    `potential` = `potential_in_range` * PR, e.g. 2.0 * 100mV = 0.2V
    """
    return [implementation(val).ValueInRange for val in self._inner]

potential_range

potential_range() -> list[AllowedPotentialRanges]

Return potential range as list of strings.

Source code in src/pypalmsens/_data/data_array.py
489
490
491
def potential_range(self) -> list[AllowedPotentialRanges]:
    """Return potential range as list of strings."""
    return [pr_enum_to_string(implementation(val).Range) for val in self._inner]

potential_reading

potential_reading() -> list[PotentialReading]

Return as list of potential reading objects.

Source code in src/pypalmsens/_data/data_array.py
485
486
487
def potential_reading(self) -> list[PotentialReading]:
    """Return as list of potential reading objects."""
    return [PotentialReading._from_psobject(implementation(val)) for val in self._inner]

reading_status

reading_status() -> list[AllowedReadingStatus]

Return reading status as list of strings.

Source code in src/pypalmsens/_data/data_array.py
493
494
495
def reading_status(self) -> list[AllowedReadingStatus]:
    """Return reading status as list of strings."""
    return [str(implementation(val).ReadingStatus) for val in self._inner]  # type:ignore

savitsky_golay

savitsky_golay(window_size: int = 3) -> DataArray

Smooth the array using a Savitsky-Golay filter with the window size.

(i.e. window size 2 will filter points based on the values of the next/previous 2 points)

Parameters:

  • window_size
    (int, default: 3 ) –

    Size of the window

Returns:

  • new_array ( DataArray ) –

    Smoothed DataArray

Source code in src/pypalmsens/_data/data_array.py
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
def savitsky_golay(self, window_size: int = 3) -> DataArray:
    """Smooth the array using a Savitsky-Golay filter with the window size.

    (i.e. window size 2 will filter points based on the values of the next/previous 2 points)

    Parameters
    ----------
    window_size : int
        Size of the window

    Returns
    -------
    new_array : DataArray
        Smoothed DataArray
    """
    new = self.copy()
    success = new._inner.Smooth(window_size, False)
    if not success:
        raise ValueError('Something went wrong.')
    return new

timing_status

timing_status() -> list[AllowedTimingStatus]

Return timing status as list of strings.

Source code in src/pypalmsens/_data/data_array.py
497
498
499
def timing_status(self) -> list[AllowedTimingStatus]:
    """Return timing status as list of strings."""
    return [str(implementation(val).TimingStatus) for val in self._inner]  # type:ignore

to_dataframe

to_dataframe() -> DataFrame

Return array as pandas DataFrome.

Requires pandas to be installed.

Returns:

  • df ( DataFrame ) –

    Dataframe with potential readings

Source code in src/pypalmsens/_data/data_array.py
524
525
526
527
528
529
530
531
532
533
534
535
536
def to_dataframe(self) -> pd.DataFrame:
    """Return array as pandas DataFrome.

    Requires pandas to be installed.

    Returns
    -------
    df : pd.DataFrame
        Dataframe with potential readings
    """
    import pandas as pd

    return pd.DataFrame(self.to_dict())

to_dict

to_dict() -> dict[str, list[Any]]

Return array as key/value mapping.

The mapping can be used to create a pandas or polars dataframe.

For example:

array = measurement.dataset['Potential']
df = pd.DataFrame(array.to_dict())

Returns:

  • dict[str, list[float | str] –

    Dictionary with potential readings

Source code in src/pypalmsens/_data/data_array.py
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
def to_dict(self) -> dict[str, list[Any]]:
    """Return array as key/value mapping.

    The mapping can be used to create a pandas or polars dataframe.

    For example:

        array = measurement.dataset['Potential']
        df = pd.DataFrame(array.to_dict())

    Returns
    -------
    dict[str, list[float | str]
        Dictionary with potential readings
    """
    return {
        'Potential': self.potential(),
        'PotentialInRange': self.potential_in_range(),
        'CR': self.potential_range(),
        'TimingStatus': self.timing_status(),
        'ReadingStatus': self.reading_status(),
    }

to_list

to_list() -> list[float]

Export data array to list.

Source code in src/pypalmsens/_data/data_array.py
320
321
322
def to_list(self) -> list[float]:
    """Export data array to list."""
    return list(self._inner.GetValues())

to_numpy

to_numpy() -> ndarray

Export data array to numpy.

Source code in src/pypalmsens/_data/data_array.py
316
317
318
def to_numpy(self) -> np.ndarray:
    """Export data array to numpy."""
    return np.array(self._inner.GetValues())

update

update(values: Sequence[float])

Update all values in-place.

Parameters:

Raises:

  • ValueError: –

    If data length differs from current length.

Source code in src/pypalmsens/_data/data_array.py
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
def update(self, values: Sequence[float]):
    """Update all values in-place.

    Parameters
    ----------
    values : Iterable[float]
        Values to store in the array.

    Raises
    ------
    ValueError:
        If `data` length differs from current length.
    """
    if len(values) != len(self._inner):
        raise ValueError(
            f'Replacement data must have same length ({len(self._inner)}), '
            f'got {len(values)}'
        )

    for val, new in zip(self._inner, values):
        val.Value = new

PotentialReading dataclass

PotentialReading(potential_range: AllowedPotentialRanges, potential: float, potential_in_range: float, timing_status: AllowedTimingStatus, reading_status: AllowedReadingStatus)

Potential reading data class.

Attributes:

potential instance-attribute

potential: float

Potential in V.

potential_in_range instance-attribute

potential_in_range: float

Raw potential value expressed in the active potential range.

potential = potential_in_range * PR, e.g. 2.0 * 100mV = 0.2V

potential_range instance-attribute

potential_range: AllowedPotentialRanges

Active potential range (PR) for this data point.

reading_status instance-attribute

reading_status: AllowedReadingStatus

Status of the potential reading.

timing_status instance-attribute

timing_status: AllowedTimingStatus

Status of the potential timing.

Status dataclass

Status(_status: Status, device_state: AllowedDeviceState = 'Unknown')

Device Status class.

Attributes:

aux_input property

aux_input: float

Raw aux input.

aux_input_as_voltage property

aux_input_as_voltage: float

Aux input as V.

corrected_bipot_current property

corrected_bipot_current: float

Corrected bipot current in the current range.

current property

current: float

Current value in µA.

current_reading property

current_reading: CurrentReading

Current reading dataclass.

current_reading_we2 property

current_reading_we2: CurrentReading

Current reading dataclass for WE2.

current_we2 property

current_we2: float

Current WE2 value.

device_state class-attribute instance-attribute

device_state: AllowedDeviceState = 'Unknown'

Device state.

noise property

noise: float

Measured

potential property

potential: float

Potential in V

potential_reading property

potential_reading: PotentialReading

Potential reading dataclass.

pretreatment_phase property

pretreatment_phase: Literal['None', 'Conditioning', 'Depositing', 'Equilibrating']

Pretreatment phase.