User API
This is an example function:
Public package exports for nanodent.
- class nanodent.Experiment(timestamp: datetime.datetime, test: nanodent.models.SignalTable, stem: str = '', paths: nanodent.models.ExperimentPaths | None = None, source_path: pathlib.Path | None = None, source_format: str | None = None, metadata: dict[str, str]=<factory>, metadata_entries: tuple[nanodent.models.MetadataEntry, ...]=(), approach: nanodent.models.SignalTable | None = None, drift: nanodent.models.SignalTable | None = None, extra_sections: collections.abc.Mapping[str, nanodent.models.SignalTable]=<factory>, temperature_c: float | None = None, humidity_percent: float | None = None, segment_definitions: tuple[nanodent.models.SegmentDefinition, ...]=(), parsed_tip_area_function: nanodent.models.TipAreaFunction | None = None, tip_area_function: nanodent.models.TipAreaFunction | None = None, enabled: bool = True, disabled_reason: str | None = None, onset: 'OnsetDetectionResult | None' = None, force_peaks: 'ForcePeakDetectionResult | None' = None, unloading: 'UnloadingDetectionResult | None' = None, oliver_pharr: 'OliverPharrExperimentResult | None' = None, hertzian: 'HertzianExperimentResult | None' = None)
- classmethod from_measurements(*, stem: str, timestamp: datetime, time: Any, displacement: Any, force: Any, time_unit: str = 's', displacement_unit: str = 'nm', force_unit: str = 'uN', raw_columns: tuple[str, str, str] | None = None, source_path: str | Path | None = None, source_format: str | None = None, metadata: Mapping[str, str] | None = None, metadata_entries: tuple[MetadataEntry, ...] = (), approach: SignalTable | None = None, drift: SignalTable | None = None, extra_sections: Mapping[str, SignalTable] | None = None, temperature_c: float | None = None, humidity_percent: float | None = None, segment_definitions: tuple[SegmentDefinition, ...] = (), enabled: bool = True, disabled_reason: str | None = None) Experiment
Create one experiment from array-like measurement signals.
- classmethod from_tabular_data(table: Mapping[str, Any] | Any, *, stem: str, timestamp: datetime, time_column: str, displacement_column: str, force_column: str, time_unit: str = 's', displacement_unit: str = 'nm', force_unit: str = 'uN', source_path: str | Path | None = None, source_format: str | None = None, metadata: Mapping[str, str] | None = None, metadata_entries: tuple[MetadataEntry, ...] = (), approach: SignalTable | None = None, drift: SignalTable | None = None, extra_sections: Mapping[str, SignalTable] | None = None, temperature_c: float | None = None, humidity_percent: float | None = None, segment_definitions: tuple[SegmentDefinition, ...] = (), enabled: bool = True, disabled_reason: str | None = None) Experiment
Create one experiment from a mapping- or DataFrame-like table.
- section(name: str) SignalTable
Return a named signal section.
- Args:
name: Section name, typically approach, drift, or test.
- Returns:
Requested signal table.
- Raises:
KeyError: If the section does not exist on the experiment.
- summary() dict[str, Any]
Return a compact summary useful for quick inspection.
- Returns:
Dictionary containing key metadata and section sizes.
- property trace: SignalTable
Return the primary canonical measurement trace.
- unloading_curve(*, x: str = 'disp_nm', y: str = 'force_uN') tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]
Return the unloading branch as aligned NumPy arrays.
- Args:
x: Trace column used for the x-values. y: Trace column used for the y-values.
- Returns:
Pair of NumPy arrays sliced from the detected unloading start through the end of the test trace.
- Raises:
- ValueError: If no successful unloading result is attached or the
stored unloading start index is invalid.
KeyError: If either requested column is absent from the test trace.
- with_enabled(enabled: bool, *, reason: str | None = None) Experiment
Return a copy of the experiment with updated enabled state.
- Args:
- enabled: Whether the experiment should participate in default
grouping, plotting, and analysis flows.
- reason: Optional short reason recorded when disabling an
experiment. Enabled experiments always clear the reason.
- Returns:
New experiment instance with updated enabled metadata.
- with_force_peaks(result: ForcePeakDetectionResult | None) Experiment
Return a copy of the experiment with updated force peaks.
- with_hertzian(result: HertzianExperimentResult | None) Experiment
Return a copy of the experiment with updated Hertzian results.
- with_oliver_pharr(result: OliverPharrExperimentResult | None) Experiment
Return a copy of the experiment with updated analysis results.
- with_onset(result: OnsetDetectionResult | None) Experiment
Return a copy of the experiment with updated onset results.
- with_tip_area_function(tip_area_function: TipAreaFunction | None) Experiment
Return a copy of the experiment with updated tip-area override.
- with_unloading(result: UnloadingDetectionResult | None) Experiment
Return a copy of the experiment with updated unloading data.
- class nanodent.ExperimentGroup(stems: tuple[str, ...], index: int = 0)
A deterministic group of temporally related experiments.
- resolve(study: Study, *, include_disabled: bool = False) tuple[Experiment, ...]
Resolve the group’s stems against the current study.
- class nanodent.ExperimentPaths(stem: str, hld_path: Path, tdm_path: Path | None = None, tdx_path: Path | None = None)
Paths belonging to one experiment stem.
- class nanodent.ForcePeakDetectionResult(success: bool, reason: str | None = None, peaks: tuple[ForcePeakPosition, ...] = (), peak_count: int = 0, prominence: float = 100.0, threshold: float | None = 1.0)
Result of raw-force peak detection on one experiment.
- summary() dict[str, Any]
Return a notebook-friendly summary row.
- class nanodent.ForcePeakPosition(index: int, time_s: float | None, disp_nm: float | None, force_uN: float, prominence_uN: float | None)
One detected force peak with aligned experiment coordinates.
- summary() dict[str, Any]
Return a notebook-friendly summary row.
- class nanodent.HertzianExperimentResult(stem: str = '', success: bool = False, reason: str | None = None, fit_start_index: int = 0, fit_end_index: int = 0, fit_point_count: int = 0, used_smoothing: bool = False, smoothing: ~collections.abc.Mapping[str, ~typing.Any] | None = None, initial_onset_disp_nm: float | None = None, force_correction_uN: float | None = None, amplitude_uN_per_nm_3_2: float | None = None, h_onset_nm: float | None = None, reduced_modulus_uN_per_nm2: float | None = None, radius_nm: float | None = None, pop_in_load_uN: float | None = None, tau_max_uN_per_nm2: float | None = None, r_squared: float | None = None, x_fit: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] = <factory>, y_fit: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] = <factory>)
Result of one Hertzian onloading fit.
- summary() dict[str, Any]
Return a notebook-friendly summary row.
- class nanodent.MetadataEntry(key: str, value: str)
A single raw metadata line from an input file.
- class nanodent.OliverPharrExperimentResult(stem: str = '', success: bool = False, reason: str | None = None, fit_model: str = 'linear_fraction', evaluation_index: int = 0, evaluation_force_uN: float | None = None, evaluation_disp_nm: float | None = None, unloading_start_index: int = 0, unloading_end_index: int = 0, fit_point_count: int = 0, used_smoothing: bool = False, smoothing: ~collections.abc.Mapping[str, ~typing.Any] | None = None, disp_correction_nm: float | None = None, force_correction_uN: float | None = None, stiffness_uN_per_nm: float | None = None, r_squared: float | None = None, linear_slope_uN_per_nm: float | None = None, linear_intercept_uN: float | None = None, linear_depth_intercept_nm: float | None = None, power_law_k: float | None = None, power_law_m: float | None = None, power_law_hf_nm: float | None = None, hardness_success: bool = False, hardness_reason: str | None = None, epsilon: float | None = None, onset_disp_nm: float | None = None, hmax_nm: float | None = None, contact_depth_nm: float | None = None, contact_area_nm2: float | None = None, hardness_uN_per_nm2: float | None = None, reduced_modulus_uN_per_nm2: float | None = None, tip_area_function: ~nanodent.models.TipAreaFunction | None = None, x_fit: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] = <factory>, y_fit: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] = <factory>)
Result of one Oliver-Pharr unloading fit.
- summary() dict[str, Any]
Return a notebook-friendly summary row.
- class nanodent.OnsetDetectionResult(success: bool, mode: str = 'relative', reason: str | None = None, onset_index: int | None = None, onset_time_s: float | None = None, onset_disp_nm: float | None = None, baseline_points: int = 0, baseline_start_index: int | None = None, baseline_end_index: int | None = None, baseline_mean_uN: float | None = None, baseline_offset_uN: float | None = None, baseline_std_uN: float | None = None, threshold_uN: float | None = None, absolute_threshold_uN: float | None = None, k: float = 4.0, consecutive: int = 1, used_smoothing: bool = False, smoothing: Mapping[str, Any] | None = None)
Result of sustained-threshold onset detection on one force signal.
- summary() dict[str, Any]
Return a notebook-friendly summary row.
- class nanodent.QualityCheckResult(enabled: bool, reason: str | None = None, onset_fraction: float | None = None, onset_disp_nm: float | None = None, rise_width_fraction: float | None = None)
Result of a heuristic experiment-quality check.
- class nanodent.SegmentDefinition(number: int, segment_type: str, duration_s: float, begin_time_s: float, end_time_s: float, begin_demand: float | None, end_demand: float | None, points: int)
Metadata describing one acquisition segment.
- class nanodent.SignalTable(columns: dict[str, ndarray[tuple[Any, ...], dtype[float64]]], point_count: int, raw_columns: tuple[str, ...])
Tabular numeric section data with normalized column names.
- property column_names: tuple[str, ...]
Normalized column names in source order.
- to_dict() dict[str, ndarray[tuple[Any, ...], dtype[float64]]]
Return a shallow copy of the column mapping.
- Returns:
Dictionary mapping normalized column names to float64 arrays.
- class nanodent.Study(experiments: tuple[Experiment, ...], tip_area_function: TipAreaFunction | None = None)
A collection of experiments sorted by acquisition timestamp.
- analyze_hertzian(*, stems: Iterable[str] | str | None = None, smoothing: Mapping[str, Any] | None = None, fit_num_points: int = 200, peak_prominence: float = 100.0, peak_threshold: float | None = 1.0, include_disabled: bool = False, overwrite: bool = False) Study
Analyze selected experiments with a Hertzian onloading fit.
- analyze_oliver_pharr(*, stems: Iterable[str] | str | None = None, fit_model: str = 'power_law_full', unloading_fraction: float | None = None, smoothing: Mapping[str, Any] | None = None, fit_num_points: int = 200, epsilon: float = 0.75, include_disabled: bool = False, overwrite: bool = False) Study
Analyze selected experiments with one Oliver-Pharr fit model.
- classify_quality(*, min_robust_force_span_uN: float = 200.0, low_quantile: float = 0.4, high_quantile: float = 0.999, max_disp_nm: float = 1000.0, peak_bin_count: int = 48, peak_prominence_fraction: float = 0.05, min_secondary_peak_fraction: float = 0.1, require_two_peaks: bool = False, disp_z_threshold: float = 100.0, force_z_threshold: float = 70.0, bin_count: int = 24, baseline_bin_count: int = 4, onset_force_fraction: float = 0.05, target_force_fraction: float = 0.5, sustained_bins: int = 2, max_rise_width_fraction: float = 0.2) Study
Return a study with experiments flagged by quality heuristics.
- detect_force_peaks(*, stems: Iterable[str] | str | None = None, prominence: float = 100.0, threshold: float | None = 1.0, include_disabled: bool = False, overwrite: bool = False) Study
Detect raw-force peaks on selected experiments.
- detect_onset(*, stems: Iterable[str] | str | None = None, mode: str = 'relative', baseline_points: int = 100, baseline_start_index: int | None = None, baseline_end_index: int | None = None, k: float = 4.0, absolute_threshold_uN: float | None = None, consecutive: int = 5, smoothing: Mapping[str, Any] | None = None, include_disabled: bool = False, overwrite: bool = False) Study
Detect onset on selected experiments using the test force signal.
- detect_unloading(*, stems: Iterable[str] | str | None = None, include_disabled: bool = False, overwrite: bool = False) Study
Detect unloading-start indices on selected experiments.
- disable_experiments(stems: Iterable[str] | str, *, reason: str = 'manual') Study
Return a study with selected experiment stems disabled.
- enable_experiments(stems: Iterable[str] | str) Study
Return a study with selected experiment stems enabled.
- get_experiments(*, stems: Iterable[str] | str | None = None, include_disabled: bool = False) tuple[Experiment, ...]
Return study experiments, optionally filtered by stems.
- group_by_datetime_ranges(ranges: Iterable[tuple[datetime, datetime]], *, include_disabled: bool = False) list[ExperimentGroup]
Create groups from explicit inclusive datetime windows.
- group_by_time_gap(max_gap: timedelta = datetime.timedelta(seconds=1800), *, include_disabled: bool = False) list[ExperimentGroup]
Group experiments by the gap between consecutive timestamps.
- group_scalar_series(metric: str, *, groups: Sequence[ExperimentGroup] | None = None, max_gap: timedelta = datetime.timedelta(seconds=1800), include_disabled: bool = False, drop_missing: bool = True) list[dict[str, Any]]
Return one aggregated scalar row per resolved experiment group.
- load_session(path: str | Path, *, overwrite: bool = False) Study
Apply a previously saved analysis session onto this study.
- regroup(groups: Iterable[Sequence[Experiment | str]], *, include_disabled: bool = False) list[ExperimentGroup]
Create explicit groups from Python-side experiment selections.
- resolve_group(group: ExperimentGroup, *, include_disabled: bool = False) tuple[Experiment, ...]
Resolve a stem-based group against this study.
- save_session(path: str | Path) Path
Persist experiment flags and attached analysis results.
- scalar_series(metric: str, *, stems: Iterable[str] | str | None = None, include_disabled: bool = False, drop_missing: bool = True) list[dict[str, Any]]
Return timestamped scalar rows for one supported metric.
- set_enabled(stems: Iterable[str] | str, *, enabled: bool, reason: str | None = None) Study
Return a study with selected stems manually enabled or disabled.
- with_tip_area_function(tip_area_function: TipAreaFunction | None) Study
Return a copy of the study with a new study-wide tip area.
- class nanodent.TipAreaFunction(c0: float = 0.0, c1: float = 0.0, c2: float = 0.0, c3: float = 0.0, c4: float = 0.0, c5: float = 0.0)
Polynomial-style tip area function for contact-area estimation.
- evaluate(contact_depth_nm: float) float
Return the contact area in nm^2 for one contact depth.
- class nanodent.UnloadingDetectionResult(success: bool, method: str = 'max_force', reason: str | None = None, start_index: int | None = None, start_time_s: float | None = None, start_disp_nm: float | None = None, start_force_uN: float | None = None, end_disp_nm: float | None = None)
Result of unloading-start detection on one experiment curve.
- summary() dict[str, Any]
Return a notebook-friendly summary row.
- nanodent.analyze_hertzian(disp_nm: ArrayLike, force_uN: ArrayLike, *, fit_end_index: int, smoothing: Mapping[str, Any] | None = None, fit_num_points: int = 200, initial_onset_disp_nm: float | None = None, baseline_offset_uN: float | None = None, reduced_modulus_uN_per_nm2: float | None = None, pop_in_load_uN: float | None = None, stem: str = '') HertzianExperimentResult
Fit a Hertzian onloading model up to a force-peak endpoint.
- Args:
disp_nm: Displacement values in acquisition order. force_uN: Force values in acquisition order. fit_end_index: Inclusive local index of the first force peak. smoothing: Optional keyword arguments forwarded to nanodent.savgol. fit_num_points: Number of dense fitted points for plotting. initial_onset_disp_nm: Optional initial guess for the fitted onset. baseline_offset_uN: Optional force baseline offset subtracted before
fitting.
- reduced_modulus_uN_per_nm2: Optional Oliver-Pharr reduced modulus used
to derive the Hertzian radius and maximum shear stress.
- pop_in_load_uN: Optional second force-peak load used to derive maximum
shear stress.
stem: Optional experiment label propagated by higher-level wrappers.
- Returns:
Result object containing fitted Hertzian diagnostics. Invalid or incomplete fit windows are returned as unsuccessful results instead of raising, except for malformed input arguments.
- nanodent.analyze_oliver_pharr(disp_nm: ArrayLike, force_uN: ArrayLike, *, unloading_start_trace_index: int = 0, fit_model: Literal['linear_fraction', 'power_law_full'] = 'power_law_full', unloading_fraction: float | None = None, smoothing: Mapping[str, Any] | None = None, fit_num_points: int = 200, onset_disp_nm: float | None = None, baseline_offset_uN: float | None = None, epsilon: float = 0.75, tip_area_function: TipAreaFunction | None = None, stem: str = '') OliverPharrExperimentResult
Fit one supported Oliver-Pharr model to an unloading branch.
- Args:
- disp_nm: Displacement values from the unloading branch in
acquisition order.
- force_uN: Force values from the unloading branch in acquisition
order.
- unloading_start_trace_index: Absolute trace index of the first
unloading sample. This keeps result indices aligned with the original experiment trace.
- fit_model: Fitting strategy. linear_fraction fits a straight line
to the early unloading branch. power_law_full fits f = k * (h - hf)^m to the full unloading branch.
- unloading_fraction: Fraction of the post-start unloading branch used
for linear_fraction. When omitted, defaults to 0.2.
- smoothing: Optional keyword arguments forwarded to nanodent.savgol.
When provided, the same filter is applied to displacement and force before fitting.
- fit_num_points: Number of points used to evaluate the dense fitted
curve for plotting.
- onset_disp_nm: Optional onset displacement used to compute
onset-corrected hardness diagnostics.
- baseline_offset_uN: Optional force baseline offset subtracted before
evaluation and fitting.
epsilon: Geometry factor used for contact-depth estimation. tip_area_function: Optional tip area function used for contact-area
estimation. When omitted, defaults to 24.5 * hc^2.
stem: Optional experiment label propagated by higher-level wrappers.
- Returns:
Result object containing fitted unloading diagnostics. Invalid or incomplete unloading segments are returned as unsuccessful results instead of raising, except for malformed input arguments.
- nanodent.calculate_hertzian_radius(hertzian_amplitude_uN_per_nm_3_2: float, reduced_modulus_uN_per_nm2: float) float
Return Hertzian tip radius implied by amplitude and reduced modulus.
- nanodent.calculate_tau_max(reduced_modulus_uN_per_nm2: float, hertzian_amplitude_uN_per_nm_3_2: float, pop_in_load_uN: float) float
Return the maximum shear stress from OP, Hertzian, and pop-in values.
- nanodent.classify_flat_force(force_uN: ArrayLike, *, min_robust_force_span_uN: float = 200.0, low_quantile: float = 0.05, high_quantile: float = 0.95) QualityCheckResult
Classify runs whose force signal remains nearly flat throughout.
- Args:
force_uN: Force values from the test section. min_robust_force_span_uN: Minimum acceptable robust force span between
the selected quantiles.
low_quantile: Lower quantile used for the robust force span. high_quantile: Upper quantile used for the robust force span.
- Returns:
Quality classification result. Flat signals are marked with reason flat_force.
- nanodent.classify_gradual_onset(disp_nm: ArrayLike, force_uN: ArrayLike, *, bin_count: int = 24, baseline_bin_count: int = 4, onset_force_fraction: float = 0.05, target_force_fraction: float = 0.5, sustained_bins: int = 2, max_rise_width_fraction: float = 0.2) QualityCheckResult
Classify curves whose onset rises too gradually in displacement.
The heuristic sorts the force-displacement samples by displacement, averages them onto coarse displacement bins, and measures how much displacement the coarse curve needs to rise from an early threshold to a mid-force threshold. Curves whose rise width is too broad are classified as gradual onset.
- Args:
disp_nm: Displacement values from the test section. force_uN: Force values from the test section. bin_count: Number of coarse displacement bins used to suppress
point-to-point loops and noise.
- baseline_bin_count: Number of leftmost bins used to estimate the
initial baseline force level.
onset_force_fraction: Lower force fraction used to define onset. target_force_fraction: Upper force fraction used to define where the
onset rise is considered complete.
- sustained_bins: Number of consecutive bins that must exceed the lower
onset threshold before the onset is accepted.
- max_rise_width_fraction: Maximum allowed relative displacement width
between the lower and upper force thresholds.
- Returns:
Quality classification result with optional onset diagnostics.
- nanodent.classify_high_displacement(disp_nm: ArrayLike, *, max_disp_nm: float = 1000.0) QualityCheckResult
Classify runs whose test displacement exceeds a hard limit.
- Args:
disp_nm: Displacement values from the test section. max_disp_nm: Maximum allowed displacement in nanometers.
- Returns:
Quality classification result. Curves that exceed the displacement limit are marked with reason high_disp.
- nanodent.classify_outlier_jumps(disp_nm: ArrayLike, force_uN: ArrayLike, *, disp_z_threshold: float = 100.0, force_z_threshold: float = 70.0) QualityCheckResult
Classify experiments with isolated local spikes in displacement or force.
- Args:
disp_nm: Displacement values from the test section. force_uN: Force values from the test section. disp_z_threshold: Robust z-score threshold for isolated displacement
spikes relative to neighboring samples.
- force_z_threshold: Robust z-score threshold for isolated force spikes
relative to neighboring samples.
- Returns:
Quality classification result with reason outlier_disp or outlier_force when an isolated local spike is detected.
- nanodent.classify_peak_balance(disp_nm: ArrayLike, force_uN: ArrayLike, *, peak_bin_count: int = 48, peak_prominence_fraction: float = 0.05, min_secondary_peak_fraction: float = 0.1, require_two_peaks: bool = False) QualityCheckResult
Classify curves whose second resolved peak is too small.
The heuristic sorts the force-displacement samples by displacement, averages them onto coarse displacement bins, smooths the coarse force curve, and compares the two strongest resolved peaks.
If fewer than two prominent peaks are resolved after smoothing, the heuristic abstains by default. Set
require_two_peaks=Trueto disable runs unless two resolved peaks are present.- Args:
disp_nm: Displacement values from the test section. force_uN: Force values from the test section. peak_bin_count: Number of coarse displacement bins used before peak
detection.
- peak_prominence_fraction: Minimum prominence for resolved peaks,
expressed as a fraction of the coarse-force dynamic range.
- min_secondary_peak_fraction: Minimum allowed ratio between the
second-highest and highest resolved peaks.
- require_two_peaks: When true, disable curves that do not resolve at
least two prominent peaks after smoothing.
- Returns:
Quality classification result. Curves with an undersized second peak, or without two resolved peaks when
require_two_peaksis true, are marked with reason weak_second_peak.
- nanodent.classify_quality(disp_nm: ArrayLike, force_uN: ArrayLike, *, min_robust_force_span_uN: float = 200.0, low_quantile: float = 0.4, high_quantile: float = 0.999, max_disp_nm: float = 1000.0, peak_bin_count: int = 48, peak_prominence_fraction: float = 0.05, min_secondary_peak_fraction: float = 0.1, require_two_peaks: bool = False, disp_z_threshold: float = 100.0, force_z_threshold: float = 70.0, bin_count: int = 24, baseline_bin_count: int = 4, onset_force_fraction: float = 0.05, target_force_fraction: float = 0.5, sustained_bins: int = 2, max_rise_width_fraction: float = 0.2) QualityCheckResult
Run the enabled quality heuristics in order and return the first match.
- Args:
disp_nm: Displacement values from the test section. force_uN: Force values from the test section. min_robust_force_span_uN: Minimum acceptable robust force span for the
flat-force check.
low_quantile: Lower quantile used for the robust force span. high_quantile: Upper quantile used for the robust force span. max_disp_nm: Maximum allowed displacement before disabling the
experiment.
- peak_bin_count: Number of coarse displacement bins used for the
peak-balance heuristic.
- peak_prominence_fraction: Minimum prominence used to resolve peaks,
relative to the coarse-force dynamic range.
- min_secondary_peak_fraction: Minimum allowed ratio between the
second-highest and highest resolved peaks.
- require_two_peaks: When true, disable curves that do not resolve at
least two peaks after smoothing.
- disp_z_threshold: Robust z-score threshold for isolated displacement
spikes.
force_z_threshold: Robust z-score threshold for isolated force spikes. bin_count: Number of coarse displacement bins for gradual-onset
detection.
baseline_bin_count: Number of early bins used for baseline force. onset_force_fraction: Lower force fraction used to define onset. target_force_fraction: Upper force fraction used to define where the
onset rise is considered complete.
- sustained_bins: Number of consecutive bins that must exceed the onset
threshold.
- max_rise_width_fraction: Maximum allowed displacement width between the
lower and upper onset thresholds before disabling the experiment.
- Returns:
First disabling classification that matches, otherwise an enabled result.
- nanodent.detect_force_peaks(force_uN: ArrayLike, *, time_s: ArrayLike | None = None, disp_nm: ArrayLike | None = None, prominence: float = 100.0, threshold: float | None = 1.0) ForcePeakDetectionResult
Detect up to two strongest force peaks in a raw force signal.
- Args:
force_uN: Force values in acquisition order. time_s: Optional time values aligned with force_uN. disp_nm: Optional displacement values aligned with force_uN. prominence: Minimum peak prominence passed to find_peaks. threshold: Minimum peak threshold passed to find_peaks.
- Returns:
Result object containing up to two strongest peaks. Signals with no detected peaks return an unsuccessful result instead of raising, except for malformed input arguments.
- nanodent.detect_onset(force_uN: ArrayLike, *, time_s: ArrayLike | None = None, disp_nm: ArrayLike | None = None, mode: Literal['relative', 'absolute'] = 'relative', baseline_points: int = 100, baseline_start_index: int | None = None, baseline_end_index: int | None = None, k: float = 4.0, absolute_threshold_uN: float | None = None, consecutive: int = 5, smoothing: Mapping[str, Any] | None = None) OnsetDetectionResult
Detect the first sustained threshold crossing in one force signal.
- Args:
force_uN: Force values in acquisition order. time_s: Optional time values aligned with force_uN. disp_nm: Optional displacement values aligned with force_uN. mode: Thresholding mode. relative uses baseline mean plus
k * baseline_std; absolute compares directly against absolute_threshold_uN.
- baseline_points: Number of leading samples used to estimate the
baseline statistics. The effective count is clipped to the signal length.
- baseline_start_index: Optional inclusive start index of the baseline
window.
- baseline_end_index: Optional exclusive end index of the baseline
window.
- k: Number of baseline standard deviations above the mean required for
the detection threshold.
absolute_threshold_uN: Absolute threshold used in absolute mode. consecutive: Number of consecutive samples above the threshold needed
to accept an onset.
smoothing: Optional keyword arguments forwarded to nanodent.savgol.
- Returns:
Result object containing the onset index and baseline diagnostics. Signals with no sustained crossing return an unsuccessful result instead of raising, except for malformed input arguments.
- nanodent.detect_unloading(force_uN: ArrayLike, *, time_s: ArrayLike | None = None, disp_nm: ArrayLike | None = None, method: Literal['max_force'] = 'max_force') UnloadingDetectionResult
Detect the start of the unloading branch in one test curve.
- Args:
force_uN: Force values in acquisition order. time_s: Optional time values aligned with force_uN. disp_nm: Optional displacement values aligned with force_uN. method: Detection strategy. max_force uses the global maximum force
sample as unloading start.
- Returns:
Result object containing the unloading-start coordinates. The current default method always succeeds for non-empty, well-formed signals.
- nanodent.load_experiment(path: str | Path) Experiment
Load a single experiment from disk.
- Args:
- path: Path to an experiment .hld file or to a sibling file that
shares the same experiment stem.
- Returns:
Parsed experiment including metadata, numeric sections, and sibling file paths.
- nanodent.load_folder(path: str | Path, *, recursive: bool = False) Study
Load all parseable experiments from a folder.
- Args:
path: Directory containing one or more experiment file triplets. recursive: When True, also scan subdirectories recursively.
- Returns:
Study containing all experiments discovered in the folder, sorted by acquisition timestamp.
- Raises:
NotADirectoryError: If path does not point to a directory.
- nanodent.plot_experiments(*args: Any, **kwargs: Any) Axes
Lazily import the experiment force-displacement plotting helper.
- nanodent.plot_group_timeline(*args: Any, **kwargs: Any) tuple[Figure, Axes]
Lazily import the group timeline plotting helper when needed.
- nanodent.save_experiment_plots(*args: Any, **kwargs: Any) list[Path]
Lazily import and save one plot file per experiment.
- nanodent.savgol(values: ArrayLike, *, window_length: int = 31, polyorder: int = 3, mode: str = 'interp') ndarray[tuple[Any, ...], dtype[float64]]
Apply a Savitzky-Golay filter with window coercion for short signals.
- Args:
values: One-dimensional signal to smooth. window_length: Preferred smoothing window length. polyorder: Polynomial order used by the filter. mode: Edge-handling mode forwarded to SciPy.
- Returns:
Smoothed float64 NumPy array with the same shape as the input.