The People’s Ventilator Project¶
pvp control pseudocode¶
Describes the procedure to operate low-cost ventilator under pressure control
Pressure control parameters¶
Set in GUI
PIP: peak inhalation pressure (~20 cm H2O)
T_insp: inspiratory time to PEEP (~0.5 sec)
I/E: inspiratory to expiratory time ratio
bpm: breaths per minute (15 bpm -> 1/15 sec cycle time)
PIP_time: Target time for PIP. While lungs expand, dP/dt should be PIP/PIP_time
flow_insp: nominal flow rate during inspiration
Set by hardware
FiO2: fraction of inspired oxygen, set by blender
max_flow: manual valve at output of blender
PEEP: positive end-expiratory pressure, set by manual valve
Derived parameters
cycle_time: 1/bpm
t_insp: inspiratory time, controlled by cycle_time and I/E
t_exp: expiratory time, controlled by cycle_time and I/E
Monitored variables
Tidal volume: the volume of air entering the lung, derived from flow through t_exp
PIP: peak inspiratory pressure, set by user in software
Mean plateau pressure: derived from pressure sensor during inspiration cycle hold (no flow)
PEEP: positive end-expiratory pressure, set by manual valve
Alarms
Oxygen out of range
High pressure (tube/airway occlusion)
Low-pressure (disconnect)
Temperature out of range
Low voltage alarm (if using battery power)
Tidal volume (expiratory) out of range
Hardware¶
Sensors
O2 fraction, in inspiratory path
Pressure, just before wye to endotrachial tube
Flow, on expiratory path
Temperature
Humidity?
Actuators
Inspiratory valve
Proportional or on/off
Must maintain low flow during expiratory cycle to maintain PEEP
Expiratory valve
On/off in conjunction with PEEP valve probably OK
Pressure control loop¶
Begin inhalation
v1 Triggered by program every 1/bpm sec
v2 triggered by momentary drop in pressure when patient initiates inhalation (technically pressure-assisted control, PAC)
ExpValve.close()
InspValve.set(flow_insp)
While PSensor.read() < PIP
Monitor d(PSensor.read())/dt
Adjust flow rate for desired slope with controller
Cut flow and hold for t_insp
InspValve.close()
Monitor PSensor.read() and average across this time interval to report mean plateau pressure
Begin exhalation and hold for t_exp
InspValve.set(PEEP_flow_rate) (alt: switch to parallel tube with continuous flow)
ExpValve.open()
integrate(FSensor.read()) for t_exhalation to determine V_tidal
Repeat from step 1.
Hardware¶
Mechanical Diagram¶

