Skip to content

Steps tendency#176

Open
DaanVanVugt wants to merge 5 commits into
iterorganization:developfrom
DaanVanVugt:steps-tendency
Open

Steps tendency#176
DaanVanVugt wants to merge 5 commits into
iterorganization:developfrom
DaanVanVugt:steps-tendency

Conversation

@DaanVanVugt

Copy link
Copy Markdown
Contributor

Includes a commit from #175

Comment thread waveform_editor/tendencies/steps.py
Comment thread waveform_editor/tendencies/steps.py Outdated
- Rename is_string -> is_categorical so booleans are treated like strings
  (held as a zero-order-hold step rather than coerced to float and interpolated)
- Reject mixing categorical (string/boolean) and numeric values within a single
  waveform, since the gaps between them cannot be interpolated
- Document the constant tendency value types (float/int/categorical) in the docs
np.full preserved int dtype for integer constants, so get_value() (the
time=None path) returned an int64 array while the explicit-time path
upcast to float. Force float for numeric values; categorical values
(str/bool) keep their native dtype.
A piecewise-constant tendency that holds each value from its breakpoint until the
next, supporting non-numeric (string/boolean) values. Registered as 'steps'.

- start is inferred from the first breakpoint; an explicit end/duration may be
  given so the final value is held for a real duration (defaults to the last time)
- shared time/value validation and start/end resolution are factored out of
  PiecewiseLinearTendency via overridable _coerce_value / _resolve_time_bounds
  hooks, so the steps tendency only overrides what genuinely differs
from waveform_editor.tendencies.piecewise import PiecewiseLinearTendency


class StepsTendency(PiecewiseLinearTendency):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The steps tendency renders as if it is a piecewise tendency instead a step function.

Image

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the pointdraw tool doesn't work properly for step tendencies. Could you have a look at that or disable the pointdraw functionality?

Comment on lines 155 to +158
if eval_derivatives:
values[mask] = slope
values[mask] = (
tendency.start_value - prev_tendency.end_value
) / (tendency.start - prev_tendency.end)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't this break for categorical values?

Comment on lines +22 to +27
@property
def is_categorical(self):
"""Whether this constant holds a non-numeric (categorical) value, e.g. a
string or boolean, that is held as a step rather than interpolated."""
value = self.value
return isinstance(value, bool) or not isinstance(value, (int, float))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- {type: constant, value: ohmic, duration: 2}
- {type: smooth, duration: 2}
- {type: constant, value: nbi, duration: 2}

When I try to create the waveform above, it will raise a ValueError in the Scipy interpolation. Can we instead catch at an earlier point that categorical tendencies may not be mixed with non-categorical tendencies?

File "/home/sebbe/projects/iter_python/Waveform-Editor/venv/lib/python3.13/site-packages/scipy/interpolate/_cubic.py", line 792, in init
x, dx, y, axis, _ = prepare_input(x, y, axis, xp=np_compat)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/sebbe/projects/iter_python/Waveform-Editor/venv/lib/python3.13/site-packages/scipy/interpolate/_cubic.py", line 45, in prepare_input
y = xp.astype(y, dtype, copy=False)
File "/home/sebbe/projects/iter_python/Waveform-Editor/venv/lib/python3.13/site-packages/scipy/_lib/array_api_compat/numpy/aliases.py", line 106, in astype
return x.astype(dtype=dtype, copy=copy)
~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: could not convert string to float: np.str
('ohmic')

Comment on lines +41 to +47
if end is None and kwargs.get("user_duration") is None:
kwargs["user_end"] = time[-1]
elif isinstance(end, (int, float)) and end < time[-1]:
self.pre_check_annotations.add(
line_number,
"The `end` of a steps tendency must not precede the last time.\n",
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't you check a minimum duration as well? e.g. this seems to be allowed but this should raise an error:

- {type: steps, value: [1, 3, 5], time: [1, 2, 3], duration: 1}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants