Migration notes for v0.3.0
The changes below describe v0.3.0 and differ from the published v0.2.0 package. Review these changes before comparing results with v0.2.0.
The “Earlier behavior (v0.2.0)” column describes the published package; “v0.3.0 behavior” describes the current release.
| Area | Earlier behavior (v0.2.0) | v0.3.0 behavior and action |
|---|---|---|
| Frequency flag | event_bool defaulted to true. |
The optional trailing boolean in a count or between frequency form now defaults to false, so overlapping qualifying windows are unioned. Set it to true to suppress later anchors within a qualifying fixed-length span. |
| Frequency windows | Trailing windows ended at each evaluated timestep. | Candidate windows extend forward from eligible source timesteps, truncate at record end, and produce retrospective classifications. Un-nested N is measured in input timesteps, not years. |
| Frequency meaning | Frequency counts could be confused with counts of component events. | The frequency condition counts qualifying timesteps, not component events. A condition that accepts zero can start at every timestep; other conditions start only at qualifying timesteps. |
| Configuration ordering | Compact characteristic keys were accepted without warning; component order/verbose settings could be used in older configurations. |
Compact form emits a portability UserWarning. Prefer ordered [[components.<name>.characteristics]] tables. Unsupported order and verbose options are errors, not ignored settings. |
| Failure patterns | A false success-pattern setting did not consistently complement the combined failure condition. | success_pattern = false reports the logical complement of the combined failure condition (non-failure). Unknown outcomes remain unknown where the logic cannot determine a result. |
| Timing | Timing could be interpreted relative to water-year day. | Timing thresholds use calendar day-of-year, including for non-January water-year starts. The existing convention maps February 28 and 29 to the same timing position. |
| Annual calculations | A day-of-water-year reset could make an incomplete trailing year appear complete. | Recompute and review affected historical annual results. |
| Unknown outcomes | Unavailable moving-average and rate calculations could become binary comparisons; uncertain duration/frequency inputs could be treated as non-qualifying. | Unavailable calculations and uncertain duration/frequency verdicts now remain unknown when evidence cannot settle them. Missing input values remain rejected. Review affected characteristic and component outcomes. |
| Annual probability denominator | Annual fractions could use only known qualifying trials. | Intra-annual probability now assesses all observed timesteps in each complete water year. Unknowns leave possible fractions; the verdict is known only when every possible fraction agrees. This differs deliberately from descriptive summaries, which exclude unknowns. Recompute nested-frequency results. |
| Daily leap day | Daily completeness required every date in the Gregorian water year. | An otherwise complete daily water year may omit February 29; other missing days remain invalid. A missing real February 29 is indistinguishable from deliberate synthetic omission and is accepted. Exposure denominator is 366 only when that year's recorded rows contain February 29, otherwise 365, including partial years that do not reach it. |
| Result dataframe | Results could carry all input data columns and use a generic dv name. |
Each result contains only the evaluated data column under its original name, then DOWY, characteristic outputs, and the component output. Datetime indexes are named time; other indexes are preserved. |
| Statistics | Historical frequency arrays and derived statistics reflect the earlier window and completeness rules. | Recompute and review historical comparisons. return_period has been removed; use portion or percentage for outcome summaries. |
| Response-surface coverage | Every defined summary could appear regardless of known-outcome coverage. | Plots now require 90% known-outcome coverage by default. Set [output.plot].minimum_coverage or --minimum-coverage to a finite fraction from 0 to 1. Exactly-at-cutoff scenarios remain eligible; all-unknown summaries remain undefined even at zero cutoff. |
| Response-surface colors | Failure-pattern plots reversed the default color map. | Default coloring now uses red for lower final component-outcome fractions for both pattern types. Explicit color maps remain unchanged; colors describe configured outcomes, not ecological benefit. |
For the complete explanation of unknown representations, denominator changes, leap-day assumptions, and worked examples, see unknown outcomes. Keep it beside the output, data preparation, and plotting guidance when updating analysis instructions.
For frequency evaluation rules, worked examples, and Python API details, see the frequency reference and the pattern-correctness decision record.
Summary denominator and removed mode
In v0.3.0, unknown outcomes are excluded from summary denominators.
For outcomes [1, 0, unknown, unknown], the portion is 0.5, not 0.25.
Each characteristic and component column uses its own known outcomes. A
group with known outcomes but no successes has portion 0; an all-unknown
group has no defined summary. Whole-record summaries combine successes and
known counts across the record, not an unweighted average of water-year
portions. Recompute historical summaries before comparing results.
return_period is rejected in [output.metric].mode; replace it with
portion or percentage. Neither mode estimates physical event likelihood
or timing. Do not treat a reciprocal portion as a measure of event spacing;
portions do not assert independent events. No compatibility alias is provided.
Event-count bounds and exposure in v0.3.0
Unknown final outcomes no longer count as definite separators between
component events. Result.event_count() and Result.event_rate() now raise
an error when final outcomes allow multiple answers; use
event_count_bounds() or event_rate_bounds() to inspect named lower and
upper bounds. Water-year-specific bounds are available through
event_count_bounds_by_water_year() and
event_rate_bounds_by_water_year(). Bounds use final outcomes independently,
so they may include event counts impossible under the source-characteristic
dependencies.
Event rates now divide whole-record event counts by observed exposure, including partial water years, rather than only complete water years. For example, 18 monthly observations provide 1.5 water years of exposure. Annual event counts are attributed to the water year containing each run's first successful observation. Rates require supported daily or monthly timestamps; unsupported cadence raises an error instead of falling back to complete-year exposure. Review historical event-rate comparisons after upgrading.
Coverage-aware response surfaces in v0.3.0
Plots now require 90% known-outcome coverage by default. Set
[output.plot].minimum_coverage or pass --minimum-coverage as a finite
fraction from 0 through 1. Exactly-at-cutoff scenarios remain eligible;
all-unknown summaries remain undefined even at zero cutoff. Summary matrices
are unchanged. Companion coverage CSVs explain each scenario's eligibility.
Failure-pattern plots no longer reverse the default color map. Red represents lower final component-outcome fractions for both pattern types. Explicit color maps remain unchanged; colors describe configured outcomes, not ecological benefit.
Plots use whole-record component summaries but omit scenarios below the
configured coverage cutoff. A companion coverage CSV records each scenario's
coordinates, raw summary, known/total counts, coverage, eligibility, and
exclusion reason. Lower the cutoff only when a less-complete surface is
appropriate for the analysis. fillin = true is rejected when scenarios are
withheld, because the renderer cannot preserve those protected gaps. Recheck
historical plots after upgrading.
Unknown annual frequency in v0.3.0
Nested annual conditions now retain unknown preceding outcomes instead of
treating them as failures. An annual fraction uses all observed timesteps in
a complete water year: one success, one failure, and ten unknown monthly
trials permit fractions from 1/12 through 11/12. The >= 0.5 verdict is
unknown, not a known-only fraction of 1/2.
Intra-annual count diagnostics reduce to an annual success if any timestep is definitely successful, an annual failure if every timestep is definitely zero, and otherwise an unknown. Interannual windows retain these unknown annual trials and uncertain anchors, including exclusive scheduling. Partial years remain unknown and are excluded from interannual counting. Recompute affected nested-frequency results; see the worked annual examples.
For direct Python calls, water_year_probability_ratio returns NaN for a
complete year containing any unknown trials, because there is no unique scalar
fraction. Nested condition evaluation still returns a known verdict when all
attainable fractions agree. Annual condition denominators remain distinct from these known-outcome
summary denominators.
Ordered characteristic tables in v0.3.0
In v0.3.0, ordered characteristic tables use the literal TOML key
parameters instead of the metrics key accepted by v0.2.0:
[[components.pulse.characteristics]]
type = "magnitude"
metrics = [">", 1.0]
becomes:
[[components.pulse.characteristics]]
type = "magnitude"
parameters = [">", 1.0]
An ordered table containing metrics is rejected, even if it also contains
parameters. Compact characteristic-key syntax and [output.metric] are unchanged.
This changes configuration syntax only: characteristic order and evaluation
behavior remain the same.
Frequency-window API names in v0.3.0
v0.3.0 changes names used by direct Python calls from v0.2.0. TOML files do not need edits: the optional boolean stays in the same position in each frequency list, and evaluation results do not change.
frequency = [">=", 1, 5, true]
Replace the keyword argument exclusive_event_window with
exclusive_windows in frequency_fx,
nested_frequency_intra_annual_fx, nested_frequency_interannual_fx, and
water_year_probability_ratio. Update fields on CharacteristicSpec:
| Before | After |
|---|---|
frequency_fx(..., exclusive_event_window=True) |
frequency_fx(..., exclusive_windows=True) |
spec.exclusive_event_window |
spec.exclusive_windows |
spec.nested_exclusive_event_window |
spec.interannual_exclusive_windows |
from hydropattern.patterns import mark_eventsmark_events(raw, exclusive_event_window=True) |
from hydropattern.patterns import mark_windowsmark_windows(raw, exclusive_windows=True) |
No compatibility aliases are provided. Evaluation results do not change.
Nested-frequency specification names in v0.3.0
Direct Python users upgrading from v0.2.0 must update code that reads or
constructs nested-frequency specifications. Shared fields such as operator, values, and
exclusive_windows remain unchanged. Names specific to the interannual pattern
now use interannual_; the flag identifying that a specification has this
pattern is has_interannual_pattern. The generic characteristic marker is
is_terminal.
| Before | After |
|---|---|
spec.is_nested |
spec.has_interannual_pattern |
spec.nested_operator |
spec.interannual_operator |
spec.nested_values |
spec.interannual_values |
spec.nested_big_n |
spec.interannual_big_n |
Characteristic(..., is_nested=True) |
Characteristic(..., is_terminal=True) |
characteristic.is_nested |
characteristic.is_terminal |
There are no compatibility aliases. TOML syntax, frequency evaluation, and generated result-column names are unchanged.