Dive profile¶
Dive profile: the geometric plan of a dive.
A DiveProfile is a validated sequence of
DiveSegment — pure input geometry,
deliberately free of model results. It offers three ways of working:
building — fluent methods (
descend_to("40 m"),stay,switch_gas("ean50")…) and explicit segment surgery, governed by aProfileBuilderPolicy;validation & repair — problems are returned as pure-data
ProfileValidationErrordescriptors; canonical repairs live onfix/fix_all;timeline — address the profile by runtime (
pressure_at(23)), and sample it for integration viaiter_samples(the single sampling authority used by models and visualization).
- class diveplan.dive.dive_profile.DiveProfile(builder_policy=ProfileBuilderPolicy.RAISE_BAD_PROFILE)[source]¶
Bases:
objectA dive profile consisting of a sequence of dive segments.
Provides builder methods to construct a profile and validation methods to ensure it is continuous and well-formed.
A profile should be continuous (pressure continuity, plus gas continuity except across explicit gas switches).
A profile should be as simple as possible (no redundant mergeable segments) — not strictly required; enforce with .simplify_profile().
Validation strictness during construction is controlled by builder_policy (see ProfileBuilderPolicy). Use .validate_profile() to check the whole profile after building with validation disabled.
Repairs: errors returned by .validate_profile() are pure descriptors. Apply a single repair with .fix(error), or repair everything with .fix_all().
- Parameters:
builder_policy (
ProfileBuilderPolicy)
- property builder_policy: ProfileBuilderPolicy¶
The active profile builder policy.
- copy(*, override_policy=None)[source]¶
Create a copy of the dive profile.
Segments are immutable value objects, so copying the segment list (a shallow list copy) is sufficient — the segments themselves are shared safely.
- Return type:
- Returns:
A new DiveProfile with a fresh segment list and the same (or overridden) builder policy.
- Parameters:
override_policy (
ProfileBuilderPolicy|None)
- property segments: list[DiveSegment]¶
The list of segments in the profile.
- start_time_of_segment(index)[source]¶
Elapsed runtime at which the segment at index begins.
- Raises:
IndexError – If the index is out of range.
- Parameters:
index (
int)- Return type:
- segment_index_at(t)[source]¶
Index of the segment active at runtime t (minutes or timedelta).
- Raises:
ProfileEmptyError – If the profile has no segments.
ValueError – If t is negative or beyond the total runtime.
- Parameters:
- Return type:
- segment_at(t)[source]¶
The segment active at runtime t (minutes or timedelta).
- Parameters:
- Return type:
- pressure_at(t)[source]¶
Ambient pressure at runtime t (minutes or timedelta), interpolated linearly within the active segment.
- iter_samples(interval)[source]¶
Yield integration steps over the whole profile timeline.
The single sampling authority for model integration and visualization: steps never cross a segment boundary (the last step of each segment is shortened as needed, so boundaries are hit exactly — checkpoints depend on this), zero-duration gas-switch segments yield no step, and each step’s dt sums exactly to the total runtime.
- Parameters:
interval (
timedelta|float) – Sample step — minutes as a number, or a timedelta.- Raises:
ValueError – If the interval is not strictly positive.
- Return type:
- add_segment(segment)[source]¶
Append a segment to the profile.
- Raises:
ProfileValidationError – Under RAISE policy, if the new segment is not continuous with the current last segment.
- Parameters:
segment (
DiveSegment)- Return type:
- add_segments(segments)[source]¶
Append multiple segments to the profile (each via add_segment).
- Parameters:
segments (
list[DiveSegment])- Return type:
- remove_segment_at_index(index)[source]¶
Remove a segment at a specific index.
- Raises:
IndexError – If the index is out of range.
ProfileValidationError – Under RAISE policy, if removing an interior segment would break continuity at the resulting seam.
- Parameters:
index (
int)- Return type:
- remove_segment_at_indices(indices)[source]¶
Remove multiple segments at specific indices.
- Parameters:
- Return type:
- remove_segment(segment)[source]¶
Remove a segment by value.
- Parameters:
segment (
DiveSegment)- Return type:
- remove_segments(segments)[source]¶
Remove multiple segments by value.
- Parameters:
segments (
list[DiveSegment])- Return type:
- insert_segment_at_index(index, segment)[source]¶
Insert a segment at a specific index.
- Raises:
ProfileValidationError – Under RAISE policy, if the insertion would create a discontinuous seam.
- Parameters:
index (
int)segment (
DiveSegment)
- Return type:
- insert_segments_at_index(index, segments)[source]¶
Insert multiple segments at a specific index, in order.
- Parameters:
index (
int)segments (
list[DiveSegment])
- Return type:
- replace_segment_at_index(index, segment)[source]¶
Replace a segment at a specific index.
- Raises:
IndexError – If the index is out of range.
ProfileValidationError – Under RAISE policy, if the replacement breaks continuity at either adjacent seam.
- Parameters:
index (
int)segment (
DiveSegment)
- Return type:
- get_segment(index)[source]¶
Retrieve a segment by its index.
- Raises:
IndexError – If the index is out of bounds.
- Parameters:
index (
int)- Return type:
- get_segment_index(segment)[source]¶
Find the index of a specific segment.
- Parameters:
segment (
DiveSegment)- Return type:
- descend_to(depth, *, rate=None, gas=None)[source]¶
Append a descent from the current position to depth.
- Parameters:
depth (
Pressure|str|float) – Target as a Pressure, a parseable string (“40 m”, “5 bar”), or a bare number in metres.rate (
float|None) – Descent rate in m/min. Defaults to the configured planning.descent_rate.gas (
Gas|str|None) – Gas for the descent (Gas or name like “ean32”). Defaults to the current gas (air on an empty profile).
- Raises:
ValueError – If depth is not below the current position.
- Return type:
- ascend_to(depth, *, rate=None, gas=None, kind=Ascent.FORCED_ASCENT)[source]¶
Append an ascent from the current position to depth.
- Parameters:
depth (
Pressure|str|float) – Target as a Pressure, a parseable string (“21 m”, “2 bar”), or a bare number in metres.rate (
float|None) – Ascent rate in m/min. Defaults to the configured planning.ascent_rate.gas (
Gas|str|None) – Gas for the ascent (Gas or name). Defaults to the current gas.kind (
Ascent) – Ascent kind. Defaults to SegmentKind.ASCENT (forced ascent).
- Raises:
ValueError – If depth is not above the current position.
- Return type:
- stay(duration, *, gas=None, kind=Constant.BOTTOM)[source]¶
Append a constant-depth segment at the current position.
- Parameters:
duration (
timedelta|float) – Time to stay — minutes as a number, or a timedelta.gas (
Gas|str|None) – Gas for the segment (Gas or name). Defaults to the current gas.kind (
Constant) – Constant kind, e.g. SegmentKind.Constant.STOP for a deco stop. Defaults to SegmentKind.CONSTANT (bottom time).
- Return type:
- switch_gas(gas)[source]¶
Append a gas switch at the current position.
The switch takes the configured gas.gas_switch_minutes (zero = instant switch). Switching to the gas already in use is a no-op.
- Parameters:
- Return type:
- surface()[source]¶
Append an ascent from the current position to the surface at the configured ascent rate (alias for add_end_surface_segment).
- Raises:
ProfileEmptyError – If the profile has no segments.
- Return type:
- property is_valid: bool¶
Whether the profile is continuous and gas-continuous.
Skips simplicity and start/end-surface checks — an in-progress profile is allowed to be non-simple and to not yet return to the surface.
- validate_profile(*, skip_simplicity=False, skip_start_end_segments=True)[source]¶
Validate the whole profile and return all problems found.
- Parameters:
- Return type:
- Returns:
A tuple of validation errors, empty if the profile is valid.
- fix(error)[source]¶
Apply the canonical repair for a single validation error.
Repair strategies are dispatched on the error type. Errors flagged fixable = False (empty / too-short profiles) have no repair and raise.
- Parameters:
error (
ProfileValidationError) – An error returned by .validate_profile().- Return type:
- Returns:
The profile instance (for chaining).
- Raises:
ValueError – If the error type is not auto-fixable.
- fix_all()[source]¶
Repeatedly validate and repair until no fixable error remains.
Fixes are applied one at a time and the profile re-validated each pass, because a single repair shifts segment indices and invalidates the indices captured by later errors.
- Return type:
- Returns:
The profile instance (for chaining).
- static make_transition_segment(segment_a, segment_b)[source]¶
Create a segment bridging a pressure gap between two segments.
The transition travels from the end of segment_a to the start of segment_b at the configured ascent/descent rate, carrying segment_a’s gas. A gas mismatch between the two segments is a separate concern resolved by a gas switch — it does not block a transition.
- Raises:
ValueError – If the segments are already pressure-continuous.
- Parameters:
segment_a (
DiveSegment)segment_b (
DiveSegment)
- Return type:
- static make_gas_switch_segment(segment_a, segment_b)[source]¶
Create a gas switch segment between two pressure-continuous segments.
- Raises:
ValueError – If the segments are already gas continuous, or are not pressure-continuous (a gas switch happens at a single depth).
- Parameters:
segment_a (
DiveSegment)segment_b (
DiveSegment)
- Return type:
- simplify_profile()[source]¶
Merge fully continuous adjacent segments to simplify the profile.
- Return type:
- Returns:
A new simplified DiveProfile instance.
- fix_continuity()[source]¶
Insert transition segments to resolve pressure discontinuities (in place).
- Return type:
- fix_gas_continuity()[source]¶
Insert gas switch segments to resolve gas discontinuities (in place).
- Return type:
- add_start_surface_segment()[source]¶
Ensure the profile starts with a descent from the surface.
- Raises:
ProfileEmptyError – If the profile has no segments.
- Return type:
- add_end_surface_segment()[source]¶
Ensure the profile ends with an ascent to the surface.
- Raises:
ProfileEmptyError – If the profile has no segments.
- Return type:
- add_surface_segments()[source]¶
Ensure the profile both starts and ends at the surface.
- Raises:
ProfileEmptyError – If the profile has no segments.
- Return type:
- classmethod from_dict(data)[source]¶
Reconstruct a DiveProfile from
to_dict()output.Segments are loaded exactly as saved, without re-validating seams — a stored in-progress profile must round-trip even if it is not (yet) continuous. Call .validate_profile() after loading if you need the guarantees of the RAISE policy.
- Raises:
KeyError – If the “segments” field is missing, or an unknown builder policy name is given.
ValueError – If a segment entry is malformed.
- Parameters:
- Return type:
- classmethod from_json(data=None, path=None)[source]¶
Deserialize from a JSON string or file path (see
from_dict()).- Parameters:
- Return type:
- class diveplan.dive.dive_profile.ProfileSample(time, dt, pressure, gas, segment_index)[source]¶
Bases:
NamedTupleOne integration step on the profile’s global timeline.
Represents the half-open interval
(time - dt, time]:pressureis the ambient pressure at the end of the step (rectangle rule, matching BaseDecoModel),gasthe breathing gas throughout it.
- exception diveplan.dive.dive_profile.ProfileValidationError(message, *, segment_index=None, segments=())[source]¶
Bases:
ValueErrorBase descriptor for a dive profile validation problem.
- message¶
Human-readable description of the problem.
- segment_index¶
Index of the first segment involved, if applicable.
- segments¶
The offending segment(s), if applicable.
- fixable¶
Whether DiveProfile.fix() knows how to repair this error.
- exception diveplan.dive.dive_profile.ProfileContinuityError(message, segment_index, segment_a, segment_b)[source]¶
Bases:
ProfileValidationErrorBase for problems at the seam between two adjacent segments.
- Parameters:
message (
str)segment_index (
int)segment_a (
DiveSegment)segment_b (
DiveSegment)
- exception diveplan.dive.dive_profile.ProfileSimplicityError(segment_index, segment_a, segment_b)[source]¶
Bases:
ProfileContinuityErrorAdjacent segments are fully continuous and could be merged. Fixable via merge.
- Parameters:
segment_index (
int)segment_a (
DiveSegment)segment_b (
DiveSegment)
- Return type:
None
- exception diveplan.dive.dive_profile.ProfileStartEndError(first_segment, last_segment)[source]¶
Bases:
ProfileValidationErrorThe profile does not start and end at the surface. Fixable via add_surface_segments().
- Parameters:
first_segment (
DiveSegment)last_segment (
DiveSegment)
- Return type:
None
- exception diveplan.dive.dive_profile.ProfileDepthContinuityError(segment_index, segment_a, segment_b)[source]¶
Bases:
ProfileContinuityErrorThe end pressure of one segment does not match the start of the next. Fixable via a transition segment.
- Parameters:
segment_index (
int)segment_a (
DiveSegment)segment_b (
DiveSegment)
- Return type:
None
- exception diveplan.dive.dive_profile.ProfileGasContinuityError(segment_index, segment_a, segment_b)[source]¶
Bases:
ProfileContinuityErrorAdjacent segments use different gases without a gas switch. Fixable via a gas switch segment.
- Parameters:
segment_index (
int)segment_a (
DiveSegment)segment_b (
DiveSegment)
- Return type:
None
- exception diveplan.dive.dive_profile.ProfileEmptyError[source]¶
Bases:
ProfileValidationErrorThe profile has no segments. Not auto-fixable.
- Return type:
None
- exception diveplan.dive.dive_profile.ProfileTooShortError(segment_count)[source]¶
Bases:
ProfileValidationErrorThe profile has fewer than 2 segments (surface → dive → surface). Not auto-fixable.
- Parameters:
segment_count (
int)- Return type:
None
- class diveplan.dive.dive_profile.ProfileBuilderPolicy(*values)[source]¶
Bases:
EnumPolicies for handling validation during dive profile construction.
- RAISE_BAD_PROFILE: Each mutating builder call validates only the seam(s)
it touches (O(1)) and raises the specific ProfileValidationError on the first problem. Start/end-surface and simplicity are not enforced here — an in-progress profile is allowed to not yet return to the surface.
- ALLOW_BAD_PROFILE: No validation during construction. Call .validate_profile()
and .fix()/.fix_all() before handing the profile to the planner.
- AUTOFIX_BAD_PROFILE: After each mutation, transitions and gas switches are
inserted automatically. Convenient, but can produce unexpected geometry.