Source code for vent.common.values

from collections import OrderedDict as odict
from enum import Enum, auto

# TODO: Zhenyu's job is to make sure the print value is an intepretable string
[docs]class ValueName(Enum): #Setting that are likely important for future adjustements PIP = auto() # PIP pressure PIP_TIME = auto() # time to reach PIP PEEP = auto() # PEEP pressure PEEP_TIME = auto() # time to reach PEEP BREATHS_PER_MINUTE = auto() INSPIRATION_TIME_SEC = auto() IE_RATIO = auto() #Settings that are read out, but can not be controlled by software FIO2 = auto() TEMP = auto() HUMIDITY = auto() VTE = auto() PRESSURE = auto()
controllable_values = { ValueName.PIP, ValueName.PIP_TIME, ValueName.PEEP, ValueName.BREATHS_PER_MINUTE, ValueName.INSPIRATION_TIME_SEC, ValueName.IE_RATIO } non_controllable_values = { # TODO: is PEEP_TIME controllable? control_module doesn't allow set_control on it ValueName.PEEP_TIME, ValueName.FIO2, ValueName.TEMP, ValueName.HUMIDITY, ValueName.VTE, ValueName.PRESSURE, }
[docs]class Value(object):
[docs] def __init__(self, name: str, units: str, abs_range: tuple, safe_range: tuple, decimals: int, control: bool, sensor: bool, default: (int, float) = None): """ Definition of a value. Used by the GUI and control module to set defaults. Args: 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 """ self._name = None self._units = None self._abs_range = None self._safe_range = None self._decimals = None self._default = None self._control = None self._sensor = None self.name = name self.units = units self.abs_range = abs_range self.safe_range = safe_range self.decimals = decimals self.control = control self.sensor = sensor if default is not None: self.default = default
@property def name(self) -> str: return self._name @name.setter def name(self, name): assert(isinstance(name, str)) self._name = name @property def abs_range(self) -> tuple: return self._abs_range @abs_range.setter def abs_range(self, abs_range): assert(isinstance(abs_range, tuple) or isinstance(abs_range, list)) assert(all([isinstance(x, int) or isinstance(x, float) for x in abs_range])) self._abs_range = abs_range @property def safe_range(self) -> tuple: return self._safe_range @safe_range.setter def safe_range(self, safe_range): assert(isinstance(safe_range, tuple) or isinstance(safe_range, list)) assert(all([isinstance(x, int) or isinstance(x, float) for x in safe_range])) self._safe_range = safe_range @property def decimals(self) -> int: return self._decimals @decimals.setter def decimals(self, decimals): assert(isinstance(decimals, int)) self._decimals = decimals @property def default(self): return self._default @default.setter def default(self, default): assert(isinstance(default, int) or isinstance(default, float)) self._default = default @property def control(self): return self._control @control.setter def control(self, control): assert(isinstance(control, bool)) self._control = control @property def sensor(self): return self._sensor @sensor.setter def sensor(self, sensor): assert(isinstance(sensor, bool)) self._sensor = sensor def __setitem__(self, key, value): self.__setattr__(key, value) def __getitem__(self, key): return self.__getattribute__(key)
[docs] def to_dict(self): return { 'name': self.name, 'units': self.units, 'abs_range': self.abs_range, 'safe_range': self.safe_range, 'decimals': self.decimals, 'default': self.default, 'control': self.control, 'sensor': self.sensor }
VALUES = odict({ ValueName.FIO2: Value(**{ 'name': 'FiO2', 'units': '%', 'abs_range': (0, 100), 'safe_range': (20, 100), 'decimals' : 1, 'control': False, 'sensor': True }), ValueName.TEMP: Value(**{ 'name': 'Temp', 'units': '\N{DEGREE SIGN}C', 'abs_range': (35, 40), 'safe_range': (36, 39), 'decimals': 1, 'control': False, 'sensor': True }), ValueName.HUMIDITY: Value(**{ 'name': 'Humidity', 'units': '%', 'abs_range': (0, 100), 'safe_range': (70, 100), 'decimals': 1, 'control': False, 'sensor': True }), ValueName.VTE: Value(**{ 'name': 'VTE', 'units': 'l', # Unit is liters :-) 'abs_range': (0, 100), 'safe_range': (0, 100), 'decimals': 2, 'control': False, 'sensor': True }), ValueName.PRESSURE: Value(**{ 'name': 'Pressure', 'units': 'mmH2O', 'abs_range': (0,70), 'safe_range': (0,60), 'decimals': 1, 'control': False, 'sensor': True }), ValueName.IE_RATIO: Value(**{ 'name': 'I:E Ratio', 'units': '', 'abs_range': (0, 2), 'safe_range': (0.33, 1), 'decimals': 2, 'control': False, 'sensor': False }), ValueName.PIP: Value(**{ 'name': 'PIP', # (Peak Inspiratory Pressure) 'units': 'cm H2O', 'abs_range': (0, 70), # FIXME 'safe_range': (0, 50), # From DrDan https://tigervents.slack.com/archives/C011MRVJS7L/p1588190130492300 'default': 22, # FIXME 'decimals': 1, 'control': True, 'sensor': True }), ValueName.PIP_TIME: Value(**{ 'name': 'PIPt', 'units': 'seconds', 'abs_range': (0, 5), # FIXME 'safe_range': (0.2, 0.5), # FIXME 'default': 0.3, # FIXME 'decimals': 1, 'control': True, 'sensor': False }), ValueName.INSPIRATION_TIME_SEC: Value(**{ 'name': 'INSPt', 'units': 'seconds', 'abs_range': (0, 5), # FIXME 'safe_range': (1, 3.0), # FIXME 'default': 2.0, # FIXME 'decimals': 1, 'control': True, 'sensor': True }), ValueName.PEEP: Value(**{ 'name': 'PEEP', # (Positive End Expiratory Pressure) 'units': 'cm H2O', 'abs_range': (0, 20), # FIXME 'safe_range': (0, 16), # From DrDan https://tigervents.slack.com/archives/C011MRVJS7L/p1588190130492300 'default': 5, # FIXME 'decimals': 1, 'control': True, 'sensor': True }), ValueName.PEEP_TIME: Value(**{ 'name': 'PEEPt', 'units': 'seconds', 'abs_range': (0, 2), # FIXME 'safe_range': (0, 1.0), # FIXME 'default': 0.5, # FIXME 'decimals': 1, 'control': True, 'sensor': False }), ValueName.BREATHS_PER_MINUTE: Value(**{ 'name': 'RR', # Daniel re: FDA labels 'units': 'BPM', # Daniel re: FDA labels 'abs_range': (0, 50), # FIXME 'safe_range': (10, 30), # Stanford's socs https://www.vent4us.org/technical 'default': 17, # FIXME 'decimals': 1, 'control': True, 'sensor': True }), }) SENSOR = odict({ k:v for k, v in VALUES.items() if v.sensor == True }) """ 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 } """ CONTROL = odict({ k: v for k, v in VALUES.items() if v.control == True }) """ 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 } """ 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. """