Coding guidelines#

This page has the rules for choices that come back often in the code: the return value of a function, the choice of a field, names, and two arguments for one value. Add a rule here when the team agrees on a new one.

See AGENTS.md in the source folder for the rules for docstrings and comments.

Extra outputs go into captures#

A function always returns the same type. To give extra outputs, for example values for a plot or a check, add an optional captures argument. The function fills this dictionary with capture_value from m3resp.processing.captures:

def detect_peaks(..., captures: dict[str, Any] | None = None) -> np.ndarray:
    ...
    capture_value(captures, "properties", properties)
    return peak_indices

A caller who wants the extra outputs gives an empty dictionary and reads it after the call. m3resp.processing.filters and m3resp.processing.peaks use this rule.

Do not add a True/False argument that changes the return type, for example from a value to a tuple. A caller who forgets to unpack the tuple gets an error much later in the code.

Choose a field by what the method calculates#

Some objects have two fields for similar things, for example ParameterResult.breath_id and breath_ids. Choose the field when you write the code, from what the method calculates:

  • A method that calculates one value per breath writes breath_id.

  • A method that calculates one value from a group of breaths writes breath_ids, also when the group has only one breath.

Do not choose the field from the data while the code runs, for example from the length of a list.

Names: what the function calculates, and the term of the literature#

A shared function in m3resp.processing gets a name for what it calculates. A value of one modality keeps the name that the literature uses.

For example, window_integral in m3resp.processing.metrics calculates the area between a signal and its baseline in each window. The EMG code uses it for the time product (ETP), with the result name time_product and the step emg.time_product. The ventilator code uses it for the pressure time product of an occlusion, pocc_time_product. So the shared function has a general name.

Two arguments for one value#

Some functions accept one value in two forms, for example gate_width_seconds and gate_width_samples, or min_peak_width_samples and min_peak_width_s:

  • Both arguments have the default None.

  • If both are None, the function uses its default value.

  • If both are set, the function raises ValueError.

With a default other than None, the function cannot tell if the caller set the value. See the step emg.ecg_gating and detect_emg_breath_peaks in m3resp.processing.peaks for examples.

Continue with Offset estimation.