Schematic diagram of main mechanical components¶
Sensors | Hardware¶
Overview¶
The TigerVent has four main sensors: 1. oxygen sensor (O2S) 2. proximal pressure sensor (PS1) 3. expiratory pressure sensor (PS2) 4. expiratory flow sensor (FS1)
These materials interface with a modular sensor PCB that can be reconfigured for part substitution. The nominal design assumes both pressure sensors and the oxygen sensor have analog voltage outputs, and interface with the controller via I2C link with a 16-bit, 4 channel ADC (ADS1115). The expiratory flow sensor (SFM3300 or equivalent) uses a direct I2C interface, but can be replaced by a commercial spirometer and an additional differential pressure sensor.
Sensor PCB¶
Bill of Materials¶
Ref
Part
Description
Datasheet
U1
Amphenol 1 PSI-D1-4V-MINI
Analog output differential pressure sensor
/DS-0103-Rev-A-1499253.pdf <- not sure best way to do this
U3
Amphenol 1 PSI-D1-4V-MINI differential pressure sensor
Analog output differential pressure sensor
above
U2
Adafruit 4-channel ADS1115 ADC breakout
Supply ADC to RPi to read analog sensors
/adafruit-4-channel-adc-breakouts.pdf
U4
INA126 instrumentation amplifier, DIP-8
Instrumentation amplifier to boost oxygen sensor output
/ina126.pdf
J1
01x02 2.54 mm pin header
Breakout for alert pin from ADS1115 ADC
none
J2
02x04 2.54 mm pin header
Jumpers to select I2C address for ADC
none
J3
40 pin RPi hat connector
Extends RPi GPIO pins to the board
(to be inserted)
J4
01x02 2.54 mm 90 degree pin header
For direct connection to oxygen sensor output
none
J5
01x04 2.54 mm 90 degree pin header pin header
For I2C connection to SFM3300 flow meter
none
J6
01x03 2.54 mm 90 degree pin header pin header
Connector to use an additional analog output (ADS1115 input A3).
none
R1
1-2.7 k resistor
Optional I2C pullup resistor (RPi already has 1.8k pullups)
none
R2
1-2.7 k resistor
Connector to use an additional analog output (RPi already has 1.8k pullups).
none
R3
0.1-100k resistor
R_G that sets gain for the INA126 instrumentation amplifier (U4). G = 5 + 80k/R_G
none
Flow sensor¶
Document D-lite alternative
Pressure sensors¶
Just use any other analog voltage output (0-4 V) sensor
Flow actuators¶
Actuator PCB/overview (link to PCB with BoM, schematic, layout, etc.)
Proportional solenoid valve (V1) (link to doc with crit specs, driving circuit, part spec, datasheet, alternatives, etc.)
Expiratory valve (V2) (link to doc with crit specs, driving circuit, part spec, datasheet, etc.)
Sensors¶
Sensor PCB/overview (link to PCB with BoM, schematic, layout, etc.)
Oxygen sensor (O2S) (link to doc with crit specs, interface circuit, part spec, datasheet, alternatives, etc.)
Proximal pressure sensor (PS1)
Expiratory pressure sensor (PS2)
Expiratory flow sensor (FS1)
Safety Components¶
50 psi, high pressure relief valve (PRV1)
Safety check valve (CV)
70 cmH2O patient-side pressure relief valve (PRV2)
Filters (F1, F2)
PEEP valve (PEEP) (include the design bifurcation in this module description)
Tubing and Adapters¶
Manifold 1
Manifold 2
Mounting Bracket 1… etc.
Bill of Materials (need to think about what goes in this table, probably separate BoMs into tables by category, but here’s a sample table)¶
Ref |
Name |
Part |
Description |
---|---|---|---|
V1 |
Inspiratory on/off valve |
red hat process valve |
completely cut off flow if required |
PRV1 |
High pressure relief valve |
Sets to 50 psi |
regulates upstream pressure to 50 psi |
CV |
Inspiratory check valve |
valve stat here |
In case of emergency power loss, allows patient to continue taking breaths from air |
PRV2 |
Maximum pressure valve |
… |
Sets absolute maximum pressure at patient side to 53 cm H2O |
F1/F2 |
Filters |
HEPA filters? |
Keeps the system’s sensors from becoming contaminated |
O2S |
Oxygen sensor |
Sensiron … |
Checks FiO2 level |
PS1/PS2 |
Pressure sensors |
mini4v |
Uses gas takeoffs to measure pressure at each desired point |
FS1 |
Flow sensor |
Sensiron flow sensor |
Measures expiratory flow to calculate tidal volume |
M1/M2 |
Manifolds |
3D printed parts |
Hubs to connect multiple components in one place |
V3 |
Expiratory on/off valve |
Festo Electrical Air Directional Control Valve, 3/2 flow, Normally Closed, 8 mm Push-to-Connect |
Opens to initiation the expiratory cycle |
PEEP |
PEEP backpressure valve |
PEEP valve |
Sets PEEP on expiratory cycle! |
common module¶
values¶
Parameterization of variables and values
Data
Values to control but not monitor. |
|
Values that should be displayed in the GUI. |
|
Values that should be displayed in the GUI. |
|
Values that are dependent on other values: |
|
Values to monitor but not control. |
Classes
|
Definition of a value. |
|
An enumeration. |
-
class
pvp.common.values.
ValueName
(value)[source]¶ Bases:
enum.Enum
An enumeration.
Attributes
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
-
PIP
= 1¶
-
PIP_TIME
= 2¶
-
PEEP
= 3¶
-
PEEP_TIME
= 4¶
-
BREATHS_PER_MINUTE
= 5¶
-
INSPIRATION_TIME_SEC
= 6¶
-
IE_RATIO
= 7¶
-
FIO2
= 8¶
-
VTE
= 9¶
-
PRESSURE
= 10¶
-
FLOWOUT
= 11¶
-
-
class
pvp.common.values.
Value
(name: str, units: str, abs_range: tuple, safe_range: tuple, decimals: int, control: bool, sensor: bool, display: bool, plot: bool = False, plot_limits: Union[None, Tuple[pvp.common.values.ValueName]] = None, control_type: Union[None, str] = None, group: Union[None, dict] = None, default: (<class 'int'>, <class 'float'>) = None)[source]¶ Bases:
object
Definition of a value.
Used by the GUI and control module to set defaults.
- Parameters
name (str) – Human-readable name of the value
units (str) – Human-readable description of units
abs_range (tuple) – tuple of ints or floats setting the logical limit of the value, eg. a percent between 0 and 100, (0, 100)
safe_range (tuple) –
tuple of ints or floats setting the safe ranges of the value,
note:
this is not the same thing as the user-set alarm values, though the user-set alarm values are initialized as ``safe_range``.
decimals (int) – the number of decimals of precision used when displaying the value
display (bool) – whether the value should be displayed in the monitor. if
control == True
, automatically set toFalse
because all controls have their own numerical displaysplot (bool) – whether or not the value is plottable int he center plot window
plot_limits (None, tuple(ValueName)) – If plottable, and the plotted value has some alarm limits for another value, plot those limits as horizontal lines in the plot. eg. the PIP alarm range limits should be plotted on the Pressure plot
Methods
__init__
(name, units, abs_range, safe_range, …)Definition of a value.
to_dict
()Attributes
-
__init__
(name: str, units: str, abs_range: tuple, safe_range: tuple, decimals: int, control: bool, sensor: bool, display: bool, plot: bool = False, plot_limits: Union[None, Tuple[pvp.common.values.ValueName]] = None, control_type: Union[None, str] = None, group: Union[None, dict] = None, default: (<class 'int'>, <class 'float'>) = None)[source]¶ Definition of a value.
Used by the GUI and control module to set defaults.
- Parameters
name (str) – Human-readable name of the value
units (str) – Human-readable description of units
abs_range (tuple) – tuple of ints or floats setting the logical limit of the value, eg. a percent between 0 and 100, (0, 100)
safe_range (tuple) –
tuple of ints or floats setting the safe ranges of the value,
note:
this is not the same thing as the user-set alarm values, though the user-set alarm values are initialized as ``safe_range``.
decimals (int) – the number of decimals of precision used when displaying the value
display (bool) – whether the value should be displayed in the monitor. if
control == True
, automatically set toFalse
because all controls have their own numerical displaysplot (bool) – whether or not the value is plottable int he center plot window
plot_limits (None, tuple(ValueName)) – If plottable, and the plotted value has some alarm limits for another value, plot those limits as horizontal lines in the plot. eg. the PIP alarm range limits should be plotted on the Pressure plot
-
property
name
¶
-
property
abs_range
¶
-
property
safe_range
¶
-
property
decimals
¶
-
property
default
¶
-
property
control
¶
-
property
sensor
¶
-
property
display
¶
-
property
control_type
¶
-
property
group
¶
-
property
plot
¶
-
property
plot_limits
¶
-
pvp.common.values.
SENSOR
= OrderedDict([(<ValueName.PIP: 1>, <pvp.common.values.Value object>), (<ValueName.PEEP: 3>, <pvp.common.values.Value object>), (<ValueName.BREATHS_PER_MINUTE: 5>, <pvp.common.values.Value object>), (<ValueName.INSPIRATION_TIME_SEC: 6>, <pvp.common.values.Value object>), (<ValueName.PRESSURE: 10>, <pvp.common.values.Value object>), (<ValueName.VTE: 9>, <pvp.common.values.Value object>), (<ValueName.FLOWOUT: 11>, <pvp.common.values.Value object>), (<ValueName.FIO2: 8>, <pvp.common.values.Value object>)])¶ Values to monitor but not control.
Used to set alarms for out-of-bounds sensor values. These should be sent from the control module and not computed.:
{ 'name' (str): Human readable name, 'units' (str): units string, (like degrees or %), 'abs_range' (tuple): absolute possible range of values, 'safe_range' (tuple): range outside of which a warning will be raised, 'decimals' (int): The number of decimals of precision this number should be displayed with }
-
pvp.common.values.
CONTROL
= OrderedDict([(<ValueName.PIP: 1>, <pvp.common.values.Value object>), (<ValueName.PEEP: 3>, <pvp.common.values.Value object>), (<ValueName.BREATHS_PER_MINUTE: 5>, <pvp.common.values.Value object>), (<ValueName.INSPIRATION_TIME_SEC: 6>, <pvp.common.values.Value object>), (<ValueName.IE_RATIO: 7>, <pvp.common.values.Value object>), (<ValueName.PIP_TIME: 2>, <pvp.common.values.Value object>), (<ValueName.PEEP_TIME: 4>, <pvp.common.values.Value object>)])¶ Values to control but not monitor.
Sent to control module to control operation of ventilator.:
{ 'name' (str): Human readable name, 'units' (str): units string, (like degrees or %), 'abs_range' (tuple): absolute possible range of values, 'safe_range' (tuple): range outside of which a warning will be raised, 'default' (int, float): the default value of the parameter, 'decimals' (int): The number of decimals of precision this number should be displayed with }
-
pvp.common.values.
DISPLAY_MONITOR
= OrderedDict([(<ValueName.PIP: 1>, <pvp.common.values.Value object>), (<ValueName.PEEP: 3>, <pvp.common.values.Value object>), (<ValueName.BREATHS_PER_MINUTE: 5>, <pvp.common.values.Value object>), (<ValueName.INSPIRATION_TIME_SEC: 6>, <pvp.common.values.Value object>), (<ValueName.PRESSURE: 10>, <pvp.common.values.Value object>), (<ValueName.VTE: 9>, <pvp.common.values.Value object>), (<ValueName.FLOWOUT: 11>, <pvp.common.values.Value object>), (<ValueName.FIO2: 8>, <pvp.common.values.Value object>)])¶ Values that should be displayed in the GUI. If a value is also a CONTROL it will always have the measured value displayed, these values are those that are sensor values that are uncontrolled and should be displayed.
-
pvp.common.values.
DISPLAY_CONTROL
= OrderedDict([(<ValueName.PIP: 1>, <pvp.common.values.Value object>), (<ValueName.PEEP: 3>, <pvp.common.values.Value object>), (<ValueName.BREATHS_PER_MINUTE: 5>, <pvp.common.values.Value object>), (<ValueName.INSPIRATION_TIME_SEC: 6>, <pvp.common.values.Value object>), (<ValueName.IE_RATIO: 7>, <pvp.common.values.Value object>), (<ValueName.PIP_TIME: 2>, <pvp.common.values.Value object>)])¶ Values that should be displayed in the GUI. If a value is also a CONTROL it will always have the measured value displayed, these values are those that are sensor values that are uncontrolled and should be displayed.
-
pvp.common.values.
LIMITS
= {}¶ Values that are dependent on other values:
{ "dependent_value": ( ['value_1', 'value_2'], callable_returning_boolean } }
Where the first argument in the tuple is a list of the values that will be given as argument to the
callable_returning_boolean
which will return whether (True
) or not (False
) a value is allowed.
loggers¶
Logging functionality
There are two types of loggers: a standard logging.Logger
-based logging system for debugging and recording system events,
and a tables
- based DataLogger
class to store continuously measured sensor values.
Classes
|
Class for logging numerical respiration data and control settings. |
Data
list of strings, which loggers have been created already. |
Functions
|
Initialize a logger for logging events. |
|
# TODO: Stub exception logger. Prints exception type & traceback |
Adjust each logger’s |
-
pvp.common.loggers.
_LOGGERS
= ['pvp.common.prefs', 'pvp.alarm.alarm_manager']¶ list of strings, which loggers have been created already.
-
pvp.common.loggers.
init_logger
(module_name: str, log_level: int = None, file_handler: bool = True) → logging.Logger[source]¶ Initialize a logger for logging events.
If a logger has already been initialized, return that.
- Parameters
module_name (str) – module name used to generate filename and name logger
log_level (int) – one of :var:`logging.DEBUG`, :var:`logging.INFO`, :var:`logging.WARNING`, or :var:`logging.ERROR`
file_handler (bool, str) – if
True
, (default), log in<logdir>/module_name.log
. ifFalse
, don’t log to disk.
- Returns
Logger 4 u 2 use
- Return type
-
pvp.common.loggers.
update_logger_sizes
()[source]¶ Adjust each logger’s
maxBytes
attribute so that the total across all loggers isprefs.LOGGING_MAX_BYTES
-
pvp.common.loggers.
log_exception
(e, tb)[source]¶ # TODO: Stub exception logger. Prints exception type & traceback
- Parameters
e – Exception to log
tb – TraceBack associated with Exception e
-
class
pvp.common.loggers.
DataLogger
(compression_level: int = 9)[source]¶ Bases:
object
Class for logging numerical respiration data and control settings. Creates a hdf5 file with this general structure:
Methods
__init__
(compression_level)Initialized the coontinuous numerical logger class.
Opens the hdf5 file and generates the file structure.
make sure that the file’s are not getting too large.
Flushes & closes the open hdf file.
This flushes the datapoints to the file.
load_file
([filename])This loads a hdf5 file, and returns data to the user as a dictionary with two keys: waveform_data and control_data
log2csv
([filename])Translates the compressed hdf5 into three csv files containing:
log2mat
([filename])Translates the compressed hdf5 into a matlab file containing a matlab struct.
This rotates through filenames, similar to a ringbuffer, to make sure that the program does not run of of space/
store_control_command
(control_setting)Appends a datapoint to the event-table, derived from ControlSettings
store_derived_data
(derived_values)Appends a datapoint to the event-table, derived the continuous data (PIP, PEEP etc.)
store_waveform_data
(sensor_values, …)Appends a datapoint to the file for continuous logging of streaming data.
/ root |— waveforms (group) | |— time | pressure_data | flow_out | control_signal_in | control_signal_out | FiO2 | Cycle No. | |— controls (group) | |— (time, controllsignal) | |— derived_quantities (group) | |— (time, Cycle No, I_PHASE_DURATION, PIP_TIME, PEEP_time, PIP, PIP_PLATEAU, PEEP, VTE ) | |
- Public Methods:
close_logfile(): Flushes, and closes the logfile. store_waveform_data(SensorValues): Takes data from SensorValues, but DOES NOT FLUSH store_controls(): Store controls in the same file? TODO: Discuss flush_logfile(): Flush the data into the file
Initialized the coontinuous numerical logger class.
- Parameters
compression_level (int, optional) – Compression level of the hdf5 file. Defaults to 9.
-
__init__
(compression_level: int = 9)[source]¶ Initialized the coontinuous numerical logger class.
- Parameters
compression_level (int, optional) – Compression level of the hdf5 file. Defaults to 9.
-
store_waveform_data
(sensor_values: SensorValues, control_values: ControlValues)[source]¶ Appends a datapoint to the file for continuous logging of streaming data. NOTE: Not flushed yet.
- Parameters
sensor_values (SensorValues) – SensorValues to be stored in the file.
control_values (ControlValues) – ControlValues to be stored in the file
-
store_control_command
(control_setting: ControlSetting)[source]¶ Appends a datapoint to the event-table, derived from ControlSettings
- Parameters
control_setting (ControlSetting) – ControlSettings object, the content of which should be stored
-
store_derived_data
(derived_values: DerivedValues)[source]¶ Appends a datapoint to the event-table, derived the continuous data (PIP, PEEP etc.)
- Parameters
derived_values (DerivedValues) – DerivedValues object, the content of which should be stored
-
flush_logfile
()[source]¶ This flushes the datapoints to the file. To be executed every other second, e.g. at the end of breath cycle.
-
rotation_newfile
()[source]¶ This rotates through filenames, similar to a ringbuffer, to make sure that the program does not run of of space/
-
load_file
(filename=None)[source]¶ This loads a hdf5 file, and returns data to the user as a dictionary with two keys: waveform_data and control_data
- Parameters
filename (str, optional) – Path to a hdf5-file. If none is given, uses currently open file. Defaults to None.
- Returns
Containing the data arranged as ` {“waveform_data”: waveform_data, “control_data”: control_data, “derived_data”: derived_data}`
- Return type
dictionary
-
log2mat
(filename=None)[source]¶ Translates the compressed hdf5 into a matlab file containing a matlab struct. This struct has the same structure as the hdf5 file, but is not compressed. Use for any file:
dl = DataLogger() dl.log2mat(filename)
The file is saved at the same path as .mat file, where the content is represented as matlab-structs.
- Parameters
filename (str, optional) – Path to a hdf5-file. If none is given, uses currently open file. Defaults to None.
-
log2csv
(filename=None)[source]¶ - Translates the compressed hdf5 into three csv files containing:
waveform_data (measurement once per cycle)
derived_quantities (PEEP, PIP etc.)
control_commands (control commands sent to the controller)
This approximates the structure contained in the hdf5 file. Use for any file:
dl = DataLogger() dl.log2csv(filename)
- Parameters
filename (str, optional) – Path to a hdf5-file. If none is given, uses currently open file. Defaults to None.
message¶
Classes
|
|
|
Class to save control values, analogous to SensorValues. |
|
Class to save derived values, analogous to SensorValues. |
|
|
|
|
-
class
pvp.common.message.
SensorValues
(timestamp=None, loop_counter=None, breath_count=None, vals=None, **kwargs)[source]¶ Bases:
object
- Parameters
timestamp (float) – from time.time(). must be passed explicitly or as an entry in
vals
loop_counter (int) – number of control_module loops. must be passed explicitly or as an entry in
vals
breath_count (int) – number of breaths taken. must be passed explicitly or as an entry in
vals
**kwargs – sensor readings, must be in
pvp.values.SENSOR.keys
Methods
__init__
([timestamp, loop_counter, …])- param timestamp
from time.time(). must be passed explicitly or as an entry in
vals
to_dict
()Attributes
Built-in immutable sequence.
-
additional_values
= ('timestamp', 'loop_counter', 'breath_count')¶
-
__init__
(timestamp=None, loop_counter=None, breath_count=None, vals=None, **kwargs)[source]¶ - Parameters
timestamp (float) – from time.time(). must be passed explicitly or as an entry in
vals
loop_counter (int) – number of control_module loops. must be passed explicitly or as an entry in
vals
breath_count (int) – number of breaths taken. must be passed explicitly or as an entry in
vals
**kwargs – sensor readings, must be in
pvp.values.SENSOR.keys
-
class
pvp.common.message.
ControlValues
(control_signal_in, control_signal_out)[source]¶ Bases:
object
Class to save control values, analogous to SensorValues. Key difference: SensorValues come exclusively from the sensors, ControlValues contains controller variables, i.e. control signals and controlled signals (the flows). :param control_signal_in: :param control_signal_out:
-
class
pvp.common.message.
DerivedValues
(timestamp, breath_count, I_phase_duration, pip_time, peep_time, pip, pip_plateau, peep, vte)[source]¶ Bases:
object
Class to save derived values, analogous to SensorValues. Key difference: SensorValues come exclusively from the sensors, DerivedValues contain estimates of I_PHASE_DURATION, PIP_TIME, PEEP_time, PIP, PIP_PLATEAU, PEEP, and VTE. :param timestamp: :param breath_count: :param I_phase_duration: :param pip_time: :param peep_time: :param pip: :param pip_plateau: :param peep: :param vte:
-
class
pvp.common.message.
ControlSetting
(name: pvp.common.values.ValueName, value: float = None, min_value: float = None, max_value: float = None, timestamp: float = None, range_severity: AlarmSeverity = None)[source]¶ Bases:
object
- Parameters
name –
value –
min_value –
max_value –
timestamp (float) –
time.time()
range_severity (
AlarmSeverity
) – Some control settings have multiple limits for different alarm severities, this attr, when present, specified which is being set.
Methods
__init__
(name, value, min_value, max_value, …)- param name
-
__init__
(name: pvp.common.values.ValueName, value: float = None, min_value: float = None, max_value: float = None, timestamp: float = None, range_severity: AlarmSeverity = None)[source]¶ - Parameters
name –
value –
min_value –
max_value –
timestamp (float) –
time.time()
range_severity (
AlarmSeverity
) – Some control settings have multiple limits for different alarm severities, this attr, when present, specified which is being set.
prefs¶
System preferences are stored in ~/pvp/prefs.json
Data
bool: flag to indicate whether prefs have been loaded (and thus |
|
Declare all available parameters and set default values. |
|
Directories to ensure are created and added to prefs. |
|
|
Functions
|
Get global configuration value |
|
Initialize prefs. |
|
Load prefs from a .json prefs file, combining (and overwriting) any existing prefs, and then saves. |
ensures _DIRECTORIES are created and added to prefs. |
|
|
|
|
-
pvp.common.prefs.
_LOCK
= <Lock(owner=None)>¶ Locks access to prefs_fn
- Type
mp.Lock
-
pvp.common.prefs.
_DIRECTORIES
= {'DATA_DIR': '/home/docs/pvp/logs', 'LOG_DIR': '/home/docs/pvp/logs', 'VENT_DIR': '/home/docs/pvp'}¶ Directories to ensure are created and added to prefs.
VENT_DIR
: ~/pvp - base directory for user storageLOG_DIR
: ~/pvp/logs - for storage of event and alarm logsDATA_DIR
: ~/pvp/data - for storage of waveform data
-
pvp.common.prefs.
LOADED
= <Synchronized wrapper for c_bool(True)>¶ flag to indicate whether prefs have been loaded (and thus
set_pref()
should write to disk.- Type
-
pvp.common.prefs.
_DEFAULTS
= {'BREATH_DETECTION': True, 'BREATH_PRESSURE_DROP': 4, 'CONTROLLER_LOOPS_UNTIL_UPDATE': 1, 'CONTROLLER_LOOP_UPDATE_TIME': 0.0, 'CONTROLLER_LOOP_UPDATE_TIME_SIMULATOR': 0.005, 'CONTROLLER_MAX_FLOW': 10, 'CONTROLLER_MAX_PRESSURE': 100, 'CONTROLLER_MAX_STUCK_SENSOR': 0.2, 'CONTROLLER_RINGBUFFER_SIZE': 100, 'COUGH_DURATION': 0.1, 'ENABLE_DIALOGS': True, 'ENABLE_WARNINGS': True, 'GUI_STATE_FN': 'gui_state.json', 'GUI_UPDATE_TIME': 0.05, 'HEARTBEAT_TIMEOUT': 0.02, 'LOGGING_MAX_BYTES': 2147483648, 'LOGGING_MAX_FILES': 5, 'LOGLEVEL': 'WARNING', 'PREFS_FN': None, 'TIMEOUT': 0.05, 'TIME_FIRST_START': None}¶ Declare all available parameters and set default values. If no default, set as None.
PREFS_FN
- absolute path to the prefs fileTIME_FIRST_START
- time when the program has been started for the first timeVENT_DIR
: ~/pvp - base directory for user storageLOG_DIR
: ~/pvp/logs - for storage of event and alarm logsDATA_DIR
: ~/pvp/data - for storage of waveform dataLOGGING_MAX_BYTES
: the total storage space for all loggers – each logger getsLOGGING_MAX_BYTES/len(loggers)
spaceLOGGING_MAX_FILES
: number of files to split each logger’s logs acrossGUI_STATE_FN
: Filename of gui control state file, relative toVENT_DIR
BREATH_PRESSURE_DROP
: pressure drop below peep that is detected as an attempt to breath.BREATH_DETECTION
: (bool) whether the controller allows autonomous breaths (measured pressure isBREATH_PRESSURE_DROP
below set PEEP)CONTROLLER_MAX_FLOW
: If flows above that, hardware cannot be correct.CONTROLLER_MAX_PRESSURE
: If pressure above that, hardware cannot be correct.CONTROLLER_MAX_STUCK_SENSOR
: Max amount of time (in s) before considering a sensor stuck
-
pvp.common.prefs.
load_prefs
(prefs_fn: str)[source]¶ Load prefs from a .json prefs file, combining (and overwriting) any existing prefs, and then saves.
Note
once this function is called,
set_pref()
will update the prefs file on disk. So ifload_prefs()
is called again at any point it should not change prefs.- Parameters
prefs_fn (str) – path of prefs.json
unit conversion¶
Functions
|
|
|
|
|
create a rounded string of a number that doesnt have trailing .0 when decimals = 0 |
utils¶
Exceptions
Functions
|
|
|
Defines a decorator for a 50ms timeout. |
fashion¶
Decorators for dangerous functions
Functions
|
Wrapper to use as decorator, handle lock logic for a |
|
controller module¶
Classes
|
Physics simulator for inflating a balloon with an attached PEEP valve. |
|
Abstract controller class for simulation/hardware. |
|
Uses ControlModuleBase to control the hardware. |
|
Controlling Simulation. |
Functions
|
Generates control module. |
-
class
pvp.controller.control_module.
ControlModuleBase
(save_logs: bool = False, flush_every: int = 10)[source]¶ Bases:
object
Abstract controller class for simulation/hardware.
1. General notes: All internal variables fall in three classes, denoted by the beginning of the variable:
Methods
This goes through the last waveform, and updates the internal variables: VTE, PEEP, PIP, PIP_TIME, I_PHASE, FIRST_PEEP and BPM.
Calculates the PID control signal by: - Combining the the three gain parameters.
__get_PID_error
(ytarget, yis, dt, RC)Calculates the three terms for PID control.
Helper function to reorganize key parameters in the main PID control loop, into a SensorValues object, that can be stored in the logfile, using a method from the DataLogger.
Some housekeeping.
Implements tests that are to be executed in the main control loop: - Test for HAPA - Test for Technical Alert, making sure sensor values are plausible - Test for Technical Alert, make sure continuous in contact Currently: Alarms are time.time() of first occurance.
_PID_update
(dt)This instantiates the PID control algorithms.
__init__
(save_logs, flush_every)Initializes the ControlModuleBase class.
Resets the internal controller cycle to zero, i.e.
Produces the INSPIRATORY control-signal that has been calculated in __calculate_control_signal_in(dt)
Produces the EXPIRATORY control-signal for the different states, i.e.
Makes a copy of internal variables.
Prototype method to start main PID loop.
A method callable from the outside to get a copy of the alarms, that the controller checks: High airway pressure, and technical alarms.
get_control
(control_setting_name)A method callable from the outside to get current control settings.
Returns an independent heart-beat of the controller, i.e.
Public method to return a list of past waveforms from __cycle_waveform_archive.
A method callable from the outside to get a copy of sensorValues
If the controller seems stuck, this generates a new thread, and starts the main loop.
Public Method to assess whether the main loop thread is running.
set_breath_detection
(breath_detection)set_control
(control_setting)A method callable from the outside to set alarms.
start
()Method to start _start_mainloop as a thread.
stop
()Method to stop the main loop thread, and close the logfile.
COPY_varname: These are copies (for safe threading purposes) that are regularly sync’ed with internal variables.
__varname: These are variables only used in the ControlModuleBase-Class
_varname: These are variables used in derived classes.
2. Set and get values. Internal variables should only to be accessed though the set_ and get_ functions.
These functions act on COPIES of internal variables (__ and _), that are sync’d every few iterations. How often this is done is adjusted by the variable self._NUMBER_CONTROLL_LOOPS_UNTIL_UPDATE. To avoid multiple threads manipulating the same variables at the same time, every manipulation of COPY_ is surrounded by a thread lock.
- Public Methods:
get_sensors(): Returns a copy of the current sensor values.
get_alarms(): Returns a List of all alarms, active and logged
get_control(ControlSetting): Sets a controll-setting. Is updated at latest within self._NUMBER_CONTROLL_LOOPS_UNTIL_UPDATE
get_past_waveforms(): Returns a List of waveforms of pressure and volume during at the last N breath cycles, N<self. _RINGBUFFER_SIZE, AND clears this archive.
start(): Starts the main-loop of the controller
stop(): Stops the main-loop of the controller
set_control(): Set the control
interrupt(): Interrupt the controller, and re-spawns the thread. Used to restart a stuck controller
is_running(): Returns a bool whether the main-thread is running
get_heartbeat(): Returns a heartbeat, more specifically, the continuously increasing iteration-number of the main control loop.
Initializes the ControlModuleBase class.
- Parameters
save_logs (bool, optional) – Should sensor data and controls should be saved with the
DataLogger
? Defaults to False.flush_every (int, optional) – Flush and rotate logs every n breath cycles. Defaults to 10.
- Raises
alert – [description]
-
__init__
(save_logs: bool = False, flush_every: int = 10)[source]¶ Initializes the ControlModuleBase class.
- Parameters
save_logs (bool, optional) – Should sensor data and controls should be saved with the
DataLogger
? Defaults to False.flush_every (int, optional) – Flush and rotate logs every n breath cycles. Defaults to 10.
- Raises
alert – [description]
-
_initialize_set_to_COPY
()[source]¶ Makes a copy of internal variables. This is used to facilitate threading
-
__analyze_last_waveform
()¶ - This goes through the last waveform, and updates the internal variables:
VTE, PEEP, PIP, PIP_TIME, I_PHASE, FIRST_PEEP and BPM.
-
get_sensors
() → pvp.common.message.SensorValues[source]¶ A method callable from the outside to get a copy of sensorValues
- Returns
A set of current sensorvalues, handeled by the controller.
- Return type
-
get_alarms
() → Union[None, Tuple[pvp.alarm.alarm.Alarm]][source]¶ A method callable from the outside to get a copy of the alarms, that the controller checks: High airway pressure, and technical alarms.
-
set_control
(control_setting: pvp.common.message.ControlSetting)[source]¶ A method callable from the outside to set alarms. This updates the entries of COPY with new control values.
- Parameters
control_setting (ControlSetting) – [description]
-
get_control
(control_setting_name: pvp.common.values.ValueName) → pvp.common.message.ControlSetting[source]¶ A method callable from the outside to get current control settings. This returns values of COPY to the outside world.
- Parameters
control_setting_name (ValueName) – The specific control asked for
- Returns
ControlSettings-Object that contains relevant data
- Return type
-
__get_PID_error
(ytarget, yis, dt, RC)¶ Calculates the three terms for PID control. Also takes a timestep “dt” on which the integral-term is smoothed.
-
__calculate_control_signal_in
(dt)¶ - Calculates the PID control signal by:
Combining the the three gain parameters.
And smoothing the control signal with a moving window of three frames (~10ms)
- Parameters
dt (float) – timestep
-
_get_control_signal_in
()[source]¶ Produces the INSPIRATORY control-signal that has been calculated in __calculate_control_signal_in(dt)
- Returns
the numerical control signal for the inspiratory prop valve
- Return type
-
_get_control_signal_out
()[source]¶ Produces the EXPIRATORY control-signal for the different states, i.e. open/close
- Returns
numerical control signal for expiratory side: open (1) close (0)
- Return type
-
_control_reset
()[source]¶ Resets the internal controller cycle to zero, i.e. restarts the breath cycle. Used for autonomous breath detection.
-
__test_for_alarms
()¶ - Implements tests that are to be executed in the main control loop:
Test for HAPA
Test for Technical Alert, making sure sensor values are plausible
Test for Technical Alert, make sure continuous in contact
Currently: Alarms are time.time() of first occurance.
-
__start_new_breathcycle
()¶ - Some housekeeping. This has to be executed when the next breath cycles starts:
starts new breathcycle
initializes newe __cycle_waveform
analyzes last breath waveform for PIP, PEEP etc. with __analyze_last_waveform()
flushes the logfile
-
_PID_update
(dt)[source]¶ This instantiates the PID control algorithms. During the breathing cycle, it goes through the four states:
Rise to PIP, speed is controlled by flow (variable: __SET_PIP_GAIN)
Sustain PIP pressure
Quick fall to PEEP
Sustaint PEEP pressure
Once the cycle is complete, it checks the cycle for any alarms, and starts a new one. A record of pressure/volume waveforms is kept and saved
- Parameters
dt (float) – timesstep since last update
-
__save_values
()¶ Helper function to reorganize key parameters in the main PID control loop, into a SensorValues object, that can be stored in the logfile, using a method from the DataLogger.
-
get_past_waveforms
()[source]¶ Public method to return a list of past waveforms from __cycle_waveform_archive. Note: After calling this function, archive is emptied! The format is
Returns a list of [Nx3] waveforms, of [time, pressure, volume]
Most recent entry is waveform_list[-1]
- Returns
[Nx3] waveforms, of [time, pressure, volume]
- Return type
-
_start_mainloop
()[source]¶ Prototype method to start main PID loop. Will depend on simulation or device, specified below.
-
interrupt
()[source]¶ If the controller seems stuck, this generates a new thread, and starts the main loop. No parameters have changed.
-
class
pvp.controller.control_module.
ControlModuleDevice
(save_logs=True, flush_every=10, config_file=None)[source]¶ Bases:
pvp.controller.control_module.ControlModuleBase
Uses ControlModuleBase to control the hardware.
Initializes the ControlModule for the physical system. Inherits methods from ControlModuleBase
- Parameters
save_logs (bool, optional) – Should logs be kept? Defaults to True.
flush_every (int, optional) – How often are log-files to be flushed, in units of main-loop-itertions? Defaults to 10.
config_file (str, optional) – Path to device config file, e.g. ‘pvp/io/config/dinky-devices.ini’. Defaults to None.
Methods
__init__
([save_logs, flush_every, config_file])Initializes the ControlModule for the physical system.
_get_HAL
()Get sensor values from HAL, decorated with timeout.
Copies the current measurements to`COPY_sensor_values`, so that it can be queried from the outside.
_set_HAL
(valve_open_in, valve_open_out)Set Controls with HAL, decorated with a timeout.
This is the main loop.
This returns valves back to normal setting (in: closed, out: open)
-
__init__
(save_logs=True, flush_every=10, config_file=None)[source]¶ Initializes the ControlModule for the physical system. Inherits methods from ControlModuleBase
- Parameters
save_logs (bool, optional) – Should logs be kept? Defaults to True.
flush_every (int, optional) – How often are log-files to be flushed, in units of main-loop-itertions? Defaults to 10.
config_file (str, optional) – Path to device config file, e.g. ‘pvp/io/config/dinky-devices.ini’. Defaults to None.
-
_sensor_to_COPY
()[source]¶ Copies the current measurements to`COPY_sensor_values`, so that it can be queried from the outside.
-
_set_HAL
(valve_open_in, valve_open_out)[source]¶ Set Controls with HAL, decorated with a timeout.
As hardware communication is the speed bottleneck. this code is slightly optimized in so far as only changes are sent to hardware.
-
_get_HAL
()[source]¶ Get sensor values from HAL, decorated with timeout. As hardware communication is the speed bottleneck. this code is slightly optimized in so far as some sensors are queried only in certain phases of the breatch cycle. This is done to run the primary PID loop as fast as possible:
pressure is always queried
Flow is queried only outside of inspiration
In addition, oxygen is only read every 5 seconds.
-
class
pvp.controller.control_module.
Balloon_Simulator
(peep_valve)[source]¶ Bases:
object
Physics simulator for inflating a balloon with an attached PEEP valve. For math, see https://en.wikipedia.org/wiki/Two-balloon_experiment
Methods
OUupdate
(variable, dt, mu, sigma, tau)This is a simple function to produce an OU process on variable.
_reset
()Resets Balloon to default settings.
set_flow_in
(Qin, dt)set_flow_out
(Qout, dt)update
(dt)
-
class
pvp.controller.control_module.
ControlModuleSimulator
(simulator_dt=None, peep_valve_setting=5)[source]¶ Bases:
pvp.controller.control_module.ControlModuleBase
Controlling Simulation.
Initializes the ControlModuleBase with the simple simulation (for testing/dev).
- Parameters
Methods
This simulates the action of a proportional valve.
This simulates the action of a two-state Solenoid valve.
__init__
([simulator_dt, peep_valve_setting])Initializes the ControlModuleBase with the simple simulation (for testing/dev).
Make the sensor value object from current (simulated) measurements
This is the main loop.
-
__init__
(simulator_dt=None, peep_valve_setting=5)[source]¶ Initializes the ControlModuleBase with the simple simulation (for testing/dev).
-
__SimulatedPropValve
(x)¶ This simulates the action of a proportional valve. Flow-current-curve eye-balled from generic prop vale with logistic activation.
-
__SimulatedSolenoid
(x)¶ This simulates the action of a two-state Solenoid valve.
coordinator module¶
Submodules¶
coordinator¶
Classes
|
|
|
|
|
Functions
|
-
class
pvp.coordinator.coordinator.
CoordinatorBase
(sim_mode=False)[source]¶ Bases:
object
Methods
get_control
(control_setting_name)kill
()set_breath_detection
(breath_detection)set_control
(control_setting)start
()stop
()-
get_sensors
() → pvp.common.message.SensorValues[source]¶
-
get_alarms
() → Union[None, Tuple[pvp.alarm.alarm.Alarm]][source]¶
-
set_control
(control_setting: pvp.common.message.ControlSetting)[source]¶
-
get_control
(control_setting_name: pvp.common.values.ValueName) → pvp.common.message.ControlSetting[source]¶
-
-
class
pvp.coordinator.coordinator.
CoordinatorLocal
(sim_mode=False)[source]¶ Bases:
pvp.coordinator.coordinator.CoordinatorBase
- Parameters
sim_mode –
Methods
__init__
([sim_mode])- param sim_mode
get_control
(control_setting_name)Test whether the whole system is running
kill
()set_breath_detection
(breath_detection)set_control
(control_setting)start
()Start the coordinator.
stop
()Stop the coordinator.
-
_is_running
¶ .set()
when thread should stop- Type
-
__init__
(sim_mode=False)[source]¶ - Parameters
sim_mode –
-
_is_running
¶ .set()
when thread should stop- Type
-
get_sensors
() → pvp.common.message.SensorValues[source]¶
-
get_alarms
() → Union[None, Tuple[pvp.alarm.alarm.Alarm]][source]¶
-
set_control
(control_setting: pvp.common.message.ControlSetting)[source]¶
-
get_control
(control_setting_name: pvp.common.values.ValueName) → pvp.common.message.ControlSetting[source]¶
-
class
pvp.coordinator.coordinator.
CoordinatorRemote
(sim_mode=False)[source]¶ Bases:
pvp.coordinator.coordinator.CoordinatorBase
Methods
get_control
(control_setting_name)Test whether the whole system is running
kill
()Stop the coordinator and end the whole program
set_breath_detection
(breath_detection)set_control
(control_setting)start
()Start the coordinator.
stop
()Stop the coordinator.
-
get_sensors
() → pvp.common.message.SensorValues[source]¶
-
get_alarms
() → Union[None, Tuple[pvp.alarm.alarm.Alarm]][source]¶
-
set_control
(control_setting: pvp.common.message.ControlSetting)[source]¶
-
get_control
(control_setting_name: pvp.common.values.ValueName) → pvp.common.message.ControlSetting[source]¶
-
-
pvp.coordinator.coordinator.
get_coordinator
(single_process=False, sim_mode=False) → pvp.coordinator.coordinator.CoordinatorBase[source]¶
ipc¶
Functions
|
|
|
|
|
|
|
gui¶
Design Requirements¶
Display Values
Value name, units, absolute range, recommended range, default range
VTE
FiO2
Humidity
Temperature
Plots
Controlled Values
PIP
PEEP
Inspiratory Time
Value Dependencies
UI Notes & Todo¶
Jonny add notes from helpful RT in discord!!!
Top status Bar
Start/stop button
Status indicator - a clock that increments with heartbeats, or some other visual indicator that things are alright
Status bar - most recent alarm or notification w/ means of clearing
Override to give 100% oxygen and silence all alarms
API
Two queues, input and output. Read from socket and put directly into queue.
Input, receive (timestamp, key, value) messages where key and value are names of variables and their values
Output, send same format
Menus
Trigger some testing/calibration routine
Log/alarm viewer
Wizard to set values?
save/load values
Alarms
Multiple levels
Silenced/reset
Logging
Sounds?
General
Reduce space given to waveforms
Clearer grouping & titling for display values & controls
Collapsible range setting
Ability to declare dependencies between values
Limits - one value’s range logically depends on another
Derived - one value is computed from another/others
Monitored values should have defaults, warning range, and absolute range
Two classes of monitored values – ones with limits and ones without. There seem to be lots and lots of observed values, but only some need limits. might want to make larger drawer of smaller displayed values that don’t need controls
Save/load parameters. Autosave, and autorestore if saved <5m ago, otherwise init from defaults.
Implement timed updates to plots to limit resource usage
Make class for setting values
Possible plots
Pressure vs. flow
flow vs volume
volume vs time
Performance
Cache drawText() calls in range selector by drawing to pixmap
Jonny Questions¶
Which alarm sounds to use?
Final final final breakdown on values and ranges plzzz
RR always has to be present, can only auto calculate InspT, I:E
make alarm dismissals all latch and snooze.
jonny todo¶
use loop_counter to check on controller advancement
choice between pressure/volume over time and combined P/V plot
display flow in SLM (liters per minute)
deque for alarm manager logged alarms
need confirmation for start button
GUI Object Documentation¶
Display¶
Unified monitor & control widgets
Display sensor values, control control values, turns out it’s all the same
Classes
|
|
|
Widget to display current value in a bar graph along with alarm limits |
-
class
pvp.gui.widgets.display.
Display
(value: pvp.common.values.Value, update_period: float = 0.5, enum_name: pvp.common.values.ValueName = None, button_orientation: str = 'left', control_type: Union[None, str] = None, style: str = 'dark', *args, **kwargs)[source]¶ - Parameters
value (
Value
) – Value Object to displayupdate_period (float) – time to wait in between updating displayed value
enum_name (
ValueName
) – Value name (not in Value objects)(str (style) – ‘left’ or ‘right’): whether the button should be on the left or right
(None, str (control_type) – ‘slider’, ‘record’): whether a slider, a button to record recent values, or
None
control should be used with this object(str – ‘light’, ‘dark’, or a QtStylesheet string): _style for the display
**kwargs (*args,) –
passed to
PySide2.QtWidgets.QWidget
Methods
__init__
(value, update_period, enum_name, …)- param value
Value Object to display
_value_changed
(new_value)“outward-directed” Control value changed by components
init_ui
()Basically two methods…
Create widgets to display sensed value alongside set value
redraw
()Redraw all graphical elements to ensure internal model matches view
set_locked
(locked)set_units
(units)Set pressure units to display as cmH2O or hPa
toggle_control
(state)toggle_record
(state)update_limits
(control)Update the alarm range and the GUI elements corresponding to it
update_sensor_value
(new_value)update_set_value
(new_value)inward value setting (set from elsewhere)
Attributes
-
self.
name
¶
-
self.
units
¶
-
self.
abs_range
¶
-
self.
safe_range
¶
-
self.
decimals
¶
-
self.
update_period
¶
-
self.
enum_name
¶
-
self.
orientation
¶
-
self.
control
¶
-
self.
_style
¶
-
self.
set_value
¶
-
self.
sensor_value
¶
-
limits_changed
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
value_changed
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
__init__
(value: pvp.common.values.Value, update_period: float = 0.5, enum_name: pvp.common.values.ValueName = None, button_orientation: str = 'left', control_type: Union[None, str] = None, style: str = 'dark', *args, **kwargs)[source]¶ - Parameters
value (
Value
) – Value Object to displayupdate_period (float) – time to wait in between updating displayed value
enum_name (
ValueName
) – Value name (not in Value objects)(str (style) – ‘left’ or ‘right’): whether the button should be on the left or right
(None, str (control_type) – ‘slider’, ‘record’): whether a slider, a button to record recent values, or
None
control should be used with this object(str – ‘light’, ‘dark’, or a QtStylesheet string): _style for the display
**kwargs (*args,) –
passed to
PySide2.QtWidgets.QWidget
-
self.
name
¶
-
self.
units
¶
-
self.
abs_range
¶
-
self.
safe_range
¶
-
self.
decimals
¶
-
self.
update_period
¶
-
self.
enum_name
¶
-
self.
orientation
¶
-
self.
control
¶
-
self.
_style
¶
-
self.
set_value
¶
-
self.
sensor_value
¶
-
init_ui_layout
()[source]¶ Basically two methods… lay objects out depending on whether we’re oriented with our button to the left or right
-
update_limits
(control: pvp.common.message.ControlSetting)[source]¶ Update the alarm range and the GUI elements corresponding to it
- Parameters
control (
ControlSetting
) – control setting with min_value or max_value
-
set_units
(units: str)[source]¶ Set pressure units to display as cmH2O or hPa
- Parameters
units ('cmH2O', 'hPa') –
-
property
is_set
¶
-
property
alarm_state
¶
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
class
pvp.gui.widgets.display.
Limits_Plot
(style: str = 'light', *args, **kwargs)[source]¶ Widget to display current value in a bar graph along with alarm limits
When initializing PlotWidget, parent and background are passed to
GraphicsWidget.__init__()
and all others are passed toPlotItem.__init__()
.Methods
init_ui
()update_value
(min, max, sensor_value, set_value)Move the lines! Pass any of the represented values
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
Control Panel¶
Classes
|
|
|
|
|
|
|
|
|
|
-
class
pvp.gui.widgets.control_panel.
Control_Panel
[source]¶ Start/stop button
- Status indicator - a clock that increments with heartbeats,
or some other visual indicator that things are alright
Status bar - most recent alarm or notification w/ means of clearing
Override to give 100% oxygen and silence all alarms
Methods
_pressure_units_changed
(button)add_alarm
(alarm)Wraps
Alarm_Bar.add_alarm()
clear_alarm
(alarm, alarm_type)Wraps
Alarm_Bar.clear_alarm()
init_ui
()-
pressure_units_changed
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
cycle_autoset_changed
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
add_alarm
(alarm: pvp.alarm.alarm.Alarm)[source]¶ Wraps
Alarm_Bar.add_alarm()
- Parameters
alarm (
Alarm
) – passed toAlarm_Bar
-
clear_alarm
(alarm: pvp.alarm.alarm.Alarm = None, alarm_type: pvp.alarm.AlarmType = None)[source]¶ Wraps
Alarm_Bar.clear_alarm()
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
class
pvp.gui.widgets.control_panel.
Start_Button
(*args, **kwargs)[source]¶ Methods
set_state
(state)Should only be called by other objects (as there are checks to whether it’s ok to start/stop that we shouldn’t be aware of)
Attributes
Built-in mutable sequence.
-
states
= ['OFF', 'ON', 'ALARM']¶
-
set_state
(state)[source]¶ Should only be called by other objects (as there are checks to whether it’s ok to start/stop that we shouldn’t be aware of)
- Parameters
state (str) –
('OFF', 'ON', 'ALARM')
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
-
class
pvp.gui.widgets.control_panel.
Lock_Button
(*args, **kwargs)[source]¶ Methods
set_state
(state)Should only be called by other objects (as there are checks to whether it’s ok to start/stop that we shouldn’t be aware of)
Attributes
Built-in mutable sequence.
-
states
= ['DISABLED', 'UNLOCKED', 'LOCKED']¶
-
set_state
(state)[source]¶ Should only be called by other objects (as there are checks to whether it’s ok to start/stop that we shouldn’t be aware of)
- Parameters
state (str) –
('OFF', 'ON', 'ALARM')
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
-
class
pvp.gui.widgets.control_panel.
HeartBeat
(update_interval=100, timeout_dur=5000)[source]¶ Methods
__init__
([update_interval, timeout_dur])-
pvp.gui.widgets.control_panel.
_state
¶
Called every (update_interval) milliseconds to set the check the status of the heartbeat.
beatheart
(heartbeat_time)init_ui
()set_indicator
([state])set_state
(state)start_timer
([update_interval])- param update_interval
How often (in ms) the timer should be updated.
you can read the sign ya punk
- Parameters
-
timeout
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
heartbeat
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
start_timer
(update_interval=None)[source]¶ - Parameters
update_interval (float) – How often (in ms) the timer should be updated.
-
_heartbeat
()[source]¶ Called every (update_interval) milliseconds to set the check the status of the heartbeat.
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
-
class
pvp.gui.widgets.control_panel.
StopWatch
(update_interval: float = 100, *args, **kwargs)[source]¶ - Parameters
update_interval (float) – update clock every n seconds
*args –
**kwargs –
Methods
__init__
(update_interval, *args, **kwargs)- param update_interval
update clock every n seconds
init_ui
()start_timer
([update_interval])- param update_interval
How often (in ms) the timer should be updated.
you can read the sign ya punk
-
__init__
(update_interval: float = 100, *args, **kwargs)[source]¶ - Parameters
update_interval (float) – update clock every n seconds
*args –
**kwargs –
-
start_timer
(update_interval=None)[source]¶ - Parameters
update_interval (float) – How often (in ms) the timer should be updated.
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
Plot¶
Classes
|
|
|
Data
Update frequency of |
|
-
class
pvp.gui.widgets.plot.
Plot
(name, buffer_size=4092, plot_duration=10, abs_range=None, plot_limits: tuple = None, color=None, units='', **kwargs)[source]¶ - Parameters
name –
buffer_size –
plot_duration –
abs_range –
plot_limits (tuple) – tuple of (ValueName)s for which to make pairs of min and max range lines
color –
units –
**kwargs –
Methods
__init__
(name[, buffer_size, plot_duration, …])- param name
_safe_limits_changed
(val)set_duration
(dur)set_safe_limits
(limits)set_units
(units)update_value
(new_value)new_value (tuple): (timestamp from time.time(), breath_cycle, value)
-
limits_changed
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
__init__
(name, buffer_size=4092, plot_duration=10, abs_range=None, plot_limits: tuple = None, color=None, units='', **kwargs)[source]¶ - Parameters
name –
buffer_size –
plot_duration –
abs_range –
plot_limits (tuple) – tuple of (ValueName)s for which to make pairs of min and max range lines
color –
units –
**kwargs –
-
update_value
(new_value: tuple)[source]¶ new_value (tuple): (timestamp from time.time(), breath_cycle, value)
-
set_safe_limits
(limits: pvp.common.message.ControlSetting)[source]¶
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
class
pvp.gui.widgets.plot.
Plot_Container
(plot_descriptors: Dict[pvp.common.values.ValueName, pvp.common.values.Value], *args, **kwargs)[source]¶ Methods
init_ui
()set_duration
(duration)set_safe_limits
(control)toggle_plot
(state)update_value
(vals)-
update_value
(vals: pvp.common.message.SensorValues)[source]¶
-
set_safe_limits
(control: pvp.common.message.ControlSetting)[source]¶
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
Alarm Bar¶
Components¶
Classes
|
Slider capable of representing floats |
|
Editable label |
Custom key press handler |
|
|
Simple extension of toggle button with styling for clearer ‘ON’ vs ‘OFF’ |
|
with respct to https://stackoverflow.com/a/51057516 |
|
-
class
pvp.gui.widgets.components.
DoubleSlider
(decimals=1, *args, **kargs)[source]¶ Slider capable of representing floats
Ripped off from and https://stackoverflow.com/a/50300848 ,
Thank you!!!
Methods
_maximum
()_minimum
()maximum
(self)minimum
(self)setDecimals
(decimals)setMaximum
(self, arg__1)setMinimum
(self, arg__1)setSingleStep
(self, arg__1)setValue
(self, arg__1)singleStep
(self)value
(self)-
doubleValueChanged
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
-
class
pvp.gui.widgets.components.
KeyPressHandler
[source]¶ Custom key press handler https://gist.github.com/mfessenden/baa2b87b8addb0b60e54a11c1da48046
Methods
eventFilter
(self, watched, event)-
escapePressed
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
returnPressed
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
eventFilter
(self, watched: PySide2.QtCore.QObject, event: PySide2.QtCore.QEvent) → bool[source]¶
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
-
class
pvp.gui.widgets.components.
EditableLabel
(parent=None, **kwargs)[source]¶ Editable label https://gist.github.com/mfessenden/baa2b87b8addb0b60e54a11c1da48046
Methods
Escape event handler
labelPressedEvent
(event)Set editable if the left mouse button is clicked
Indicates the widget text has been updated
Return/enter event handler
setEditable
(editable)Action to make the widget editable
setText
(text)Standard QLabel text setter
text
()Standard QLabel text getter
-
textChanged
(*args, **kwargs) = <PySide2.QtCore.Signal object>¶
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
-
class
pvp.gui.widgets.components.
QHLine
(parent=None, color='#FFFFFF')[source]¶ with respct to https://stackoverflow.com/a/51057516
Methods
setColor
(color)-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
-
class
pvp.gui.widgets.components.
QVLine
(parent=None, color='#FFFFFF')[source]¶ Methods
setColor
(color)-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
-
-
class
pvp.gui.widgets.components.
OnOffButton
(state_labels: Tuple[str, str] = 'ON', 'OFF', toggled: bool = False, *args, **kwargs)[source]¶ Simple extension of toggle button with styling for clearer ‘ON’ vs ‘OFF’
- Parameters
state_labels (tuple) – tuple of strings to set when toggled and untoggled
toggled (bool) – initialize the button as toggled
*args – passed to
QPushButton
**kwargs – passed to
QPushButton
Methods
__init__
(state_labels, str] =, toggled, …)- param state_labels
tuple of strings to set when toggled and untoggled
set_state
(state)-
__init__
(state_labels: Tuple[str, str] = 'ON', 'OFF', toggled: bool = False, *args, **kwargs)[source]¶ - Parameters
state_labels (tuple) – tuple of strings to set when toggled and untoggled
toggled (bool) – initialize the button as toggled
*args – passed to
QPushButton
**kwargs – passed to
QPushButton
-
staticMetaObject
= <PySide2.QtCore.QMetaObject object>¶
Dialog¶
Functions
|
Creates a dialog box to display a message. |
-
pvp.gui.widgets.dialog.
pop_dialog
(message: str, sub_message: str = None, modality: <class 'PySide2.QtCore.Qt.WindowModality'> = PySide2.QtCore.Qt.WindowModality.NonModal, buttons: <class 'PySide2.QtWidgets.QMessageBox.StandardButton'> = PySide2.QtWidgets.QMessageBox.StandardButton.Ok, default_button: <class 'PySide2.QtWidgets.QMessageBox.StandardButton'> = PySide2.QtWidgets.QMessageBox.StandardButton.Ok)[source]¶ Creates a dialog box to display a message.
Note
This function does not call .exec_ on the dialog so that it can be managed by the caller.
- Parameters
message (str) – Message to be displayed
sub_message (str) – Smaller message displayed below main message (InformativeText)
modality (QtCore.Qt.WindowModality) – Modality of dialog box - QtCore.Qt.NonModal (default) is unblocking, QtCore.Qt.WindowModal is blocking
buttons (QtWidgets.QMessageBox.StandardButton) – Buttons for the window, can be
|
ed togetherdefault_button (QtWidgets.QMessageBox.StandardButton) – one of
buttons
, the highlighted button
- Returns
QtWidgets.QMessageBox
GUI Stylesheets¶
Data
(float): inter-update interval (seconds) for |
Functions
|
Apply Dark Theme to the Qt application instance. |
-
pvp.gui.styles.
MONITOR_UPDATE_INTERVAL
= 0.5¶ inter-update interval (seconds) for
Monitor
- Type
(float)
-
pvp.gui.styles.
set_dark_palette
(app)[source]¶ Apply Dark Theme to the Qt application instance.
- borrowed from https://github.com/gmarull/qtmodern/blob/master/qtmodern/styles.py
- Args:
app (QApplication): QApplication instance.
pvp.io package¶
Subpackages¶
Submodules¶
pvp.io.hal module¶
Module for interacting with physical and/or simulated devices installed on the ventilator.
Classes
|
Hardware Abstraction Layer for ventilator hardware. |
-
class
pvp.io.hal.
Hal
(config_file='pvp/io/config/devices.ini')[source]¶ Bases:
object
Hardware Abstraction Layer for ventilator hardware. Defines a common API for interacting with the sensors & actuators on the ventilator. The types of devices installed on the ventilator (real or simulated) are specified in a configuration file.
- Initializes HAL from config_file.
For each section in config_file, imports the class <type> from module <module>, and sets attribute self.<section> = <type>(**opts), where opts is a dict containing all of the options in <section> that are not <type> or <section>. For example, upon encountering the following entry in config_file.ini:
[adc] type = ADS1115 module = devices i2c_address = 0x48 i2c_bus = 1
- The Hal will:
- Import pvp.io.devices.ADS1115 (or ADS1015) as a local variable:
class_ = getattr(import_module(‘.devices’, ‘pvp.io’), ‘ADS1115’)
- Instantiate an ADS1115 object with the arguments defined in config_file and set it as an attribute:
self._adc = class_(pig=self.-pig,address=0x48,i2c_bus=1)
Note: RawConfigParser.optionxform() is overloaded here s.t. options are case sensitive (they are by default case insensitive). This is necessary due to the kwarg MUX which is so named for consistency with the config registry documentation in the ADS1115 datasheet. For example, A P4vMini pressure_sensor on pin A0 (MUX=0) of the ADC is passed arguments like:
- analog_sensor = AnalogSensor(
pig=self._pig, adc=self._adc, MUX=0, offset_voltage=0.25, output_span = 4.0, conversion_factor=2.54*20
)
Note: ast.literal_eval(opt) interprets integers, 0xFF, (a, b) etc. correctly. It does not interpret strings correctly, nor does it know ‘adc’ -> self._adc; therefore, these special cases are explicitly handled.
Methods
__init__
([config_file])Initializes HAL from config_file.
Attributes
Returns the pressure from the auxiliary pressure sensor, if so equipped.
The measured flow rate expiratory side.
The measured flow rate inspiratory side.
Returns the oxygen concentration from the primary oxygen sensor.
Returns the pressure from the primary pressure sensor.
The currently requested flow on the expiratory side as a proportion of the maximum.
The currently requested flow for the inspiratory proportional control valve as a proportion of maximum.
- Parameters
config_file (str) – Path to the configuration file containing the definitions of specific components on the ventilator machine. (e.g., config_file = “pvp/io/config/devices.ini”)
-
__init__
(config_file='pvp/io/config/devices.ini')[source]¶ - Initializes HAL from config_file.
For each section in config_file, imports the class <type> from module <module>, and sets attribute self.<section> = <type>(**opts), where opts is a dict containing all of the options in <section> that are not <type> or <section>. For example, upon encountering the following entry in config_file.ini:
[adc] type = ADS1115 module = devices i2c_address = 0x48 i2c_bus = 1
- The Hal will:
- Import pvp.io.devices.ADS1115 (or ADS1015) as a local variable:
class_ = getattr(import_module(‘.devices’, ‘pvp.io’), ‘ADS1115’)
- Instantiate an ADS1115 object with the arguments defined in config_file and set it as an attribute:
self._adc = class_(pig=self.-pig,address=0x48,i2c_bus=1)
Note: RawConfigParser.optionxform() is overloaded here s.t. options are case sensitive (they are by default case insensitive). This is necessary due to the kwarg MUX which is so named for consistency with the config registry documentation in the ADS1115 datasheet. For example, A P4vMini pressure_sensor on pin A0 (MUX=0) of the ADC is passed arguments like:
- analog_sensor = AnalogSensor(
pig=self._pig, adc=self._adc, MUX=0, offset_voltage=0.25, output_span = 4.0, conversion_factor=2.54*20
)
Note: ast.literal_eval(opt) interprets integers, 0xFF, (a, b) etc. correctly. It does not interpret strings correctly, nor does it know ‘adc’ -> self._adc; therefore, these special cases are explicitly handled.
- Parameters
config_file (str) – Path to the configuration file containing the definitions of specific components on the ventilator machine. (e.g., config_file = “pvp/io/config/devices.ini”)
-
property
pressure
¶ Returns the pressure from the primary pressure sensor.
-
property
oxygen
¶ Returns the oxygen concentration from the primary oxygen sensor.
-
property
aux_pressure
¶ Returns the pressure from the auxiliary pressure sensor, if so equipped. If a secondary pressure sensor is not defined, raises a RuntimeWarning.
-
property
flow_in
¶ The measured flow rate inspiratory side.
-
property
flow_ex
¶ The measured flow rate expiratory side.
-
property
setpoint_in
¶ The currently requested flow for the inspiratory proportional control valve as a proportion of maximum.
-
property
setpoint_ex
¶ The currently requested flow on the expiratory side as a proportion of the maximum.
Module contents¶
alarm¶
Main Alarm Module¶
Classes
|
An enumeration. |
|
An enumeration. |
-
class
pvp.alarm.
AlarmType
(value)[source]¶ An enumeration.
Attributes
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
int([x]) -> integer
-
LOW_PRESSURE
= 1¶
-
HIGH_PRESSURE
= 2¶
-
LOW_VTE
= 3¶
-
HIGH_VTE
= 4¶
-
LOW_PEEP
= 5¶
-
HIGH_PEEP
= 6¶
-
LOW_O2
= 7¶
-
HIGH_O2
= 8¶
-
OBSTRUCTION
= 9¶
-
LEAK
= 10¶
-
SENSORS_STUCK
= 11¶
-
BAD_SENSOR_READINGS
= 12¶
-
MISSED_HEARTBEAT
= 13¶
-
property
human_name
¶
-
Alarm Manager¶
Classes
|
-
class
pvp.alarm.alarm_manager.
Alarm_Manager
[source]¶ Attributes
dict() -> new empty dictionary
Built-in mutable sequence.
Built-in mutable sequence.
dict() -> new empty dictionary
When we
update_dependencies()
, we send back aControlSetting
with the new min/maxBuilt-in mutable sequence.
Instances of the Logger class represent a single logging channel.
Built-in mutable sequence.
dict() -> new empty dictionary
dict() -> new empty dictionary
Methods
add_callback
(callback)add_dependency_callback
(callback)check_rule
(rule, sensor_values)deactivate_alarm
(alarm)Mark an alarm’s internal active flags and remove from
active_alarms
dismiss_alarm
(alarm_type, duration)GUI or other object requests an alarm to be dismissed & deactivated
emit_alarm
(alarm_type, severity)Emit alarm (by calling all callbacks with it).
get_alarm_severity
(alarm_type)load_rule
(alarm_rule)register_alarm
(alarm)Add alarm to registry.
register_dependency
(condition, dependency, …)Add dependency in a Condition object to be updated when values are changed
reset
()reset all conditions, callbacks, and other stateful attributes and clear alarms
update
(sensor_values)update_dependencies
(control_setting)Update Condition objects that update their value according to some control parameter
-
cleared_alarms
¶ of
AlarmType
s, alarms that have been cleared but have not dropped back into the ‘off’ range to enable re-raising- Type
-
snoozed_alarms
¶ of
AlarmType
s : times, alarms that should not be raised because they have been silenced for a period of time- Type
If an Alarm_Manager already exists, when initing just return that one
-
_instance
= None¶
-
active_alarms
: Dict[pvp.alarm.AlarmType, pvp.alarm.alarm.Alarm] = {}¶
-
logged_alarms
: List[pvp.alarm.alarm.Alarm] = []¶
-
dependencies
= {}¶
-
pending_clears
= []¶
-
cleared_alarms
= []¶
-
snoozed_alarms
= {}¶
-
callbacks
= []¶
-
depends_callbacks
= []¶ When we
update_dependencies()
, we send back aControlSetting
with the new min/max
-
rules
= {}¶
-
logger
= <Logger pvp.alarm.alarm_manager (WARNING)>¶
-
load_rule
(alarm_rule: pvp.alarm.rule.Alarm_Rule)[source]¶
-
update
(sensor_values: pvp.common.message.SensorValues)[source]¶
-
check_rule
(rule: pvp.alarm.rule.Alarm_Rule, sensor_values: pvp.common.message.SensorValues)[source]¶
-
emit_alarm
(alarm_type: pvp.alarm.AlarmType, severity: pvp.alarm.AlarmSeverity)[source]¶ Emit alarm (by calling all callbacks with it).
Note
This method emits and clears alarms – a cleared alarm is emitted with
AlarmSeverity.OFF
- Parameters
alarm_type (
AlarmType
) –severity (
AlarmSeverity
) –
-
deactivate_alarm
(alarm: (<enum 'AlarmType'>, <class 'pvp.alarm.alarm.Alarm'>))[source]¶ Mark an alarm’s internal active flags and remove from
active_alarms
Note
This does not alert listeners that an alarm has been cleared, for that emit an alarm with AlarmSeverity.OFF
- Parameters
alarm –
Returns:
-
dismiss_alarm
(alarm_type: pvp.alarm.AlarmType, duration: float = None)[source]¶ GUI or other object requests an alarm to be dismissed & deactivated
GUI will wait until it receives an emit_alarm of severity == OFF to remove alarm widgets. If the alarm is not latched
If the alarm is latched, alarm_manager will not decrement alarm severity or emit OFF until a) the condition returns to OFF, and b) the user dismisses the alarm
-
get_alarm_severity
(alarm_type: pvp.alarm.AlarmType)[source]¶
-
register_alarm
(alarm: pvp.alarm.alarm.Alarm)[source]¶ Add alarm to registry.
- Parameters
alarm (
Alarm
) –
-
register_dependency
(condition: pvp.alarm.condition.Condition, dependency: dict, severity: pvp.alarm.AlarmSeverity)[source]¶ Add dependency in a Condition object to be updated when values are changed
- Parameters
condition –
dependency (dict) – either a (ValueName, attribute_name) or optionally also + transformation callable
severity (
AlarmSeverity
) – severity of dependency
-
update_dependencies
(control_setting: pvp.common.message.ControlSetting)[source]¶ Update Condition objects that update their value according to some control parameter
- Parameters
control_setting (
ControlSetting
) –
Returns:
-
Alarm¶
Classes
|
Class used by the program to control and coordinate alarms. |
-
class
pvp.alarm.alarm.
Alarm
(alarm_type: pvp.alarm.AlarmType, severity: pvp.alarm.AlarmSeverity, start_time: float = None, latch: bool = True, persistent: bool = True, cause: list = None, value=None, message=None)[source]¶ Class used by the program to control and coordinate alarms.
Parameterized by a
Alarm_Rule
and managed byAlarm_Manager
Methods
__init__
(alarm_type, severity, start_time, …)-
pvp.alarm.alarm.
id
¶
Attributes
itertools.count
: used to generate unique IDs for each alarm- Parameters
-
id_counter
= count(0)¶ used to generate unique IDs for each alarm
- Type
itertools.count
-
__init__
(alarm_type: pvp.alarm.AlarmType, severity: pvp.alarm.AlarmSeverity, start_time: float = None, latch: bool = True, persistent: bool = True, cause: list = None, value=None, message=None)[source]¶
-
property
severity
¶
-
property
alarm_type
¶
-
Condition¶
Classes
|
|
|
Base class for specifying alarm test conditions |
|
alarm goes out of range for a specific number of breath cycles |
|
value goes out of range for a specific number of breath cycles |
|
value goes out of range for specific amount of time |
|
value is greater or lesser than some max/min |
Functions
-
class
pvp.alarm.condition.
Condition
(depends: dict = None, *args, **kwargs)[source]¶ Base class for specifying alarm test conditions
Need to be able to condition alarms based on * value ranges * value ranges & durations * levels of other alarms
Methods
__init__
(depends, *args, **kwargs)- param depends
check
(sensor_values)reset
()If a condition is stateful, need to provide some method of resetting the state
Attributes
-
manager
¶ alarm manager, used to get status of alarms
- Parameters
-
property
manager
¶
-
class
pvp.alarm.condition.
ValueCondition
(value_name: pvp.common.values.ValueName, limit: (<class 'int'>, <class 'float'>), mode: str, *args, **kwargs)[source]¶ value is greater or lesser than some max/min
- Parameters
Methods
__init__
(value_name, limit, mode, *args, …)- param value_name
Which value to check
check
(sensor_values)reset
()not stateful, do nothing.
Attributes
-
__init__
(value_name: pvp.common.values.ValueName, limit: (<class 'int'>, <class 'float'>), mode: str, *args, **kwargs)[source]¶
-
property
mode
¶
-
class
pvp.alarm.condition.
CycleValueCondition
(n_cycles, *args, **kwargs)[source]¶ value goes out of range for a specific number of breath cycles
Methods
check
(sensor_values)reset
()not stateful, do nothing.
Attributes
-
_mid_check
¶ whether a value has left the acceptable range and we are counting consecutive breath cycles
- Type
Args: value_name (ValueName): Which value to check limit (int, float): value to check against mode (‘min’, ‘max’): whether the limit is a minimum or maximum *args: **kwargs:
-
property
n_cycles
¶
-
-
class
pvp.alarm.condition.
TimeValueCondition
(time, *args, **kwargs)[source]¶ value goes out of range for specific amount of time
- Parameters
time (float) – number of seconds value must be out of range
*args –
**kwargs –
Methods
__init__
(time, *args, **kwargs)- param time
number of seconds value must be out of range
check
(sensor_values)reset
()not stateful, do nothing.
-
class
pvp.alarm.condition.
AlarmSeverityCondition
(alarm_type: pvp.alarm.AlarmType, severity: pvp.alarm.AlarmSeverity, mode: str = 'min', *args, **kwargs)[source]¶ - Parameters
alarm_type –
severity –
mode (str) –
one of ‘min’, ‘equals’, or ‘max’. ‘min’ returns true if the alarm is at least this value (note the difference from ValueCondition which returns true if the alarm is less than..) and vice versa for ‘max’.
Note
’min’ and ‘max’ use >= and <= rather than > and <
*args –
**kwargs –
Methods
__init__
(alarm_type, severity, mode, *args, …)- param alarm_type
check
(sensor_values)reset
()If a condition is stateful, need to provide some method of resetting the state
Attributes
-
__init__
(alarm_type: pvp.alarm.AlarmType, severity: pvp.alarm.AlarmSeverity, mode: str = 'min', *args, **kwargs)[source]¶ - Parameters
alarm_type –
severity –
mode (str) –
one of ‘min’, ‘equals’, or ‘max’. ‘min’ returns true if the alarm is at least this value (note the difference from ValueCondition which returns true if the alarm is less than..) and vice versa for ‘max’.
Note
’min’ and ‘max’ use >= and <= rather than > and <
*args –
**kwargs –
-
property
mode
¶
-
class
pvp.alarm.condition.
CycleAlarmSeverityCondition
(n_cycles, *args, **kwargs)[source]¶ alarm goes out of range for a specific number of breath cycles
Todo
note that this is exactly the same as CycleValueCondition. Need to do the multiple inheritance thing
Methods
check
(sensor_values)reset
()If a condition is stateful, need to provide some method of resetting the state
Attributes
-
_mid_check
¶ whether a value has left the acceptable range and we are counting consecutive breath cycles
- Type
Args: alarm_type: severity: mode (str): one of ‘min’, ‘equals’, or ‘max’.
‘min’ returns true if the alarm is at least this value (note the difference from ValueCondition which returns true if the alarm is less than..) and vice versa for ‘max’.
Note
‘min’ and ‘max’ use >= and <= rather than > and <
-
property
n_cycles
¶
-
Alarm Rule¶
Class to declare alarm rules
Classes
|
|
-
class
pvp.alarm.rule.
Alarm_Rule
(name: pvp.alarm.AlarmType, conditions, latch=True, persistent=True, technical=False)[source]¶ name of rule
conditions: ((alarm_type, (condition_1, condition_2)), …)
persistent (bool): if True, alarm will not be visually dismissed until alarm conditions are no longer true
latch (bool): if True, alarm severity cannot be decremented until user manually dismisses
silencing/overriding rules
Methods
check
(sensor_values)Check all of our
conditions
.reset
()Attributes
Get all ValueNames whose alarm limits depend on this alarm rule
Last Alarm Severity from
.check()
Get all ValueNames specified as value_names in alarm conditions
-
property
severity
¶ Last Alarm Severity from
.check()
:returns:AlarmSeverity
-
property
depends
¶ Get all ValueNames whose alarm limits depend on this alarm rule :returns: list[ValueName]
-
property
value_names
¶ Get all ValueNames specified as value_names in alarm conditions
- Returns
list[ValueName]
Changelog¶
Version 0.0¶
v0.0.2 (April xxth, 2020)¶
Refactored gui into a module, splitting
widgets
,styles
, anddefaults
.
v0.0.1 (April 12th, 2020)¶
Added changelog
Moved requirements for building docs to requirements_docs.txt so regular program reqs are a bit lighter.
added autosummaries
added additional resources & documentation files, with examples for adding external files like pdfs
v0.0.0 (April 12th, 2020)¶
Example of a changelog entry!!!
We fixed this
and this
and this
Warning
but we didn’t do this thing
Todo
and we still have to do this other thing.
Building the Docs¶
A very brief summary…
Docs are configured to be built from
_docs
intodocs
.The main page is
index.rst
which links to the existing modulesTo add a new page, you can create a new
.rst
file if you are writing with Restructuredtext , or a .md file if you are writing with markdown.
Local Build¶
pip install -r requirements.txt
cd _docs
make html
Documentation will be generated into docs
Advertisement :)
pica - high quality and fast image resize in browser.
babelfish - developer friendly i18n with plurals support and easy syntax.
You will like those projects!
h1 Heading 8-)¶
Blockquotes¶
Blockquotes can also be nested…
…by using additional greater-than signs right next to each other…
…or with spaces between arrows.
Lists¶
Unordered
Create a list by starting a line with
+
,-
, or*
Sub-lists are made by indenting 2 spaces:
Marker character change forces new list start:
Ac tristique libero volutpat at
Facilisis in pretium nisl aliquet
Nulla volutpat aliquam velit
Very easy!
Ordered
Lorem ipsum dolor sit amet
Consectetur adipiscing elit
Integer molestie lorem at massa
You can use sequential numbers…
…or keep all the numbers as
1.
Code¶
Inline code
Indented code
// Some comments
line 1 of code
line 2 of code
line 3 of code
Block code “fences”
Sample text here...
Syntax highlighting
var foo = function (bar) {
return bar++;
};
console.log(foo(5));
Images¶
Minion
Stormtroopocat
Like links, Images also have a footnote style syntax
Alt text
With a reference later in the document defining the URL location: