From 105b36165c3b8f9acff1d7a0399abac0d4f437ed Mon Sep 17 00:00:00 2001 From: Sean Marquez Date: Tue, 28 Jul 2020 18:42:47 -0700 Subject: [PATCH 1/2] move display code to project-tetra-display repo --- Documentation/HowToRunDockerFromPython.md | 31 ++++ Documentation/HowToUseSPL06_007.md | 16 ++ features/environment.py | 8 + .../runs_backend_from_docker_image.feature | 8 + .../steps/runs_backend_from_docker_image.py | 25 +++ rpi_check.py | 115 +++++++++++++ runtests.sh | 6 + sensors.py | 157 ++++++++++++++++++ setup.sh | 12 ++ 9 files changed, 378 insertions(+) create mode 100644 Documentation/HowToRunDockerFromPython.md create mode 100644 Documentation/HowToUseSPL06_007.md create mode 100644 features/environment.py create mode 100644 features/runs_backend_from_docker_image.feature create mode 100644 features/steps/runs_backend_from_docker_image.py create mode 100644 rpi_check.py create mode 100755 runtests.sh create mode 100644 sensors.py create mode 100755 setup.sh diff --git a/Documentation/HowToRunDockerFromPython.md b/Documentation/HowToRunDockerFromPython.md new file mode 100644 index 0000000..bfdda5e --- /dev/null +++ b/Documentation/HowToRunDockerFromPython.md @@ -0,0 +1,31 @@ +How to Run a Docker Container from a Python Script +================================================== + +Docker is a very useful tool for when you want to run an application from a known environment. If you're developing a Docker container and testing the components within it outside the container, you may want to write a test program to validate your container. The obvious way to do this in Python is by calling shell commands with `os.system()`. But you can, in fact, use the Docker SDK to do this! + +This snippet here +```python +import docker + +client = docker.from_env() +image = client.images.build( + path=".", tag="example:latest") +container_name = "example_container" +client.containers.run("example:latest", + name=container_name, + detach=True, + auto_remove=True, + ports={"8000/tcp": 8000}) + +# Test that it's working + +client.containers.get(container_name).kill() +``` +is equivalent to this shell script. +```bash +docker build -t example:latest . +docker run --rm -dp 8000:8000 --name example_container example:latest +# Test that it's working +docker kill example_container +``` +You can learn more about the Docker SDK at https://docker-py.readthedocs.io/en/stable/. diff --git a/Documentation/HowToUseSPL06_007.md b/Documentation/HowToUseSPL06_007.md new file mode 100644 index 0000000..2087cc9 --- /dev/null +++ b/Documentation/HowToUseSPL06_007.md @@ -0,0 +1,16 @@ +How to Use the SPL06-007 Pressure Sensor +======================================== + +The SPL06-007 is a calibrated pressure sensor often used for drone applications. This describes how to use the sensor via it's I2C interface, though it'd only really be a change in the first step to use a 3- or 4-wire SPI interface (and in hardware of course). Note that I connected the sensor to a Raspberry Pi via an I2C multiplexor (mux), so the second step isn't necessary if you don't have that. + +- To initialize I2C, I use Adafruit's busio.I2C(board.SCL, board.SDA) +- For the mux select, I write a [0-4] integer to 0x70 (there's also a mux on 0x74, but I don't have anything connected to it right now, so it doesn't do anything. +- I then reset the sensor to clear any previous state by writing 0b1001 to 0x0C +- After that, I set the sensor into standby mode by writing 0 to 0x08 +- Then in the case of the tests I'm having issues with, I set the sensor to measure pressure at 1Hz with 16 measurements per sample by writing 0 | 0b0100 to 0x06. Because there are more than 8 measurements per sample, I also set the sensor to bit shift the pressure by writing 0b0100 to 0x09. +- I do the same to get the temperature, but now it's 1Hz 1 sample, so 0 | 0 gets written to 0x07. +- Then I set the op mode to "command-pressure" by writing 0b0001 to 0x08 so I can read out what the current pressure is. +- After waiting a few milliseconds for the measurement to be ready, I read addresses 0x00, 0x01, and 0x02 to get the pressure measurement. +- Then the op mode is changed to "command-temperature" by writing 0b0010 to 0x08. +- Finally, I read the temperature measurement from 0x03, 0x04, and 0x05 + diff --git a/features/environment.py b/features/environment.py new file mode 100644 index 0000000..b227a11 --- /dev/null +++ b/features/environment.py @@ -0,0 +1,8 @@ + + +def after_step(context, step): + if step.status == "failed": + try: + context.client.containers.get(context.container_name).kill() + except NameError: + pass diff --git a/features/runs_backend_from_docker_image.feature b/features/runs_backend_from_docker_image.feature new file mode 100644 index 0000000..fc03f9e --- /dev/null +++ b/features/runs_backend_from_docker_image.feature @@ -0,0 +1,8 @@ +Feature: Runs backend from a Docker image + +@wip +@slow +Scenario: + Given a Docker image is built + When that image is run on port 8000 + Then there will be a JSON packet sent every 1.0 seconds diff --git a/features/steps/runs_backend_from_docker_image.py b/features/steps/runs_backend_from_docker_image.py new file mode 100644 index 0000000..1d9fd4c --- /dev/null +++ b/features/steps/runs_backend_from_docker_image.py @@ -0,0 +1,25 @@ +from behave import given, when, then + +import docker + + +@given("a Docker image is built") +def step_impl(context): + context.client = docker.from_env() + context.image = context.client.images.build( + path=".", tag="zmq_proxy:latest") + + +@when("that image is run on port {port}") +def step_impl(context, port): + context.container_name = "zmq_proxy" + context.client.containers.run("zmq_proxy:latest", + name=context.container_name, + detach=True, + auto_remove=True, + ports={"8000/tcp": port}) + + +@then("there will be a JSON packet sent every {t} seconds") +def step_impl(context, t): + context.client.containers.get(context.container_name).kill() diff --git a/rpi_check.py b/rpi_check.py new file mode 100644 index 0000000..bcd82da --- /dev/null +++ b/rpi_check.py @@ -0,0 +1,115 @@ +# This is almost entirely copied from +# https://github.com/adafruit/Adafruit_Python_GPIO/blob/master/Adafruit_GPIO/Platform.py +# except for the method is_on_raspberry_pi, which was added for this +# project + +import platform +import re + + +# Platform identification constants. +UNKNOWN = 0 +RASPBERRY_PI = 1 +BEAGLEBONE_BLACK = 2 +MINNOWBOARD = 3 +JETSON_NANO = 4 + + +def platform_detect(): + """Detect if running on the Raspberry Pi or Beaglebone Black and return the + platform type. Will return RASPBERRY_PI, BEAGLEBONE_BLACK, or UNKNOWN.""" + # Handle Raspberry Pi + pi = pi_version() + if pi is not None: + return RASPBERRY_PI + + # Handle Beaglebone Black + # TODO: Check the Beaglebone Black /proc/cpuinfo value instead of reading + # the platform. + plat = platform.platform() + if plat.lower().find('armv7l-with-debian') > -1: + return BEAGLEBONE_BLACK + elif plat.lower().find('armv7l-with-ubuntu') > -1: + return BEAGLEBONE_BLACK + elif plat.lower().find('armv7l-with-glibc2.4') > -1: + return BEAGLEBONE_BLACK + elif plat.lower().find('tegra-aarch64-with-ubuntu') > -1: + return JETSON_NANO + + # Handle Minnowboard + # Assumption is that mraa is installed + try: + import mraa + if mraa.getPlatformName()=='MinnowBoard MAX': + return MINNOWBOARD + except ImportError: + pass + + # Couldn't figure out the platform, just return unknown. + return UNKNOWN + + +def pi_revision(): + """Detect the revision number of a Raspberry Pi, useful for changing + functionality like default I2C bus based on revision.""" + # Revision list available at: http://elinux.org/RPi_HardwareHistory#Board_Revision_History + with open('/proc/cpuinfo', 'r') as infile: + for line in infile: + # Match a line of the form "Revision : 0002" while ignoring extra + # info in front of the revsion (like 1000 when the Pi was over-volted). + match = re.match('Revision\s+:\s+.*(\w{4})$', line, flags=re.IGNORECASE) + if match and match.group(1) in ['0000', '0002', '0003']: + # Return revision 1 if revision ends with 0000, 0002 or 0003. + return 1 + elif match: + # Assume revision 2 if revision ends with any other 4 chars. + return 2 + # Couldn't find the revision, throw an exception. + raise RuntimeError('Could not determine Raspberry Pi revision.') + + +def pi_version(): + """Detect the version of the Raspberry Pi. Returns either 1, 2 or + None depending on if it's a Raspberry Pi 1 (model A, B, A+, B+), + Raspberry Pi 2 (model B+), or not a Raspberry Pi. + """ + # Check /proc/cpuinfo for the Hardware field value. + # 2708 is pi 1 + # 2709 is pi 2 + # 2835 is pi 3 on 4.9.x kernel + # Anything else is not a pi. + with open('/proc/cpuinfo', 'r') as infile: + cpuinfo = infile.read() + # Match a line like 'Hardware : BCM2709' + match = re.search('^Hardware\s+:\s+(\w+)$', cpuinfo, + flags=re.MULTILINE | re.IGNORECASE) + if not match: + # Couldn't find the hardware, assume it isn't a pi. + return None + if match.group(1) == 'BCM2708': + # Pi 1 + return 1 + elif match.group(1) == 'BCM2709': + # Pi 2 + return 2 + elif match.group(1) == 'BCM2835': + # Pi 3 / Pi on 4.9.x kernel + return 3 + else: + # Something else, not a pi. + return None + + +def is_on_raspberry_pi(): + """Method to determine if the current platform is a Raspberry Pi. + It's able to tell Pis from similar boards like Beaglebone Blacks. + + Adapted from https://github.com/adafruit/Adafruit_Python_GPIO/blob/master/Adafruit_GPIO/Platform.py + """ + try: + if platform_detect == RASPBERRY_PI: + return True + else: + return False + except FileNotFoundError: + return False diff --git a/runtests.sh b/runtests.sh new file mode 100755 index 0000000..e61f32a --- /dev/null +++ b/runtests.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +echo "Behaviour Tests:" +behave +echo $'\nUnit Tests:' +python3 -m unittest diff --git a/sensors.py b/sensors.py new file mode 100644 index 0000000..4e842ba --- /dev/null +++ b/sensors.py @@ -0,0 +1,157 @@ +import os +import random +from abc import ABC, abstractmethod + +from processsampledata import ProcessSampleData +from rpi_check import is_on_raspberry_pi +import constants + + +class SensorsDataABC(ABC): + + @abstractmethod + def __init__(self, + pressure_sampling_rate, + pressure_oversampling, + temperature_sampling_rate, + temperature_oversampling): + super().__init__() + + @abstractmethod + def connected_sensors(self): + pass + + @abstractmethod + def calibration_pressure_sensor_connected(self): + pass + + @abstractmethod + def poll(self): + pass + + +if is_on_raspberry_pi(): + + class SensorsData(SensorsDataABC): + """Actual implementation""" + + def __init__(self, + pressure_sampling_rate, + pressure_oversampling, + temperature_sampling_rate, + temperature_oversampling): + pass + + def connected_sensors(self): + pass + + def calibration_pressure_sensor_connected(self): + pass + + def poll(self): + pass + + +else: + + class SensorsData(SensorsDataABC): + """Dummy class while I work on the real thing""" + + def __init__(self, + pressure_sampling_rate, + pressure_oversampling, + temperature_sampling_rate, + temperature_oversampling): + self._fake_data = \ + ProcessSampleData("TestData/20200609T2358Z_patrickData.txt") + self._data_index = 0 + + def connected_sensors(self, not_enough_sensors=False): + try: + if (os.environ[constants.SENSOR_QUANTITY] + == constants.NOT_ENOUGH_SENSORS): + sensors = tuple([(constants.PRESSURE_SENSOR,)] + + [(constants.PRESSURE_SENSOR, + constants.SENSIRION_SENSOR) + for _ in range(constants. + NUMBER_OF_PATIENTS-1) + ]) + raise NotEnoughSensors( + f"{len(self._tubes_with_enough_sensors(sensors))} " + "tube(s) do not have both a pressure sensor " + "and a flow sensor") + + elif (os.environ[constants.SENSOR_QUANTITY] + == constants.TOO_MANY_SENSORS): + return tuple([(constants.PRESSURE_SENSOR, + constants.SENSIRION_SENSOR, + constants.MASS_AIRFLOW_SENSOR)] + + [(constants.PRESSURE_SENSOR, + constants.SENSIRION_SENSOR) + for _ in range(constants. + NUMBER_OF_PATIENTS-1) + ]) + except KeyError: + pass + return tuple((constants.PRESSURE_SENSOR, + constants.SENSIRION_SENSOR) + for _ in range(constants.NUMBER_OF_PATIENTS)) + + def calibration_pressure_sensor_connected(self, fail=False): + if fail: + return False + else: + return True + + def poll(self): + """Pulls data from the pressure and flow sensors""" + self._data_index += 1 + return tuple((self._fake_data.pressures[self._data_index-1], + self._fake_data.flow_rates[self._data_index-1]) + for _ in range(constants.NUMBER_OF_PATIENTS)) + + def _tubes_with_enough_sensors(self, tubes_sensors): + tubes = [] + for tube in tubes_sensors: + if (constants.PRESSURE_SENSOR in tube + and (constants.SENSIRION_SENSOR in tube + or constants.MASS_AIRFLOW_SENSOR in tube)): + tubes.append(tube) + return tubes + + +class Sensors(): + + def __init__(self, + pressure_sampling_rate, + pressure_oversampling, + temperature_sampling_rate, + temperature_oversampling): + self._sensors_data = SensorsData(pressure_sampling_rate, + pressure_oversampling, + temperature_sampling_rate, + temperature_oversampling) + + def calibrate(self): + pass + + def calibration_pressure_sensor_connected(self): + pass + + def tubes_with_enough_sensors(self): + tubes = [] + sensors = self._sensors_data.connected_sensors() + for i in range(len(sensors)): + if (constants.PRESSURE_SENSOR in sensors[i] + and (constants.SENSIRION_SENSOR in sensors[i]) + or constants.MASS_AIRFLOW_SENSOR in sensors[i]): + tubes.append(i) + + return tubes + + def poll(self): + return self._sensors_data.poll() + + +class NotEnoughSensors(Exception): + pass diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..c2d587e --- /dev/null +++ b/setup.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +if ! [ -d venv ]; then + python3 -m venv venv +fi + +if [ -f requirements.txt ]; then + pip3 install -r requirements.txt +fi + +echo $'\nrun this:' +echo source ./venv/bin/activate From f426632f93319b8487d929a79d977c0cc482eb3c Mon Sep 17 00:00:00 2001 From: Fletcher Porter Date: Wed, 29 Jul 2020 02:42:18 -0700 Subject: [PATCH 2/2] added missing files --- Dockerfile | 23 + .../HowToRunAnApplicationAtLaunchOnAnRPi.md | 14 + .../HowToSetUpAnRPiForHeadlessDevelopment.md | 28 + Documentation/HowToTurnOn.md | 35 + Documentation/TubingDataInformationScreen.odp | Bin 0 -> 160245 bytes Documentation/TubingDataInformationScreen.pdf | Bin 0 -> 87180 bytes README.md | 38 + Scripts/__init__.py | 0 Scripts/green.py | 18 + Scripts/i2c_scan.py | 24 + Scripts/poll_spl06_007.py | 32 + TestData/20200609T2358Z_patrickData.txt | 546 ++++++++++++ Tests/__init__.py | 0 Tests/test_causal_integral_filter.py | 72 ++ Tests/test_causalvelocityfilter.py | 56 ++ Tests/test_discretetransferfunction.py | 167 ++++ Tests/test_i2c_interface.py | 47 ++ Tests/test_moving_average_filter.py | 49 ++ .../test_patienttubingdescriptorcalculator.py | 30 + Tests/test_sensors.py | 35 + Tests/test_server.py | 23 + Tests/test_sfm3300d.py | 123 +++ Tests/test_spl06_007.py | 391 +++++++++ __init__.py | 0 causal_integral_filter.py | 19 + causal_velocity_filter.py | 34 + constants.py | 19 + discrete_transfer_function.py | 123 +++ i2c_interface.py | 227 +++++ main.go | 93 +++ moving_average_filter.py | 46 ++ patienttubingdescriptorcalculator.py | 46 ++ process_sample_data.py | 101 +++ requirements.txt | 9 + rpi_check.py | 116 +-- sensors.py | 252 ++++-- server.py | 65 ++ services.conf | 7 + setup.sh | 16 +- sfm3300d.py | 171 ++++ spl06_007.py | 774 ++++++++++++++++++ tca9548a.py | 19 + 42 files changed, 3686 insertions(+), 202 deletions(-) create mode 100644 Dockerfile create mode 100644 Documentation/HowToRunAnApplicationAtLaunchOnAnRPi.md create mode 100644 Documentation/HowToSetUpAnRPiForHeadlessDevelopment.md create mode 100644 Documentation/HowToTurnOn.md create mode 100644 Documentation/TubingDataInformationScreen.odp create mode 100644 Documentation/TubingDataInformationScreen.pdf create mode 100644 README.md create mode 100644 Scripts/__init__.py create mode 100644 Scripts/green.py create mode 100644 Scripts/i2c_scan.py create mode 100644 Scripts/poll_spl06_007.py create mode 100644 TestData/20200609T2358Z_patrickData.txt create mode 100644 Tests/__init__.py create mode 100644 Tests/test_causal_integral_filter.py create mode 100644 Tests/test_causalvelocityfilter.py create mode 100644 Tests/test_discretetransferfunction.py create mode 100644 Tests/test_i2c_interface.py create mode 100644 Tests/test_moving_average_filter.py create mode 100644 Tests/test_patienttubingdescriptorcalculator.py create mode 100644 Tests/test_sensors.py create mode 100644 Tests/test_server.py create mode 100644 Tests/test_sfm3300d.py create mode 100644 Tests/test_spl06_007.py create mode 100644 __init__.py create mode 100644 causal_integral_filter.py create mode 100644 causal_velocity_filter.py create mode 100644 constants.py create mode 100644 discrete_transfer_function.py create mode 100644 i2c_interface.py create mode 100644 main.go create mode 100644 moving_average_filter.py create mode 100644 patienttubingdescriptorcalculator.py create mode 100644 process_sample_data.py create mode 100644 requirements.txt create mode 100644 server.py create mode 100644 services.conf create mode 100644 sfm3300d.py create mode 100644 spl06_007.py create mode 100644 tca9548a.py diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..80d744e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM golang:latest +EXPOSE 8000 +RUN apt update \ + && apt install -y libzmq5-dev \ + python3-zmq \ + supervisor \ + python3-pip +RUN go get github.com/pebbe/zmq4 && go get github.com/gorilla/websocket + +RUN mkdir -p /var/log/supervisor +RUN mkdir -p /src/zmq_proxy/static +RUN mkdir -p /src/zmq_proxy/TestData +WORKDIR /src/zmq_proxy +COPY main.go /src/zmq_proxy +COPY static /src/zmq_proxy/static +RUN go build + +COPY requirements.txt /src/zmq_proxy +RUN pip3 install -r /src/zmq_proxy/requirements.txt +COPY *.py /src/zmq_proxy/ +COPY TestData/20200609T2358Z_patrickData.txt /src/zmq_proxy/TestData +COPY services.conf /etc/supervisor/conf.d/services.conf +CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/Documentation/HowToRunAnApplicationAtLaunchOnAnRPi.md b/Documentation/HowToRunAnApplicationAtLaunchOnAnRPi.md new file mode 100644 index 0000000..222e5dd --- /dev/null +++ b/Documentation/HowToRunAnApplicationAtLaunchOnAnRPi.md @@ -0,0 +1,14 @@ +How to Run an Application at Launch on a Raspberry Pi +===================================================== + +Running an application at launch is fairly simple. You simply use the `autostart` system to add to the boot procedure (there are other ways, but `autostart` guarantees that the X windowing system is loaded). To do this, you need to create a file `/home/pi/.config/autostart/TetraVentilatorSplitter.desktop` (or whatever name `*.desktop`), and add this bit of code to it: + +``` +[Desktop Entry] +Name=TetraVentilatorSplitter +Exec=# Whatever you run to execute the application +``` + +Then you can save that file and `sudo reboot` and the Pi will launch into the application specified. + +This is based on the tutorial [here](https://learn.sparkfun.com/tutorials/how-to-run-a-raspberry-pi-program-on-startup/all). \ No newline at end of file diff --git a/Documentation/HowToSetUpAnRPiForHeadlessDevelopment.md b/Documentation/HowToSetUpAnRPiForHeadlessDevelopment.md new file mode 100644 index 0000000..9460600 --- /dev/null +++ b/Documentation/HowToSetUpAnRPiForHeadlessDevelopment.md @@ -0,0 +1,28 @@ +How to set up a Raspberry Pi for headless developement +====================================================== + +Writing software for a Raspberry Pi is an interesting challenge because the outcome of the software often depends on the particular hardware configuration of the Pi, especially if you're writing software that uses sensors and other auxilliarly hardware. The easiest way to write software then is to connect a monitor and keyboard to the Pi and do development directly on the hardware. However, this is suboptimal because you can't necessarily use your favorite text editor, and Pis up through the 3B+ can only connect to one monitor. A better solution is to do headless development where you send files from your big computer to the Pi over a network communication protocol. + +To make this happen, you're going to need to set up SSH on the Pi and SFTP communication on you big computer. + +SSH +--- + +There are many online tutorials to set up SSH on the Pi. I think [this one]() is good. Also as a quality-of-life thing, you can add your Pi's IP address to `/etc/hosts` so you don't have to type out the whole IP every time. + +After you've done all that, you'll need to get onto your Pi with a monitor and keyboard and enter `ssh [username]@[hostname]` into the the terminal. Then you can remove your monitor and keyboard from the Pi for good. Enter `ssh [username]@[hostname]` into your big computer's terminal and you'll be set. + +SFTP +---- + +The details of how to set up SFTP will depend on your text editor. I'll show how to do this for Sublime Text. + +1. First, make sure the package manager is set up. Open the command palette with Ctrl+Shift+P (Linux/Windows) or Cmd+Shift+P (Mac) and type `Install Package Control` and hit Enter +2. Again open the command palette and type `Package Control: Install Package` and hit Enter +3. In the text box that pops up after you hit Enter, type `SFTP` and select the first option that comes up (the description should say something like "Commercial SFTP/FTP plugin - upload, sync, browse, remote edit, diff and vcs integration") +4. Open the root directory for your project with Sublime such that you see the side bar with all the files in it. Right click on the root folder and from the Tooltip menu select `SFTP>Map to Remote...` +5. This will create a file `sftp-config.json` in your project's root directory that defines how the SFTP plugin will connect to your Pi. Make sure to add this file to your `.gitignore` because it'll contain sensitive information like a password. +6. Enter your Pi's IP address for the `"host"` field, your username on the Pi (by default `pi`) for the `"username"` field, and your password for the Pi for the `"password"` field (make sure you have a password on your Pi if you don't already). +7. By default, you need to manually tell the SFTP program which file to upload to the Pi when. But if you set `"upload_on_save"` to `true`, then it'll upload every time you save. + +Once you've got SSH and SFTP set up, you can just write code, it'll update on the Pi automatically, and the you can test you code in the Pi's terminal on your big computer. diff --git a/Documentation/HowToTurnOn.md b/Documentation/HowToTurnOn.md new file mode 100644 index 0000000..7e00138 --- /dev/null +++ b/Documentation/HowToTurnOn.md @@ -0,0 +1,35 @@ +How to turn on the Tetra Ventilator Splitter +============================================ + +1. Ensure that the splitter is connected to a power supply + +2. Ensure that the airlines connecting the splitter and ventilator are attached (detailed in a serperate document) + +3. Flip the on-off switch to on + +4. After a short boot-up sequence, a screen showing data for each of the patient airlines should appear, which looks like this + + ![Tubing data information screen](https://cdn.discordapp.com/attachments/718703783730741290/720436682851352697/VentilatorDisplay_1.jpeg) + + - If this screen doesn't appear, ensure that the Tetra Ventilator Splitter software is installed + +5. Verify that all the tubing connections are good + + 1. Plug in a patient tubing to port 1 + + 2. Connect the patient tubing to a lung model or a balloon + + 3. Turn on the ventilator + + 4. The numbers on column 1 of the Tubing Data Information Screen should be changing + + - If the numbers are not changing, make sure the stop valve for that port is open + + 5. Turn the knobs on the control valves for that port. The PIP and PEEP values should change with them + + - If they aren't changing, ensure all the pneumatic connections are made and tight + + 6. Repeat substeps 1.-5. for ports 2, 3, and 4 + +6. Sterilize the patient tubing used for testing and begin treating patients + diff --git a/Documentation/TubingDataInformationScreen.odp b/Documentation/TubingDataInformationScreen.odp new file mode 100644 index 0000000000000000000000000000000000000000..99481f6dbca5dc8d499f5a84957cc84ba0e50efe GIT binary patch literal 160245 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%0ArR)82x&&RA)nqEGLmV6gz^8d!m{ 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%0D7Cw|^vjYlb%$q5{7Z{~!RcyCzc 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 literal 0 HcmV?d00001 diff --git a/Documentation/TubingDataInformationScreen.pdf b/Documentation/TubingDataInformationScreen.pdf new file mode 100644 index 0000000000000000000000000000000000000000..44eccc57e7565585f74be80b3a8e5f8686764f12 GIT binary patch literal 87180 zcmb@t1yo$ivM@YoaQ6VgHMmP~cbCE4-JL*i_XKx$cM>$XyIXJw?(hvc=iGPi_pkS@ z_tyGrYW3_X>+0(2+I!Otxq^ro9TPn(9C=TEPkT>ePZk_A5hIbEp(PwIFN2JUt(mhq z5etZ-#2{v2?QG)6AZBggY$9S}WM^!`#|P)+>}X|C)75%;M^K(t-nH z=y6rIazfJ^ip3?pWqs5`vb6f^24%chcH&lG*;&!y&GumFO-!m0sXNKGKL>m>1sVA3 z&_0E=U?3Pg5-()vD0EY-{`^mJ*7qGjpPGZ|-gl64aZu~{4}oxft&1ij{rUi^%06+*(}kMAUStFhN1309^jwiwL~N-f zy~dOp_XOv4k#Id+uoOMW&Mb@aAHLkae_l_J$)Z&YQl;=vvebN3sH5jkVUe>o%8kWd zZr5#a;hU>jNWLzunEV8xIeJ`Z^1~&E?NwKT*Lfn@e0N_Wz^6qLds;)=pI~;aEmRXB z6G{pXF0$_Z>=dSV3)jz!aO}uNBs1M$5wv9jE9LklrGqa?LktpYN`m7i>e)hk7q$pN zSO(ab9y^AjuX>RcF)p6=+&-r^+DS8aNxE((o$mqdRhBXG+8&lRHlZ1L1PMoC+nN z8lxva@Jmcz<-eB|9p~!wkCWIip!oE|oZ70}oFrLJ#5lAH5+a?W{Ly-9u)UO}0^@!WTuaB>+##JE2kA@0RvN77RfbvRq`DUS zZbz^6zMS^2PkuZ0dq)sc%6U&K6PryH(#kLT;a zWlhE$d)pY_5Nt#wV|P_^8=2f45&xHH9`;XThZO6AX_}os+vA-~Fdo z3Guz@VB3D0N&b2E3m73d&la4Ct?}PW4RrOkI^o_H<=X`(JL?iGZO}N3uDlt=450fVvsPgFf(^1V&w!~3t2cjDVR74+u7LL z*_zlo6LAtT2-{iPIV#&57@07Ln7CRPnJ9@1{Zj};gjN131OJo>HdZE9rvIu5uM4jm z02C=PNihHz7ytkU`T$;+0m1+XaPT(-0VD{aV4$ENA)(;jy@Q59fI~olhl7VlL_$MB zL_$S^heyFeK}E;F#Kc5E#>Tn#CS6T1_9E6go1^Fg2h0DN5uGF!)rGH6$Wer zf(QbP1OSc-27wCp+6y26ISF#@&EJ0j`W++`7z7MBEQpN&V}z(n+5B5W@d*e%{^Fd*K?TtvvYd;9&3ZmXK^8P0-vb}zM--(g-U zpN;S+@J9a!AXW(p+NhCYNH?4wHr|Mkm-B>jHJ&e?w2&=UBM(P8A?0smBzMAz%jC-a z!{65Hgrk<>wm6;}Z}hkUbUo?uc2$Eb_Z0CY@|urrJ$!!{Z%hDyoIOmaD(BxY6OO>! zQDJyrAsbL%00q|>^lu1-)X5i)=_5K+55S(tQU7=Ro-;o%DO6S3908E}nfri2^Iy1; zlLF$7lf!jV*#iJr^}8zNQs=x}V(DD?Zyx}Ff#3elYlU)rUe6$>e}4OY`+o3FqU+X0 zB!TUAt&wES(neq72PU7m`(VJQVYex4kIR7%(1BH=OLmPD->AF1w?-@;ns6a~1>>^A zVwJGijNQKgd`mu1nzk8bGriQ~qv^D>t5`dDF%_~_jA`b?dG{Nd@DX00#fCG&uZ4Du z+de(JWTYZK;V-gwkad}1$Ke9KpFE;C=FaHxIvU$#zA@~E9L)cs0suZi>>X6xbJWG~ z$k-$;=7(;sCyTR{vP|CwUS8`IwQ&Olt&L(=$I_4$NEQAbm7bZN!R5fhUH`}=u!EoX z)-GDt%x<3Vfv;j6m78#N{N3(Xz%AXngwEcZFYE6a zcpSKv+-FPM9&Af0@6vntCIIcvU0cXDS$;k~ftuAZx*>A|K({So?MLZHVn6bbqz|!3 zTpLg20K(li3)=k0$Gb;7#ON&T&RRa#`1_vOeTO-dMVKKcSv_BKF)42$X+2meK=5OBD#BxFYY_Xe2Bg+*OMV* zM|nkbe65D~N|!QAH`;ceXYUOjvhMXkW3VnSzF|+-T*Ce3Q(M)*p*suYR<7CgoK`iT zUAzu*1;7t4uaVrsPA;BbIlJumjBxI4Q65z_JM-`$MSIHG6+LMaLGU#Bul*WGl_%?8Hpn+idP!N9S=~*E7y{ zw-dZ{X6JB3-0GEw?~o8k>K|`L8_j@qR|t8S53VId2eI z7AGAddH-o6@Wknk*@>HHAf%&bb1U+%3~z1`Vrm_|BYrebURXWcO^+i8e#{Oz>wH95 zTaT&xSI)p`UB9kDB`dkJkLFjDT0048NMg^hslQPNi!yhq_BnVfv#Qb4-_5U)YJ!Jgv7Io@l0f3#W zdU^Ve{qw^8_GfMm?wvEH+<5bEGHyj^i@$s}#jPr*;a#+qZ8XN)LFM}S7jPis=2K=0 zZ(*G)xzH7d!yaoZ2`K*TOBs_b!4G~T&^}EU#fV>G|@n ze8z^g%u5&@f&#KDU+TSVke=&su5JhwFYd>cvTB>djhRni{)*#*15)lF9{yrO)MF7o zG^wEsT@qBxp)A;5!6avdhmYl!y5;P?&2G!SMDG}GmcCdv0P2VKfoKrl`75+YS1?tVThG>%ly+_lMK|L~@Y8$&(Bp&Wq%gY{6!t6}Va(xW@s$~&Ge{V~ zkcuN)lPk0k(KArs@U%mJ98LzJf{m;prQfFs!8X{_Ce_qk94gTj;;s%7u!~0$z@cX^A7Vd93fIuBqEe%}(E)z5@X0ocHCx2WFU*UI47I z49M6A@gb81A!RNL`Pv%6uLk){8z7=hl(d&VCYmfQ%?7Lo3Wxys7TZ7fohJVgDDs`$ zSON4z!QPWqg`>l%hU`&NQ{v{u%+DD%IJF)QX9r@MNP9?b?l;mPCF!6H%~__1NT5FF^S;oq!z zc4zNRYq1P^>o|i10BPNyAk`IUZ6QrWpE-UBbn(IA9!4sU5P?{F7aG8V4-=YMz?=%kksoCRqGn|i` zG6lDnzla*7`4q??yZX1if{+@T#`y`#R3-j+-o!JwgHHijAQmkBLI6FDGo|uH@SmOu zBML%~Cir~eV~7fHS(u?yj-{Skrr%g#wx;G*Hr|hCl^;f1b}`&|P4QUfgI&VoDk;;bcFXwv_ zVI*vR9HwF+R;637I2`D!fUl)0>UM_-dW!jf0JsBD$^5Ts4wsLIPO+}tB>O3@!kGJ+ zR))EY(Lz#7+Ny&UO`kRQlCQ}dW<>)!04(;M<7zY5N#2ImTsxO1(=fH6rl%IzBuQD> zyf2`BK1!WVQDk~v?o~;42e55qW7YLecylYm5 zMD%Cp9%2&pMU*$<{{;L%Z;{+605C{!FfeFHC~!z<2#^{S=p_;w0QL?W1r-gQksSkz zhzXOKML>v{ghN5!pOlQ1P0*fPSRC}02?Kih1cL&91+0jbv;2V2-m|WMR%TtE4ey~f zxQkcTx~H`8gc6eZsbsliktqO=Vw@#aR6#SP``ePq3)9aej9*P|Bdba{M3n~SvzN-l zcmmji-sY+5A-Ca@5RHNKRjG0&u12|Lm$hmnxtkkp5>$j-(;D8{ivrdEEliw)?-5`XeP3AR^I zl1HoMeRS9Y?lk5vSdBNJK<+ZHmX0$GV(zcc$K0c9JsC}vcop}p^crEFF@G28%pZfZ z;aOz{PSo}kv2OSZ>dxxNJg2Y;IgvYRGmR#Gw~ie ze@w^9mlJP?gN2U?J&5j$?|Hir+;8^MlqBb}EQ!n#r|8r)X%e)p9?s85i~N{g0kQl{ z_f!MryZJ(rTasU|?wL^{Bwcf!l-ChUZG$tI`H zeCXYMvY-Vcg-xJ7i1wvq*fN#z{t_eEV#nN%R2`49TwwasK7IH2Lb2l9=Y1{L4MUy zxPx|~Tg?@roi#JPMO3ET+Z7 zu2+=E7|tFUbQ;W1~N5o4F4@YJgH-x75@ct0FlEQcyp3We+9AAT(Y z15}TQTxNE77Y2MiT*g&x%AIZ-{Q=SNBFB)>$Y?mbrG8AKww}~9ySk^Yn!N0L!u=fN zInLbp$lKVzT;qs8ZS6Z$V6&?3YP8Oj@Cul489GiAM2aLB`)@IQ&e{Ce8yf#|)<1RD zKbzLsj(2rf#o@{L?+}kG<1fVF0?8!Pb5m*%T>Vi7>HjzQS0AAEkATKeyyXs$l}n3S zJi&k03y6-(RlYwt@`i&W`#)CH5z^(loO&|P#$ExZgJMR)9%?Y5YB9Y_Mrb0vja`Jb z)@*}neO;?HRb?c7T0EoAoza9hzLY)>z;;;K0Fv2D{Ev!vp`(&#@`n9wP4!Gydz*IK zFv}KW`Zs=)Rkcm4i_A{;ikArd;K;oWGO01-=5D>^@$>0pK^^52^G|fh9vw$@U!PZ( zdvs6!av@Iy2!0t-$bXscq)T*u(1#{8T!~q{p+=|h`=9$?RKka&6MG385 zOj~cqw)wJ+4N$I$uEVVF?k1|Gb1*j3rw=)y<6_D+To2^>%YxR`l5*skGY@0!^AURKVFA2acDNMkjSKc zz#wN?%;mgFo_4VV=x%Hmirn|3n^{`O$pc*H~ zZB$&nvcIi6|B%u!&ztY3b4J4P%zxQ_p_nPfGAQPFffoLjUoYz-O|?0O&@|>ozsgHHua6y=~s z2Rp_`{{8u7uQPe0N)Oo^QLFAG6qEOh?n~-haZhw3!mU#6lE=UJ-CTdqx4Cs5zxX8J zAI~*boSBD@4c3%Tx|fb7#*|M#oVZ>6DNk+}e!NQcUruz{h-sW~&1`HP+qOI;tuT_4 z(x!cmiDz8TPTtbx74WEd@2H#!=_j(K0X*-p$xjkbKYJphv|*17k2=|JU29q#;TwNo zyP4lPj^F#bw{9L;`3fLBze#9nOLOzZYG+h9y&5=hb^6fO21@$M7rng*wb+cZzIt*w zqmL)$#9bKjbabW@Q*|v}=rAq>l`ko|-0)xa89%cp{Eo<}C zwF3?1rRl;i#Ako*v8^d0;#URg)S8{v>FFAE7nTR?I5F1_C2I_WF7H&^<)1XrI#u#& zSZ!ZxTKP&nN8Sb9*0jFbzKpl#0Xxc=c}C3Dbv(-OaOCswC*JFA>=|b~P1~nyyyI#4 z{~s?>L0(j~v9`Nib>Q&^Zv!RR8b4dB=n8M!on#lY#>-$ zB~^YNbORYJlhpf~zFd5EiJocbKwspsE$2R+=D^i)1e{;4^Rs)aPGJt8)(oBG^1Lq5 z!(H&?qqyE=Qh}}&XFAXAJ;$$rJUx@MHeEvpxje~B)J#LCQSpfW^z$NKi(XnOxu*52 zzo(_8!GiV@J%8^M!8=%F zyQfyskacYgj<(F1;rA)|Fy3wB;SYD96-PNxsBu@(Ja-#C?uDE1i^O$(u3fpQg5I~W zi9m!^UOhET(#gioQtWM3ZtE_5ca9vMW}3)n8!%Z`mdo3=m506+-IT13R@!;M!khd| zxNaAI;amGtCK^ATm%6-Hk9Ka-aQ!%rWoNaFr~R~4bmYK6YU%0}rp%JIY+dH1ZpH+f z<=~FxcyCWb{yv-jrY`upwf_9ONglf+-aoEzZdde(Jm3F}Php>Xk{IxlzUAdQeVO%D zPmbc`0iMb49=qhX$MoQ=kwD0nQ2(~#xOw38T6`|xKWLXNBl1nLntbo07t9pZE9~=k zm~E$)|Xg|7A z@}eDqL11t+{I39<&~tFzv?zpCf0@rWi%cktsv^s%Ve=IZMiKKl(5*6Q=(ObG1HCcv z&AQF!%J5tl7Nf301Z3f_00X32jV~UvQ-%wD$nl}NZL%eMd@?)L;RiAbv-TT7#%~6BUK!iZGFsG)hfy znDU`Lh+EEc2;~YwBT9Ilm@t-8zr{w7$UcvPGqXTNf5eaoFaj-?0jx4U{A7(gtig~x z?kO}f3b$olKlBjokjAV*B!4g*1F{LE2q5<9FT10pF9j}7KWTw1JMbST&l+~BU zpi5Ztv<&o;a5L+$BU+PR->gh($`;(l`&h*p!Z3PT{Fz?iACl zACV4(RIPj-G~w+Mh#%GtI*4_s(NixMeHZ&Yl&e{-CYdPVbWD^lU|UFj zGu?+q#x}(u6A7bSI`u08S-Wo7kQh5eihzdkJQry(HQ~3_Wx7lAiDe;MqHUCMVlQ=7 zbTYGSvlIBZUm-%eeyDbBrl1j8q(1|7LLS*q-|yTo&R;9{6TM_KBjVka*@l^Z4JRb( z!+wJ*A__yk;b!l+OVniLLRm?rv(N1}P|C-|*>}Vdk?wgPjC$YQALE>VFv$UK%sG@s z^#vPx>>6ApG)v$70ID!)TPb&A-Xh^Ra^di@^n%A&ZKuET0XR2X>%t7yt8R&Yyi_x@ zr-qFlAu|*~!BV~BDiT>zJO0JDRecJJMlme7hYt|@!pOjf58Q+ejyzu!sOGVn4O7#3 zFenv~6TxB@4C`xNDgKIis0femg=y$wsBWFQ^0nbiJienp{1Q@2|NEB=vKevu-kv8} z)6G|aq;T>VoU*7_*2|uSKM>eG(f~P6oHRW z@eY9t|85ViftAW%jX5q`@RK2f4*7)teK z4RK!5m`D)_vqDWGn5GG9M!{BrW6HbB>1qxAv0SzBh;N#;Kq3*e`=OkvMklWt0)JO@ zeCO)`xaL(?hvl+$X)!K~tFqc9LeFE9fX0@0mU9-d_qZQ;$Ywor85pprpsiioh%VfI z-U=cv`*4#7!w6n^(OB-`umOw3VeGjqD~9^OCC0cpkh+ZXHL{`WCdyF+t7VS4@V#F4 z45kWY{B?_XSxxur)bVVTWXM|tQm2-RhP_M8(N_i*9BE%N_kX;LVZ$R6Qf;;15vpXn zQbRI}{k1&h)zgBK)Vk5nJVR^Kj&rrh}I>5}nt)Taj)N zT0KdRB(+9V{E_lT@N>Za_x@fMLXgE&Oa7A5_!+AHd#$D6Y_Es^BXA70+d0)}@PO2;lU|kHZC5+8l zQ3kAGolJ#l)!br3OL`k_@y(f36BR86yr>d}Kn_ADWY9+49_KnAfR4Kj-^F^g5aw_s zO@S$?C*Oxc@fWY!1G8kO5TMU>SSgD{j(6ErMJ4~6+*xfACyy_RQ7U4;3QB&?EclYR-8C|GvoBXvFgXST^Y z?qFi&oV9cj9Cqj4qNkax_zs$eq=ynw-F}4VGz7AllE&Uy^&}qPk=$6z_h`I6Gs#JH zcqJRS*2QUSrUM97=LXMib8YV3T1JiONPu;_KMRT5ES@!^kuramtO}!_Pn^+OtMG6ePG>Zb52-(9B4J4`(rjN6 z;^dIa7`w2BNswEL1d3f#C8C<7OZ4w*d}NI?FkkqXB)!Rnp&?LF-4magA;QZ}1{de( za4X1PQV=i-ML9u$uDpkx7lA5VGDot2zvFLzG>2*{Y8>SGNo<&}@ArqOcU7@`2i!jd z#+wEjvDLAHeU0G7mesSdn#H(=Jxd!(AM<=Uk5Fd+}vzMOQHbU4{(6DDIL^cF!!D*xgc^Ns4nky7$@Uy z0r=poZ+!QAY+`zB*=IIl-{Mo<<`o`C-r{sZmV&UMWvWzBl=S+g74ICOp3Rv4r@O9mxRsFv86>agZIHNAHzudov>Q!6%Ag*?)=dBS!KY0|gJtsqivo9aU+;@(N%Zy-$q1g_FN}ul{*>H6u;a zk~}9ohx=+FFjBM{ImD$V`N?@pwVrzTJE_)(LGIb)8WUrjY}aI{Ss%QUa8*OEN}E0H zx)IlA`bAa&hqM@&owoGn3at_>=ht0LrG<0^Khh8c|%Q8GoJ;0H>ejNhHCneNp3bmJ{X*Cj?BHc z1l$j+I-5&rVpG^e#fvxRJNy1uel~Mf2{i%P=Ios<0W5EQieL@3D!f;~lrX$_gqGpL z5RH7g*{(%G*?=)}O{CHi890>|Dutv;dLEQ6mdR(;??w3tA7wU1!x}O5TcFF2Ez_k& z302iigulX?)3X*YE6ScWTniZ~6@IAo{^}PGRt-KWY0C*LF`IPGVI10N&!qF~C5`!s z-FF^w6lIXtiegqER-QXyN+dP2yhuXTqfDxQT&-L=_JTrmftHB#zQj z4{`S^t8r+R6Kid2M+zC#A~GC@PkQ3XBkv8u6$j@xDoQy~!q=KpUIG2j^xWiB2B&z`kE)i!3oq*aeXIWe)?h$oE4`rk4Y0h>GpCHh?x%sk<}b^5qh zcnXl<4|b-b$+y)GE&`N$>bsRG|ti-aWXo3g%X-q z#04Wq+CIOh3*rsb`^Jt#{O+f7b$N=}Id&0W2jjJxis;-yQ2->`Wi~WI5?pexBUEmL zOFU6e$k&O`@Jc~Ug2Qjs29PBa5Kxje?-od2BE4WG;ta;)xfXWFMG^(dyT=TzgA`E% z(DInWrnJKDzElNX1>z<`e)bh5QUbS`M%O_8*$aitsH-@Ic|^7}(!+63ApW&hk`21Y zEXhPQevo2Hc&c*MbUu%;ajZs)!-d4YeoT>?h90VO6pdT-I6d#2Zkl*ec-a(^<)CKB z1ZYg&>(4@T%Hl6mv+`>Z*Wi}))2x!u#L09{bc}HVUTYg~!Q3+s{=$XTH(Q#i<2qRD z`uY(6kSkP$f<*1eW`8=P}7xAK+S_MH@d3PP9oB;fSRti9VFC0=MJIYK|_O1 z9lik=I4S@F4U(8i5FLY2(clNOfg^3Gf_UH& z&C-x%LtXq3L=iM9ceZE5KK@Z|uCR0y%b;8fF;~O*`Gz+BW1sSFVFAt)T_^GA@6~ED zGOh@zhI)F>sGeM|zQ{l`VcTc&aFIb43Th+ty_zP8`tfvX>3q=)wblSrBFJNBwX%=1 zG!n%)HJXLeN=0%9wEFo$;0ahUJ>=%mL43E?8pm7XROD6TmFi5)ig_=*4SDiBv#ee*$&5vD1>QvI2vWB-@jPy6 zPz$_UBF`fTj}SnvQT!6J5dS+avq$q*NzVPZwf;CZSSP|2nBvK2b3r;kX9`Cw4KL$% zGP7CVtztx=rYcFn|^5cV&?0r^=C1CO>fKa`09BNGmNSxwq@52E4}~J9pa2(; ztvN;C)yd|39;JhPL^VO~k1K$HK!dkvpfA7R9wMXHh+lYnP7<@JbJvUaR#=HZ z!D`FBXgU?o=JlT6gU}@7a6trDl!4p3k+l^Lp`wq})MX6I1I{#_0ijjI$&3LivGVHF zU?S*=GAWu+i`j!@L27yjyRa#eG=5)`xPkE03MIwz65VP^A(Fn;%yT7WhTj_%^Axm5 zZ;|iA9QPfi6E5yDm6;6OVML1y_|Xge5J-X25jA#%C}G#J@3DV}-9+Jk|A64znaO%w z3h;W$1IitDz_7<+O56SZA_LFi>07Gug{o!kcfGXeuFCc{xJ*mth3sluwv?1s2!R)Xtx+C4OAe(v(OlM-S3r+QMAV`DGclAY zOdn3^hWFi34ma})^x2LS-PcAo?R$7hl3Ak;UM1TtdwhCaI8;p_6mYkICO;0*>*Util1cYzq2D{<-H^ z$}09QfnVynx9a~s4FJs#It?&JzlRF7(XAcwO%E%<$&adBNta~VDh}4hnmo80!-=L3 zdiiQDHG&c|1Rd2LUR2jmkS8D!>T|hE%UGYKG(tstjP7wU>hNl7EwM}&`X(lO5Id4f z718RIjS$|sghU_AORr?di>;N(=uXjY^Cja#^vjQHKASrJ3L4hr8md|%-qYS8Tz?y_ z<80ABacwgrN)|c@g0jHTz0-r=?ws7w?DO}1vKB1{bd3*FiN{*prpM)s{U%?POuEqu zNc$S+9?P%c5-6a_-=m_6t_cfDDv9e+S<=G!v{WblMp~6!yWsM{b5`jmWJ+_XCm&do zCr_S^<9?(btS+hv6E|NxiRw-}BtvZ*mXIS3?+t8_Qkk5erclu+0KojgRwK~3G%-!Q6{iQFpbkcdj$Ntfgy*f1x!u2_9=V22h$tch=7 zO)7X<37uTRoRK-g%Z6N%yzY5OA2)->R?f=9P8w^x*q?6|w@d{dHQyCqqhb(G)Z#2f zUiO~(v#-1jh4bKuL5(&!9raNXm(7jD+#1jl!pdT_&g9nz!8Y4`q;Q|&g>*^f1xer* zN9u#!kc|o95E{aQM6AiWW!Va1R`_aHw;SIKb`Oj$eo(RXl&!62pCO9_RvNQG>x3at z3r6XZK*6SS`Jh>eNh7X?gU&o+%vx@zL_h;?Kx96*fjoKGL$`%#1`FC|rpNpvKXyz- zJ5bkw?~J*B9y`H^wE`rKfbPvWP|16FbE``+BHkj{>j z_qYLCs#PZ7^wczw$HoD{16Y=u!f|7((=R!vHmC%`7TUDwBRPJw2XJ9n#@)arKwKg@ zb!SR-gEwJ6QcD8R8A>MoVov_C8#?)*@)S%GN>Q6g%YB3v##J;>b~{I!W~zsTt%w-( zR*+bQqI@gWJiOB3@p$VzN7G;(kP^9Q5FiDMc%?T);}-9w_9CjHJYm38b>~fpeAC}G zMq_0&XhUstUBF+*Rz!Peg`W25o;h*GgnL`2a*U52T5q%5$G+NFFs3&#BU@=jX?6zo ziMFKxV9oiH@)h9NRuR(&d8;yG2C2PE-djLDYGqXzTobaf5h-XCft3;4LXTQe9_O{H z0>%Lw`JJ#_?cJ0d9_TO3+@-x5cYFuN0}8@Fx8}%+^*&zVX=%HWV12Aekg(3;7B#5d z?eoIemU1G&xQHEQXK&1+ns+#KMAHW&)62lOXd3JBO^K9sY+~-O`RWD-m^_Eji?rcv!2#?CpO>g7otmLa`?n?VSf@X zr7wC`NeNdqZ((e@7f4N%pQ+ox6!+#Aa^ea>gt)0X_>?x{-lXwdIN5fTDE5>gP-_mm z?Ig@wT9Qs>y0U2ZC)X-v{@9o}lBR17{6;HT1D)7VTw%#U!!wxQg}Xc8!IQjHZo!Nl zI>?ZZQQ##6^UjAJjhy#u#2zD-;|Dg_bdxo9wq-M}ho&iIcB?6+j6vYlmD=R3+GR2X z^XO>sp`|#Uo9zUw@V7DJ&#nE5Pbq4TLwlT?EqsV`3WpQJb4x@7*f#SU%JzGoaN*Vx z8KmfV==R>zE+v+9i`jNANv&j&_Z2`@7jWApo?GwuJ--dHL}q|r=1Ps}mAaY|jS zPxnN^WiYQ=6^7_a0nL zJI$tKG^O-P%jFhd(7sivz#<(KI0wZrNz@bTG~u?==FV9ygh$zod#)zk8KV>RYML>v zE=mralHw{UkA)NW#<#eQU(+&Ea*>B2AuO|^eB|Z`S2*NvZXBkf=dMelCZLEf7oBZC z$IHnx4(C;zH{zN6`b(AzOUkh|M(`qLMM}w4F>agi6QSU4cGAhJ`WQVhg&rc@C*QI$ zWelR+cdvi1`H0#{Eq=Aiw$5`alFrJ`6w{646;QIly|qDNZo!pUW(wC>p90iyXox6~ zToGlcf7#kT#dwkyDdNzazAUcJ<5frsXo9y~pP^Av$JeUq@#r`5F1!vYckg4*_M)e| zd)b;s?$nA`Dd2>#{KW0-0?dp}$xu`dF-DUM%$>y@5s%+DJw4(7u+lh=yr99`Rp@IY z^QFICfs9(%W%TM27&DW1{t8er=rWV9OS z9zS_*9MWG?j%@X6-@4y`eqb^yC?nN@iT#bO=G4SHNK;$MM09(xdz-alwkX zwV88tW$9qB5He?6QlpZP5>*#Hmy6E_oHV3Si%#zT0SoW;Y`gvEeu6YXYCFSDiH`on z#`mE+U-V*+3^!uB^ZLD`a%~H);nQXg5SLAxRFrMw<{!U!lv=mqk?lgyPtCqWJIx^v z<$n=V@rl-TtnymFC~=pJEGYR!S3lYY+QU;33;S*FWVj&a(@^yaphKU3j7;d`9Q0zi z{bplz&)e`4PT2Jd_|-LOH2(^Cnz37SZ|r{steJK^tv4t26U&xmPTiMQMfI$}KfpsO z<<);i;;vVaY)#sG9#hTaZf8IA zc{Tj6+l@b38xOM}-GAEuw9|1$5V~XB@HKa=Jg_LW-T8w?mFxey_5J_^Y5iyWFFVc0 zO{CQ2Kd>x}GrU*NqJxewPv@fp|95T7A9+x#dOH8_?Z4YWPcED}6=H|zAAR#eLFtHcybD@aw*T5S6K&< zc~5)7N{`07ITjNap)?Tsm)2lyD1kLRh<;eY?i##TZSHP!26cJhBs(FA5QkFwMm*8rKKz_44sY~sSPiMkCbd`fB{@1pEH2x-_? zbx6&RdPC3b^JivXl1peH3uI3EOuIBf)_@Ufc8XHHu@b}M=SS}6yui^P&(ALbf**XW z`sLbcDMA$zy<3z8EnU_(?ZG@hHH;HlPEhMwo*R%J5F(VYbL?lcA9m@gOx2ZF4cXke z{fSCdZBjxMybt8$%Z!_?kokM5cX#MgP~E!^N6MCadbQ=jGp)OjMb+zp%mj2d8k2R0 z@^{Jw8fV)uPhOL{zL1wcUjc5N!L>Hm7CF!52eyXh{w;{e`H2e(a}Vm&0_u{N>ckb? zGd94b7b#Y`MYVm|;KcYMsR2dskj1!@Pup20dJVjUw#a9fK9B)?5A%^3zJ}%jwO^M6-_T@Rxexwz z>rkd1G43AkwA^@Erww@DC)&NuIxXge*!Z}Mt)}W|O&cMY_C>U3apzn-9ZdRYyzs$W zK+7t!jGBjBhvad<`%fxg+S^uiH^I?RL)5m2kN$A6Q(px}+>1gUC+FB~l1<(fM8L-i zR-v6;;0@PmoJbPvKU}{M{MytCauNls29)lBvXab>mDya>GM*~G`ea~|BEBOvRP6}d z{7Ja$r-gQWR*cxWZReGGR)~E?cZ0x{q7-7>52sOCi{iuFj?|7WJ(sbe=M`X1WPBUJjC$2GHpnPreSn5N}nHjJ-gvgVn{J(MlU9 z^98N#$-CR!_UBW<_Op%ZHFL^9MbBUJ>@D>G(7QM3lGgy=P?x3qU&i=CXMV4QgSbh9 z`@gA$(9{~sEc1WW}pLe?+h+R6q8^t(A?{t@4uCkOSf-g z*Y?XrMV+7;AvNJxLa`AY-gE9cK;Z6Jb~jJY_5PpgaY-q#{vD0m9IUPDgXzDeovnHC z)o;^%`KB&Cvw$t;Wb|I+LM0aOwYZ0)a>YS8Xkf3F7Pa$JOxi8nojjULvSB}D5c&6t zl7<#m{0VCJ_>`2=16C$AU89WwAuMC;cSHb&qSUs0Vqxl@(S`@A$^$SWUB;$$js4D+ zMbLhdXhJ|KZFxz3!Q9GVM#0tE)i7;xScE}#5?#K3Y-KFZ<&Ddu_`9?(9P?fNVC}PG zVX~I>uK>mzGsVu8b6|7U9tJDvmp}Iy)wXU==)l1J!WPq6$1Q;uCb2QHS3sni3KgA> zpip%3=HC;$NmIoDZPY#+?ten0+F0Cm9^N_0{z9x7H!Kg7VDm-2G4_&o-&<5ak^j3} zGCQ`)Fj=SRr|zH(@yqbWNsbp{VIfZS#mC9NZUo;YSE!25*aopLW{)u}zAK4ksOKLB zs3cTj?3Zt_gQ?31S#FSW=wYy(SH5Gzsx zhw{|eN^a*;V-N=9T9Lv6k>6VHa;l>2xr!SSY%?)$+$l)vwh7b}r2`^aHpR7e+KA^J zFWQrf7m{%*5^T#%ndZu{=1ljS0ALXq@`E}`SY90L_zTN^Vj%I5Yp5PK(g8Seug9mpXU~qRC+zAle zgAVTQ?m>cka3{DE2p$3nxxDB6-}%4qu6yrvSI=7ARb95byK3)eKNa9!&81(hrs7=Z z=}@25B}(vzJ0&;FQF?#eu*BI(PM_CiCromb#w= zkpJ`b1U@~Or+C)2_3-pIy1JsKbIfOa8C9p)Was9sR^wmjc_Lq2I?I@~&r^>euryR9fm>3MUA@5`3k|I!4=K$zik? zUV8B1rEwJSNzNveO4jd+%*%;+nK5q#N-(K385Hs|2*TP&3>@!T+aVh<1Im*I@koI@ z3%ZvywPALKT2^bZ*6Qz#?w;R{M5DZCJ=^DlDOIexg@AAtOG|<$mW$2KP*xjC+2}AK zy?{TtfpcGK^Tmql?rV_8RhWN@7Nw!vsXqqa zfDvHlmZy8Z?N1HuG0-~wsh#|&afSftM*i3PEm#=c*NJ5x>s3~Oy!e2b!}+9KRJB(i ziz1=1M;2t7X>GeK*~@lHIEa~eHrC^??@$2%lIaD9*cr&QEw$@?aTYJ#+Vfqe*Z;e$PLjP~kyU!&d*l zfZg%(gyFw{;G!5ZLG7;2=obwgc~ntTwDvbYh}K0#MyV6a)Koz|B#^fH|_r~ zDOV5ROZ}d|fUARr(Y?QbFLQFfFoWuUqItxX*Svwe4wioyI#H;!fj{YXv^vM1Rex~S zHrV&8+9q9sJigRFE&uzlRnlaB@XP(ESWIQpjIJ}dgl2`)!r z7=0{>t5@YIC4d=^b-;c;G5kmGxc)Yqxm(GQ6c^_mn-l13HW=S~A;bQvW0uU7nQQA4 zD_DHf?+lZg1xvb8=CFWT-iTo4D?5{}&*m zbT1byA2XOx$@Epqt|!vuk|_{GNqwZ-}Q<=N}o>a_};t*c(~a2|VXXW+%12lScVLC_{ynB91Y$p~9N!Qh>v~KrwSl#+{dDvzd}Nc4lg67*kE~=exYF z!GcoDajU~xyLO4nxl#sR^2Eerup$c8VziU{H$CmH?mWZ_0gusjbfd%t8^3s-&Ark( z$5>?g-e&)5AMvx3=gRc$xXgH}Z_2Ez>^XrVgjYvxyVMcwm_{l?uBgn>;e(V!E$EeU z6#+}M*!?!$WS@LpZScb@Jj)7LaC3#`HxxriCOz&evYpBr)^3m4P8CT36PjZRvo@gf z-ZL10wJTz5qIn*rFH|$pvW|P1yQ1I+KEq7TU7Ql`!LZ$6vHY)xKOQdT8pURB%_i*m zmd|AmzkU+{j%QL04Vo1TUzP`%Rwg$%N=muWyqz!))M%lUT?#WN%2_K=vE(rS3NEUK zgO=_3S(+2YE%7kIeX(Nd(!5QDDur#7E;k`#mpV6|U%9%}fZV5#A&?El7W}V(&F~2) zVC;_$r*iU_)X0MYS*ls2?*fh(rt?{GQP4U$V8pMA2Hl;=sQsH#YIk2{x#)C|akF3l zT4Yp}DrwZVy6jR9hs9rjVh}u0*g`Y|7kZPI#mVL3dYPGPBWlcWQK4QASlmjHgcReU zFI1|wqHu_8T>XTPK9Dw6fk+tvO0kl^nC0jGpa6*$|HX7dK*E!u#C^~Mq{dD2RoNO; zVYay{{#{f&U@_9&T|9nRAN*~Y9(6ylk}UCyiO%_g?na7DCF)>K+gdCWn(R#gzH7#6 z*pca|u^y@qUCl4#bPWyHDe_+|ar>Wv{LE{?E7i>dl9@d3lqHx1lau>(_T{j{MQdbf zv|++1huar}`d~;%~l$-c~+#jW{L0Zo2tGN8Y&=2|!D{YapQw?d= zHSylp1Xd&)dn&E86%v*gc@rsUj0t9U_v#xMXhD5uctG7RRm1+dfr>Qp$pz<_0*=WZ z3orVK-LeK?E*k>d@55d@n9Zf8{`}ZSx~61h4>fEJGq>xUDqQXsG;cQ8jqhdt@z~n411z z{Do*&5j~QE?UF~q$FT51dRF%oL3qvA&Smj5Y)|)OnNZ;)uN=!G-1=}r+WM`xfj%^f z9eC@3XfODih%ua-2hZi94U3D~m$%{FUqIUD`~+O}Kqc?}gp2pAEbO~K7bBG_FrdbV zFuQ3{zBqw)^)UQCD<%l?K5|$%acO&dF0Jj8WF54U@=%7IrC9@!$+oja_a>hImpz(d zzmz*R&z)`0J==epWlr6?n|(p)aHAqNkoSf8k_~&uxfYDyaGze+cDLe%5_Kehc8%(3 z*h;??&ub{}F)4x4TMjv6F_4D(9Nw51ot<3e&RkC^2n0f4X%_@XcUs+`x2@(_lln@Z zzTW_;Nbg<={^VU}zc0^5S~8K8u&AoFb(Apr*z`voRAQwbyVqn5>sh(tF_yA~S&_D7 z{~&KA*KH$OCrlr`m}7&zs+y#BDtw$6LUb`%XI1Bymw%qtcp92mmMDrV8j`i3U)Gon zgr(y?L$q5-79E9H1x^F~QJ|yCpX{~A51t)j#3RFBd8uGDk}0`cO;w3g=IBV1@<{YOP5FDSv=4Q?~-wv1}p?@!E^~)h>SnVO^%13}L5gIR1WM4VChG zN)H#emS3-BS?_VE2(3L6sVE$IP%b3E4SXgy)4g%hRHzXk{8VT zXey)w=~QqPC?at9Rej7B>iUc#aF}|*CDsndYG?GmPz8os360L0~pPjjD#&q(sJgQhQg>uH?ZrePi znilu5sM^l$CrVffuA0dS(LK%Jp6gUZ;S{qqr}YnuJd|x)tRvYUEaxI z+AW`0mzNB{vUw^Zbd?(GlN3VeF`m=7&{?5rK3rOVolOv2UYZV}rlZd;@zjKKyP}sA zFyq<)#4&CxZJanYRG!8II=4R2y`i|F=PqqApU{J%A{=-0{&}AeLTMx8%|3xktku%l z<|;g$aH#S{6?1}?`f8n0L0Da~bEQUiEau=?(|pJh&b?|dpo`hD(nnZ8tKtyY^ffd5 zNye1&$={BUwyp)%F^|%8z2sfE99to?}UvtuBL5{BE{@RW*xf6O;8n0LjRJL7EJ`lS)T3KF*ucrN(nTE zC$o3&U*y6|goA??byd9@fVcQ?WGIrr8=h9SDa8H;ziVa7f7~s<-H;vg15aGs)aX3j zLh#Sa&aD+BQO^$Tp3cf>C#|@N8TA;AFP5TqXc3_inUWJ$;UDapYJ++kqm*}Qz8K0X zt|r2a0zh<6Eb!0ff9ia=*ztnfzc6*m>$EkXx@qVBG@2^a|AtmUU8hEz=GAt(WbhY| z3VE9;(({RV9Vf8pbI=nn3=!L+Yr>!%5_!!>SNuFgZGX|)hc?8ecZJ8bdQ+2~jaS6V zvE;7txfB97V2sX&QlXu#(bIZfci1?_nG{*4Tmsr>bNAhzZ^V4HJv}Y#?3l%g;9;CH zeU1CLbpT&0F#jvoH#KjPKC#7+sM5g_x$JY{5Q*9a<3Mub#>7uN-9XJL210bqR_H;5GID_WwUCA^J&dhR~hJdOizUvi^i|4%Yd>@M&J3?jgoU+ z^tzm{{6H0;T%fVZfhc|&J!kaW?`duvp5_7!Un)LrVALw4!9Lhc6mSHITCnnjG)LBv zlFAxO*7fEdPaDnrshqhL+zGvY*WzHAx;5lrG~Lm^E{ecmAM2SvkrI9Vvk407Rx@`Z z@W1Vk6Zr1Ret9k^4x7nkbb>7lKG@lo(vP|jgn|ZcU&&iHvh*h^KFJz;@DpQH ztgpwU9WEbHvJ2_Ds>Cu0Ig`VfpMas48U4puXrrR`^UF-JVtE9TsQpV^vA|^ z>rR@{EM^L9T}gdRHIhzPz|)kHHUq0xkhmq~?48aRfsL;+Z+lu3fGtPuiBD=}4Zrb_ zS=`>L>gVY;x&{^5MW-09ai+2oSTXqAK!8G;!yPl!v*DKXKXqvuL%HT>lgJ8t75LxV z4_vhf`_?FE#yT_2x;=f^A27{uV23HkRd>ae7zC+^ZocrICuOcfb(7cKtwfEtRm?Kp zBkX@_#Mt7j#6-6-k{&G^59D1AQA!-N3}+HfSRj)3xIP$PC%nmB5#`%l6m8tcE-hV2Nxac?2Omip&kF|=Yn$^^Vdf)8jtA)J z+1;^OuQVW)s)g(tC^9h`)pnqT#_fSkq6Nds9f;YI$!I6RjZ7FEJE!t{XAY%|Ct`KY zy6In%w{nH-L3S*%>hl3)M3x;1?})6@W?QXjh8R=ST^WB63__J*9Moh>4yE350^=h3 zmM$C2Yt^Z4!ArYbM`c0=h84d^h!r}Ux<1<~cmiE>BBuS8(om?Pep^$OvI3C~ZoUHP-M?1{S*6Y@yx3yzSvj7EUTMlEiA$lUod}qnmtsF!yq}XiGCR@Tg2^}5 zQEki_dRw(lrL)I+&8?1wJiS;rZ)O>=m%I+xs}xS&+!Sk$?)rK52z7!u zps`=7hU*UHP++=EZCh|VY+KSK+hJ8 zHBWfu%K7`5^QH!Z_?<0ipoI2io^{NDbM4ywD>)gK{1C^Ru-4q33Gibe7nwv6C#o1+q#nw-Mjpit} zq8kBaB;ra1H`SHG2HhzMU`Q zulAGYDtHxn&$4u2_n71uaw@ajQv3Is_p~p-Q9-F14CqhIS&OD{v!qO)($wingmQWsHHb_uMXHK{xD%GGnu*@OuHN$@tFH z(qIxVXuc-nWD2aN)>gXf^orebH!n9x9`EYE$;-V1dxzSOVE>LZR-|zQ?~TKUl8u7o z{S4_}s07$?p}mbLJ|$}5PCTF|bzFhhAXgvA|;<&z*i>=a%`wAMVw<3I1RL95d;(migiu7b+Vd@jq zAIfJEQFSGXuhZ`}_|Cgskk)KwkofRWJ~8;P5GeC zmX2)d(#*=o#qu$cyYD_-a{BNUYSVo(W>c-yulkg-TWWMF3iXr9{DFj=T=Z zn4i%%E-SIu%`na4genHHq%2b3v}>Ptt;O}@v^ik56YK_Lwtl%={H_m~kflYFm8CSW z>*7c?UT&Y@L&nJge_xy!Z=HD4&N65^r|-@4-Fls7G^IZrnJab3jn}fR#MQH2KbShs zP-T)D(Nqr1UG{vYJo7A`);7_r%Ghl0YJ!T&1tU<{aMa4vIB5_6x5aJI*QX5*XzoY{ zxFMf_8Po(VmzY1+AYCJLY)x~`@R8O!Y~R`8B`;+w$2Zt|TK80rzk=}46g3m8p2K;V z!YzGah$X-51e&e@u8AVHJ_pk)_M;oAcaYN=d=k7E?>O-5PA{=A-FPsJ5YW7jmN!y zNi(LHn9Qm+FLu%i6;%^86HU=gjNCt!8A2XxW`ay(lHfV&UMW@8pc^7+x%>TlOiX>g z^m8kqOfX?MW6i$$sF06q%9I4-fO)#>FCahkQ5aj_rADHihsMPLbLW2?CdK zr?)i$4<`s##SAJ-cH9h8NNpxH(~nIWAUF|iFLpH|TKjscp|FL|B`#)3uadZv`RE6d zaB!?;r&Sw+AP%ucsn@sX81VaS1k?sSEvyzNbAQqNlz6E*p8{p`8)i^UYKplrMsa82 z@9HO~z`z8#)gp7NX_PUT`v6j6xDoTDI>ALkqkrrn95G*HX(*hjOm8*1mV2IhpR8RR z5;t})5=DvY?ftQpfFF0{$Fu_m7Kb{{CT^L(rkJ3A0K6w|kKZ86tnFR;G@AU{1&r?R zBx`W}nFCRWCt$#x%ME_enxEL9im9RDk<>G^4Jza(@)vOZzKrH|nwfLVU0aHqw(gOT zyfIE+))A&FMVyBQqP@3wGN7&vO`m|AsO}q@OHnm`wp}0icvaKGj~CA(?E4tX{=xKx z&52D_VxtwKwrQ3;03r$Ky_NLvMHvFV`?wF~NLuAXbD`= zRIyXl$N4tx8cW~7*F8z8P^$_wTNctB%$JM}8cMyI(t^?23l^}3L-wb-i^AAIiwRHa z(N`9q&2#<`Lw_4o$Ig7JxZL1GJEcI(I1A{gblGscZo=CDGqkdGtD3sf#x?Xx`ifhT ztXv4RI0{mm36iU?b3DqRG#IS$G%D6;sdn8jpy$lzM-g1d7pzw35XOI;P>Jv+cfG-0 z_nToZ{Y{vh@djdlbXT?`V+do=Ocxh9%CffPYiL(V^2aXTPz4HDq&w$&(gpICXAM#? zDo|~GIqj2@VMb&o!S)kDOM>IhA9p-(QhEA=zsM&xg5M@pDgkO8Cw#7Upr%Jq$@A!H z{O|`thAZ&EzWlDa&8VO^;6*=Mh~I-v!JZo}6}+5&*7I9fO=YN9nZ-d2+w7};P^`hJ zEG4luo|QeR9agUt9P3yUy*5i_h1`t!fvoQ+>~6r}Wy_%LwXTlx z{!bT8$0w7{d*2L=Jv`<7)|#rT2bJWv%vt@JdB<^!hOE-z7LPWH%RVFVbA3m^{)S9!Ys3&<)CD1U_@mv$|B z8`+T^79xZ_EOzUwcRO+=KlBL~ui8tGPJi>Yvd-6gqt;GrZ%LV3s<;OnPo5xXvzP1y z^|m8?WJcjItwb_A<~tSt0z8*a{sQ>nRljK1IZcXKjod+Q zp+RX4m%JYza7Hzn1NP8vk2d-GjLaNqlqxI*2E5D+vk4r^^FqnYzI`-SNwY}XV6Phf zNJwTCxD9XHlpmiHxA6|m-D|z*Pc-F`k&@Xj=k7rlSW-C|km-=YWydZe!iHR3QZ99o z{fN4H&w@&jTIzWe%cOlqnd`%6?J$#;1>N@qgu*WSZ8^Kp%`VkH4g@KL$b_FdfQn}R z&DQT)EvkmhqbOM?7yEil%Ma-@mELm~KtT}RZxh$o~ z#oH~dQyRBoj%f+0ODRWszwx!Sox&8@lAr2X!^~`?SOU74*yt@Vd~_1Tvo@O0xDMGH z$?^SgjIRYfEHMq^ADZvpPnqcX(OdTFioL3YAehT9TwAI-xQg-JI#x(44|0igDDBbo z>{n`6p7AFSw5m5s+X}P4T_ECa`=F8THQsP&V&b#N$~C+FE_&~#9Clpuo;N=4E4n{@ z6FR9~-`q}m2w)pe{~_|9T>7R}x<9$wqrJP)A z@>I_r-KJeP*E+lNpzWGBTWw2+uxj@6NBruFt<1DRRqj;Iw3?&m5Vd_UUGG8ya0FeP zf5jyTErG_vi67_P*XiKt!t)aIX(_fZQke_H060OhT;)7mbqaTGuphDvBHe1dL`Bne zH}%RjJ%D)CDDkjs_$-hGBor0M{|;J~z-g%8I9AuvPVoNyFrsj>W9>`U@KtNe-nZ;& zeQ(Td1ZydbbVaoHoQ4K>Ob(EH(kur=>R$Tw+fQoDKN*7Z%68+BI=Vk!@G!tC+F<-| zEo_Dl9|tricAT{2lsJmr!bK?`eEKiQ4858vE!v7r&(^MG$=HhqVF3aA>YP7A{ZS;R z4^?~pLZ))_bfMp~$JolU|4{xaWE(M-vWj)n5?rz{-zRbl$c9d%tbgSv>=yE(tK0VjG75GQwKBCi~ST`g& z`wl%(3=OBqTMW~X@J_QnHQnf(pFuI7yhdx~aK zLzx~wcB=bcii z{SDUcoI>H+4c(T~5y`8^>yAlil1I*9N_klpCnxAgfmy>(d1Pc}49{Jcwux#)$!%kj zIu&4m_RUqdFk{w>o+P{jTr2rvdOHs@Wp_4Z6>+ssOi6lW6eAROc)>52$0#<=&k3mm{W}!7?qcXqkBK?`}n5qf$1UZACDIqepSL34*@8n2>}+ zjoktYAxV+|X=h1}^bOq)b~6)EuL!%b2_9ge{-7q7{X$Yo(`v_iIisha5DHi^-P%Q= z8Naw5U$%slzy$dkgD$>? zXxt24a{&({CP>y_z!cMOvy*AQXmKBEB`eU^6led-vUNMbO;-sf`BUDEujaEP!}!@z zG9Rjj!1$Zq1vS(oTMIwR4yA`pl_K3J64O~DK9nrz#`0L~aT-EYTHHGxxhF4~Dr(w{ zJr%ai=6)`otg`xIyCRXY^BNlsw%z8>?F#58Q&b@@FbZhSIuTcSeX5~I}#Km2>zU{@-O$=ISTsvvx1T3=RDZ<%R^zZb86$-r|ifANt2py6-Odxc1e;KP}YRlla1v2wiVnA%{S~p=xAt^ z-l0xX3@o+TB}snVKp`WKQ}^w7xAVTLhSg)N@R$y8ZW=f7bQ8JvdHJ51uZf{G94ZUI z*7JGE{xTHK0T$Ir>(EFJYWwl3ZQ&P0;;p;^Kw+`W>mI)GW(o4tY{;GrMNeAcyy;oc z_bUEjNh==kph^lHdJLC#Ai_>bAKLv%cr3$*WV7SBa#whxP%xx-4kd(}ToMuiy(E zkJT_JL(6nxZ)z<0>)a!@DX~ToQ)%oKIJ)M%h#Lf{J6Mkej`fdqrs_k$j;R|af;HG9 zY3J`gQ9!04Q}rB13@X=2K?+yqn8HXV{R;lPzH{OS)kb``Pxg4~8J-zm6`J3?l5*Al z)Vo+&P%gboOWkKdMJMb#TS_enB_CZpPSlfHmodkr3JI5YRiLfrsyiYc%yVP)&R7>H zQ#G7yQoUYx=;U{`Jy8@iG?tt66!gyZXO`BUa2c7}_b1!@2yR6qB$lm5X?aWPp4)q*Q-d;1yp~s^#d<+oT zdcN64S4A~cNJ=pYIOJ$i=-afqnT3NrIis4o?uCke(5Ct^Uz8qxRr=TR+}iXJfU*eb zTDOZ5I{sUQNmFA3qAi4_BDdP`fXCZ~ePDBolYVTtf}awuw3q2QG_WWKjex}}E3kKx z-xZd78`0fEfPxAlX6fpwq<18*Bb3_(t0oXe>4&sM*_ii!%I_L7Z=>ecYL6Pkq%rP( zi>%G(g6kT*eb`yQ(lV8aUCy4uwKZA_6HgilvoL{fb%?E%YUQ_ECC7BiLQ{akKnqt- z?{+{;jw0A19%Oc?|IH}%oORr@%xG?8wh6a)Zb4N>IZ~5&(6foqjq#U^t19sAZ>yo^r@A-uJNy*v(!ahEl!-ho51>XJ>N?ZFWeV!yyG{MgW*qSoG4Zg7R7b-yt5H$w3$S6g-sD0qo}GP({-jwKR~P%{l-kqC8r|o zT*t-thuU7$+F06?BBTz+9aUlw}pW(?5HMX}Fj&CNUr9Vj^7S!~Unr8g} zpa?B{i2@IX-R>6GX?M#EZymp>QdfT!KsCwMhlK($T=g)KAw`(}r=LxVRd&KLT&0Cu z(Hduh)Y1n`F?i1i&)F*2sLpaX9%(0I_9!txbBOeNdts|R3n*M9Vw5>qo^zm?DAR-kWk}@4 z;7011@u%_@)yVRyMij;&Vi?;fsookn|D~Fd1dL!&tkJ9%?8F1#6*l&oACBRY>o+~c z^>cv7!q`iI~G2k=U6p<(74jLrEk zW{XDg{_EXWc668jVnr8wbs>FVjGAFT#EH_ptSJXtH{NEUx>5X~VG zpJyIct3@@njF9Q=av_vic1`Ds3PEzlX0Nr_v@;$-*emp=R-6t)G5T>B1xF%aYjij8 z=8gY_x*nrEYgRv>pM!8l)Vo$DCHS)0G>z6%#wb*87PlEqakDm_8hCCfx<o@*lDUs_ewAHLU@?&DwNAVL;`La|^@ciN& zy!(-+IXN_srR+YAKxq`6AFr6h2y9+L{TeOh!Sot|WOt2NK%9g;&Um&A+q&l(UQFgu z2qMjC-r|x&C{qS4eU0WD4n5*T{Kc55Ev**2wu@@12VWTVT_zQ_@#USq5i+N!4hG!f zHdQH6&(<4tXiN}2pkZLiZ7`HZ*7D<&)@5<601;i7z_`i|?ui;jwdSA3TJ}^DhIFV_ z5M4G?q`m8|4yi=I*||2;Son9m6f!U<92+p!v}paLt|W;gUlV}aEboOS^~RmuHzozd zmhVEqFSM6lE_uNkV#aO4#Y>L%Dg{co{i^7%mC=#^7=?XemLjCNl)Cw4M!wX;CbY`W zx=s*SiM46Y%)$^;_N$;|davnSgg{M*gf8n}K>7=koPNX17at`qn987g3?Rqnsqz!k zW?Up4X?sPNX~F7#OlQx*l}i~LuQ-4oLBfo)<)gd>LWr{7hvqebId0k_-rKnEMQ5!U zWYpe_$KScIWsy)%<)upq#(Rm;(tf_Nl_YJnH|1jiZcE?ly+s}pPd7!|$Ks;01XQSY z$C;uU18y!&&{OC!%sO}0s~~vY&eLlAM`R9XCDvrLdO1R{9w3FJxo^oRl8Q8N0mmK& zQ~63Awrk5l$Hrxr&si0=Oi17FwMF|6lEWAX{>u&e0G7)5%2hJyp zlNWotMfPI-ZB+$%Z>pZh`o~8bWRRbu`Nu3lfBpjAk{Ly^bA8Q!$U|2eQT|REv>WpQ zegEuqkdMcH@e=K+_AemBHpg=4(@a%?_&pvMby+|~^O@q9zAMisMlU2IjXw!H^0-DC~`vDLyJa9c({hGuDA{I0W&+$pm#VdCw#8e z7UKbGig^*^9%8G0^A~+u3B|9bDV-(f-^3gtk`sf~e-?g-G}M$P=xk+L^~bN8Y9%xj z;-&OmX|Ugabj!Et(cgcDXZce_c*)~QEuvy)Y0`H^(H|Yn`uWi#W={D%OfF4b zUY?62Xb)3F0!+_YO^K`f@|KgjwE0X#Pm3}4Q}h7WZz9V)Zw4%0f+d?O?854YfVHMg zQ z#FwoZ=GQy^le9U9f_pgFB@ed=%q2Dz5)k$%M9yHO_I}vV+?{~ZC)^A#UZA95-ZOyt z7?(&5NrJ37AgKcTBkGDy@G#EkQ{{`>fRcH?GZyq$ty_T!oV`!JIZbq!eRrRsMOF&} zb;sRaA(aNV?KLDofFSoIsY=|2xLnK6p8AbmyV{I1RNW@=ik)#JSXo1w`CDS6`Ya={ zKSW5B<*Bq&gN|qCE0zWZq9=7Pbt(I@H8fvQQ93Djd9gtxg15;fA25Kr0{$G9yzh2B zP4|fkLY%P>k(XXtc~^t0iMmrR56u1^&nXX3d1N7Tk#y#B6Y5_pyABq3j4PAcH`k?OFXFH~{T2<_MdmP$Xu#h&xnTRy4Y-El)b z36RNuS*3RFyY@ zwW=;j=}1}=Pm4FrI8JPneYI5=@6+7hsB!90q?Y#N&TWqBMx`I*tph&_ys==es-{I|A!G0F)$Km^P zWmf~drvff+-K;H1-dcs)sFCoBGzq+o3)$HtU%!OW4G2ZT_DA#-lYO1XrF>prV`A=~ z>!ENpCC~Acjz2fGJ~U@a5(cZL(K7Ic*~h**b{Djki;){t*9NN4iowN3^o`VCRaOyK zh8M-YGR-6POW9F0%ooUQoysnb-wh$mHK@ONpQJW4ay%*-H%FJ?KCZkL?ZtJv6O%dg zaTlMU-;&9apPqx_&d(>svpB?i22DczC(Rq%Bz^C#s~mZGi>=ZquO4Qj=2ra0cAxhj z0qcbs2yxl8wTSz4QQ~O_!+Uu>b`mJa7Snj955I&TCF(m7g*?mgN6#g;MyTI4^nbakSk*Y!+cNSmPuI@ghJOr=S zwfZ#@4;3qAiu}yA(R8ojqjITn@Twz?#fQ{*uDkZA0E@>7qP; zUbPSuM&i=Eq3hpVJZf?+_OlX5Os3m0(R$z9^@SE<`u8vT`1;(Rf3qnkt>|p^VyzhA zV@t?tCmqyYRAb5gxEcbK)7X8WzoNYVz^RcwVIeIQh&YP(`%gE`APu}A2i~@LE+9fK3YH>KsT(bTqpnfQFIzNC7bMGcky$vx%}J>;lmRC)r<+QAsqIULDad*hKXqRuaOBPT=fKc(fc5=T-^Vz{q$k-g<22DwK0m>P{rlISwIe$>h@F;ku^%R`Wl z%cyhhEdJ>u!^K|Q7u;VoS{%e7AJei%I~QUmUV_h+vb;2+cFF{Eb}v>+;c}ZOlm&+7 z+qB}SuO%2K2>iGLQ$d z)U{QmlBp+48zN$rW!q{5MuAq?b%*>XdLJObG zQMTwY$uvmnr~7Uk#g>IS7&(THPCz5|{?%0mXyPjVQF&DpT($KS`r`0gA3{e?)6s+G zs9TP6Qeg_;&8(})XwU<@=);%56tcGI*75Gr+0^fI~tD-A&KstzF!HaS??1S^Jgvqar#0b|~_ zi4s`Sk(tTHZh{XV8(B#4^%Ne8SwC=GldyOd&;Y?8RX9a;aHN;8`axL99phaSo2c9qU7fxsrKI zPIaENq_=cA6bV{QPycz#MB@`XcF&6e?V`?Bo>F)3Ug<#1`{wH(7#H!QW5QKd#tk+! z6jyQooES3ri6^g;5V1(zXh*y8*FUiQVK#r6z~!c!tKh*(9f4)JX=gSrhxrN?8u;~6 z2*!PCeSrlv%8^bImocxiASZOZbeBkSX2H(8G1{tB45gl2Ktj_}Z{;31&r#t9YR0h*f9rcK=;zh^fMj?!4{DW^~yKRj}PcOq%!rmmC9}J=R&th_(5X z#`H;t?gO*x!_YVJN(b}1&Q3VO@XL%W0cK0u79Fg^c;?j4kNyegzXk$IJ#Wa)yVjEx z`mNx+b9U;@_K6s*1XX^nCyJb?oyEyKJ^DKXt;n5}G2`YZr#pQANQq;=^-U7AxWeU> ziF|+rIG#VN1LK?E{9i%j8&_K5y;4Ncq{g_ zVJM{A0wu>%9viQDWm>i!Kls&{OYfcg5R)M|ct~^cLLeXjcP^WUsCvvVVI~;H5QD+G zW05RReuC-O=uU%l2iT7w?05$2w!(;f`SZeQXlm(6g@v_0W}L|^7m&JXXUCG&`30Uh z*IIW7_)>qWvX-J-H2D;$iO{3@<0(7RC|KaaH-25Y67hA>%yd>M*yxoNZriN+ zv_9f1;v;VhYhTT5D&qWo{ufF$BrQ`c6gImBE&=o8lVHUhL~&FiHwCueNbp9S(KvXO zDl+m;Z!FRxZ+!_qMkuCe(Mjr(_RrvJplQ<56JvPKXTpwLni$~jj>C>Od1CbRSL0Pp zKX;qwd@!1KYOSVhHHz1xI?PXzzZBV}(UBwF*LMq!gyZ@kSlx7E;#nqG(@>`AC5$5M zOEq=nO6>$;zH0spurS5$JFPYd1QO}m>%wkkd*2@8OPAs|)^pwoVn*s8lj1T2xGd$< zjZ;urwr(C3U`8Wt`@i<)tclBOf=o)6?Cr; zGsnQI6J-7ILwXUl#VN^O_yPe2C#jDBw9(zHK@tg7EW|yri^z=pW@M{x>3W#cHO*k< zYQdsb1mdipO@VGP(&*96PYuR=is3|o8`Rgc0|I$IBq!)wXj)0PNH#=qVW%1^)ePRfud8@o|HY}z2W3d5g zw4UH+yI2=r?ZtWHY$u+Ky zKCfz@lR`Z2w|@cWbcZWQ7E&XPyTIxLl4VUknlk{p@}@GL5+w+yKIA&+Su-ioOBbIr zs~uifHAecER^6_$GN(sgMvn}TX@?Y}27oAcpZc+yj;&sT!ioxqyG&d;XuTm#nfeXX z`_%{fC`NBue;H`sw5FR9L1I{Cltnb$Q3_-l(ZZ8PLaR=MQul?OX_s-~qAz`Oqy$LI zdd?NN8VQhf_9b4&(O>+@9e%@6Rv076q;bt|C2h;aA54SQFl9C6cVJQz)5mo3Y1t8raW`Pe*tyV zDLh?v5z}TSv589jd5(YfXf+9x3muF748R*c0n@rtV;Ah$9foSXNp_Ssbyl$NJ`#_> zIOSq4rncifDvp{|$%MSgysJLQ4q(Iix*ckm{6c~DVrB|MwPGQ`;E-oFHsZPPxul$Yk}R+#J;pJ@oa4O{v$e%nl3d2BV`!5>S`Epi2V73Sl6;P z#+8Bzq&GXu!|559{ZFcZJ_!G%>Xiwu@Z(~+s68)u{mb6qg~avRXKO{ckm2=1X0xgx zS5_X7M@-sQe@R|=o>$qs4fv^A22Z>TLtFf2;g{}sQ&5IJYQNk^+SkPZ)%4Yf(rL4k z`YJWGGdub}J&KY-I{KE58))aG*!NQ7nLTNeP!-vHk=Sq)I;eT2=-Oaw=~G}QTf0Y697?uF#pxS-ocb(jn#(5`DcEIU7meSScN!<|)7==P=17AR zahUnbU=JDl!%PNt&*i5HI3+E;?Vd05Bx7ZB<)0;G{aJ9QS~a8nIgq_%XVa*Pa{d=( zZyg-R5Bv+RnVFd}X0~JIn3VlsTk;fVak+86~1ia(v2>C=I!!ub6yhYA%* z)69B0E1fp;M!rl6R&aCWI)0flKIAvO_ot;Qbc5?N8Pu5$466Ihj)$h$IQ&9!z@Lnf zE!FH4z;!v&AfVFNH0IF^azmxh*)6m}zzWWi-OfNBE9Sjv3QBU{v8nb5H?ojqwlHMetZ5W&-xUlg_1?V~xmiN-CDTn!*Cx zjW)25(xWP?E!AhZ)i;)jKm^d zN`P|e8s|ygpd)}^MmM0r6z||-B0oGTU}-2^eZkg6TwUqmXCsL8S!70=m0zZ2oK15_ zmtkiM_TUQLOfg=er$LZ3V3$Of=|ICq5DyEAccN@qmRwKoZDUR0$SzhPLQ1?9dgEu+ z>HrRx!Et4a*feR;3s+4B1Lzu@~W5o&+NtcgXkJI4d6%7=NJ!n*5zebwf101aP z<#e257TtP+lN?OYJxUx+Q-qu3+T1F4wnhk_t3O-8{zXRIg;pG7|V63;Yn^NGo7vv zUdCT4jdCMR5}A!%n_3l`aB|ni@M^JpZFo&cdkcc|vx~_QlBAw+VobAk{i@97^sOzT zZ@bJ~Hw*dfMdTxyZPH8c&;S`;1bE2b1jWuWbi)u&q6sd_E7uf4E-Yv1|xjK z$}Z0aoU!80{*;7m4#fVFD|qf-{sj}V1(0Yd`=e+_Bg+x|3?b=zvM~qx_kopifAZ8= zeE=w%54DW^QEI-_YMu9i93CRqjlSQC{nBc4uY{tDLF>%O7)LaHDqxgWbOiUX2*8GB zJ%L1T9}`xMW^47;dtiw~ldDT?Yf!qV5pp{kypNlfVfzRQTyc=aVoQl197nn5EZ4iT z#q?N?W2J%I$@zI<9Ud8PzzC(P$j5#Jf$OtLT|IAE?4YbK#`=4;C^tkX;af#ESLIGA z5@N=lj2uESWvI6QmF@dqz{6<4UiwHdt{g*42m2@jRen+y>xf8I|{g^JDVYgH036 zq3m7+ok_bL@1ZL$N;JsqwZ&+H+sJD(*`T#S!L8^)F4?hiOAajwNCG@WB2Ie|e+h4} zWui*HO4YW&WHHrggYpQ{iG|>Ah^)gG61A|e9l4O6>bapo<}pN7ztYh~QVG=D+a;(I z@YO7T74dxvb0@V|_c78*<&X{~bJ`MNJW2pV)ljq(P&3MSd4RaZ z;c5v0FaM`v%V`4LNVg`lCSLoSFsg1myzF5FJR42&^s*WbumbO^l26c3^5k{7UE*^R zHw2pZjg!VaubXzHfbEy2;L_dxy-=_5wEl8-=s>2>*b4<=1E|!mXex(Z!Q0?X6h24rs{MR4vI=?w3>^@PGbTjO?6dReRcpd{Sme zcRmpXebiY^oW`+04EaX$6@{pL+E4ph<}?Tmb+um_&5>g=AWYD5`$vInSMOc-k8t3U zlZdFL5jOoLv(`7>g-s_n1dkFWrJp2azih<6w;Cl2+n=lcSSHuz$gbf|Vnj$@4oP?E zTQFG$ae2@n9pI;oMb#ZnInNe(DJuQk5bf7DHcCr{+#syj z%S&OJM0YIlC%awqs9Dv`p?~C2>}-W~>cz z{4Vs(RicqDS~UYWS=b&`gnI#u^WAW*~5+>s(U%(EsvJ8ip%b}d#_Yhc%LD3eIlQ`>{0B~ldh|> zeXKI|c(Sz~Jq^g~U*4Xva-~3pZf!BhJLM;&&P>T>3&`mkoiuYtvcWDM^&U*I=!T7B zn<9l&j&t#0&JM2!&cx}D&0Gvo5ZmIm8p6;Lu1x{mBM76DF?2&|RFHAi#(n#+*O_rO zH62=&msh@4m~48E6@u$wZLs_G<(8AD8t;;f472kvf!C@1S93f(gXCv4;V#E$FsPSm z$?CR%=Rk?i%^XTZtTF>3uxD~!qCq*b%16ZD!sv^Iuo_0cfG?^*U%OjN$QL!QQK|Q8 zn%~Mb2A+({h}f;wulnmHy-6DagryYEQ!y%>gK}tqDt4|qT^&zxbT4H`-uFsU&>l zmMCFo#T=SR9BBW@gj0n3v~VD$YoG8+0MGX$(? zgPMfoEiz(tGQriN!J^mXL3?Rkfq&d>sG;H;B**kOyP2r$b24U0yQYE-n;Jq5!LL;< z%h1Iu;A}0;%hk!G^_YN*KMy1@H~}5HkS1=!@FVqSx*^MI+}jDKyWOocEp7)ps(W5rjXtRv{+r8uF^G+*NAz4WkKo}cmMrL3#B9o$gfBpBsN z@B)7oI%gS@osBA*qi)Z10pRkgwy2~by8?f8+RT6;H}xOoPNrc8YiCg1G=Us%7T+#A z2E8`PmIipTgJ^+YqJAisbkzu~^w69qSBjk}+8JdCB$4gb@@-5_qq!8D-ya`dRb5@P zxZUkp;ZDde5ceTj#I(Q`{p?%S=dQ>uh8##c{aS`}mevB9s|XcNC)dRbjh@#bF|nzu zh&gqqpAt9CT?;PSU1%Op$E*0$Y@9XbXgXrH{0q#_m|W_sLY<@V$!sO@eM*&lw<{IP z2+Y|2{wDed_{$%F>FR0-Vz4xmxt+fN_}+ROcPkfH-q>|yPblY8HJ=b# z()m*8(L0HBon^7HJmelT8;6xtUMJSLwNmJ-olO<cT_C0Z1(K)RaJp?^tD>M))PaY?R^?~~0 zx_5o?wc_Mpk~EdHcbf~`vDafYH5!I`SDqI8tQbXk=?rTYPPH@mY(6+N0LY{pLR~4!gTOCSkG{hOl3)}9bSq^vQI@g(?L~qvMR&IDd37SvL$L#*hk ztF1m{D;PNhwww%)Jo$+Wi<`g|k?ztQTfxyU1N@P2=iH@p1s$k4w%IgwCC1d|c|5_9 zyAWxiV}XioEvNF>da6v0-)WV}8M)xvZNBz1LzQ7S%3!6D)|s(?1=og^Xym!t*Q1BT zl}IU(Q{rF8x0CZ!DmFGE$1}G3iuEv4-N^ssoAX3JVI$MV5aZcA+$XpRZZ0q6rs1r*xJVCT!KzWa_$*gHOtEk>BcTQ7|lk z7B8F$S~#6exf;cgZ7Q6pgzkzHJa!VXtBK**t#ymZ(c8eW{+`CDp;v7&k7WB({7@z| zLA!T*=|bPICK;NVGViP~108aSDcMo%9_VN_FDq%4Y^S=dAT8ikY`ElVK6V3VV8t8R zjyb(qOyoF4yDFJ#iN*l>5_~WZ@@zu{IlqAeKEPd2@8|jd{}fbXI6@G8Lk#6Gh;fdv z5aENpQ5M(q{~_mg3d{MU$#7-(LEJR2$o}u_`_>2X{}ikKfAtyI|9+7*{MT&o_#c9Q z6|(=DWC0&%?*q6c1%`+3MFc~TQt{`)A(U;ys@Jg&(MB|A8O^U&75 z{J&ds@)ywg7r=iji&;EN2olC7$$$nLhC$k-Q2vs6hNCdTkCC43xt{C!=q9L4gN}s% z>V&udG-&?!yX!p9xdxc>@GGeM&4{2Y^Eb?M3@d_k;!&0VU{s!E`53}6M6oL_ACMB` z46YxHh&TVFHUHO~W?=az&25^AbG`?}^}j2xU2FA^ONyWy!trrW<~WuV{?W(&JI?X^ z8wMnAe2B#~o&85Pz`*{|00AA7A3 z*U|?K%YDK>1><>!6F|3&Nxl2>?)&H3kz5#5>Nw z4)g!zLLW4@#QE0tlJfsOOdr?%e=S6*?7jg@8Ta#m!jO+%6@Nj+Q2ZGDqYwMx2hO01 zffy%P62JfaFot=C4>OzRZ~iwLcjFArA58|Qf5f2Q|BnUaeftRw1W@!3SPBvh>L0!w z7#bNXKt!1Z4ba1oq&-eBNPY(4jfW3%n{5}5-9T7()?b)R_0w?r6OO{82Lm?cL`*4U5AIKEAeEFrZ~xzq z`*Qtou_ibRQ7DZr{(gIAx04_oirEJawxmbz2iob$@7X`VFN6!o`=ee1p)(ncCosYHjPyHBAdfZJU)M9e9VYO(yhKJ)B>DWm!1q>Y*g8-nib`D) zq)NXN#{s`Lz1e5((@6Hgzv7b6fRgZ`p+S%N@#wSU5gEPD8KVMi$j={p1N3I>*2mbL ze+HcUcQcn@H{=6yCVEMQj#Jbm)Nb-~$N_@&uEU}6e##85(_nlfxGq>0o zmc%|te?2>d2od4JBlyf!=<8}QCOWdg9aWuc8;Ox5X^Z%#)cR1oCk@?;+2I9NFN1Ae zFXSSWZ?zPV<$u#-fMICE&eT}zbIYMu-;3n)xOi9MY^p*4LBr8u9U5OQPD4Q+W)*7jW$&ZC4r?1{_+jpoL zO(coHg}Gk?l${u#PlYzFUQA~oF+Vj23%oe-eisb~RQVY+bLO+yMoS)s8lvapu-^$cDOZ%;*1M<>E8x8*4QJ2Hi7yU3eAFqC^z2@6*#p|TD zD$2|F@k|-WW-`a-I*ceK0=_<)f;&1rL7bq<6oMIq5O9oj8d#=LjPKjG-BYF-*Jaf0>3li0ll*yzi}b;JD* zQh4+_?$kcc_SH9y&?t45h&*%n?4N6#@A~92!t8S^6z610uiq#94g(RnM-%Y+(|g~h zN~xo^*SdH4B1>V#u)1WO)YpH_e?&W#?eX0!n4omfjMX@Sa~@m8xFn80^wM=q-a=K_ zTlO2w0O<+yXO_ls*qYFs&ONq!DD}(1;LHW`>pIH_bCn3zMlL?H&g0F5Z|EO$RLSB`E-NgqLm0P{xuy9rJq z51gpXi)q)V_PB2IYh7`-TQIjM+j!VK*jha_4)QoJ3M=vY%Gq`SYzU>2x%#Stfu_8_dDu`AC*cz;r^9{lFeY(B7z)N=7vg?0Y54x+Z(=<8>8b8wx&GaUQ4%szU&!eo9b~Q7KsuR z3j9!g=s7WLiJ7MA&;srSE`lwQDVF=?vbxX!6Ut$B-<-`^THmECU~Ied@y`|Z27c>~ z;<;8;17VjzV_Qx2!=F@yaug=>uVb37XV)8n==#LXO6r<=KWJTs&JELjg?=06uW?eH z(R<@w4uTU5f}>g79(;}p`Ek$I+0nLV9^NoM*N9e5&M}jwlHFUz>6abNm*4aUsUNcK z*y72(uEE;v75&bF+cK(`uXu5G4=YbC6ZgP-VE_&TT`41NbL5L zrCeP8xo2wt>E!_=cUp3d5g46efVZ^J0+cZl8k$lakV&HKnyH-vMwnJ;zRX^+hggcp zf`-p9L;H)P%ze7OZN=7ixhBmq_x8s@US97}yeIus^muiagMi9|*gvi@j`gL$+Ct3N zCs!!9%9aZ6+{-pTW^LySF{0NTuU$HT$#?CB3MWjiMH^PHTMz>B22Z8_W78FYJVYmHXQZyI!QXUj5 z=H#EpA7p=tKF==*mS&~^nG_$DE?a4{n3{E5X3up(TSVz3E{L55YCz4}Pq|7t%cd1SS!Hu#wDV(XAR2)0!@Y|{I4)+ulw8Bv1`}(YS z__}1k^G_|mYn9Z{lcvd22#R&`EcdQ{p)WD)I5gt0Yuj8YV-rPE(RQ{%s?mWjD3D%O z;CCqqKyVti3WpdBr~tI3%X;=(ZTl_XJvw}jp0g+xFl?|pf^#Sg$4D7iTlr1UH}`wF zsNkDLn%@CTdK%*5;-_L;a9tF68bDo4S}GT|_6ybSV)B?((*1p9*^XLH*46s3CSQ5v z4j$6ar@T{Mj0guq?-+2ttI=2+lBK+GS2Z$Ts+wa27Q9v|iav(TzXX@oU>O-pA#cx16T67kUkm1GpXanof`R3;rBRep*dR|Lo zzpKAH^Kbsz41LnK=*sL+OnNr6gPy4=Fm7ceN7na@hLK6}#dXTe{RunBZe(87-(@cy z#>P?(#Do$5c?(So!gLN-vT+2$vi zfWBDCAyS0=UC)VD{6;VMz?@DGYDHwYLB#}0V@6ldYHd+7IXh?8`hFql5S=;J@7``r zoYc-G+KV+SpB;Wni_HF-^DDeSlIm506ks8an5g6ul&t(Rw;C_ZJS~*v1n;!nIJZq8 z_4j~$k+Ab?7z>kOuSu*lOtxosbgF79zCuy{Ish`pNo!-;O=|}4q)bl&0I#HH3htg9 zL<+gDdRERq!2j6@HU|T>C%~$7v#RQ@Q`!krkqTNMmzVL#!@j`^T&oRFoqk|cqmAd7 zRZgBDIP8Xo32w~FTHZ#&$xFX`Ebl`7i=Cf6sjHuR^BZi9w^kzWp#_mS{pKjKOgK#r85)O@oIcp7iM+vMM6b6EzzJggAczhGH~awL{}sBfD6qp<=;CeGA$5w>sN119{T_+IKc< z?wH)pJDfepsfbsp^oWx~IM^Pj)=77ubLECLc>#Hv4(Fac5aWI5N9Djb2;QYdH>ejb zN)FpuaYxBztBxoHWZxq;KuPZ&T%@JB0!p9EKSJZmD?6fp7RE^w*oQ$*+mTF7jog)P z6$)L3Q2{W+GkcqFvuFGk0jU7c4HgW66?Ggph+rJ58_I&rcsV}z{LN`?>wEo9xQZs; z(yEuf6#aVA8C+9aus`vjU{vAfmuvZcBJ`}c{Mqz9Z0~cx0B4+~aUstF8ZAmk_5}F# zP-euD!Rrw-TmH(i;Gmb9vhF+5Z?;1quhecI`_#da;alYVqC3bTq|@=W_)nZ9px!<7 zzQ1%d2Ae^v(PaD{(Z9)TE!yX+2Yo8|d&*8C-vYKZ_d{l*$v=u3ag2(U6lx-b$+Pu7 zz-uj<#ae*lqO=6_!Us2qgpM92V>N}Ere?j7=~v|d*3XB0?q>?WN=v90t9;M@k@Iex zuqv0`=m=9`l1Ho3!2Fcb?p&wXUm-qabeOH+_w1xxxDJV&9L4`DSX}<0(jmsMO^0F! z7O&q!tqajkF+eg$7{Ag3qS(1Q#_x+Rq{d}Wk3~A(6bFwX?Q3p@V-Of*@Rm>AU1q$( zUd6K`uGeT~j^c(K>WUq2kW;f{J5IlA1!`p?bf4k5#qbz~S|db=VH@jy&PgjI-!Hm5 zop7W`ap12QVf@5W{PbAw?6E`%QG+$b7vltSA|7HCoa@y4oWB5F!?MTuBTNy;pQsOw zC`5v0c%ee}sfe&uh@Z1s{3CJz-i`(vU!!DN17Ns6Q${5}cs~%e;gdPJFx*#Pdy;- zS8^+ln$f6ggGhL8Mt2#=85odsL%tqv0Iumjd^sPyZGbpJ<8C+@g^F>xuI+?NOB+`oW2 zKT=@foK~9tj*}xL;v!szstmEmx7QAm7}SbCaEwk9Mx70P{jpGi5B0{Er(WLA(Ik#6)UX8!s13o?CB`|(XE z_MQEO1VxG)yXYr}!om*|47t&uVzBu**Q@NpjR{eDkLvtcIqJEkb3oVQa5KcDrPBYI~(%n&Q)k zRDi>NR@KTTj8o&kn`o?2;<{ND#zePYtIXEB2hYo!PN24d<$?$bS<`5FJFKod-#uq_ zfUk0r=uI8VP0mb_K8*nKxxRNkw3tpI2OP3G=w6K*A(QullClh0{|F{YTzq*SjB^P3 zji{oH>pV$3@7Qyj1H^~jn^$ZdU5Y#ei-w^zbB-O6C{9wj6ZYUyAn!rWe0q7s>##zb z#Sy>$@KSr&Wx35IS+bKYc#QoE7_n@~#~jhv6jXjk_h%LO9sSnhi$BD_iJmXJ&i!}| zeh87N-%qu3|6&w2<;9eb|2iWZBoRn!LQK%j*(0|dcnl@s;gib~xG}4%d+_>pM=FVL z(}EH(fA(s5Td@B4RSfkeL+BRoFCcQ*|97pV9zbGkc9 zf5Hm$&EE8x?|3TcpJU``WaG^ot`n3SM#c$JF)FP8SjOIOL|H9_OI+Ctya6tOoc6u_ zDF-m{_LHRF9aW+Hs92<|)FmfqQ*>yD^cwsq$Y7PKV&y(>kNacHwBFw)@}9Q+gQ9A= zu!<;z?}oi8n{5jabfb0~_3`kAx~1XQyktGmLiJ8zjS^@8I=U6#kVh}k9gfo3#>RV5 zgMI8}HCa70C9PI}Y)0!?kl;!e!9(c}S^-dr7AT87LHYSnA%X*8#4@1JGDW?mv94+u zo?#RM)`W_TBiq#@2vMF%Jo~={PY;2j^{M<4eAyR?6od4hv*MX(=P(kM-ne7=EnyzE z9vsU_U2eVlN82cOKin3I|Hj3vKAP@|2 z!OW@$k#@?ip_$YA4hk&%oV!2P9##y)W_Td~v_Qd-@AFn^TN^bu_&6?TaRSBv&IL zM|NgzUY1@AS>3^##Qb4}sbRF%q6NFz2?W#~^yLLPzp#-)M&4xN7y~YW(CH+2Jk!PJ zg`XoN5%CR0ja^ar)*;sq63w5tmN8jt+9I!{!OCz~@HuYo<5OJKFKQOhdko&AmNJH) z{G?gvd!Ut-7WljZ`qLiz+@G9L9{dgM;BtE@Zcq#-{0q){jOUoo+N+hI9yR+L4clOI zVZ3Y-v0PP_xRcg4Uh6CNvz|!K-bj|b-k8S%@ZKCFPHQet_B7Y`wr@|*$Jbv9Ebm#+ zFp)!u*>7fE?;oGF&EFB8{6q(ronUx;$bY-=3++ukYv3-Z`jL6RYddVS4IrAY+(KN?r{ zsa!eX0kHHuj28$l1bqTt$5qPuV)u!iX-bRubDK$N2&9Pr0_>2}Aw;d|@LfO%+EEW| z)2PZe_X0-x!G!h+mDsoOM-}$WD~d zHw2#*xgno}jP(hb{rlIS{0K7W?_&T}gv4x}RT{bicbzUBSke0C{z0ooCGrK-gncB_ zXRZSYlJ=3nhl@)g?m0^6UJ!U-`{uqlQJ^EZVw&u4)>KmEgxvyeepB5+Yb{!SNVnjT zeOG5YU|Ps>kDJ{@ayb(@3;<9sg*VuX8|hG0`}qPz@js)Jj}>sY2E9ofCF<7W1Aru{ zW0A-Z{ic-pGf7v|e=?J=gEf7-?7vT9qB@;%AAyhvVMJNzIUtcZhuaECz}KKqIe>_N zjwn|UEaE8nZ#?<3u;x)W?Fcn4)}9?n${rPua91?D&s-4JUTB0G>$~HA2UP#L{WH5@ zTyM++6L0K6kZJYWRxtZ&7M1dn4W?@8UrlSolpAgX3uR7vR`BcH0`cwI^Tjk# zI^t-%V0PS#xLG1^E>3M}QAMs*No61s`jXF0ZJ@CVeo#u7^xMF>QG|h-$ckpd*4hgR zb19-vB=%cyz45ftJZ{qfIg2C_6A?A05qWKlzpfJ;=PDS7$tnEE>Ye<6J|8W-o!Hk7 z+12uMU$O;oPOg;%);ViD`PKAVPv3kVG(RVv@}j)}XK=l+i?D-Ab0_}9=v%E7LBjmR{qAv5 zE>ZMtE0AY1vCVFepn~Asss?H+!4!a0@)D~!JoW(0QW$&8D+7*>w7?TE@e) zdy)^7W#iiWFCb=8M$`QBU|FQszAUET26GGE63pB2BxtG;=|}&*m6L6uo#hfI4lCAP z1EBMQ&;zag0{$cbA%UJDq--}Zg40)1@UdXqPS8Q0zK*JHQOkkm_cL}&WpY6mK;W<& z_?MrWX*$PYD{iQ$x((C>ETsH)fnZ4}{D+~!$bpd3B6K$?$U7{xl4ZcFLTXM#6@mIn zWq`+JGd!PY-AK8NVIT@2QP zSAo!^pAg2!pUbMJm&H^LPNbJOsYn&$popdp!52_fe#~fz{K0 z*=UEp2@ES1n68fiCBQ4;1zIeuN0|t%RU8X}mb(J@5p?{8!0@cz!=SWKjouKl7ST0k8+GTe#VZwnNl6!wbgytZ_9} z%M?)Tz#nMgMWa9-5N751$VCzaT$uN99OZ-KRw=0R(qI_&7vDxtzNHuuey+dxJs4>R zWll^QocR@ux`3vO^5tpHDMQ1xaLy)jq*3|5^SspcSz6GsfsQs|kYb z%E2-)0pa&R9DOr=in%V)T0pTEa4CN|v+7Uk8L@*62zJ*#Xyf94E#RJc)bCw?K=*d8 zMSyomLwc2`a`^}hb3GDwDYLdbS1on7w)^bzExLp0Z2T^0j1ff!hgyJ`Uz%nJP_2N8 zQPs+YaB^C_{>pN;9Hypx)8V!2Pp~RCE6hAZF(JOxF8c1N9`c?M3}AW&Bz`9WhG=2M02d}(X%pELv}B!EUbga^IT3i69M8&gO{6OFKG1ggnq8;ypkQ{;j(Z4cX}(9l{Hvav2hU5lDW>wVBU^ ztUiucLlaAe&xM-}r7!{ypH1(vE_2)H+~FdTJQLr?U2Ds*aSdPREiEPGzy!Vv%tuxK zDqM@WNku!6>Se+VSpt9_N*lOkILH12y z74Dx4=Ip}{O03n4XrL4{s5D%Rr4Mrz8BA_Xm`?*N1OUt5K)HOr8R(J;$BMrgk1LIi z7N+4`omxFskDw7sWhC5CJSlOYO;y751qg$_3Q$|J=a@Rjzctcfl_^25C_#WVQW2u* zt|zSVIP;7y&N<*X$scj`MHPlw;dx7&8!16SN)xuSHIK;;hb9u}yQJAceu>3kV$sGa zigAK+f<&bc-iw8quJaQCn{LYV8bk8oIWRdb#%F!|q85%u2;4o#lDUH)fG)kn=wRJ( zS@mDXJQ9}(91;CgV=)2THq4fyfFIZ(JayuAfNBc{4kdC9jGtmE)8d2iLgdD&O=4O) zpyJZEx+!e{oWV%jqxC?vmdYhtqp*~z4s?90I+2aQ<4 zA_qzjhn(4s*IIZ?tT}-H7zy`(;g^sM<@-)DsRVgRFs?2A&I&toB7p2iLch=oE1kfM zz9D>Tg#R2xo=nKDUfZ7!KdmBHJcrjH?D2SRWuH{c`m7-57ZLu1su+vXEh$e5WmOL3 z#etITenYxMUZZn2Qfo=PMVg7GlI(n-8#LO;djaH6GYnhZt^mmCKP!!u76z(GOWPrh zEm&xQfAdy4nODin(G!xZ1Ac~P6-^kofQ1cAi0ptp^JbBQ z4`fMPP+v&8O`(<=lcG4HrcO`p*J`s+)v>Peey0Bm028C1l?CfE$Za1xu6aBp0+?P^ z7BH+|-SfUh-U|Ob>$c{$kh)3!3utSXSvE4U0G|8^$re6_Vsv{OPV`3f%iX%=Y?Tlt zuq{E*oTS7=<9rx;gwNJmfLxO#NrZfkqG(Wrs42kRR%}5D_qz?0eZvLTH=Z(L>;t-> z)G!+eWYF%2*y7+nMZ(Z0=IstSkXI{Y4Ikk}`P37J3(g_+EGD@`dD!lq-4T8+qe6l4 zeq!;zTeRnUQsnsyV1lj&Yv{?njhIQ6Sl8lm@$h~ik)){9qz{6_lT*pqMdc`@Rj2cm zGnuIthg77Iycyu11!a@7i=VIT2saBg$uJ64&<)#I&pSqvyx%iGfn}joH446`@zUb| z0x+R&lu`|q3ar8;aO0h-C$v}q!z3`ZM1)O#0NcPwh1ZVow~SJ2@qkf`r4EmJs#>x* z36Q(SUU_j|6pK752uTXtKSxOWGCf&}NU?N<5hgix4Lx|zjkHi{K&B9>s0^p<28CsS zkj!|1L$<`Ieu=b{(*n_OGxk0$t3K`ch1y*yuBXJ=l}wdhG(-nk{1V$4pE}0?8kYs; z8=zzZh6SEF95;Ss0iGOUU9cCFTg~#ZI$*e8%UPldPpehcmN-hi0r^lg=+o*Xkthg#0X76JYh^B;c>mAh6(6wO|u|~te=uJ@Y>By|#@PikLki|S9;Bs>`ouF&seU5U| zg(i3DEYvkbfIpu#B~jeW|{f}g;o*Al`#g4$44`f`V7z}92# zHSygKdVelU-Xk11p)c|cp~Wu4fzv1@xKZ_-7S*`QrhCpO?1Q38ik@j{KC(*%tuDx%AL_6 z!|F0HXhpK7zt~zY7=;X8d&pWVN#ek;m1#TXcBoGaS*MYQdWZ2vJxG1? z*F&uQ?g43;nu`G&b>Zux>Yl_O@5vZh)#>{R!`Uduc(H^%`J~2MHeR@5GG--|{n2NQ z^%nlL(WxI$Sf5CN!K;~j%iqxm?iS4y0C zfEU9JFtVeF0jM((iB1n5i66=$8lAqYum$2t9Eg;0OZ9PrVvUsrQC&-%7`=v7O1JbV zOVl14KPcPvm?x!ns&tMcwS;hAwiuE>Qpf2c?Fs5& z%@0U@6ev+DXnc+uQ6W7=+8)m}GX5e!&FcXh-p~YFr;tAqQHjafrbEr=ZBmL1E+W4- z7s|4un^iSfWoQpZVqSE!k!UBoh^(m-z00T&b%LV%t?m)D?Hs*UI7DD+C@&{K1_(3a zgBl^-Fn<^%NvYY9ZKpY|I=~0RA?G;}N;~P_a$R9kUrqs=CQR z(QkR~cjNLNQ!krwq5BSk7VAIK1>xVE>hVJ-(-mdY$WDe5VyRAo)upCm7tTXnDwDY4 zc{&9*xB;Ow^ZM9)ol+lVNpj;{n6a^k#uSL1x!W9`VVS3JZM3b96+0j1oNq{|%St95 z>|C3FP)S2fSp2!hBurzXM23K{@(w0g!p(xWd3rE`C}n+1;nn^@GkJl50xRNO5@3fu ziv*JyvD7wa#oSVF%Kc*KB3-~@>0x3&7d{j0>b)YSLO3Hn2T=FLMPVvMp+cAp79|gv zKzeIPrymovqGKiC1E)B6HqV_E(+{D0Vymgjs#Sp83DVxxemrCOG9c|FovnBSez?-f zwY|}36&9J+3kPX`TYB&m_&*6$_sWJe^T+I*u!X$O8O1fJ|X_e9+z1Dg8QxcUp#5kj%x%qmq($*bdL);Yu&8-^>G_+LR1}OBu3P_)U+CTktJPUy zNLt7}`?p%s`kyh2UwC-ZSaN@2=jQ$yV=-03&jDusqZo`{Yqs-!?ZSOv*ty zIhx0>P;7is)Y-jLbczZO4&d{9Pm%E?gU-gEc$+aHnqi-nkrE)#eUb*u(x z8;bA2ICMxw7)pkn2?mA|O7zAR2uUtEnDn1X#d*dH$^Zd-LC4%uc7sYA9i~yD#ckOx zAth6MYHEb~1MX@{2F-(*fF)xAd?hyBvhP=om(8|nn7?T`!n4a)pg7?JO~{~w*!}{( zJ(?LI5#s6wt?xvrp~6-I$_mt&T(Z19S}_0c&bP69P|*Y;k=rEXmRD(YYwDAE)-V(? z>REcOyM_o2QGUwh{wdeU`t17%pN{$m)ztx#(=D3m0LqN@K0G$6+NK6eUTu(4ld?gY z6byK~ib@1Zw{a&sMpIq{OcYBacZ%k7Lb0jvTbHI@=A0pvDkh%i2t*|Z^zQSihuCja zGx*QG4+kjv?A9+aWB|edocOqx|z+Xy|re8A#qQcsDPOamG8A(JS55k82fp zmfI4_0OApG0m@WS5OOF{DdeC7;Pg=sm&W4L&(*;xLc4IY>?3aqsUbeulrMbG7G5)m zP!ylQ;6#lnO|q29jP``_s}oI*W6L*~MICe5MY%q+_@WD$o;Ie#juKA&#wA6=@CdPS z0OyT94^pisoVF4T>Sg+YiWmg_C)w>w$Hm#r71s!}Gt5;UeLugxa4MpciF53BRuBv! zmcmx$-i4YQbfnqu;p0?|!)*PIsi00qJ)+{0MmheoXhRX#V8h?~G zG1x^;yK+Ee*_%}~9TPy{p@gGpz`6vQVRElaoqG1SlIZdMx~(NeLCXO}o~cLHUmfV5 zY;FhsF92geoWFC43=fM0BiI9wm~t}e-LM+jT3d-g9}%y>3cndu)g8``LA6MCG75B3 zrja{4KrKpywE?3}4`@~Ij06fy5kYWKDq<(mJJEihOjx3AHnB_c^V?Gw`(zAmM{qG7OhdzMhCPkr@3hn}^-~(j@chs-I z8(jD819BLRr~|ai0KIoKO#tlxwJnfwQ~iKs{gytEhonLE2vn3#Pp!s+5LC*%bIu=v z9P<$@6j+MWSY8pC0yRD3k`Obf=`Sr!Vfc0&1FAsJhbtM$`i}bajPbiD`6#IqdrfZ< zvXCzhJNUqTV#IKoC8yv6pkT3yh|o*J2gVHoLG%e&0Mbw;G3^W%)?SN<>?aOrQt5IK zfVL~Jc?@8&e#Xb}ZvM-+C6`N%lL9kk z2M9zUZlZKC)WDkt7dB4A5NRN(QXLXb#KbnH(Qh9va9enZP<_>Y{{TdQzN92@4R*?$ zxQI1XUh?J2fau!7AVEVjmFU|I{{S(fO|3%~nz{rM zP^|&9Ea??@iku1d_H6*}QDcvp7E%cudtAZ4N&1l65I^+~N+?HWrnidOKIs7PnVXC1 z7{1tR%7=g;9RPKNWZ@!=UJ!l^i%Ddz1E!#&2nk{;ncgT-1?)?ss$}#8?(%3`Yq;_l zrzn|ZBg(0Kuhy>xX9!;`b?uAolNy@SW9|M-tk`6$&14hKtzV zTK92$HaQbUDDWG(9p%DB-oQdm{Uj`-L<3-w1w{aCBo<@X0x8fHP*afGfFr8br5Crh zRJ4D~Ydi%(-xXs=tpb>QvX zbmsXb+Wdg&(ETCw70y%(c3(Nf5^N|?@mx8+4@z z{{Y9vO_B%)gH+D^<9iTsMm*ow^;ygHz98X7gX4auk|pr@Kc zv2lZKH>#ReCW1W-`m=H}N zR%R~}MxhZS(+FCw4)nV8IlZdACFpcY1a%$xR@elEurv#x(0;k;HFAH_42U5}IU}bY zb7q6!_*@b97`{b9?l3E(37^c%Lm-24bEju9G6jSZ%wky$d|QbO=CWS^2a4lnKdD#*T%i4f zak(3=04x;HiY=yxmPm)py@(J16A>G=1GCMkqZl-Bw>Ig?xrV`F(FK8P#nQv~P<``g z`E{yFZldX&#S5IzxYp1LL*ndRVbw(1ACwUo?ZQ;wahF&Fv`b;2h$NQxVw z3%O&Ady74S&@ELh)^XOdp>~B$k!iCma8r$9yoiqoiAU+tWTydIL$iSnK*FZ%T!_^w zC{YZ>Io&dcIJyh04V>@YQ$`BQArP}7bdQ~oAz&vXMmD&7SsR&s%JoH_R(5F2-x8u zc$MDgC@6B(4bP);;l@(8G*(!Xj?B^Wj_nbNEFoh!abG!qP0N=n=QQ7?P>lpgx=dF< z065G5-h;K}e_Z)k0`lkU82s&NsoTl>iR6`EdXpR4Q9HvUI#) zi7OPel0$<<0C^)`YK)}VHkBDeBaPu#PJnxZZnokUMiJbfEC<;7WbU~ITw)OvC_yWS z)O)r>4*>)YppX=>7x*p^2*HlR_Go)tzjcV%4n#z9%L;$kgH|h-cno7;CG1{Px%pAtw zN&%<9mquK25CDIl@;p}`Tp4ekpL}rN9jrVd9Fkikl*R~v`q>GYr*)lLn)$301-$YTzK(E#3W_K6!wh&0C`^Db$DN3E>*P@ZCnPy?)@lvD-^fT(SGI47|{hVVA)hyYSSHjdZaL)#0$D-e-8D%r-qn7)?| zT2W5Hv>A7c8i#}_EO#cY0D+aS1A>CZVl5g(wMX`C0Nqx_id&@gPMDUeyT>6LDhO~t zRIki24J*0@fG>fC0wFREdCPGApdVI7x>>$7A0E zwidvF3Am&~dR!neGY3|{v=0Jt#ytN3)-SE}zL(Pf0P)xV*$QQDWOHJaf+3b9T?(&MwPd*o8f??1C(c0$xxe zi-4CXpnwF7R1j805fD&guGm~O=4R72P0}{z*4)#qNDLZVX_Mw{lUQw=rfzzO7MYLW77!k@n4Py^nqC z`g;*VFCv8P?b`dmTj%_(SqL>Z zkOnrlUD8`;s^=j71BlDrZJVR|=P&#%#G#LA7xwn_58Q_G;t1{5ll@{hailt3Zcm!mm!9F5GqceDzyEZHkq2Cw z?m^_?LdcC!9Pku>hlJyu@pni*37Pkx@QCUVdI&v^JJI9lDEc`*1GSz&htM$kC32xk z^aFG``VQKKc(e*qu19t7(LwrmuqQr@3eY`3OZT8-Q1&8pB|40p*d2ctU4^b?e+RX$ zMP`(R%F%MvgKomh;#<*b^agh|nvIsBZq$nh<4y6K_|Q6>zn zN738ZjW1^_pq2aLvG}u4%7!);SE!5V zE{(s09B2kw38Q@wYQBa4#as!WtJvqbh4BT*0(kir!8ZB@`ZG?$1-KSBGE7mCN@aaIEfbZL(_1AG2A7o6-arQp$QSLK7ef(tH0xJ?i-$y@0Kf`92sf_#aH}T8( zuS^BAhWS487xp{c!`yF$HkkD{&}MWKdKCQ&+wmN{0$+?b;LGtY{4IP3K88==cbIaf zf!V}-z;0l-us`7zz^9(;=dRXWr@MiFXS`|r+40|u|0`Y?zYeVcde{l0|1P=fNBA=a!G~wOOeT{B zp8(UxY-hg1{D3(QpA*dAnNL_3o5hCNnQSTB%=W;jcCmZm^CbIcE{!|R#R1QSy4!U7 zbPwqs)%{#|hBpb{)Fb_ipWio@H}?8C8s9yB+xXDJRdIu%&fs1@fLguVDcJ#C;kx~`;YMvz|tS^2QX$c`|E zFtzac1`}nrFngI>nPKK-=2KQ+jjWYTW%JlYYzrG@2iP6#ZETEvk$sK*3ww_J96oVQ zx> zI-fyLqNkGgJU+?pWUJUG(alT|=V5-${2J(a4eDU48K6|=A-tQp0uM9Ux=Z+Z%sgC! z&Tt{X^>fTV<{UGRt;S1nJ=)03P+H?1+#?W_a?haC+!2`Duc75jcoV*o`G7Z}A&i(3 z=<^rsbS})kfL>+azyfy<`XeV|7e38A$Swye_z5>(*Mu_JAD|zzTksX=Nu~-R@iYC6 zK*u%s5#S3AxDbEL#u3ZZ02R$<|B9|go0$Jbr(qxOM&H97+|-$c;zktYP6BtkoGs)sA-oE>%4*ERzr## zC}$ba#Y*51cf#j(;1e8BP$%s1i-3#$8V&Oe%m`YqvtZyl2yrir*P&JM2hbhy^{6|3 zE1C-YU|0NdXz?NRCb|VZgs&aH4E3T6*g3D`Wx9pTaoxiBRAvwJ3RBPAHhFyk+d=F` z@4@HC5Sg!g8tvi!fa+0M{Kok2fx2^n!`^|`q6^U}nC1J>!(w(66^++0`{N7QUYPG2 zXhrf)2F_VOZlB{w>V+G8AR%;sb1Syc6(n3t%Av*xCyG=X!1n zcQyA3LXm|{7d5VID36rQzo2y9+>$x7XBHO~&X`^>ZEAivZ%S@XD3~3{%9Q;X={|3o z$L(^aI#TR5$!am1jG{p=@H&oVFv_nAENqoyq1G4|3M^hcmBa&WkkFQt&>E8=Y2oBD zF}al%lP8yqK*@DqC>c>oMiM2lB$uMnsrhnMK#m=&49FvR)ruy7Z>kJ5%dyiGuBPx_ z3Y!7W%!CSZm3u>_9K)@0Rczt54ST9uE1|jlMzJDL5f!KAqy3^0KqEjgSD<%4cFo5W zU|dym_cKUuhC#*B0+m%UPoR>FAjSr(+B#y(S2R^sdNVVdr{>3SMSEav3C}Hs}UJF zh{^3TjHD?5bDBfE=p3}CeGU|Zzh(@zVjZv|oiRg2>mF$?NhkGVx}X%0_k4ta0s^Q1 zJ~^dLP2q#mM~HxgP7WrQHGkU(6A1K5G6aA=v>b5T z);zZW(4Uz}7Wjsd2wDq~*x-sLB`%}2-XRnz2sg)=R+2NS<)p48IfGhGqIzopD0!G_ z%c(JaDDiKVoGDcs=Ekt|-(*LX{H67Qr7Ko7$yIw=RopIZm=sg;=Opq}D3(&u#CjPO zV!SNP1)^M?C`=+vrWhB5f1VO`$B3W@s-!7cUKo>F7b||Vn3?$>RvL+)A+=~QQB56Y zY;JgReBPw^q~V$NurOednoAp2?b#zv$^%kUI$WX#K=G)dDO0Y9p_Q;RgYZ8RADu&7 zvo{t2lvR)dKz~Y-8l64%OG)=FiVbngtC~1Ht%n?mc~jNw3RP2iHu{m^EtF|Z>O5(6_9OL4$Qwq2sP%e3D5pf>{S(YlMZpSL#{eGFer zeELs^zke1ADE)(AQ##$Vde5prCh*O4(y=-Yh+2Hjv;`Q+?PMfGl^{3-<3)$S8WPZg zVFsV#g%ReCND9(%r&uHk+$oGadR}*mVUK`PXaEyo8ghrFbERXYHPYGA>akK(2C(!w zcr&JF+A?iH@Gz|5=Q2C`c|?akLozo?tn=xh3mpcVQ$U{|;2D!?1V@G&1r6W@qfto# zpxlfjs1f1#Ctv{@DU382it0>er6>T2qMw1`Z&r({aKzH6V=_R`Kvdr_j4=HNWDav9 z7(d0!m?>Z}3-FT|%P_u?_&X7!Brz+I-f9JZB>v&B$wYy_44cgq_#9Gr0*pfn0iZ?w z!8-^>!t}4DR5}Z8>{QEJQmF*UDWizN;lv-HXJ%$a1h{x_I4yWL3eTvhBQ=CQ~i8dc=L`BYWDgH57 z*2?6a@edO?bH>jCB20h?U!ybVc14P26{khW6kWO0w_7aWkHr5TF_HV`*p7nBKIz(_(4yG%n4g zH!BNevZ#w|GSTHe&}a%8NF@nIbjE;@K{lK)oHW1^#XlY{Qg76%;iNDe@@J^w!)37QfCD>*!nK8X$Mg79ZzpOY3z#{R4`hWxIiZ=hBAdhIbQTrPnnhr? z?DF4#5I6v$H z38mw=BbQ;F$(pU3sjJfI%KR}uRZE=1h zZKJ-+yusS->`oi?zhZjT^{VGDDSvnU-SgMvl!iz$i}Ua3WZe?iexpqvribYWQ-VFje|zcA0cF7G?D#b zbW<2sgzgdm&J2?^0^sa0St0;V((PiT1VvWLIDl=8N)t9cC53~HwjyL#$pdjTGm-)j z-Fh6|Wksw>17*w{oCp*c!h zr^{?5l(v9upa$BK82}=gRaBV4q)I4|mBRw@0PV~y4h6D!JoUlhzWr;T*b*84@Fzz$ zF~uvtwe7JVZQb^m?(o=0x76P9eE;|d<1haZ-*$B64aZ(M@!T;&MZ1BamI4(4-^L#v zU_=#vtOoEJAOKMAQCZ~YN!)Y-)+NE51`jtfMh)j0z-xd2K%&vH1l^z{SeFEI8Vrqc z>gux^z-xd2K+;If31&V4>yltjgCnyW4YSCq)*AL2?l!~>qlPyOXAA-|_zk^=LBl>Z z>7*fU5dFYwu)r~_foGqNkE$)?HL_P?#OruY%^1i+^e7a=c>QYt5sA#e^tSdjM~B`i*p6C9y1kJjxmdtNXQi1X0jZ2y&S*TzsJzM%^krSq(h-w0* zz!_{MSQR=>-ewT>q9B5}3E6my7h6TU7ZZUK&f5um0|99i*@{wuZ#bPUXR0k=D-IEc zk!ss@@7C8^?^!O1!+Dz)_dm#mzV}2`Z*}1nWBtr^-J8pAeR1pv@Q4NDE7e?n%!#h8+2U65}k#g~o-BMxn{L!T728QL1HHAU|h*V1CZB zoW1#X=L@qkXH6-~UuayISv930vtdf7(4N^or8R#r|J9s#GT#q;kYjT>`P30+|8TA^ zMZhD>BN0gkb*~lmqCqqYI1@lox*{U!d_JpKmE|*u&eWn{kqBfqL0Tff8pjYd@{43Q zib1#ggbPcqh^y5#=;HDtMp(IgDv4Zns>Tq)vJsi&;;BO8qVG{2HD474nL>8vWTvt;elzSmRdCZ!NRdT3M?` zdR9phQqvl(GNCVP8lg3778#Y*M@D2dk^V_K_?~e7KxQ#8g>X$m)U<4=CUkT5^n`#> zl1pjAsdGS2r%#og9&0&8LZV>;#k6d3xtvtA%$}74x(YM1*be05nhEL(Pjr_Q$AsKj z_k^*qV&ID1ZVTQP`{SAJ-`sTM(g&h{y!)r`-SNN`mp}CQrI$R^l(r&R*s*GM>;_!= z+U*$Mc>Cbz8$UjN$)jxEZ$^*4_{?+95Lt8=*bu8g7Fj`~nHsUneq5pVrDuRiX_GRn zNbiDW9#2B^#FD$>=Tt@A-{=a-2CV282AOJrB3V%b)iMlZg-ulBOY^5o+OkNZx-62q zES5$|rn)IhUD-U)UvufVj$J#xAD4XVM>DFbzt>gs`1p&u z!>Q@Z){Y;4_QCP-huaDtpEaZE-3Q+KS6&9J$AzF_`e5JZqS?&rk$i*MkmoU{-IP0>-%oqkoSF+J5Y^#wh%MwH&;y=Fau0f* z&VAN%JomS$ujT41oj8N;H-bGoW!E~oGBZKli_{Xx@AA9D`FX`9TuJ^CZgGC2zB#;3 z-x=O!+GYBc=@auOVcYCt3+AMP>|$48ro+8vO3xH#im$*@X1T?(&l0!j_F0~=d|+WM zPs669)bdoLg=(D^MYdAlY=p`Y3*Af>p0I99NTmpin^MG+jTVcKbpcB{;LfL112p2! z7sUlD-QRWie88BrxuB{Xu@DTZDQ!|40+KzKq%3`$q~mC6hp`dyl%|52*&y%ept2LD zR5q0_5I;3cSU@&WiU~de_!F@*0ipxW)@;h`5$58EB`1PHQb-O>4?Pjmm4NISCJZe! z5`S3%o(B0#yFbtvnnCg-=8Qn`^pepM=I#<)LO9`5l-ViDb;Qu<3c9ljH1<`Xv8V!N z3q@>=1=&aW<2>W%%Xo%&XzHUw)6Ud(rZw^wf_|Rr(!85YjyI8+@l==QEo2RNiOhtb zF=s-((G=ser&WWDZl(mEqnj-J=9@%sJ{1Oj2D}aQpMs>yTOdwUBG8RoRHr8Ccnbt* zOOSH4nZ>hU-;mGD;vB--gq-<|Dm7CbPFEnr@`8m)bts&1CR^HZXyX${7WFTlx#`vQ zxTtFPRXfsS?(P%U?|x*tWN>92@wwJM+q1fGbLWP8L+MwqT=?j(mK&Bv+Af@S$(hfty7xYzzs#c*_7!>vj91>*VZXqU&3MT|!Ao7tAv7i`m6!?&moj|l+vhWlj zYcD7o6;FUO5hI~wfhUVE5EepcK{(88L~cB5|GH#t7Z&vFDe1JzTTh)OVvKN9TL~<3 zQIYg3BFNODK^HZ*XW9ZFzh;9b6tFpn&CN(@%SzXFgY=9J z*6P5V3yNu2RIG$krz>IZ6eSDrPIkXsdZf7is_`*@FtJ7^9a(`IYCHOK-QiCc6537yp+Bhm9nkiyNQT3Jt)2qUbWg<7>-oOv2j+*( z`ZRN{Ip!Jla2_&3f11BIU2kShR-cGdnXn^;V|gU*b6`h2MIqCt8dD;iOCwpAM#L^v zsvCicafoGZ#YCkaJuqWVF;&aMK7a9Eggp^5X-~vV)OrWSL@q@`7FG1~RZM&cdLzMv zLsj+_6Agg3=xGH}4W6QM;6AtK2tJH5(K#$4(8`i{S-6FeE$I2B^nmGf_;d@g+)9aF zaJs~%X!Z`t#v24)5ByXz*uBWcTfLZ^BkkOY!&_QVUlF0`nZ+RLK{peqN}o!oduZRj zl(eh2EnDrKQ&?Ad{5X5(jaxPqFTBY9Lvdm2+8aM#N3^X#rj6RS-+m|)a#3-x%RovneHlSseP%l%Dq~*+E6F8*jt=+ z?#;T*h7M`7eY3N}y&b0-c%AuTwn5h*UTo@Oqq?ZrWfEOJPOyOv>zJgwJCaV190}cB zYIJ0KsYd6eCZa$za;m2bRI3vtHB~t{q5x$b1fVR104i4*jaagS#nT0h1PRy{D!wu`iOk%_i@uo2BjE1s=xuEbVS4kEXNTh4`BCKAKiQPFAGWPGtHiH?ldTb=8gs@2sxqJ0kpCzZ@6ei22ZBUzrT$_dj8#T7oFE;G*cUxJ`K&}e!j)Ri_ML*AM+|D%cJwH>1WCWz zWx3*6q9XJW-5N~i#0C?>;>hwqLd`^P9}AG5^PI?)057od`Yl32~JCbNqKF{_>y365}cLsc)A86waLWO=UZqgCM!atIh}qoe z4({hCSC+P>1|FoUwbP+H4+=@T|kQ1zX3Ln_G?R)+!pTFyo1A*1^d%rW>)Uj;m zTrTw8nl)>i4nJ{lEQk4F*P6NCy?^X`%+Mv5EWh(xW3P~1x;p+g_czc!rn8Q68_G$d z$WRg-)L>X}NhJY~2BZN{?pLY!ox~0{CBeod*p~!*H5imZx4PJj24Dq<(O_p_zsC$R;QuC$OE2OR2 z{lV+lJ;v+Jd#pD}*JfWGyw!Z0^|sWE{XDr(k4()B*}b7OLud*PAv7h;&K1rGp(sc~ z^VA*Q>%ELO=rm8w$O+=0&Z$cr)95m$8Zt7REERHLAgC6_iX%Y_wd4v;D<5xUYB1Yk zHtI5c=^0+Vz;i6a<6w3cr1828@6@yi*%r5?;k46EG!@hHSdt=P8864JxEJrmJRZTZ zh-qquoRYF&CFxj4P9w}DMuq}2xX=I^%Y>FyF63bu3B>Nlxn*G`-4MCe&bb$bIjl=94IznESqwN#%XN`ORm zWDOB-E$V3>pbL!PumrmJDdL?an1U@y?Oyl%(bKfV|=?+^Te>iqe z$sGJj)8M7oefGou8vo}V_zzO|O&2ZbudG@haJ7YJ-xuxqSx4uKJ1sZdyz}DPqM}W? z^Pb$c^?3ilyD-`1@pstMAWhSlf+NTkKcn3Mi5f>XXn<7%Bn==}gNMk{>}Mzu7F({e zVk=p!<){}JCujE=1-FkgVoR!^rxq$bmk_8fr>d3o4B^;I&ruSTo^2^4ZpL(PWRbyy z{l1En3Ritfy{k2))%AVm`|O?O`=$HIjkQPI$aJzBbz4on=0WoVrY8*t#V1WBr|CM= zUm4btwZ__Gy~@g3={a|3I$dE+uHzV|Nb1}WrOruwt zOMI!CWJ=Y@IaO7RGaFO0j|`rf_%@jv;W@LaWO_apaTv+-tpt?Q}dI30_RVP@wO_josTJ@dPlfBsEi zQ%k{K$^be{Md|qIh|7{_?bT`Jz7_V>o;qKfeREoy?-Kr!)N{-^w}hP7YIeDnJ6oN-PS)wO z?v?JA7)j#1K2bo2nMVj7w3}%#W(aB}SkLdK0F96%@-ts?MEKV574rvDYRJ)AicjyOb?N zvh#`wCDekUr4fos0+Dc|K(93fdI~7`=+09J#z#rTNsTy9M)Bn9^OmrplRz49t#g!f zRjZZ|Iea)p$)crnY)dKC=k4?sRM9oI^l4NfAux$-4k431zrdLxdg8}^<8c1_hu$6k z06YHldu+jnb)p z06Xtq*s$dLFh=y#NGgaOyBzv*Yz+NbevY8Rn%$z|xO)_X$ zG>G)9C}L?e{Kq#DpAH)gi4>~rozbo&O!F>I#$k)1)|G`dmLP>QMvqW4{r83CPWUJW2 zW{xJMx;(`$z0G8EusV#aKAqq&il#}|!=@x^H6^ZxbI1!HdW~zqqXz7x2LMibUu>W^ z#Rhs)Y)IS`tIvGWNICk zj5|3ekiu$)R_W)}45rMDBy> zLy^Rdu!Xk>K?`s4Vzb_=DccCP4WIFuiK}4L&w#EcSgthb-lVlU0lb(iir%X zEFx)%E@o=c%;J3rkAehd&U^mwscLH_U;Ha)fqK=%(%$sNCTvm<0OhkOx^j~=fSe>almrKp;Orzg zkOXHX!I??0oY;6QeogABxKq0bwXrw+Vw4q|JxX1#$hIsah59#S=gmMzs9izKWuEJ4^;qg@w< z!&``+kiiTT(Yxf(T-eyc=2WH-F2($W(R!f zDPnd}`Q@uu?YrnPK=7{dPA(I;jvZy-MdSPl|`hxUc zd9SRW>zeDm&~>4=S%0xN7!g~= zL6MWGt{~Hk1CeYfBcUeIt;Q9#NhBID;ohS5+*Bl|gH}Rv;s8!5Vv5dl8LFPfc^d6O zgwFqZRC_ckB|RFICOsNG_r*t}^uz<(l}DrgMYG*_(yP(LqtWo$Q(t~BN*|2cN|K+8 zrf3IfV5KvJI&y4m(&7KE`{&-eVfTrRTi>{B)h*L(4{W>S(FX_m_m6k#ezIr9iW}p% z-#7l*4a??^ea7B@?AaH7|HAWsAooTKK?1!2nt%=Lpf@9ziy*gy=3;ZDSvS)$({~Zm zAl5nRee0PHUDVL-X!VWyU()?P~c>J-Z zO1O(KdRilwVUTk+>m*IndR`+syU`kyq!TtQ*&?=9+n|l}Qvy=n64~erF@Pn5v*%uY@mZox@(Agk;zG!-`}+}4>=G+Q?$&;qWB|}}SI~~t$61<& zs7t*0WfH0)J4sc1Pdl`gc@rH``b;Im)X~Y7e7NY6mZ8A_jkEvE)n7A+KG|M4s|z7jwMH zkivTn9=nc19B(ujEqc3zQdo!J(|e8SmTVLh^7LU#F`6mN)z7n3vWxhLP_18TtgtS! zU1-19T4&!Rbm-UHckq`A1NuY!Ve3KrNBn1oT%#=)<(hLWxz-$efnyGuZQriHPJcW5 zJ=25uA?6|D1Ewd@LH@Aim)y(zD~5NtcdT#Q&+?xdd`6y(*hGDaS00}!N)EkqS5MBp zqQ%PDkxeh?gMu|^AtJ{jux4xunn&US*zEQ&Sob=eV1acGnk^2q*`f!Y85Z>psE%|Dj1@UB z`Q9BC?3~_eGg-`Zcy_bNL{3Z?2J?2S)nY-Sa#5^Zcy#uKg}}+@LOOx6J1R4 z$;YnTS(Vu7T`>5&s;7l_UGeO$Y3?rvK$W{J(zAj^DkYA<#4U~a>tjqsEV6u6)38}K z$;^@XNiYje!u~%ojHX*xrLm$FtCBNM?iXYw z(+-&#$(hjlK~S8bL;Xnn#E>wZbTfqJFo%`y6FnxXyOOKh;wKM?GAARF-wdW`#cJB< zO9$;GC?6c~fc+^YFzMzAyOmxPY-!P+86Jx*(umslPA`^-CzuR&r`c`KG3J?i2fxj{!*;3T($s6sdu%t_Z%nz~al81C@rd-a?XcrL@omRP<}v9LN8FcT zPjOo;3s$P^%9&#Hc{yvP^%^T{^&}>tJhHH>yv7@uZMB*t;1wcbJ&u%=pj~u8#A*U& z5HyNlLW?QnQLvFG4IrQ7V+wpneT;8}DSOfi7>PJWn1+b4%pS2bYwSnujC}+zIB3OL zsLCsnEQ+&;Y?^MWHL=T0aT5azu;4&}6)?n<4SVIwfiVCI$F_jknC3nW;AyvX_LN6D z1uAu#TRKf4 z=CHP*9P!r=&MpzNW|vq%mOhzUV#`V;n=0H)^fR=jB@CNs@}@!IlpN)~DSTi9Iq43< zz`{W*yUH;yzjU$77Sb8VH~;*#aF##(*WvN5^6crCHx`ete^|=R_HMGKbGc)8Y~6YJ zHfGajzkFgrbG`c7o*RRmWJYc*L^7hbO%7(MwA692bg_donlcFYb-BsGHPYKBy}Y+i zdc~5sRX9^V8#FV~?@;#;aCeooa?*??#CInA`y{9~@xG ziCoH;Zi@9uFgL*m5?3U=2Iy2v)7Qu=%01u6uQIS!^FMXxc-CMd7~+*vEJiV5>FKuy zutZ~{2Qe$z?IL66<&?}~SdB9W?22+U453{|6EYQT=^9AkIZns%vki+lU67wDHi_HW zt>UZfUwPpH9tZf45Y(6Oa|~tXT5~hk%r^L7(@xRoY8Wb#CJPD|G;~-!z1!|X2zEu&nU;b zc1m9Mq?cqKlljk?i`FGSlK~^DT2h~Jl56-a=g2ku+3@LvegOuRtAwx*E}4A@lD<@5 z%2HqDo#v$m>^EG)G6uKVR!qLQrHbN+Xvj}5G3e9NOJTKNA4)HQ;H4p%2KzH93jrPi z3Vea2e4q%z$I%^=u<00Q!s1jgMux0lF>-k6}cIYoLY!`RoUCedt^}=rb9>WjO?S^lOkD+_TpP;9N{o=3C zFT_{T@5R5Pzlxusvtm9>M|2~nn2SQ!+uJes}oqhsL`>sk~-= zPs285H~ofdIUZp)GMf>L@*|#Jrk7=^aW#xSfS5F0FL`Cd_1;8Ghf^)mTd1J=G<3WL zx1`L>Of6@o;EcTmR9wrl_?-lIf(IR(;O-LK-Gb}juE9M7cXxMp2=4B#3GVLp4duCQ|Vi$ zS*1uSsi{RU;cP0|Xpemu*ZHW3htD%nxta+pt6E#2HKsKiZ*OR#r>XneMfMftqg%K2 zh*#_y+HrD#DKlXU!j*0idG%J>kAN>K_zXrQ!SE3jP=3NNfy&#Kc;hv`Yq}lWNSevO zFqINRhLoyVv-nV~PgpfkEaF5+$psWVf$2>23do;up+9}?d%`_C$qaH#lqxl$ucYn< z+hj?K{A%8RL%KsHt(ILE#-{n{qmNvA@Y(P^fBLp)V(<@PqYA@nv-ii6775ej#5Bg} zOYf(m)?&xfJxhSm@}gn|!g*;J$_7+b>dyN`MfrEg&`Lp6$}Y#1y=mI|BzLU&35nI3 zq}1#vP*#*teuxZp;KsmsETT4)u)XB{d5iAk8^~PMEg~WI6na5cD2;QLP3NckHq*AJ z4IjQxFSzxyr4sx8b)en(9eGGT9mRvi3iFM*yWZtDI1{6D27iaqt6OPmDK{6+uhytK zIH)n&7ueBLj-anwTa@B?ZR4|4r{co-Bc!yOIChFY^O+%OTz&>Jnvb$1GEey4ijPGQ zF=XHCa#-bOVlf%ci}`WB#}j>3k`JR%k<-Jv;FO1mMOFN6lW*k8W}SRzrR&42rCzbF zYZB*FT>ptw5aY_j3lmbdzM_%xXe{-6pr{V%T5Eg$6qle!mv(6jmq zP~{YM%+c(I+gsZlX>UX65%q27%l|?^ZNXe12$EF!)!3m)3h(=HVR<<01xkw-(hY|A z;$u~`ZHs*rI#oLjERe{XK9hxJlZu4^XrfTAgXqjfh$}M}3tew(Q zZFcxBS@&Z{Q2x27K;363{i-`=>5l^+$dcZpXud4CPbGw{s4G}(>Gw0 z@$>9aIbPFRV1ga64Lv z#}SxKuMZg<$B52|ao-+8dT}f?4Xe8%ZdH}_8a-QU-`O&4x4qZBivWg z=NsuIbaT8H`0*4=_AIWzFrnq=j@#(wiN4uLmHhe|oR-I|Td^cM!fhD5S9eQxvSu_ehm;OqGR~ye@bYi;NQbkm{pSSbH&Jq~c1%q$3x~5#ml> z$p8rEZciWB!>Hx8vMxv^V7pAf=u^Wn-Iw7+gTZ-w?)6Oi&d9ArF}?JB9SJ?3d>v6e zo&f8dN}r91OK(^(#MT^2c=jvaiY{-#Q?C;Gjfq`Fy^bupTu^=89h6&AeVq{<68FKg z^i6OG(v@2Oq8Am)bZP{PGq`YZl3N*+&nKV<7l5SjmB?WDkt0CyUHxuaW~E>JJzRjI zDc7mug7|d*=OaSLZlZwJT&V@=Uk(ansginp0U@7LrH4f+Qbm7Z!^)DzVrfh3^5C_@ zPPcVAXp@n8cy~F_{^Gx)kCrD)4mZjq^2VNkL<^|IZj@$gd|wN8JrxW4p@r0=~ChM)yauE?a5SW#Y?vtYYA-*DzN z2uM*e5&iDumN_ajgJ{Fm(Hc3QuqP@L>dA@cLGdvq>|!5lDKkKuf=aO6astUT2hUPr zSR1+uAyUGwp$qE~)t>0vUhd`I!_awYPGjWchaVLIxY0`@3=A&e5?nk7QoyBQl>y6w zOVTRGi5sWFWl_a?fg;3Uj!#o{*Iz#v5H0NIUN?WX+MRrmS0@T)70dvi#+yl){b&jV zCa)oV2KQ=59f5jPT=v*QUZ2?;+Bsbyd*%6$r`W*iE*NUNPs z@6jwEnKj8}I+hJJ!nopw8kM4yM*#iqM5^u z<)R-XEgepHC_ywdKa}($Y@cG192tBzCA`%&!$avr6aH9Zz->vMqJ0ialW9uM{PY z^UJ8X#G~>C86RFHAO@?g7))eyg=o~Ft3tkn6z6=F1caG5IYv%HS4oJK`N!f?$XD#_ zPN28^7|QLHvm%XimcVh`nE&!K>7qG6EZ-JI19saylSZKdmSvK+IJ3@Gy*j*J3!!Kj zP^vH-g^eCrjq)2@Tc{~(N(W&^;V6u>*j-6v>D|7a{`VNsI{%x(uu^P&$B7qxmImA< zZGmOtP4Z{DTpMZqRJhrwctzZ(c<~hUVtjQ`MOA@D+@aa&m*M@?xXHN*4r+gQAg!_k zc^-aqgLDitIQyAHV~sb7x9IwR2?hB9?NaD4wJ0r13*U zW-rdY6G{s_L+jWz9YytH5arP>xx<{mGA8z z9`Bpu>>cf=lO;Gi4mzeCvcX>sJ5Iistk;|LGcQ_b<7zEquF}rmh_v8{r2#FuT7JKoS*2jC~JS-M_ zM+q&_%WCt}spAH$dMvls7)gi z9P33}9&;|YUQCq2t+a8D_kK7HXh{^Wd_1;3Jv<^s&Gm2)f?DEic_@gxb*y)s6`r>~ zHancIWJn+zGAmBiSY2G37j#V%V8YJvc+O2yo8B48g_%W=fWR_N;hvbE`?$I?*C2kP zc00@dQXDFT-D?BXS-u%NxwboQcBDseDb}2?sjtx}-?vzwn4X=>prf+6=W-@7ct*)X-$F`);Dz3946Pb_lqQhDS2B zJU?Ak=ket`e!aCfZS;Y_!s6;$U7W5%rs&Du(P@Bk%yKhVrV2TlNua{yiH~V@spH!8 zYMtQNacVZTu${)L`u-)NxEcrJVVenG5+1*#!mS+7OHaKWSxD%S@efj>FFo98ZrS(JeF>|`D1G)qQ=X$>222#Br5Mn=L>r{Np-9a zkB<*RZ(`QOnReH;c9+rHl_jZ(Nj*hvnyR26Wp)TwF^+xl1Z_E8UO&1^FZmd{4i92q zDJDa@zt_)}v-Z%z0b~;EXwO4E!k9F92x_dmCbIAYZxO3)CcIZ_FmB}8_$6_+-{)?< zTHzatSw27WeChLt=X70au!8Jq_^eS^17{N>sh-NL)1(dj(4Hb7I`fhAQC2PJGCrok z8PNhTD6SM&p@9CWHGXv#W~=Z@dg(xM0dQ3rSIVBG*Y>liAjcjLCI^kMRYOnU8RufK z-aCKZ3eUU8GrDjJW~A~R*%|>v8!S!atV)%`TGkY7t|ZX9Ffre6p)Je!vOS47>!!?O zl^)A6SS^9~bBTOL9q+%komX>q+QOF6tcUwY+wUN$K-S4wW5kkyWSqJ2@%YWu)sg-L{B+N4pOD4=H?F=hR4<8mE9Bwahx`W*CETncC7cKf*{W39=@?t0y@WvexAmr!%W)DXUgtWpBg9Q)^63 zq|(u8PRR)_X+np^4-XF?V#h1JLn@0&s3_IY*3f}iRTZdV0U4X)r&FF)W)V7|P(#5O?o z%(XCJTI9H-&IF3pudMQ;MVNC@TF&-tNxV2z9U12W*W&Y$>_W~4VpZT`e_LDL{X;zD zv)5t#&LLNF#i>bKTh9GM`2T<9BHU=oWe|KtWV`qN;)S~iH)?B;{PPv{Hr3Km_L7uB z>hOkIq-ZPUXJf0x-@n` zw~yYyePXnE?7)L?#$AEh__jmhzUDoCIC3~J^z%DxN1Tram=yu23GX{{`U)R91}`G( ziz3+#MjQA`@-xz%2>LQUUu&Q?#GdkwGS<@RccTO}{Om7{Um%|N(QRCmJ5H!^^*p(* z2GKGLkxQB7W~MDLk|Tl_O0zcL0erV|rUhR9_lNH}j@nz?IWJK_ccn{0$3IR-_-Vz? zrfkEt^ZZ>a{KT*c@`|>NvtNi07$um_2XdxyKevx7!zP@K(2d(0S0h1$dq(~oylCnh zbk274rb*9dQcQ~-yI-Y#LxBJqAb?qkYerJ3tT!FraJ`h8eK*spe7Jk3z zW6{E=ZDkPt;pAxp)0+xR70wEwQKRF0M4rsNu-iINBwb|u@MA2l!0FW4dxr{qVb%xY zELgyoq;FYGn4o=ld0ljV1o>OFfMxf4DR-2R(-ir`3!K_#Mz(|6b^)T)&9- z4@~tsNRYq`=iLWu|E9yDBiz@cCF!rU4UEh0CI5PV?6)8%xPlSwyLry~$=$J#7IhZO z{koyY{S6#x?pLSVxh@)#b`X^F?@k5oI|Od5K0jXWL?0;PZ)c|5P;v}Eh`VF5Nk6jT zyW=DAhC@A`>p~+zp6jyW$DSVzK*w;@=Kg?GW@eX@Va4;u9DzD905ZPMN&0e`)PWlA z>xHYC+D9ZOHl_gU#weEP2&j+>l11`)(#0 zZ-6qsNRcr`)86M+)+V<029|wlWF=1T91)Qrx3OrEw#Mn)@q1lKK?%D25M3e^aMEH7$RJ^oI;=CAYRrfUxBd!Ef zpq_zk)_0O|3QXc@elPp<{*@ngI&}-~ObUG9mo|nLiN6Vw=rl^3pqK@y31mgm8NzxJ zYMsF%wrbJs)40ZH&m3O=OrK_Q&2^5<;75!(W#;%6^a717>K@*OBIqu1uYm1$4d0C1 ztFVwaGW7uQ&D5e6k4B5Ce{2>?q_R<8Sqk&3x4})GiD|d*Lh9MnM?!7P6g+Kg)Oekh zT7u1#6hfB1BmB<7EK~4)@u|AC#8%&@ADs1CZZQe|P4jCrE1@f6mcSFnM|X|EuA$3s zWyKj+j{LVI>^x4(QxEwI#QURF0v~#&Qxf{xwCF0VIQ{v0jEgCeetAV^Hti#G5qN!7 z7M)tWj~gA86ty9y2{e2{qJToXL{gVQ>Pi9u&b)%3oeLCbp|7(vSz$6$JH35tH79g4 zx7nqJj!(zSi&rwzq=y?j=yQM%T6T6xyMA(HSh>JdzdaZA9hY6eXVetgkUMudl5WwE z4d$&JVR!a04AWE!g-nblUimH8CDah|p}Sbdof!2`m*Nzcr){wu`*h6!+&-usmWGP* zV8~*1FlBk0vMQW48#{spYh9W~( zDHluS=U-w%Wz>k8uQKYK7XZrAG$UEJM{X;&-sJrR{8%I>WV9*Fw@*6ir+)DX1h(-x zOh|PKuh7TDY1#1+>bz!odP}BJ<$ag>UIN({wxpIhDFt#B=F6XR4hIiCRDb#ySRP}j zP;==|DWo<9vr~{>&F6~{$>^S z-R=GSkkg~<&;5)r3>g-guckjt>t}u`R+a+hl$C2M)4O!QsR+O1%ZFX_&R7mhw@m1c zcQ8k4JFYBTz~$AO%{UqX)|q^HZAt)9rRUM@_$L`_LjiyEu|X+2Rjq{zY@K% z|2xr}l8X(HPQ=>EK?rDXU}tLMU=2$22CB;FSpw+<`QKht{C1{#7Sc+vZyDf>?E%c7 z0!TwZ!1|j84J#`%fQE^Y8Nf(SPY+}*RaD!AH0q*|40-R5{zg0X?*WQ zLSahCPt_YY*CP`u2Oq9NjYY=q;6e_R7OfC-YSObk3y9ANj8X+}}t@SVEHJ={r2>R*vI>(4$ zFEp7a9ynyL?=)|b73S;Bo}Ad|G}bRv&)Px(Xl0}&iCI3Tr3j5nYk+}l3QRS%o%ahn z>ua<-@#f~d=DU)4bYa;fV?0#)X@JuoiUGJxr%|XoOm;)1Q7l!#kpw{o$xXZ1LGBy( zSI+}1%rzUyX!kvuL>W!#xDqd(7u3W~YlJmk5+g64A0%%gf>d8cw`SYF7O$cX$gzB|Asp zA5zdBvB0~tXrgEL7FAMuf0da)@u+HQ=wM>6!Nx)lUm$=_@+aDa3`vVZA= z${-uC|08>|t@URR|9e>h-d3FgES-|IvX$vu5=FpUB>zWfGcf$yL4UppeKY9TKyK>OLEEGI(3AVd1ShqEANEBhGz zZqXZ!x;S~WGl;wph`jCGNBx;etI zWf}a~c}M%)=7{-t_xAD7Sj%W z{AY7l??RmQjPEaSd%L$+y}XtFmX*k(7@X9tdhOQ4mf-9-?2NbfyvS1S^ZQ&eO=*}2((yPiQ%WUhIF+5R{$7vdo7X z6sBD`{#SOhvXp&Xz^E}Ks{UEzS!BHOAe{b>N2NUWEVaU{I2PvdghHxO+;#OKQR{q z_aY>sE~L{Txq=JRohB`>-esQ?y9Q_*e>yU|`Q(H$UvuP~pV3hdiJgm6S*HZ=r37 zcwR<%8$OWf{RRh&EJl=WhuvrNUv4KkTrr$}{%8b2ih3nBt)=c_9EmGY?(FxJ7FCg9 zbJHqI;(AMxk9#$VvjuxP`$$I>5}fQA^6h%foeqTeFg;Ej%AGexHVpzdA4e2?MQop; zwa1LGe|{ZLP7HLc$vL8B9ZEMIr!pc{ZPLDHiMX`B#GEmg$~WX787%-#m>1y9_@6C)V=oqE}y z9exV)W59aNeWf1h@@V$aZsn8Hwmff$u`O47a?3ZI+l%fenU~Wiw*zlih3BH8wJoMJ zsmrk22)+~xF;D-Va^3G*R0I5~lbl@>N6^7mF)?D(9U3I4!tiU4WiHo9C$BcDZA2UFJIcI2W?X z+-CCBy6GGSdbS30@ObdKvfVq_l!dw#LS-!km)qwsWT2;iKV_lCi`w#;STPaiQ%3jE z03?)AS+u48bz^;HS!4aLrB0{c7gaKIeun_Ao|mB29^Ni1gN)dDp0i`{#}96}^QsG< zH2Dnas$LD-jl7g1dtgObF)65GQGj6FWh$(nM}whM8&LYt8 zg_mDbE~r!rUzi?)QFdm7)lN#ri!NtUq}oXoJf*gW!YrijA=`u2W1lGFQcjHNl1^09 zNu_xzMzRtri>>8P`Z7;H6K+G-m8d4YND%fs!{s9Z*5)Y#7b#!Bu037jmgD%U;ErgI zu-Abpv+mo^Ly%4=Tqhb9pIZCM3!ooKI2KWlj4fiZ+!FbEu;Y>v%Nq58hc*iy3A@z< zXP>svS*y2)xaYDp)#TV*yZtqAP# z^rPl`R|41DN%E11r1Tu4dT+5=P-5Bm_AjUXNtgC}Izs4`*5o{yoVs=2)9zhE8?Aqa zr#A9RtQ*0uLZ?*pa$3tDR$i{ftso!?vgcsilJQDsZLKPWHC>WeOWV>ujw(n zRLzn{S`vaMT%v+e{#85DdVF}+VmO{w?Wc*}nD4#)uHpFDP%1DjiGg@E+K9DCQ*X;= z*_^BP?jpRgc|}`QmHNSn0J-h+kMKrFrDKQm#yP^p+Wk}+8z-%v{TYrl)KqH8lFVTJ zz@2*Y^V7M7I{A8gbFPhLvmvx&TwBg=@Ilq@+^Pv{JXQ(vcs4u_+;-}^U|ZsQXth*Bfj zS?n%1yP(Z5?9ye@3xusK3(Hp1aVj(|ZXe9z;m7j`$6ulXWGsIs%TG1Kp#O1C|SG?hheNh30!>j#W{`}nzF`8_} z3DyuL6t84xL<(&6(bB}B|9wOI&GJ50h7SX#VXMpsG&RO3lgxsRZ}Rf)vy@Q))7eD% zg>Pj?I$B2yT*W=dQPcn!V%I_d>wCs)8$yM$AJVgX8% zjwfP)vy^}B@bCbW{GK7r+q-}EgHZ8W_{`;z1t#=UBCOf*iJT~2JhnyXc#+j^2zmwL z=a43}fTva~f$F{5akT204>cpN9VW>TFw_iEC1J*nGy8SUB336YxXj5v0V0D&c8R|f zfBrOa_1dg`VZJm%w8bi=RmEO%LPQu%6e;O7VqsP?pEnES{O+DJD46C%GtBFd+;Dl5 z^`nKD zB?`Fl{N=0{%4;^m=monw5+cAr2nlAwX8a(2LXOerLxe=d76tPT%5NuZx~SU}ve=bL z7qJ9bHrU6?YxKHsaTnTPG6fMAkMIj-TID-=?s{{Jj*uf1Ol~Rfsbb^t=yhenk9Z(U zeRr+ESSLr0pb!?MYHCm+Q$=uUUVFW1VqMZjXv zwCnW#*qw&~CIX*O{-&^R`&LY60u>jXV8)T1Fz_O6zE_s*Rr(uCJn^8Ull~f)WS3k} zK}$Hp?N}7ni8<38%o)xg-~I{sb&pcfZ=8i&(r;X~VVg+$Q|XL-M{ZqYE|b8^up7b&%e?bS4y?v3^|`HlYGHTjec2tzd0%a0r(Ds?J9%uV5a|`-6N4BB}C%}BP zlA^an+#L<;WBWi4yvzgP9>dp})^6Oe_n;gf}fXT4x+yr0Aw+E**L@qUQq0^{X$e#TIFE(9+Jfu)nsZm!~sI5HN9MLyYTce0kNF+qd6|VFFz6 z05++pSBZD44++$%yiR{KTuPV6U=KDSr9S`2`6{l}C?KMOo>M!tcqHoYhm~iJ7nu%I zr0-#o@Wf#7f|KX6qRm71fs1&v@_ z{iup(`4s1!MP(>)ATy`6P$gQMzEq<%^M} zl=?}=K&+%&g}GOY7EVFWmv7mRC@~KT9PEHwpJzr_y`FZR6OXoG*J9BnHk#rGd<<5z zRVqA;7So;u#eh0Daz@nzV)ov#=P`T3yie7+b8(gVs!JSAwE3sLh@T8H{K5J{+dL9l zzwJ`T7KBwc;@*0aMpvsJED+yLWu_7k*mTWX+2op#ejm}oJYJ#7Bjvq+1ZGLE2RW=O z&OPxMZ?!#LH}LTWwtZDA?hn7(dhAgijfncIMPkym!23Vr6loK|KU; z0_o;2CC3vpvnn)n-Z$3@m8deG3ZQ<_Orwt8xa`5V>Vm5!L&pp`HdKId_ zGr8a;CcS+9U!wal4(hTnHm~ zL!TK?YDzV*lIzLV>bRRE1GgH{Zu4#_`-R<qoh4|P>1$$_7$K}wba8U~atQ-q!g?B?`Y-HADuQ;d~jJPRPB~JYjit2cH z64pGF$XRlKrn*{5jqeYN9mUulJwoj=)HQ^(%y<$rPLEI1?>m>r*e)U-;kX5j~|ey@jcFH>ljd??jeCh;hQ(7NrV zp+Qbo#c4ZmC*oa32u>u{(;+Swuh3+Kbeu{ayi?Ax^w}18A(LC)5}ynO?T9=cOhF&J&rK^SG$SZN$RlWpy)!_k_;dEY{ z+3I<+T?sk7K26tL0!;H&LZ(TYCe5kMxghwWxWy8Uj3F5<(MvQ*2M>L#f~Dvovtzuu zAGD;x>qaA2%bP^mC(#Tao$6#v+ETY>btZ-+=1XUnTz!|~ZM@j)`A}wxyTPK)yy-At zZ!6|BTU(RKXI4=|%+ht4*(=$wzLu$#Id+cuZ19$Gpd4AF8en@ocKb1uv8~`;n7`N< zzItQjz?|oq*KKF3?M`sFt%*gb>>l0*KD&9Z;-2i!A3%c1XBCx^qs_V&4DG{$wjj(J zTZ>$uFZqPsiTYiE1{)vu3~JJ$_vRkbcS+X^z@FLbPjGFiZZJS_6amR*HmNHIcjE{N z=A--NaJEVvfOU=JPt?U=;R3_4!cHhkX^{gLeg>v^^!I$uTBzW^2prspiaYV05& znR&E5F9Cj|p)yUOL-u0M5_S5t$x(l&cRES1b+R^h7(5G-F$CaZUG>+>wbxgWZ=EJF zVptZguX9lt0Wju1WSM~1l-@spVWEHUBhZvV9s0tm~SP@HogHI*_&1nIiGX z4;TmQG_iQMMo6JJV{qqR8aCzIgp|oTMreZIe|vrV-9s_1%Ot~!k`eypdlu}q zF14=|0{Ct4hHnA+0#4Ha@ge*nJcFv%ueG(xR5)S?JoN%PSii1k)XymrV_oTAsTH&p zP>yt3>1xT*U?2tBW`FsdpiEM|-=!sPQsrdUA(_GvK;dsew%?!qR-}C8;g=(C!%eQ= z#0B3S@Y>nhsa;C{X?p)qxyO7d82zN~2gi>gYSEv_iGV&wq&sA9Z^1+Cjt4=qM>lt{ z)iZVfYOnT0cIb(&w6D(3MAW=Z#?WK!<4AhZbl3=wg1k|XK9ydTNItjwl3X((3uv%G z(@(SNVbYsTaZ}k}kUt1MNNGmPE@K8?Ltn*~+F_}YmdZxC35tnoHAJ#xTBl6VQy6J} z+nadk@{vn0@nZx;@w1~HgOc36pG@;(0OWiy-Gbq!_Su{S+~|oR*H{YeN9PZ{7szX4 z4Hc6lzPa{)T*`~U=ouzs_ z+6avj>sfW~(d9$)6_zDfRjLOn+@}GPZ?Z}J)kAR6r4H+7C_Q7hIzyd}?K{KM3 zs|6s2Oi~^4!IZjYdi{ghQ5Jp~Fr^@`X%^v{1$kL%UFpyV;}*kNaoNlS zLdM=&RMfo8o`qFHx!kgHjrh34%Ie(pfNi$U)NwS7#R^ceQaPeLyEmuYS#%(x`iv2% zvbpqoX)8V_nXs355&qC=rim2xLG!N2s>Ip~#Y%~dtk-YWlxN4X1;EMri-z?Aui(PKTbJRr=jIP znf_lYYqMNArtJ|){vH=U8_|xpP2GQ!WIUu`KZ_qtF}iK9j>NV#OKIh>7N*SHX0Fjo z3-WDg%LIdV4cB%NtvC(hp&rBEAi3Qej%Z>Yxo%gH-4R$K<)uB+c)A@*F!{WAcY0^8 z(_(3TM<$bCU18M)=FtL?$l0BN` zq}d`FtZIB3hJQ~sDNtvdjw(Voqvrj&g8qxXxC?{4GVtAe>AX*raxajs$>{Z5qv=Y(gBfQcd^Y$RDrq@1E1lpQ{cH_#4$`$MpV-U~9G5J#{btZ<&x3~MY( ztdY+z@_X?G7Xf#ucaAU;SlblA!2_Nj?|8CzkSbvh@TJ_J@Jo;YBL}_ zKP^E`U>-B%yqebfzI+DrqIovEBLfk`>`-}oS^i#OaAemk|t3;g<+ zqF*@TR1jCSt2p9(HAny_y420kucq_@W-UOD%VmC`D-S42?zYb)M3kKdtWEM|qbTZ( zx=Q+hgR54nWZhZU&l2*u??(YUDx4N!hc1B-JoFs>Gi;O~?boZmb$l3Gu@3fImiE zy}Nq+g3+uBS%EPHQxO77Wywjo(h+Yz>Pm2*n@UTPPTD!YAvdM#3BWhh6qax%u{Ppt zJ8fb|9i`HS5oRCLqCO6?$9C2*)`m{O8;eMOAB^t{Z?W1*`^`mMSR+S7(U4R4hf5}Hv2iFL!6W{on?#XJ)=X| zcM^n%E>tawb4_FL3D@!ob&Ei){c3@w4@0CSjIwh^@-^!N&Ej*2yDOT9Uc2hAvF6W$ z<=0G2bBFe2r-SI5@wyNiaZS}@$Sf_Ab1A^ql_b3y&uODoy_)hGH7ykE5=x4SV zC>%H9sMp|8mWb!1*^=y6@|%dEze^TKo}KM9s0Q4RRD#Z#!m0hDITcMlV5z zmb3+}%KvC;uU84MtVXSfZJo!xsE%@jBp7@@>8on-s(kKmld5f;6!d7x=Y{fODSFHI z)#G>W@!~X*Cd@KZxV*|4D2?R}xyAYb0dN_$o}s@G!oMb5K7hvvML}q2Bv@5n*OR1zksVhCVs|s%IXPrH6**)RMsHXjA*@_s}nS z5zAvSIiF@1(4+lNruwB@JIfd$Hyxu5F0G}6ygLQoWoTYRsGbt59F12DD~7V}-Kgv- zYbw%Ov+8$Hlmq24r9JI}^F8h2`%cYFEF-*Zi`cZuytfpr1>Ixr%AZZQT}hA1Im(2D zHZA!^t>ns`-N4gVEdK@cZ#@J2vxI4u;!Ykw-~Y0$r`%`&%%-A zjw?nNX(YrUp-0XVVOM@0rqCH0QjLdU-SVTQwlA(s>S4^Q97!Sxp!q1(4FRERiv}J4 z%Mn5si}ow|AUXNq&4*Q7I&?7}h!Lu5de%Y3!b<=gJbv$o^z7G^4Bgpv5dG&)2mbV% z58q*7l|MH8E~=G><6JN;nHBe2=bb9_Fc;@DPxdv$Cf$M`%ei-}2+qwt9sdnn^|&^Z zl&7=CW99m%Qt`V~-iB4xO+1$~UB_-_ErOH@WsftIE<{+pS%G;!gaiN^^o5^*s^7#c zz=3DaUGBi_OsVR7{EZ%*vP((D^zuhi1IRhS{@*HPwr>?IKL2!6$v^bLwZ1htn4%xAIO#4(B&Vvd z5E3dxt{>8#gz>v_%JLF&1-edW#ShiS&9QK7I@C)B6ZhifG&N(Y^dh+~bSSED72Fbb zWj$=%s}E@&tfxubKviw_Q{A=6p9U@k7bCtlT92D!!3HkvZ+sZY%>N4?_6IZbpA-%Azi;F(iiVMq;lCg>|3QdF^2_!BkONMif;mp`Strs{ z$c#qGc=oVM_`JJnqZfRn_Oo8sKC4J`f4TT}>c_Tce!Cz)@DPx5$k2^7z(i{c45Z&c z6H{in+qlRYIx$L##i(D8549IHu)xmK>D6GgwsAeP?Wmb@z8UZ#V{g@Qn|w~5A|Dg` z6l$h%#y-R&%gVF-$uWyI4U=o@m}o#}!%`C3adOrf9g~N4kke2SwYV=4BYC+@S?ndl z8M%9pms+wqI+vmD^WvsM!A+ItlD9@uo_JEL(gFdJfBSlj{!&qO+dB_6OUM5f0WAM^ z(ZA;U{~)pck17AJOcrP+{|Cu>L#;qq*8j$#{)o5#;Gr1aChk9{@^4$xiZB2e-i8f= zp+E%I8%p+{s{eyJf_ATcqsIUYf0BcAUuE^pfCdgAvA88O;Eygq6Hg~+XKkPebkLxa z6B40Q0)BG^~{Z*|yEt=_pvbe|ZXI^Ixud3mZvOLwgOtA6>px z|GLw^b;0;gtWZ!71fW_QgT@5v>(7~irIWP*TJak=m|9!?Iefq$*!!%YV|gIf3kXi@8oZj&+q79Vr}=Ax0qS~@)pQTY;WFr^B()3UITr-{^2>$C3;qn zXW#07=)CDNg1jjR+J6~D-2RWLH-`&>E`ikFRNoxW1~SLS^k=*pIvN1~rTb>?%`8ZV zRhXWh8B}L|8_L`9X6J1fplg3j9B5dKARQ)#zs_v`(>2H&LZD5ZDTFu~-!xenSm+s8 zKm{6lHgbA;^3Q*Bz&AUf5iC6jhlB<7`qvA<%EH3L0x$ynDPw10V*|PA?FF#x zMdLqY94w%9_)i(zKV|H!^lblZ%fiCQ28yZwXv@X|!khn>jPWfl{-MWA|4(~tEbJ`* z95Wj$1M@%IvNLlqgO>Dv*aOK}|7j0ojqQK6WnpIhXCLe=tc?G=Eh`&nG5u#BEF5oN zi~p4U?><-=*#7AQc2>r}`_I8n4@6Yky>0KUXzB_CO(mUzwY3B2FZ0`ShNTm?GO`9R zzQy@lMF^k);AUkL*($3<8PDAT&+ zCp%}PCTACy<|^pBIhtCynp+r}IT<^fIk~twJG(f$SOV>EG&Td?^z8^LtBOk!i%P&r R&ce*p*o;e6)z#mP3jns$m{kA( literal 0 HcmV?d00001 diff --git a/README.md b/README.md new file mode 100644 index 0000000..19835db --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +Ventilator Splitter Display +=========================== + +A system to take pressure and flow data from sensors on a ventilator splitter, calculate descriptive parameters based on these data like PEEP or Tidal Volume, and display them for medical professionals to monitor. This is for use against COVID-19. + +To set it up for tests, run `./setup.sh` to build the virtual environment and then `source ./venv/bin/activate` to activate it. To do the tests, run `./runtests.sh`. This will first show the results of unit tests and then behaviour tests. + +To run the display, first make sure Docker is installed, then run these commands. + +```bash +docker build -t zmq_proxy:latest . +docker run --rm -p 8000:8000 zmq_proxy:latest +``` + +Then open http://localhost:8000 in a browser. With this, you'll see a webpage which every second writes some JSON in a bullet list, where each bullet ought to looks something like this (though it won't be printed as nicely). + +```json +{ "0": { "Flow Rate": -0.12102553332090354, + "Inspiratory Pressure": 25.185687032203397, + "PEEP": 7.600443036648329, + "Peak Pressure": 29.143715376593427, + "Tidal Volume": 2982.643040302767}, + "1": { "Flow Rate": -0.1853025137003232, + "Inspiratory Pressure": 27.589362195098154, + "PEEP": 9.0296093948397, + "Peak Pressure": 32.05751894822633, + "Tidal Volume": 123.60199756683565}, + "2": { "Flow Rate": -0.23654912423232322, + "Inspiratory Pressure": 26.474812956451874, + "PEEP": 7.607352013212795, + "Peak Pressure": 27.6944434648811, + "Tidal Volume": 3712.3769706397325}, + "3": { "Flow Rate": 0.13331473843016745, + "Inspiratory Pressure": 10.52283673388029, + "PEEP": 7.33283292927223, + "Peak Pressure": 23.519565988527702, + "Tidal Volume": 359.06476658825846}} +``` diff --git a/Scripts/__init__.py b/Scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Scripts/green.py b/Scripts/green.py new file mode 100644 index 0000000..db458c5 --- /dev/null +++ b/Scripts/green.py @@ -0,0 +1,18 @@ +import tkinter as tk + +# A cheezy thing to make a green screen to superimpose images onto + +root = None + +def destroy(event=None): + global root + root.destroy() + +if "__main__" == __name__: + root = tk.Tk() + root.title("Green") + frame = tk.Frame(root, cursor="none", bg="green") + frame.pack(fill=tk.BOTH, expand=1) + root.bind("", destroy) + root.attributes("-fullscreen", True) + root.mainloop() diff --git a/Scripts/i2c_scan.py b/Scripts/i2c_scan.py new file mode 100644 index 0000000..1bb6c75 --- /dev/null +++ b/Scripts/i2c_scan.py @@ -0,0 +1,24 @@ +import constants +from tca9548a import I2CMux +import sys +from pathlib import Path +sys.path.append(str(Path(".").absolute().parent)) + + +pressure_sensor_mux = I2CMux(constants.PRESSURE_SENSOR_MUX_ADDRESS) + +print(f"Initial scan:\t\t{pressure_sensor_mux.scan()}") + +for i in range(8): + pressure_sensor_mux.select_channel(i) + print(f"{constants.PRESSURE_SENSOR_MUX_ADDRESS:#x} Mux Port {i}:" + f"\t{pressure_sensor_mux.scan()}") +pressure_sensor_mux.close() + +flow_sensor_mux = I2CMux(constants.FLOW_SENSOR_MUX_ADDRESS) + +for i in range(8): + flow_sensor_mux.select_channel(i) + print(f"{constants.FLOW_SENSOR_MUX_ADDRESS:#x} Mux Port {i}:" + f"\t{flow_sensor_mux.scan()}") +flow_sensor_mux.close() diff --git a/Scripts/poll_spl06_007.py b/Scripts/poll_spl06_007.py new file mode 100644 index 0000000..bfa526d --- /dev/null +++ b/Scripts/poll_spl06_007.py @@ -0,0 +1,32 @@ +import time + +from spl06_007 import PressureSensor, Calibrator, Communicator + + +if "__main__" == __name__: + print("--Initialization") + comms = Communicator(dump_communication=True) + print("--Set Op Mode") + comms.set_op_mode(PressureSensor.OpMode.command) + print("--Set Pressure Sampling") + comms.set_pressure_sampling() + print("--Set Temperature Sampling") + comms.set_temperature_sampling() + + calibrator = Calibrator(comms.calibration_coefficients, + comms.pressure_scale_factor, + comms.temperature_scale_factor) + running = True + with comms: + while running: + try: + print("--Get Pressure") + raw_pressure = comms.raw_pressure() + print("--Get Temperature") + raw_temperature = comms.raw_temperature() + pressure = calibrator.pressure(raw_pressure, raw_temperature) + temperature = calibrator.temperature(raw_temperature) + time.sleep(1.0) + except Exception as exception: + print(exception) # TODO: change this to logging + running = False diff --git a/TestData/20200609T2358Z_patrickData.txt b/TestData/20200609T2358Z_patrickData.txt new file mode 100644 index 0000000..5adfeff --- /dev/null +++ b/TestData/20200609T2358Z_patrickData.txt @@ -0,0 +1,546 @@ +15:23:04.509 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:81.99 +15:23:04.509 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:81.99 +15:23:04.509 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:81.99 +15:23:04.509 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:82.59 +15:23:04.556 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:82.59 +15:23:04.556 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:82.59 +15:23:04.603 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:82.59 +15:23:04.603 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:82.59 +15:23:04.650 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:84.32 +15:23:04.650 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:84.32 +15:23:04.697 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:84.32 +15:23:04.697 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:84.32 +15:23:04.744 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:84.56 +15:23:04.744 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:84.56 +15:23:04.744 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:84.56 +15:23:04.790 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:84.56 +15:23:04.790 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:84.56 +15:23:04.837 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:85.29 +15:23:04.837 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:85.29 +15:23:04.884 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:85.29 +15:23:04.884 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:85.29 +15:23:04.931 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:85.29 +15:23:04.931 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:86.07 +15:23:04.931 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:86.07 +15:23:04.978 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:86.07 +15:23:04.978 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:86.07 +15:23:05.025 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:86.64 +15:23:05.025 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:86.64 +15:23:05.072 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:86.64 +15:23:05.072 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:86.64 +15:23:05.119 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:86.64 +15:23:05.119 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:87.37 +15:23:05.119 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:87.37 +15:23:05.165 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:87.37 +15:23:05.165 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:87.37 +15:23:05.212 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:87.37 +15:23:05.212 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:87.82 +15:23:05.259 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:87.82 +15:23:05.259 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:87.82 +15:23:05.306 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:87.82 +15:23:05.306 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:88.36 +15:23:05.353 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:88.36 +15:23:05.353 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:88.36 +15:23:05.353 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:88.36 +15:23:05.400 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:88.36 +15:23:05.400 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:89.14 +15:23:05.447 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:89.14 +15:23:05.447 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:89.14 +15:23:05.478 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:89.14 +15:23:05.478 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:89.83 +15:23:05.525 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:89.83 +15:23:05.525 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:89.83 +15:23:05.572 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:89.83 +15:23:05.572 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:89.83 +15:23:05.619 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:90.30 +15:23:05.619 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:90.30 +15:23:05.665 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:90.30 +15:23:05.665 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:90.30 +15:23:05.665 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:90.30 +15:23:05.712 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:105.70 +15:23:05.712 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:105.70 +15:23:05.759 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:105.70 +15:23:05.759 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:105.70 +15:23:05.806 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:152.34 +15:23:05.806 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:152.34 +15:23:05.853 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:152.34 +15:23:05.853 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:152.34 +15:23:05.853 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:152.34 +15:23:05.900 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:185.70 +15:23:05.900 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:185.70 +15:23:05.947 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:185.70 +15:23:05.947 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:185.70 +15:23:05.994 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:185.70 +15:23:05.994 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:207.69 +15:23:06.040 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:207.69 +15:23:06.040 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:207.69 +15:23:06.087 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:207.69 +15:23:06.087 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:223.76 +15:23:06.134 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:223.76 +15:23:06.134 -> SLMx10:0.00 TidalVol:16.07 Pressurex10:223.76 +15:23:06.181 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:236.22 +15:23:06.228 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:236.22 +15:23:06.228 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:236.22 +15:23:06.228 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:236.22 +15:23:06.275 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:236.22 +15:23:06.275 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:242.47 +15:23:06.322 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:242.47 +15:23:06.322 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:242.47 +15:23:06.369 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:242.47 +15:23:06.369 -> SLMx10:20.88 TidalVol:0.73 Pressurex10:238.15 +15:23:06.416 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:238.15 +15:23:06.416 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:238.15 +15:23:06.416 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:238.15 +15:23:06.463 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:238.15 +15:23:06.463 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:234.72 +15:23:06.510 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:234.72 +15:23:06.510 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:234.72 +15:23:06.557 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:234.72 +15:23:06.557 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:234.72 +15:23:06.604 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:234.04 +15:23:06.604 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:234.04 +15:23:06.604 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:234.04 +15:23:06.651 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:234.04 +15:23:06.651 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:233.10 +15:23:06.697 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:233.10 +15:23:06.697 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:233.10 +15:23:06.744 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:233.10 +15:23:06.744 -> SLMx10:0.00 TidalVol:0.73 Pressurex10:233.10 +15:23:06.791 -> SLMx10:62.25 TidalVol:2.91 Pressurex10:224.76 +15:23:06.791 -> SLMx10:109.91 TidalVol:6.76 Pressurex10:224.76 +15:23:06.791 -> SLMx10:124.96 TidalVol:11.13 Pressurex10:224.76 +15:23:06.838 -> SLMx10:131.45 TidalVol:15.73 Pressurex10:224.76 +15:23:06.838 -> SLMx10:132.21 TidalVol:20.36 Pressurex10:182.42 +15:23:06.885 -> SLMx10:133.99 TidalVol:25.05 Pressurex10:182.42 +15:23:06.885 -> SLMx10:121.53 TidalVol:29.30 Pressurex10:182.42 +15:23:06.932 -> SLMx10:123.73 TidalVol:33.63 Pressurex10:182.42 +15:23:06.932 -> SLMx10:117.43 TidalVol:37.74 Pressurex10:182.42 +15:23:06.979 -> SLMx10:104.89 TidalVol:41.41 Pressurex10:171.78 +15:23:06.979 -> SLMx10:105.57 TidalVol:45.11 Pressurex10:171.78 +15:23:07.026 -> SLMx10:105.34 TidalVol:48.79 Pressurex10:171.78 +15:23:07.026 -> SLMx10:97.14 TidalVol:52.19 Pressurex10:171.78 +15:23:07.026 -> SLMx10:79.20 TidalVol:54.97 Pressurex10:171.78 +15:23:07.072 -> SLMx10:87.42 TidalVol:58.03 Pressurex10:165.27 +15:23:07.072 -> SLMx10:105.12 TidalVol:61.71 Pressurex10:165.27 +15:23:07.119 -> SLMx10:105.57 TidalVol:65.40 Pressurex10:165.27 +15:23:07.119 -> SLMx10:101.31 TidalVol:68.95 Pressurex10:165.27 +15:23:07.166 -> SLMx10:103.99 TidalVol:72.59 Pressurex10:152.73 +15:23:07.166 -> SLMx10:94.34 TidalVol:75.89 Pressurex10:152.73 +15:23:07.213 -> SLMx10:102.87 TidalVol:79.49 Pressurex10:152.73 +15:23:07.213 -> SLMx10:99.77 TidalVol:82.98 Pressurex10:152.73 +15:23:07.260 -> SLMx10:93.70 TidalVol:86.26 Pressurex10:140.39 +15:23:07.260 -> SLMx10:93.28 TidalVol:89.52 Pressurex10:140.39 +15:23:07.307 -> SLMx10:93.70 TidalVol:92.80 Pressurex10:140.39 +15:23:07.307 -> SLMx10:94.13 TidalVol:96.10 Pressurex10:140.39 +15:23:07.354 -> SLMx10:100.65 TidalVol:99.62 Pressurex10:140.39 +15:23:07.354 -> SLMx10:92.01 TidalVol:102.84 Pressurex10:129.58 +15:23:07.354 -> SLMx10:87.63 TidalVol:105.91 Pressurex10:129.58 +15:23:07.401 -> SLMx10:93.70 TidalVol:109.19 Pressurex10:129.58 +15:23:07.401 -> SLMx10:96.71 TidalVol:112.57 Pressurex10:129.58 +15:23:07.447 -> SLMx10:90.33 TidalVol:115.73 Pressurex10:119.28 +15:23:07.447 -> SLMx10:88.45 TidalVol:118.83 Pressurex10:119.28 +15:23:07.494 -> SLMx10:83.96 TidalVol:121.77 Pressurex10:119.28 +15:23:07.494 -> SLMx10:78.42 TidalVol:124.51 Pressurex10:119.28 +15:23:07.541 -> SLMx10:75.91 TidalVol:127.17 Pressurex10:119.28 +15:23:07.541 -> SLMx10:69.55 TidalVol:129.60 Pressurex10:111.85 +15:23:07.588 -> SLMx10:67.37 TidalVol:131.96 Pressurex10:111.85 +15:23:07.588 -> SLMx10:62.94 TidalVol:134.17 Pressurex10:111.85 +15:23:07.588 -> SLMx10:60.36 TidalVol:136.28 Pressurex10:111.85 +15:23:07.635 -> SLMx10:57.84 TidalVol:138.30 Pressurex10:111.85 +15:23:07.635 -> SLMx10:46.64 TidalVol:139.93 Pressurex10:103.90 +15:23:07.682 -> SLMx10:46.19 TidalVol:141.55 Pressurex10:103.90 +15:23:07.682 -> SLMx10:45.31 TidalVol:143.14 Pressurex10:103.90 +15:23:07.729 -> SLMx10:46.94 TidalVol:144.78 Pressurex10:103.90 +15:23:07.729 -> SLMx10:42.00 TidalVol:146.25 Pressurex10:96.86 +15:23:07.776 -> SLMx10:36.81 TidalVol:147.54 Pressurex10:96.86 +15:23:07.776 -> SLMx10:29.59 TidalVol:148.57 Pressurex10:96.86 +15:23:07.776 -> SLMx10:21.57 TidalVol:149.33 Pressurex10:96.86 +15:23:07.822 -> SLMx10:0.00 TidalVol:149.33 Pressurex10:96.86 +15:23:07.822 -> SLMx10:0.00 TidalVol:149.33 Pressurex10:91.31 +15:23:07.869 -> SLMx10:0.00 TidalVol:149.33 Pressurex10:91.31 +15:23:07.916 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:91.31 +15:23:07.916 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:91.31 +15:23:07.963 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:87.98 +15:23:07.963 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:87.98 +15:23:07.963 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:87.98 +15:23:08.010 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:87.98 +15:23:08.010 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:85.53 +15:23:08.057 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:85.53 +15:23:08.057 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:85.53 +15:23:08.104 -> SLMx10:23.09 TidalVol:0.81 Pressurex10:85.53 +15:23:08.104 -> SLMx10:26.39 TidalVol:1.73 Pressurex10:85.53 +15:23:08.151 -> SLMx10:27.29 TidalVol:2.69 Pressurex10:83.82 +15:23:08.151 -> SLMx10:29.24 TidalVol:3.71 Pressurex10:83.82 +15:23:08.197 -> SLMx10:31.62 TidalVol:4.82 Pressurex10:83.82 +15:23:08.197 -> SLMx10:35.12 TidalVol:6.05 Pressurex10:83.82 +15:23:08.197 -> SLMx10:35.25 TidalVol:7.28 Pressurex10:81.85 +15:23:08.244 -> SLMx10:38.41 TidalVol:8.62 Pressurex10:81.85 +15:23:08.244 -> SLMx10:40.18 TidalVol:10.03 Pressurex10:81.85 +15:23:08.291 -> SLMx10:42.14 TidalVol:11.51 Pressurex10:81.85 +15:23:08.291 -> SLMx10:44.29 TidalVol:13.06 Pressurex10:81.85 +15:23:08.338 -> SLMx10:0.00 TidalVol:13.06 Pressurex10:80.83 +15:23:08.338 -> SLMx10:22.07 TidalVol:13.83 Pressurex10:80.83 +15:23:08.385 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:80.83 +15:23:08.385 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:80.83 +15:23:08.385 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:80.83 +15:23:08.432 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.15 +15:23:08.432 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.15 +15:23:08.479 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.15 +15:23:08.479 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.15 +15:23:08.541 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.23 +15:23:08.541 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.23 +15:23:08.541 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.23 +15:23:08.572 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.23 +15:23:08.572 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.23 +15:23:08.619 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.47 +15:23:08.619 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.47 +15:23:08.666 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.47 +15:23:08.666 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.47 +15:23:08.713 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.47 +15:23:08.713 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.57 +15:23:08.760 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.57 +15:23:08.760 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.57 +15:23:08.807 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:77.57 +15:23:08.807 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.21 +15:23:08.807 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.21 +15:23:08.854 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.21 +15:23:08.854 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.21 +15:23:08.901 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.21 +15:23:08.901 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.50 +15:23:08.932 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.50 +15:23:08.932 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.50 +15:23:08.979 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:78.50 +15:23:08.979 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.10 +15:23:09.026 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.10 +15:23:09.026 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.10 +15:23:09.072 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.10 +15:23:09.072 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.10 +15:23:09.119 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.84 +15:23:09.119 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.84 +15:23:09.119 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.84 +15:23:09.166 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.84 +15:23:09.166 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:79.84 +15:23:09.213 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:80.79 +15:23:09.213 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:80.79 +15:23:09.260 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:80.79 +15:23:09.260 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:80.79 +15:23:09.307 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:81.40 +15:23:09.307 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:81.40 +15:23:09.307 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:81.40 +15:23:09.354 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:81.40 +15:23:09.354 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:81.40 +15:23:09.401 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:82.11 +15:23:09.401 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:82.11 +15:23:09.447 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:82.11 +15:23:09.447 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:82.11 +15:23:09.494 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:82.11 +15:23:09.494 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:83.00 +15:23:09.494 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:83.00 +15:23:09.541 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:83.00 +15:23:09.541 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:83.00 +15:23:09.588 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:84.37 +15:23:09.588 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:84.37 +15:23:09.635 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:84.37 +15:23:09.635 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:84.37 +15:23:09.682 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:84.37 +15:23:09.682 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:85.06 +15:23:09.682 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:85.06 +15:23:09.729 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:85.06 +15:23:09.729 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:85.06 +15:23:09.776 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:85.70 +15:23:09.776 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:85.70 +15:23:09.822 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:85.70 +15:23:09.822 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:85.70 +15:23:09.869 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:85.70 +15:23:09.869 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:86.17 +15:23:09.916 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:86.17 +15:23:09.916 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:86.17 +15:23:09.916 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:86.17 +15:23:09.963 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:86.17 +15:23:09.963 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:86.66 +15:23:10.010 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:86.66 +15:23:10.010 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:86.66 +15:23:10.057 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:86.66 +15:23:10.057 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.52 +15:23:10.104 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.52 +15:23:10.104 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.52 +15:23:10.104 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.52 +15:23:10.151 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.52 +15:23:10.151 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.84 +15:23:10.197 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.84 +15:23:10.197 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.84 +15:23:10.244 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.84 +15:23:10.244 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:87.84 +15:23:10.291 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:88.71 +15:23:10.291 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:88.71 +15:23:10.338 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:88.71 +15:23:10.338 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:88.71 +15:23:10.338 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:89.20 +15:23:10.385 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:89.20 +15:23:10.385 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:89.20 +15:23:10.432 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:89.20 +15:23:10.432 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:89.20 +15:23:10.479 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:89.53 +15:23:10.479 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:89.53 +15:23:10.526 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:89.53 +15:23:10.526 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:89.53 +15:23:10.526 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:90.51 +15:23:10.572 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:90.51 +15:23:10.572 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:90.51 +15:23:10.619 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:90.51 +15:23:10.619 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:90.51 +15:23:10.666 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:93.39 +15:23:10.666 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:93.39 +15:23:10.713 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:93.39 +15:23:10.713 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:93.39 +15:23:10.713 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:93.39 +15:23:10.760 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:130.82 +15:23:10.760 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:130.82 +15:23:10.807 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:130.82 +15:23:10.807 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:130.82 +15:23:10.854 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:173.50 +15:23:10.854 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:173.50 +15:23:10.901 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:173.50 +15:23:10.901 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:173.50 +15:23:10.948 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:173.50 +15:23:10.948 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:198.69 +15:23:10.948 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:198.69 +15:23:10.995 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:198.69 +15:23:10.995 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:198.69 +15:23:11.042 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:198.69 +15:23:11.042 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:216.32 +15:23:11.089 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:216.32 +15:23:11.089 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:216.32 +15:23:11.136 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:230.78 +15:23:11.136 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:230.78 +15:23:11.183 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:230.78 +15:23:11.183 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:230.78 +15:23:11.229 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:230.78 +15:23:11.229 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:241.08 +15:23:11.276 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:241.08 +15:23:11.276 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:241.08 +15:23:11.276 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:241.08 +15:23:11.323 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:241.08 +15:23:11.323 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:242.37 +15:23:11.370 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:242.37 +15:23:11.370 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:242.37 +15:23:11.417 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:242.37 +15:23:11.417 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:236.14 +15:23:11.464 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:236.14 +15:23:11.464 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:236.14 +15:23:11.511 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:236.14 +15:23:11.511 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:236.14 +15:23:11.511 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:234.84 +15:23:11.558 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:234.84 +15:23:11.558 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:234.84 +15:23:11.604 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:234.84 +15:23:11.604 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:234.84 +15:23:11.651 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:233.93 +15:23:11.651 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:233.93 +15:23:11.698 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:233.93 +15:23:11.698 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:233.93 +15:23:11.698 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:231.45 +15:23:11.745 -> SLMx10:0.00 TidalVol:13.83 Pressurex10:231.45 +15:23:11.745 -> SLMx10:36.68 TidalVol:15.11 Pressurex10:231.45 +15:23:11.792 -> SLMx10:80.97 TidalVol:17.95 Pressurex10:231.45 +15:23:11.792 -> SLMx10:110.84 TidalVol:21.82 Pressurex10:231.45 +15:23:11.839 -> SLMx10:125.20 TidalVol:26.21 Pressurex10:206.98 +15:23:11.839 -> SLMx10:133.99 TidalVol:30.90 Pressurex10:206.98 +15:23:11.886 -> SLMx10:129.94 TidalVol:35.44 Pressurex10:206.98 +15:23:11.886 -> SLMx10:133.23 TidalVol:40.11 Pressurex10:206.98 +15:23:11.886 -> SLMx10:116.72 TidalVol:44.19 Pressurex10:174.21 +15:23:11.933 -> SLMx10:124.71 TidalVol:48.56 Pressurex10:174.21 +15:23:11.933 -> SLMx10:117.91 TidalVol:52.68 Pressurex10:174.21 +15:23:11.979 -> SLMx10:120.32 TidalVol:56.90 Pressurex10:174.21 +15:23:11.979 -> SLMx10:111.54 TidalVol:60.80 Pressurex10:174.21 +15:23:12.026 -> SLMx10:94.34 TidalVol:64.10 Pressurex10:166.82 +15:23:12.026 -> SLMx10:88.04 TidalVol:67.18 Pressurex10:166.82 +15:23:12.073 -> SLMx10:90.95 TidalVol:70.37 Pressurex10:166.82 +15:23:12.073 -> SLMx10:93.70 TidalVol:73.65 Pressurex10:166.82 +15:23:12.120 -> SLMx10:103.54 TidalVol:77.27 Pressurex10:166.82 +15:23:12.120 -> SLMx10:108.30 TidalVol:81.06 Pressurex10:162.15 +15:23:12.120 -> SLMx10:98.89 TidalVol:84.52 Pressurex10:162.15 +15:23:12.167 -> SLMx10:103.54 TidalVol:88.14 Pressurex10:162.15 +15:23:12.167 -> SLMx10:105.79 TidalVol:91.85 Pressurex10:162.15 +15:23:12.214 -> SLMx10:110.38 TidalVol:95.71 Pressurex10:147.83 +15:23:12.214 -> SLMx10:107.39 TidalVol:99.47 Pressurex10:147.83 +15:23:12.261 -> SLMx10:95.85 TidalVol:102.82 Pressurex10:147.83 +15:23:12.261 -> SLMx10:105.34 TidalVol:106.51 Pressurex10:147.83 +15:23:12.308 -> SLMx10:105.57 TidalVol:110.21 Pressurex10:147.83 +15:23:12.308 -> SLMx10:105.57 TidalVol:113.90 Pressurex10:135.06 +15:23:12.308 -> SLMx10:105.12 TidalVol:117.58 Pressurex10:135.06 +15:23:12.354 -> SLMx10:90.33 TidalVol:120.74 Pressurex10:135.06 +15:23:12.354 -> SLMx10:88.66 TidalVol:123.84 Pressurex10:135.06 +15:23:12.401 -> SLMx10:93.49 TidalVol:127.12 Pressurex10:135.06 +15:23:12.401 -> SLMx10:92.85 TidalVol:130.37 Pressurex10:125.45 +15:23:12.448 -> SLMx10:85.99 TidalVol:133.38 Pressurex10:125.45 +15:23:12.448 -> SLMx10:83.56 TidalVol:136.30 Pressurex10:125.45 +15:23:12.495 -> SLMx10:82.96 TidalVol:139.20 Pressurex10:125.45 +15:23:12.495 -> SLMx10:83.56 TidalVol:142.13 Pressurex10:115.58 +15:23:12.495 -> SLMx10:78.61 TidalVol:144.88 Pressurex10:115.58 +15:23:12.542 -> SLMx10:79.20 TidalVol:147.65 Pressurex10:115.58 +15:23:12.542 -> SLMx10:72.32 TidalVol:150.18 Pressurex10:115.58 +15:23:12.589 -> SLMx10:69.55 TidalVol:152.62 Pressurex10:115.58 +15:23:12.589 -> SLMx10:62.77 TidalVol:154.81 Pressurex10:107.87 +15:23:12.636 -> SLMx10:53.27 TidalVol:156.68 Pressurex10:107.87 +15:23:12.636 -> SLMx10:50.29 TidalVol:158.44 Pressurex10:107.87 +15:23:12.683 -> SLMx10:51.69 TidalVol:160.25 Pressurex10:107.87 +15:23:12.683 -> SLMx10:45.60 TidalVol:161.84 Pressurex10:100.52 +15:23:12.729 -> SLMx10:42.42 TidalVol:163.33 Pressurex10:100.52 +15:23:12.729 -> SLMx10:37.08 TidalVol:164.63 Pressurex10:100.52 +15:23:12.729 -> SLMx10:32.60 TidalVol:165.77 Pressurex10:100.52 +15:23:12.776 -> SLMx10:26.84 TidalVol:166.71 Pressurex10:100.52 +15:23:12.776 -> SLMx10:0.00 TidalVol:166.71 Pressurex10:93.42 +15:23:12.823 -> SLMx10:0.00 TidalVol:166.71 Pressurex10:93.42 +15:23:12.823 -> SLMx10:0.00 TidalVol:166.71 Pressurex10:93.42 +15:23:12.870 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:89.08 +15:23:12.917 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:89.08 +15:23:12.917 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:89.08 +15:23:12.964 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:89.08 +15:23:12.964 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:89.08 +15:23:12.964 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:86.54 +15:23:13.011 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:86.54 +15:23:13.011 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:86.54 +15:23:13.058 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:86.54 +15:23:13.058 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:86.54 +15:23:13.104 -> SLMx10:0.00 TidalVol:0.00 Pressurex10:84.14 +15:23:13.104 -> SLMx10:23.50 TidalVol:0.82 Pressurex10:84.14 +15:23:13.151 -> SLMx10:24.87 TidalVol:1.69 Pressurex10:84.14 +15:23:13.151 -> SLMx10:25.41 TidalVol:2.58 Pressurex10:84.14 +15:23:13.151 -> SLMx10:28.77 TidalVol:3.59 Pressurex10:82.03 +15:23:13.198 -> SLMx10:33.72 TidalVol:4.77 Pressurex10:82.03 +15:23:13.198 -> SLMx10:33.22 TidalVol:5.93 Pressurex10:82.03 +15:23:13.245 -> SLMx10:34.10 TidalVol:7.13 Pressurex10:82.03 +15:23:13.245 -> SLMx10:36.29 TidalVol:8.40 Pressurex10:82.03 +15:23:13.292 -> SLMx10:37.21 TidalVol:9.70 Pressurex10:80.91 +15:23:13.292 -> SLMx10:44.29 TidalVol:11.25 Pressurex10:80.91 +15:23:13.339 -> SLMx10:38.68 TidalVol:12.60 Pressurex10:80.91 +15:23:13.339 -> SLMx10:0.00 TidalVol:12.60 Pressurex10:80.91 +15:23:13.339 -> SLMx10:24.02 TidalVol:13.44 Pressurex10:80.91 +15:23:13.386 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:78.96 +15:23:13.386 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:78.96 +15:23:13.433 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:78.96 +15:23:13.433 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:78.96 +15:23:13.479 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.34 +15:23:13.479 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.34 +15:23:13.526 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.34 +15:23:13.526 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.34 +15:23:13.573 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.34 +15:23:13.573 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:76.98 +15:23:13.573 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:76.98 +15:23:13.620 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:76.98 +15:23:13.620 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:76.98 +15:23:13.667 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.35 +15:23:13.667 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.35 +15:23:13.714 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.35 +15:23:13.714 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.35 +15:23:13.761 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.35 +15:23:13.761 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.62 +15:23:13.761 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.62 +15:23:13.808 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.62 +15:23:13.808 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.62 +15:23:13.854 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.62 +15:23:13.854 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.89 +15:23:13.901 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.89 +15:23:13.901 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.89 +15:23:13.948 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:77.89 +15:23:13.948 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:78.65 +15:23:13.948 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:78.65 +15:23:13.995 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:78.65 +15:23:13.995 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:78.65 +15:23:14.042 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:78.65 +15:23:14.042 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:79.28 +15:23:14.089 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:79.28 +15:23:14.089 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:79.28 +15:23:14.136 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:79.28 +15:23:14.136 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:79.28 +15:23:14.183 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:79.68 +15:23:14.183 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:79.68 +15:23:14.183 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:79.68 +15:23:14.229 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:79.68 +15:23:14.229 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:80.53 +15:23:14.276 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:80.53 +15:23:14.276 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:80.53 +15:23:14.323 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:80.53 +15:23:14.323 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:80.53 +15:23:14.370 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:81.24 +15:23:14.370 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:81.24 +15:23:14.370 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:81.24 +15:23:14.417 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:81.24 +15:23:14.417 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.31 +15:23:14.464 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.31 +15:23:14.464 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.31 +15:23:14.511 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.31 +15:23:14.511 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.31 +15:23:14.558 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.77 +15:23:14.558 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.77 +15:23:14.558 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.77 +15:23:14.605 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.77 +15:23:14.605 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:82.77 +15:23:14.652 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:83.66 +15:23:14.652 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:83.66 +15:23:14.699 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:83.66 +15:23:14.699 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:83.66 +15:23:14.746 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:84.74 +15:23:14.746 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:84.74 +15:23:14.793 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:84.74 +15:23:14.793 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:84.74 +15:23:14.793 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:84.74 +15:23:14.840 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:85.38 +15:23:14.840 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:85.38 +15:23:14.887 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:85.38 +15:23:14.887 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:85.38 +15:23:14.933 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:85.38 +15:23:14.933 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:85.81 +15:23:14.980 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:85.81 +15:23:14.980 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:85.81 +15:23:14.980 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:85.81 +15:23:15.027 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:86.59 +15:23:15.027 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:86.59 +15:23:15.074 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:86.59 +15:23:15.074 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:86.59 +15:23:15.121 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:86.59 +15:23:15.121 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:87.05 +15:23:15.168 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:87.05 +15:23:15.168 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:87.05 +15:23:15.168 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:87.05 +15:23:15.215 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:87.73 +15:23:15.215 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:87.73 +15:23:15.262 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:87.73 +15:23:15.262 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:87.73 +15:23:15.308 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:87.73 +15:23:15.308 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:88.34 +15:23:15.355 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:88.34 +15:23:15.355 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:88.34 +15:23:15.355 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:88.34 +15:23:15.402 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:88.34 +15:23:15.402 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:89.17 +15:23:15.449 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:89.17 +15:23:15.449 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:89.17 +15:23:15.496 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:89.17 +15:23:15.496 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:89.43 +15:23:15.543 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:89.43 +15:23:15.543 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:89.43 +15:23:15.590 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:89.43 +15:23:15.590 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:89.43 +15:23:15.590 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:90.00 +15:23:15.637 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:90.00 +15:23:15.637 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:90.00 +15:23:15.683 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:90.00 +15:23:15.683 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:90.00 +15:23:15.731 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:108.28 +15:23:15.731 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:108.28 +15:23:15.778 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:108.28 +15:23:15.778 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:108.28 +15:23:15.778 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:153.91 +15:23:15.825 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:153.91 +15:23:15.825 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:153.91 +15:23:15.872 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:153.91 +15:23:15.872 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:153.91 +15:23:15.919 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:185.73 +15:23:15.919 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:185.73 +15:23:15.965 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:185.73 +15:23:15.965 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:185.73 +15:23:15.965 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:207.11 +15:23:16.013 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:207.11 +15:23:16.013 -> SLMx10:0.00 TidalVol:13.44 Pressurex10:207.11 diff --git a/Tests/__init__.py b/Tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Tests/test_causal_integral_filter.py b/Tests/test_causal_integral_filter.py new file mode 100644 index 0000000..4077c7e --- /dev/null +++ b/Tests/test_causal_integral_filter.py @@ -0,0 +1,72 @@ +import unittest + +import numpy as np + +from causal_integral_filter import CausalIntegralFilter + + +class TestCausalIntegralFilter(unittest.TestCase): + + def test_constant_zero_data(self): + dt = 0.01 + t = np.arange(0, 2, dt) + to_process_data = 0*t + desired_processed_data = 0*t + processed_data = np.array([desired_processed_data[0]]) + + filter = CausalIntegralFilter(processed_data[0], t[0]) + for i in range(1, len(t)): + filter.append(to_process_data[i], t[i]) + processed_data = np.append(processed_data, filter.get_datum()) + rms_error = ( + np.sqrt(np.mean((desired_processed_data-processed_data)**2))) + self.assertLess(rms_error, 0.05, + "Fails to integrate a constant 0 signal to 0.") + + def test_constant_one_data(self): + dt = 0.01 + t = np.arange(0, 2, dt) + to_process_data = 0*t + 1 + desired_processed_data = t + 1 + processed_data = np.array([desired_processed_data[0]]) + + filter = CausalIntegralFilter(processed_data[0], t[0]) + for i in range(1, len(t)): + filter.append(to_process_data[i], t[i]) + processed_data = np.append(processed_data, filter.get_datum()) + rms_error = ( + np.sqrt(np.mean((desired_processed_data-processed_data)**2))) + self.assertLess(rms_error, 0.05, + "Fails to integrate a constant 1 signal to t+1.") + + def test_linear_data(self): + dt = 0.01 + t = np.arange(0, 2, dt) + to_process_data = t + desired_processed_data = 0.5*t**2 + processed_data = np.array([desired_processed_data[0]]) + + filter = CausalIntegralFilter(processed_data[0], t[0]) + for i in range(1, len(t)): + filter.append(to_process_data[i], t[i]) + processed_data = np.append(processed_data, filter.get_datum()) + rms_error = ( + np.sqrt(np.mean((desired_processed_data-processed_data)**2))) + self.assertLess(rms_error, 0.05, + "Fails to integrate a t signal to 1/2 t^2.") + + def test_sine_data(self): + dt = 0.01 + t = np.arange(0, 2, dt) + to_process_data = np.sin(t) + desired_processed_data = -np.cos(t) + processed_data = np.array([desired_processed_data[0]]) + + filter = CausalIntegralFilter(processed_data[0], t[0]) + for i in range(1, len(t)): + filter.append(to_process_data[i], t[i]) + processed_data = np.append(processed_data, filter.get_datum()) + rms_error = ( + np.sqrt(np.mean((desired_processed_data-processed_data)**2))) + self.assertLess(rms_error, 0.05, + "Fails to integrate a Sin[t] signal to -Cos[t].") diff --git a/Tests/test_causalvelocityfilter.py b/Tests/test_causalvelocityfilter.py new file mode 100644 index 0000000..b07de79 --- /dev/null +++ b/Tests/test_causalvelocityfilter.py @@ -0,0 +1,56 @@ +import math +import numpy as np +import unittest +import matplotlib.pyplot as plt + +from causal_velocity_filter import CausalVelocityFilter + + +class TestCausalVelocityFilter(unittest.TestCase): + + def testInit_nominal(self): + + velocity_filter = CausalVelocityFilter(100) + self.assertIsNotNone(filter, + "Fails to initialize a velocity filter") + + def test_differentiates(self): + + dt = 0.001 + t = np.arange(0, 10, dt) + velocity_filter = CausalVelocityFilter(100) + to_filter_data = np.sin(t) + filtered_data = np.array([]) + desired_filtered_data = np.cos(t) + error = np.array([]) + for i in range(len(to_filter_data)): + velocity_filter.append(to_filter_data[i], dt) + filtered_data = np.append( + filtered_data, velocity_filter.get_datum()) + error = np.append( + error, desired_filtered_data[i] - filtered_data[i]) + rms_error = np.sqrt(np.mean(error**2)) + self.assertLess(rms_error, 0.1, + "Fails to differentiate a data series " + + "approximating sin(x) within <0.1 rms error") + + def test_rejectsHighFrequency(self): + + dt = 0.001 + t = np.arange(0, 10, dt) + velocity_filter = CausalVelocityFilter(70) + to_filter_data = np.sin(t) + 0.001*np.sin(100*t) + filtered_data = np.array([]) + desired_filtered_data = np.cos(np.arange(0, 10, dt)) + error = np.array([]) + for i in range(len(to_filter_data)): + velocity_filter.append(to_filter_data[i], dt) + filtered_data = np.append( + filtered_data, velocity_filter.get_datum()) + error = np.append( + error, desired_filtered_data[i] - filtered_data[i]) + rms_error = np.sqrt(np.mean([err**2 for err in error])) + self.assertLess(rms_error, 0.05, + "Fails to differentiate a data series while " + + "rejecting high-frequency noise within " + + "<0.01 rms error") diff --git a/Tests/test_discretetransferfunction.py b/Tests/test_discretetransferfunction.py new file mode 100644 index 0000000..d925444 --- /dev/null +++ b/Tests/test_discretetransferfunction.py @@ -0,0 +1,167 @@ +import unittest +import math + +from discrete_transfer_function import DiscreteTransferFunction + + +class TestDiscreteTransferFunction(unittest.TestCase): + + def testInit_nominal(self): + tf = DiscreteTransferFunction([1], [1]) + self.assertIsNotNone(tf, + "Fails to initialize a discrete " + "transfer function") + + def testInit_divideByZero(self): + with self.assertRaises(ZeroDivisionError, + msg="Fails to raise an exception when the " + "denominator equals zero."): + DiscreteTransferFunction([1], [0]) + + def testInit_divideByZeroMany(self): + with self.assertRaises(ZeroDivisionError, + msg="Fails to raise an exception when the " + "denominator equals zero."): + DiscreteTransferFunction([1], [0] * 50) + + def testAppend_nominal(self): + tf = DiscreteTransferFunction([1, 1], [1]) + tf.append(0) + self.assertTrue(tf.is_full, + "Fails to append a datum to the transfer " + "function's buffer") + + def testAppend_manyData(self): + tf = DiscreteTransferFunction([1, 1, 1, 1, 1], [1]) + tf.append(0) + tf.append(1) + tf.append(2) + tf.append(3) + tf.append(4) + self.assertTrue(tf.is_full, + "Fails to append many data to the transfer " + "function") + + def testGetDatum_nominal(self): + tf = DiscreteTransferFunction([1], [1]) + tf.append(0) + self.assertAlmostEqual(tf.get_datum(), 1, + msg="Fails to give the quotient of the " + "constant terms when the " + "numerator and denominator are " + "both length 1") + + def testGetDatum_firstOrderTerm(self): + tf = DiscreteTransferFunction([1, 1], [1]) + tf.append(1) + self.assertAlmostEqual(tf.get_datum(), 2, + msg="Fails to add a first order term " + "in the numerator") + + def testGetDatum_secondOrderTerm(self): + tf = DiscreteTransferFunction([1, 1, 1], [1]) + tf.append(1) + tf.append(1) + self.assertAlmostEqual(tf.get_datum(), 3, + msg="Fails to add a second order term " + "in the numerator") + + def testGetDatum_underFilledBuffer(self): + tf = DiscreteTransferFunction(list(reversed(range(10))), [1]) + tf.append(1) + tf.append(2) + self.assertAlmostEqual(tf.get_datum(), 4, + msg="Fails to return data using only " + "the lowest order coefficients") + + def testGetDatum_fibonacci(self): + tf = DiscreteTransferFunction([1, 1, 0], [1]) + fibonacciNumbers = [1, 1] + tf.append(1) + tf.append(1) + + for _ in range(4): + fibonacciNumbers.append(tf.get_datum()) + tf.append(tf.get_datum()) + + desiredList = [1, 1, 2, 3, 5, 8] + self.assertTrue(all(math.isclose(actual, desired) + for (actual, desired) in + zip(fibonacciNumbers, + desiredList)), + "Fails to generate a sequence of numbers " + "with the numerator having non-constant " + "terms\n" + " " + str(desiredList) + "\n" + "!= " + str(fibonacciNumbers)) + + def testGetDatum_inverseFibonacci(self): + """invereFibonacci(n) = + 1 / (inverseFibonacci(n-1) + inverseFibonacci(n-2)) + """ + + tf = DiscreteTransferFunction([1], [1, 1, 0]) + inverseFibonacciNumbers = [1, 1] + tf.append(1) + tf.append(1) + + for _ in range(4): + inverseFibonacciNumbers.append(tf.get_datum()) + tf.append(tf.get_datum()) + + desiredList = [1, 1, 1/2, 2/3, 6/7, 21/32] + self.assertTrue(all(math.isclose(actual, desired) + for (actual, desired) in + zip(inverseFibonacciNumbers, + desiredList)), + "Fails to generate a sequence of numbers with " + "the denominator having non-constant terms\n" + " " + str(desiredList) + "\n" + "!= " + str(inverseFibonacciNumbers)) + + def testGetDatum_regularAndInverseFibonacci(self): + tf = DiscreteTransferFunction([1, 1, 0], [1, 1, 0]) + regularAndInverseFibonacciNumbers = [1, 1] + tf.append(1) + tf.append(1) + + for _ in range(4): + regularAndInverseFibonacciNumbers.append(tf.get_datum()) + tf.append(tf.get_datum()) + + desiredList = [1, 1, 1, 1, 1, 1] + self.assertTrue(all(math.isclose(actual, desired) + for (actual, desired) in + zip(regularAndInverseFibonacciNumbers, + desiredList)), + "Fails to generate a sequence of numbers with " + "the numerator and denominator having " + "non-constant terms\n" + " " + str(desiredList) + "\n" + "!= " + str(regularAndInverseFibonacciNumbers)) + + def testStr_nominal(self): + tf = DiscreteTransferFunction([1, -1], [1, -1.85, 0.9]) + self.assertEqual(str(tf), " z - 1\n" + "-------------------\n" + " z^2 - 1.85 z + 0.9", + "Fails to represent a transfer function as a " + "pretty string.") + + def testStr_leadingCoefficientOtherThanOne(self): + tf = DiscreteTransferFunction([2, -2], [1, -0.8]) + self.assertEqual(str(tf), "2 z - 2\n" + "--------\n" + " z - 0.8", + "Fails to properly format a transfer function " + "that has a leading coefficient other than " + "one") + + def testStr_leadingCoefficientsAreConstantTermsAndOne(self): + tf = DiscreteTransferFunction([1], [1]) + self.assertEqual(str(tf), "1\n" + "-\n" + "1", + "Fails to properly format a transfer function " + "where the leading term is both constant " + "and the coefficient is equal to 1") diff --git a/Tests/test_i2c_interface.py b/Tests/test_i2c_interface.py new file mode 100644 index 0000000..5574d48 --- /dev/null +++ b/Tests/test_i2c_interface.py @@ -0,0 +1,47 @@ +import unittest +import warnings + +from i2c_interface import I2CInterface, DeviceNotFoundError +from rpi_check import is_on_raspberry_pi + + +class TestI2CInterface(unittest.TestCase): + + def setUp(self): + warnings.filterwarnings("ignore", + message="I2C communication", + category=UserWarning) + self._i2c = I2CInterface(0x70) + + def tearDown(self): + self._i2c.close() + + def test_warn_when_i2c_isnt_available(self): + if not is_on_raspberry_pi(): + self._i2c.close() + with self.assertWarns(UserWarning, + msg="Fails to warn the user when I2C " + "communication isn't available."): + self._i2c = I2CInterface(0x70) + + def test_read_returns_a_byte(self): + self.assertTrue(0 <= self._i2c.read_register(0x00) < 256, + "Fails to return a byte when a register is " + "read") + + def test_read_returns_several_bytes(self): + self.assertEqual(len(self._i2c.read_register(0x00, + number_of_bytes=3)), + 3, + "Fails to read several bytes from a single " + "read.") + + def test_read_fewer_than_one_byte(self): + with self.assertRaises(ValueError, + msg="Fails to raise a ValueError when " + "fewer than 1 byte is requested."): + self._i2c.read_register(0x00, 0) + + def test_read_from_bus(self): + self.assertTrue(0 <= self._i2c.read_data() < 256, + "Fails to return a byte when the bus is read") diff --git a/Tests/test_moving_average_filter.py b/Tests/test_moving_average_filter.py new file mode 100644 index 0000000..a73f630 --- /dev/null +++ b/Tests/test_moving_average_filter.py @@ -0,0 +1,49 @@ +import unittest + +from moving_average_filter import MovingAverageFilter + + +class TestMovingAverageFilter(unittest.TestCase): + + def setUp(self): + self._buffer_size = 4 + self._filter = MovingAverageFilter(self._buffer_size) + + def test_get_datum_constant_series(self): + for _ in range(self._buffer_size): + self._filter.append(1.0) + + self.assertAlmostEqual(self._filter.get_datum(), 1.0, + msg="Fails to calculate the mean of a " + "constant series.") + + def test_get_datum_increasing_series(self): + for i in range(self._buffer_size): + self._filter.append(i) + + self.assertAlmostEqual(self._filter.get_datum(), 1.5, + msg="Fails to calculate the mean of a " + "constant series.") + + def test_get_datum_empty_buffer(self): + self.assertAlmostEqual(self._filter.get_datum(), 0.0, + msg="Fails to return a default value for an " + "empty buffer.") + + def test_get_datum_party_full_buffer(self): + self._filter.append(4) + + self.assertAlmostEqual(self._filter.get_datum(), 1.0, + msg="Fails to pad the buffer with zeros " + "when it's only partly filled with data.") + + def test_illgally_sized_buffer(self): + with self.assertRaises(ValueError, + msg="Fails to raise an error when the " + "buffer size is set to 0."): + MovingAverageFilter(0) + + with self.assertRaises(ValueError, + msg="Fails to raise an error when the " + "buffer size is set to negative."): + MovingAverageFilter(-1) diff --git a/Tests/test_patienttubingdescriptorcalculator.py b/Tests/test_patienttubingdescriptorcalculator.py new file mode 100644 index 0000000..619988e --- /dev/null +++ b/Tests/test_patienttubingdescriptorcalculator.py @@ -0,0 +1,30 @@ +import unittest + +import numpy as np + +from patienttubingdescriptorcalculator \ + import PatientTubingDescriptorCalculator + + +class TestPatientTubingDescriptorCalculator(unittest.TestCase): + + def setUp(self): + self._calculator = PatientTubingDescriptorCalculator(0) + + def test_calculates_tidal_volume(self): + dt = 0.01 + t = np.arange(0, 2, dt) + to_process_data = np.sin(t) + desired_processed_data = -np.cos(t) + processed_data = np.array([desired_processed_data[0]]) + + self._calculator.add_tidal_volume_value(processed_data[0]) + for i in range(1, len(t)): + self._calculator.add_flow_rate_datum(to_process_data[i], t[i]) + processed_data = np.append( + processed_data, self._calculator.descriptors["Tidal Volume"]) + rms_error = ( + np.sqrt(np.mean((desired_processed_data-processed_data)**2))) + self.assertLess(rms_error, 0.05, + "Fails to integrate a Sin[t] flow rate to " + "-Cos[t] tidal volume.") diff --git a/Tests/test_sensors.py b/Tests/test_sensors.py new file mode 100644 index 0000000..e978aba --- /dev/null +++ b/Tests/test_sensors.py @@ -0,0 +1,35 @@ +import unittest +import time + +from sensors import Sensors +import constants + + +class TestSensors(unittest.TestCase): + + def setUp(self): + self._start_time = time.time() + self._sensors = Sensors() + + def tearDown(self): + self._sensors.close() + + def test_all_tubes_have_enough_sensors(self): + tubes = self._sensors.tubes_with_enough_sensors() + for i in range(constants.NUMBER_OF_PATIENTS): + with self.subTest(i=i): + self.assertIn(i, tubes, + f"Port {i} is missing sensors.") + + def test_calibration_pressure_sensor_present(self): + self.assertTrue(self._sensors.calibration_pressure_sensor_connected(), + "Calibration pressure sensor is missing.") + + def test_poll_and_connected_sensors_are_same_shape(self): + connected_sensors = self._sensors.connected_sensors() + sensor_data = self._sensors.poll() + for i in range(len(connected_sensors)): + with self.subTest(i=i): + self.assertEqual(len(connected_sensors[i]), + len(sensor_data[i]), + f"Contradicting shapes on port {i}.") diff --git a/Tests/test_server.py b/Tests/test_server.py new file mode 100644 index 0000000..50b654b --- /dev/null +++ b/Tests/test_server.py @@ -0,0 +1,23 @@ +import unittest + +from sensors import Sensors +import server + + +class TestServer(unittest.TestCase): + + def testPollSensors_nominal(self): + sensors = Sensors() + data = sensors.poll() + self.assertTrue(len(data[0]) == 2, + "Fails to generate exactly 1 pressure datum " + "and 1 flow rate datum for a patient.") + + def testCalculator_adds_and_gets_data(self): + sensors = Sensors() + data = sensors.poll() + calculator = server.Calculator() + calculator.add_datum(data) + self.assertIn("PEEP", calculator.get_datum()[0], + "Fails to add data to and then get data from " + "the calculator.") diff --git a/Tests/test_sfm3300d.py b/Tests/test_sfm3300d.py new file mode 100644 index 0000000..b13084a --- /dev/null +++ b/Tests/test_sfm3300d.py @@ -0,0 +1,123 @@ +import unittest +import math + +from sfm3300d import FlowSensor, Calibrator, Communicator, CRCError +from tca9548a import I2CMux +from rpi_check import is_on_raspberry_pi +import constants +from i2c_interface import I2CInterface + + +class TestFlowSensor(unittest.TestCase): + + def setUp(self): + self._mux = I2CMux(constants.FLOW_SENSOR_MUX_ADDRESS) + self._mux.select_channel(2) + self._sensor = FlowSensor() + + def tearDown(self): + self._sensor.close() + self._mux.close() + + def test_serial_number(self): + serial_number = self._sensor.serial_number() + self.assertTrue(0 <= serial_number < 2**32, + f"{serial_number} is not an unsigned 32-bit " + "serial number") + + @unittest.skipIf(not is_on_raspberry_pi(), + "Cannot determine ambient flow unless connected " + "to hardware.") + def test_ambient_flow(self): + measured_flow = self._sensor.flow() + self.assertTrue(math.isclose(measured_flow, 0, + abs_tol=1), + f"{measured_flow} != 0 +/- 0.1 slm : " + "Fails to say that there is no flow in still " + "air.\n" + "Note that if this test is performed in a " + "breezy environment, then the ambient flow may " + "fall ouside the range of this test.") + + +class TestCalibrator(unittest.TestCase): + + def test_zero_one_parameters_and_zero_data(self): + calibrator = Calibrator(0, 1) + self.assertAlmostEqual(calibrator.flow(0), 0.0, + msg="Fails to return 0.0 when measured " + "value and offset flow are zero and " + "scale factor flow is non-zero.") + + def test_zero_scale_factor_flow(self): + with self.assertRaises(ZeroDivisionError, + msg="Fails to raise a ZeroDivisionError " + "when initialized with a scale factor " + "flow equal to 0."): + Calibrator(0, 0) + + def test_one_parameters_and_data(self): + calibrator = Calibrator(1, 1) + self.assertAlmostEqual(calibrator.flow(1), 0.0, + msg="Fails to return 0.0 when measured " + "value, offset flow, and scale factor " + "flow are one.") + + def test_one_parameters_and_large_data(self): + calibrator = Calibrator(1, 1) + self.assertAlmostEqual(calibrator.flow(10), 9.0, + msg="Fails to return the correct value " + "when the result is non-zero.") + + def test_actual_data(self): + calibrator = Calibrator(32768, 120) + self.assertAlmostEqual(calibrator.flow(32780), 0.1, + msg="Fails to return a reasonable value " + "given actual data the sensor could " + "return.") + + +class TestCommunicator(unittest.TestCase): + + def setUp(self): + self._mux = I2CMux(constants.FLOW_SENSOR_MUX_ADDRESS) + self._mux.select_channel(2) + self._communicator = Communicator() + + def tearDown(self): + self._communicator.close() + self._mux.close() + + def test_is_present(self): + self.assertTrue(self._communicator.is_present(), + "Sensor is not useable at the moment.") + + def test_serial_number(self): + serial_number = self._communicator.serial_number() + self.assertTrue(0 <= serial_number < 2**32, + f"{serial_number:#x} is not an unsigned 32-bit " + "serial number.") + + @unittest.skipIf(not is_on_raspberry_pi(), + "Signal isn't 2 bytes + CRC8 unless connected " + "to hardware.") + def test_raw_flow(self): + self._communicator.init_flow() + raw_flow = self._communicator.raw_flow() + self.assertTrue(0 <= raw_flow < 2**16, + f"{raw_flow:#x} is not an unsigned 16-bit flow " + "number.") + + # @unittest.skipIf(is_on_raspberry_pi(), + # "The signal cannot be automatically be made to " + # "fail on hardware.") + # def test_raises_CRCError(self): + # """I'm not sure how to make this test fail. It definitely fails + # when not on a Pi, but on the Pi it's at the mercy of whether + # there's actually a bad signal. + # """ + # self._communicator.init_flow() + # with self.assertRaises(CRCError, + # msg="Fails to raise an error when invalid " + # "data is received."): + # self._communicator.raw_flow() diff --git a/Tests/test_spl06_007.py b/Tests/test_spl06_007.py new file mode 100644 index 0000000..92a35b6 --- /dev/null +++ b/Tests/test_spl06_007.py @@ -0,0 +1,391 @@ +import unittest +import math +import warnings + +from spl06_007 import (PressureSensor, + Communicator, + Calibrator, + SensorConstants) +from i2c_interface import I2CInterface +from tca9548a import I2CMux +from rpi_check import is_on_raspberry_pi +import constants + + +class TestPressureSensor(unittest.TestCase): + + def setUp(self): + self._mux = I2CMux(constants.PRESSURE_SENSOR_MUX_ADDRESS) + self._mux.select_channel(0) + self._sensor = PressureSensor() + + def tearDown(self): + self._sensor.close() + self._mux.close() + + @unittest.skipIf(not is_on_raspberry_pi(), + "Pressure sensor won't be present unless you're on " + "hardware.") + def test_is_present(self): + self.assertTrue(self._sensor.is_present(), + "Fails to identify that the sensor is present.\n" + "Note that if the sensor is not connected, this " + "test will fail.") + + @unittest.skipIf(is_on_raspberry_pi(), + "This can only be tested non-interactively off of " + "hardware.") + def test_not_is_present(self): + self.assertTrue(not self._sensor.is_present(), + "Fails to correctly identify that a sensor is not " + "present.") + + def test_set_op_mode_standby(self): + self.assertEqual( + self._sensor.set_op_mode(PressureSensor.OpMode.standby), + PressureSensor.OpMode.standby, + "Fails to put the sensor into Standby Mode.") + + def test_set_op_mode_background(self): + self.assertEqual( + self._sensor.set_op_mode(PressureSensor.OpMode.background), + PressureSensor.OpMode.background, + "Fails to put the sensor into Background Mode") + + def test_set_op_mode_command(self): + self.assertEqual( + self._sensor.set_op_mode(PressureSensor.OpMode.command), + PressureSensor.OpMode.command, + "Fails to put the sensor into Command Mode.") + + def test_set_sampling_default(self): + self.assertTrue(self._sensor.set_sampling(), + "Fails to successfully set the oversample and " + "sampling rate to default values for temerature " + "and pressure.") + + def test_set_sampling_valid_values(self): + self.assertTrue( + self._sensor.set_sampling(pressure_oversample=1, + pressure_sampling_rate=1, + temperature_oversample=1, + temperature_sampling_rate=1), + "Fails to set the oversample and sampling rate " + "to valid custom values for temperature and " + "pressure") + + def test_set_sampling_invalid_values(self): + with self.assertRaises(ValueError, + msg="Fails to raise a ValueError when " + "oversample or temperature values are not " + "in the set {1, 2, 4, 8, 16, 32, 64, 128}."): + self._sensor.set_sampling(pressure_oversample=3, + pressure_sampling_rate=3, + temperature_oversample=3, + temperature_sampling_rate=3) + + def test_pressure_without_sampling_set(self): + self.assertTrue(math.isnan(self._sensor.pressure()), + "Fails to return NaN for pressure when the user " + "has not yet set the sampling parameters.") + self.assertTrue(math.isnan(self._sensor.temperature()), + "Fails to return NaN for temperature when the " + "user has not yet set the sampling parameters.") + + @unittest.skipIf(not is_on_raspberry_pi(), + "Cannot determine ambient temperature unless " + "connected to hardware.") + def test_ambient_temperature(self): + self._sensor.set_op_mode(PressureSensor.OpMode.command) + self._sensor.set_sampling(temperature_sampling_rate=8) + measured_temperature = self._sensor.temperature() + standard_temperature = 20 # degC + self.assertTrue(math.isclose(measured_temperature, + standard_temperature, + rel_tol=0.50), + f"{measured_temperature} != " + "20 +/- 50% degC :\n" + "Fails to return ambient temperature in " + "degC.\nNote that if this test is " + "performed in a very cold or hot " + "environment, the\nambient temperature " + "may fall outside the range of this test.") + + @unittest.skipIf(not is_on_raspberry_pi(), + "Cannot determine ambient pressure unless " + "connected to hardware.") + def test_ambient_pressure(self): + self._sensor.set_sampling() + self._sensor.set_op_mode(PressureSensor.OpMode.command) + measured_pressure = self._sensor.pressure() + standard_pressure = 101325 # Pa + self.assertTrue(math.isclose(measured_pressure, standard_pressure, + rel_tol=0.10), + f"{measured_pressure} != " + "101.25 +/- 10% Pa :\n" + "Fails to return ambient pressure in Pa.\n" + "Note that if this test is performed in a " + "very low pressure environment,\nthe ambient " + "pressure may fall outside the range of this " + "test.") + + +class TestCalibrator(unittest.TestCase): + + def setUp(self): + # an example of calibration coefficients gotten from the hardware + self._hardware_calibration_coefficients = ( + 199, -249, + 12179, 14472, -2172, 1284, -7681, -33, -823) + + def test_zero_coefficients_and_data(self): + calibrator = Calibrator((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + 1, + 1) + self.assertAlmostEqual(calibrator.pressure(0, 0), 0.0, + msg="Fails to return 0 pressure when all " + "coefficients and data equal 0.") + self.assertAlmostEqual(calibrator.temperature(0), 0.0, + msg="Fails to return 0 temperature when " + "all coefficient and data equal 0.") + + def test_zero_coefficients_and_non_zero_data(self): + calibrator = Calibrator((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + 1, + 1) + self.assertAlmostEqual(calibrator.pressure(10, 10), 0.0, + msg="Fails to return 0 pressure when all " + "coefficients equal 0.") + self.assertAlmostEqual(calibrator.temperature(10), 0.0, + msg="Fails to return 0 temperature when " + "all coefficient equal 0.") + + def test_one_coefficients_and_data(self): + calibrator = Calibrator((1, 1, 1, 1, 1, 1, 1, 1, 1), + 1, + 1) + self.assertAlmostEqual(calibrator.pressure(1, 1), 7.0, + msg="Fails to return 7.0 pressure when " + "all coefficients and data equal 1.0.") + self.assertAlmostEqual(calibrator.temperature(1), 1.5, + msg="Fails to return 1.5 temperature " + "when all coefficients and data equal 1.0.") + + def test_one_coefficients_and_zero_data(self): + calibrator = Calibrator((1, 1, 1, 1, 1, 1, 1, 1, 1), + 1, + 1) + self.assertAlmostEqual(calibrator.pressure(0, 0), 1.0, + msg="Fails to return 1.0 pressure when " + "all coefficients equal 1.0 and data " + "equals 0.") + self.assertAlmostEqual(calibrator.temperature(0), 0.5, + msg="Fails to return 1.5 temperature " + "when all coefficients equal 1.0 and " + "data equals 0.") + + def test_zero_scaling_factor_raises_exception(self): + with self.assertRaises(ZeroDivisionError, + msg="Fails to raise a ZeroDivisionError " + "when initialized with a scaling factor " + "equal to 0."): + calibrator = Calibrator((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + 0, + 0) + + def test_returns_standard_pressure_given_actual_data(self): + calibrator = Calibrator(self._hardware_calibration_coefficients, + 253952, + 524288) + # Raw pressure and temperature found by solving the compensating + # equation for raw pressure and temperature given the hardware + # calibration coefficients. + # This is true for this and the following few tests. + self.assertAlmostEqual(calibrator.pressure(-2968390, 167393), 101000, + places=-1, + msg="Fails to return sea level pressure given " + "data that matches that.") + + def test_returns_1_5_atm_pressure_given_actual_data(self): + calibrator = Calibrator(self._hardware_calibration_coefficients, + 253952, + 524288) + self.assertAlmostEqual(calibrator.pressure(-3053970, 167393), 151500, + places=-1, + msg="Fails to return 1.5 atm pressure given " + "data that matches that.") + + def test_returns_2_atm_pressure_given_actual_data(self): + calibrator = Calibrator(self._hardware_calibration_coefficients, + 253952, + 524288) + self.assertAlmostEqual(calibrator.pressure(-3132150, 167393), 202000, + places=-1, + msg="Fails to return 2 atm pressure given " + "data that matches that.") + + def test_returns_3_atm_pressure_given_actual_data(self): + calibrator = Calibrator(self._hardware_calibration_coefficients, + 253952, + 524288) + self.assertAlmostEqual(calibrator.pressure(-3274260, 209505), 303000, + places=-1, + msg="Fails to return 3 atm pressure given " + "data that matches that.") + + def test_return_standard_temperature_given_actual_data(self): + calibrator = Calibrator(self._hardware_calibration_coefficients, + 253952, + 524288) + self.assertAlmostEqual(calibrator.temperature(167393), 20, + places=-1, + msg="Fails to return 20degC given data that " + "matches that.") + + def test_return_freezing_given_actual_data(self): + calibrator = Calibrator(self._hardware_calibration_coefficients, + 253952, + 524288) + self.assertAlmostEqual(calibrator.temperature(209505), 0, + places=-1, + msg="Fails to return 0degC given data that " + "matches that.") + + +class TestCommunicator(unittest.TestCase): + + def setUp(self): + # A bug in adafruit_platformdetect causes resource warnings + # to come up in unittest, so the warnings must be filtered out + # https://github.com/adafruit/Adafruit_Python_PlatformDetect/issues/89 + warnings.filterwarnings("ignore", + message="unclosed file", + category=ResourceWarning) + self._mux = I2CMux(constants.PRESSURE_SENSOR_MUX_ADDRESS) + self._mux.select_channel(0) + self._communicator = Communicator() + + def tearDown(self): + self._communicator.close() + self._mux.close() + + def test_set_op_mode_standby(self): + self.assertEqual( + self._communicator.set_op_mode(PressureSensor.OpMode.standby), + PressureSensor.OpMode.standby, + "Fails to successfully set the SPL006-007 into standy mode" + ) + + def test_set_op_mode_background(self): + self.assertEqual( + self._communicator.set_op_mode(PressureSensor.OpMode.background), + PressureSensor.OpMode.background, + "Fails to successfully set the SPL006-007 into background mode" + ) + + def test_set_op_mode_command(self): + self.assertEqual( + self._communicator.set_op_mode(PressureSensor.OpMode.command), + PressureSensor.OpMode.command, + "Fails to successfully set the SPL006-007 into command mode.") + + def test_set_op_mode_undefined(self): + with self.assertWarns(RuntimeWarning, + msg="Fails to raise a warning when an " + "undefined op mode is set."): + self._communicator.set_op_mode("Undefined Op Mode") + + def test_calibration_coefficients(self): + self.assertEqual(len(self._communicator.calibration_coefficients), 9, + "Fails to generate a list of 9 coefficients.") + for coefficient in self._communicator.calibration_coefficients: + self.assertIsInstance(coefficient, int, + "Fails to generate a list of integer " + "coefficients.") + + def test_set_pressure_sampling_sets_scale_factor(self): + self._communicator.set_pressure_sampling(oversample=16, + rate=1) + self.assertEqual(self._communicator.pressure_scale_factor, + SensorConstants.COMPENSATION_SCALE_FACTORS[16], + "Fails to get the correct pressure scaling " + "factor of 253952 for oversampling=16.") + + def test_set_pressure_sampling_invalid_oversample(self): + with self.assertRaises(ValueError, + msg="Fails to raise a ValueError when " + "pressure oversample is not in the set " + "{1, 2, 4, 8, 16, 32, 64, 128}."): + self._communicator.set_pressure_sampling(oversample=3) + + def test_set_pressure_sampling_invalid_rate(self): + with self.assertRaises(ValueError, + msg="Fails to raise a ValueError when " + "pressure sampling rate is not in the set " + "{1, 2, 4, 8, 16, 32, 64, 128}."): + self._communicator.set_pressure_sampling(rate=3) + + def test_set_temperature_sampling_sets_scale_factor(self): + self._communicator.set_temperature_sampling(oversample=1, + rate=1) + self.assertEqual(self._communicator.temperature_scale_factor, + SensorConstants.COMPENSATION_SCALE_FACTORS[1], + "Fails to get the correct temperature scaling " + "factor of 524288 for oversampling=16.") + + def test_set_op_mode_undefined(self): + with self.assertWarns(RuntimeWarning, + msg="Fails to raise a warning when an " + "undefined op mode is set."): + self._communicator.set_op_mode("Undefined Op Mode") + + def test_calibration_coefficients(self): + self.assertEqual(len(self._communicator.calibration_coefficients), 9, + "Fails to generate a list of 9 coefficients.") + for coefficient in self._communicator.calibration_coefficients: + self.assertIsInstance(coefficient, int, + "Fails to generate a list of integer " + "coefficients.") + + def test_set_pressure_sampling_sets_scale_factor(self): + self._communicator.set_pressure_sampling() + self.assertEqual(self._communicator.pressure_scale_factor, + 253952, + "Fails to get the correct pressure scaling " + "factor of 253952 for oversampling=16.") + + def test_set_pressure_sampling_invalid_oversample(self): + with self.assertRaises(ValueError, + msg="Fails to raise a ValueError when " + "pressure oversample is not in the set " + "{1, 2, 4, 8, 16, 32, 64, 128}."): + self._communicator.set_pressure_sampling(oversample=3) + + def test_set_pressure_sampling_invalid_rate(self): + with self.assertRaises(ValueError, + msg="Fails to raise a ValueError when " + "pressure sampling rate is not in the set " + "{1, 2, 4, 8, 16, 32, 64, 128}."): + self._communicator.set_pressure_sampling(rate=3) + + def test_raw_temperature(self): + self._communicator.set_op_mode(PressureSensor.OpMode.command) + self._communicator.set_temperature_sampling() + raw_temperature = self._communicator.raw_temperature() + self.assertIsInstance( + raw_temperature, + int, + "Fails to return raw temperature as an integer.") + self.assertTrue(-2**23 <= raw_temperature < 2**23, + "Fails to return raw temperature as a 24-bit " + "2's complement number.") + + def test_raw_temperature(self): + self._communicator.set_op_mode(PressureSensor.OpMode.command) + self._communicator.set_pressure_sampling() + raw_pressure = self._communicator.raw_pressure() + self.assertIsInstance(raw_pressure, int, + "Fails to return raw temperature as an integer.") + self.assertTrue(-2**23 <= raw_pressure < 2**23, + "Fails to return raw temperature as a 24-bit " + "2's complement number.") diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/causal_integral_filter.py b/causal_integral_filter.py new file mode 100644 index 0000000..50a40f1 --- /dev/null +++ b/causal_integral_filter.py @@ -0,0 +1,19 @@ +from numpy_ringbuffer import RingBuffer + + +class CausalIntegralFilter(): + + def __init__(self, initial_value, initial_time): + self._y = initial_value + self._t_buffer = RingBuffer(2) + self._t_buffer.append(initial_time) + + def append_integral_value(self, y): + self._y = y + + def append(self, dydt, t): + self._t_buffer.append(t) + self._y += dydt * (self._t_buffer[-1] - self._t_buffer[-2]) + + def get_datum(self): + return self._y diff --git a/causal_velocity_filter.py b/causal_velocity_filter.py new file mode 100644 index 0000000..d7cb2ce --- /dev/null +++ b/causal_velocity_filter.py @@ -0,0 +1,34 @@ +import numpy as np +from numpy_ringbuffer import RingBuffer + + +class CausalVelocityFilter(): + """Calculates the derivative of data that's appended to the + internal buffer and allows you to get a moving average of the + derivative with window size defined by the init. + """ + + + def __init__(self, windowSize): + """Initializes self. + windowSize defines the width of the moving average buffer. + Too narrow and it doesn't do much filtering, too wide and it + lags behind the acutal derivative + """ + + self._derivativeBuffer = RingBuffer(windowSize) + self._previousDatum = 0.0 + + def get_datum(self): + """Get the present rate of change of the incomimg data""" + + return np.mean(self._derivativeBuffer) + + def append(self, datum, timeElapsed): + """Add a measurement and an elapsed time to the filter's + internal buffer to be able to find the rate of change. + """ + + self._derivativeBuffer.append((datum - self._previousDatum) + / timeElapsed) + self._previousDatum = datum \ No newline at end of file diff --git a/constants.py b/constants.py new file mode 100644 index 0000000..09ff89c --- /dev/null +++ b/constants.py @@ -0,0 +1,19 @@ +# Constants for the display software for the +# Tetra Biodistributed Ventillator Splitter + +NUMBER_OF_PATIENTS = 4 +PRESSURE_SENSOR = "SPL06_007" +SENSIRION_SENSOR = "SFM3300" +MASS_AIRFLOW_SENSOR = "Mass Air Flow" # TODO: find part no. + +# These must be from the set {1, 2, 4, 8, 16, 32, 64, 128} +PRESSURE_SAMPLING_RATE = 1 # Hz +PRESSURE_OVERSAMPLING = 16 +TEMPERATURE_SAMPLING_RATE = 1 # Hz +TEMPERATURE_OVERSAMPLING = 1 + +# Environment variables for testing off of hardware +SENSOR_QUANTITY = "SENSOR_QUANTITY" +ENOUGH_SENSORS = "ENOUGH_SENSORS" +TOO_MANY_SENSORS = "TOO_MANY_SENSORS" +NOT_ENOUGH_SENSORS = "NOT_ENOUGH_SENSORS" diff --git a/discrete_transfer_function.py b/discrete_transfer_function.py new file mode 100644 index 0000000..2b41a99 --- /dev/null +++ b/discrete_transfer_function.py @@ -0,0 +1,123 @@ +import math + +from numpy_ringbuffer import RingBuffer + + +class DiscreteTransferFunction(RingBuffer): + """Generates a single-input single-output transfer function that + transforms data based on the given numerator and denominator + coefficients. + + Add data to the internal buffer with + DiscreteTransferFunction.append() + + This class is inspired by the Discrete Transfer Fcn in + Matlab/Simulink. + https://www.mathworks.com/help/simulink/slref/discretetransferfcn.html + """ + + def __init__(self, numerator, denominator): + """Generates a transfer function such that the values in the + lists numerator and denominator are the coefficients of a + transfer function of the order of the length of the longer list + where the first element of each list is on the highets order + term. For example, + + DiscreteTransferFunction([1, -1], [1, -1.85, 0.9]) + + results in a transfer function of the form + + z - 1 + ------------------ + z^2 - 1.85 z + 0.9 + + where z^n is the nth most recent value added to the buffer. + """ + if all(math.isclose(i, 0.0) for i in denominator): + raise ZeroDivisionError("Denominator must have at least " + "one non-zero term.") + super().__init__(max(len(numerator)-1, len(denominator)-1)) + self._numerator = numerator + self._denominator = denominator + + @property + def numerator(self): + """The coefficients of the numerator of the transfer function + in order from highest order to lowest""" + return self._numerator + + @property + def denominator(self): + """The coefficients of the denominator of the transfer function + in order from highest order to lowest""" + return self._denominator + + def get_datum(self): + """Calculates the value of the transfer function given the + contents of the buffer. + """ + + numerator = self._evaluate_polynomial_over_buffer(self._numerator) + denominator = self._evaluate_polynomial_over_buffer(self._denominator) + return numerator/denominator + + def _evaluate_polynomial_over_buffer(self, coefficients): + + return sum(coefficient * bufferValue + for (coefficient, bufferValue) + in zip(reversed(coefficients[:-1]), reversed(self))) \ + + coefficients[-1] + + def __str__(self): + """Makes a polynomial representation of the transfer function. + + >>> print(DiscreteTransferFunction([1, -1], [1, -1.85, 0.9])) + z - 1 + ------------------ + z^2 - 1.85 z + 0.9 + """ + + numerator_string = self._z_polynomial(self._numerator) + denominator_string = self._z_polynomial(self._denominator) + + fraction_bar = "-" * max(len(numerator_string), + len(denominator_string)) + + padding = " " * (abs(len(numerator_string) + - len(denominator_string)) // 2) + if (len(numerator_string) > len(denominator_string)): + denominator_string = padding + denominator_string + else: + numerator_string = padding + numerator_string + + return (numerator_string + "\n" + fraction_bar + "\n" + + denominator_string) + + def _z_polynomial(self, coefficients): + + polynomial_string = "" + for i in reversed(range(len(coefficients))): + if (i + 1 == len(coefficients)): + polynomial_string = polynomial_string \ + + self._z_term(coefficients[-(i+1)], i) + if math.isclose(coefficients[i], 1) and i != 0: + polynomial_string = polynomial_string[1:] + else: + polynomial_string = ( + polynomial_string + + (" + " if coefficients[-(i+1)] >= 0 else " - ") + + self._z_term(abs(coefficients[-(i+1)]), i)) + + return polynomial_string + + def _z_term(self, coefficient, degree): + + if degree == 0: + return str(coefficient) + else: + coefficientString = ("" if math.isclose(coefficient, 1) + else str(coefficient)) + if degree == 1: + return coefficientString + " z" + else: + return coefficientString + " z^" + str(degree) diff --git a/i2c_interface.py b/i2c_interface.py new file mode 100644 index 0000000..9fd53f9 --- /dev/null +++ b/i2c_interface.py @@ -0,0 +1,227 @@ +from abc import ABC, abstractmethod +import random +import warnings +import time +import math + + +class I2CInterfaceBase(ABC): + """Implements an I2C interface using adafruit_blinka. + + Parameters + ---------- + address: int + The address of the I2C device you want to communicate with. + dump_communication=False: bool + For every read or write to the I2C device, the transmitted and + recieved communication will be printed alongside the time in + millis since epoch. A write will look like this, + 1594169517918.1819 TX -> 0x0c09 + and a read will look like this. + 1594169517938.8496 TX -> 0x08 + 1594169517939.2563 RX <- 0x40 + """ + @abstractmethod + def __init__(self, address, dump_communication=False): + super().__init__() + + @abstractmethod + def close(self): + """Deinitializes and unlocks the I2C bus.""" + pass + + @abstractmethod + def scan(self): + """Returns a list of all visible I2C addresses.""" + pass + + @abstractmethod + def find_device(self, timeout=5): + """Delays until the device is visible on the I2C bus. + + Parameters + ---------- + timeout=5: float + The amount of time in seconds this method will search for + the device before raising a DeviceNotFoundError. + """ + pass + + @abstractmethod + def read_register(self, register, number_of_bytes=1): + """Returns the contents of the bytes located at address address + on the device. + + Parameters + ---------- + register: int + The device register you're interested in. + number_of_bytes=1: int > 0 + The number of bytes you'd like to read from that register. + """ + pass + + @abstractmethod + def read_data(self, number_of_bytes=1): + """Returns the contents of whats on the I2C bus. + + Parameters + ---------- + number_of_bytes=1: int > 0 + The number of bytes you'd like to read from the bus. + """ + + @abstractmethod + def write_register(self, register, to_write): + """Writes to_write to register + + Parameters + ---------- + register: int + The device register you're interested in. + to_write: int + The data you'd like to write to that register. + """ + pass + + @abstractmethod + def write_data(self, byte): + """Writes a single byte to the the device address. + + Parameters + ---------- + byte: int + The byte you'd like to write to the device address. + """ + + +try: + + import board + import busio + + class I2CInterface(I2CInterfaceBase): + + def __init__(self, address, dump_communication=False): + self._i2c_address = address + self._dump_communication = dump_communication + self._i2c = busio.I2C(board.SCL, board.SDA) + while not self._i2c.try_lock(): + pass + + def close(self): + self._i2c.unlock() + self._i2c.deinit() + + def scan(self): + return self._i2c.scan() + + def find_device(self, timeout=5): + start_time = time.time() + while not self._i2c_address in self.scan(): + if time.time() - start_time > timeout: + raise DeviceNotFoundError("Could not find I2C " + "device at address " + f"{self._i2c_address}") + + def read_register(self, register, number_of_bytes=1): + return self._read(register=register, + number_of_bytes=number_of_bytes) + + def read_data(self, number_of_bytes=1): + return self._read(number_of_bytes=number_of_bytes) + + def write_register(self, register, to_write): + self._i2c.writeto(self._i2c_address, bytes([register, to_write])) + + if self._dump_communication: + print(f"{1000*time.time():.4f} " + "TX -> 0x" + bytes([register, to_write]).hex()) + + def write_data(self, data): + byte_data = self._int_to_bytearray(data) + self._i2c.writeto(self._i2c_address, byte_data) + + if self._dump_communication: + print(f"{1000*time.time():.4f} TX -> 0x" + byte_data.hex()) + + def _read(self, register=None, number_of_bytes=1): + if number_of_bytes < 1: + raise ValueError("Cannot read fewer than 1 byte.") + + data = bytearray(number_of_bytes) + if register is not None: + byte_register = self._int_to_bytearray(register) + self._i2c.writeto(self._i2c_address, byte_register) + self._i2c.readfrom_into(self._i2c_address, + data, + end=number_of_bytes) + + if self._dump_communication: + if register is not None: + print(f"{1000*time.time():.4f} TX -> 0x" + + byte_register.hex()) + print(f"{1000*time.time():.4f} RX <- 0x{data.hex()}") + + if number_of_bytes == 1: + return int(data.hex(), 16) + else: + return tuple(byte for byte in data) + + def _int_to_bytearray(self, integer): + if integer != 0: + return ( + bytearray( + reversed([(integer >> 8*i) & 0xff + for i in range(math.ceil((math.log2(integer) + + 1)/8)) + ]))) + else: + return bytearray([0]) + + +except NotImplementedError: + + class I2CInterface(I2CInterfaceBase): + def __init__(self, address, dump_communication=False): + warnings.warn("I2C communication is not available on this " + "hardware. All data over I2C will be random " + "numbers.", + UserWarning) + + def close(self): + pass + + def scan(self): + return [random.randrange(0, 0x80) + for _ in range(random.randrange(0, 10))] + + def find_device(self, timeout=5): + pass + + def read_register(self, register, number_of_bytes=1): + return self._read(register=register, + number_of_bytes=number_of_bytes) + + def read_data(self, number_of_bytes=1): + return self._read(number_of_bytes=number_of_bytes) + + def write_register(self, register, to_write): + pass + + def write_data(self, byte): + pass + + def _read(self, register=None, number_of_bytes=1): + if number_of_bytes < 1: + raise ValueError("Cannot read fewer than 1 byte.") + if number_of_bytes == 1: + data = random.randrange(0, 255) + else: + data = tuple(random.randrange(0, 255) + for _ in range(number_of_bytes)) + return data + + +class DeviceNotFoundError(Exception): + pass diff --git a/main.go b/main.go new file mode 100644 index 0000000..519c6ac --- /dev/null +++ b/main.go @@ -0,0 +1,93 @@ +package main + +import ( + "log" + "net/http" + "time" + + "github.com/gorilla/websocket" + zmq "github.com/pebbe/zmq4" +) + +const ( + writeWait = 10 * time.Second + pongWait = 60 * time.Second + pingPeriod = (pongWait * 9) / 10 + maxMessageSize = 512 + publisherSource = "tcp://localhost:5000" +) + +var upgrader = websocket.Upgrader{} + +type subscription struct { + subscribe string +} + +type Client struct { + conn *websocket.Conn +} + +func (client *Client) readPump() { + defer func() { + log.Printf("read pump closing") + client.conn.Close() + }() + + client.conn.SetReadLimit(maxMessageSize) + client.conn.SetReadDeadline(time.Now().Add(pongWait)) + client.conn.SetPongHandler(func(string) error { + client.conn.SetReadDeadline(time.Now().Add(pongWait)) + return nil + }) + for { + _, message, error := client.conn.ReadMessage() + if error != nil { + if websocket.IsUnexpectedCloseError(error, + websocket.CloseGoingAway, + websocket.CloseAbnormalClosure) { + log.Printf("error: %v", error) + } + log.Printf("Breaking from reader") + break + } + log.Printf("received %v", message) + } +} + +func (client *Client) writePump() { + subscriber, _ := zmq.NewSocket(zmq.SUB) + defer subscriber.Close() + subscriber.Connect(publisherSource) + subscriber.SetSubscribe("") + for { + message, error := subscriber.RecvMessage(0) + if error != nil { + log.Fatalf("Trouble reading from zeromq %v", error) + } + log.Printf("Received %v", message) + data := []byte(message[1]) + error = client.conn.WriteMessage(websocket.TextMessage, data) + if error != nil { + log.Printf("%v\n", error) + break + } + } +} + +func serve(writer http.ResponseWriter, request *http.Request) { + _client, error := upgrader.Upgrade(writer, request, nil) + if error != nil { + log.Print("upgrade: ", error) + return + } + + client := Client{_client} + go client.readPump() + go client.writePump() +} + +func main() { + http.HandleFunc("/ws", serve) + http.Handle("/", http.FileServer(http.Dir("./static"))) + log.Fatal(http.ListenAndServe(":8000", nil)) +} diff --git a/moving_average_filter.py b/moving_average_filter.py new file mode 100644 index 0000000..961b430 --- /dev/null +++ b/moving_average_filter.py @@ -0,0 +1,46 @@ +import numpy as np +from numpy_ringbuffer import RingBuffer + + +class MovingAverageFilter(RingBuffer): + """A moving average filter for an incoming stream of data. Used + like so: + + from moving_average_filter import MovingAverageFilter + + bufferSize = 4 + filter = MovingAverageFilter(bufferSize, default_value=0) + filtered_data = [] + + for datum in data: + filter.append(datum) + filtered_data.append(filter.get_datum()) + + print(filtered_data) + """ + + def __init__(self, size, default_value=0): + """Creates a filter instance. + + Parameters + ---------- + size: int > 0 + The length of the buffer the moving average is performed + over. A long buffer will filter more noise than a short + buffer, but will also introduce lag. + default_value=0: float + The filter will pad the the buffer with default_value when + len(self) < size. + """ + if size < 1: + raise ValueError("Buffer size cannot be non-positive.") + + super().__init__(size) + self._default_value = default_value + + def get_datum(self): + """Returns the mean of the buffered values.""" + + padding = np.array([self._default_value + for _ in range(self.maxlen - len(self))]) + return np.mean(np.append(self, padding)) diff --git a/patienttubingdescriptorcalculator.py b/patienttubingdescriptorcalculator.py new file mode 100644 index 0000000..9d776a6 --- /dev/null +++ b/patienttubingdescriptorcalculator.py @@ -0,0 +1,46 @@ +import random + +from numpy_ringbuffer import RingBuffer + +from causal_integral_filter import CausalIntegralFilter + + +class PatientTubingDescriptorCalculator(): + + def __init__(self, current_time): + self._flow_rate_sample_times = RingBuffer(2) + self._flow_rate_sample_times.append(current_time) + + self._tidal_volume_filter = CausalIntegralFilter(0, current_time) + + def add_flow_rate_datum(self, datum, current_time): + self._tidal_volume_filter.append(datum, current_time) + + def add_pressure_datum(self, datum): + pass + + def add_tidal_volume_value(self, tidal_volume): + self._tidal_volume_filter.append_integral_value(tidal_volume) + + def _flow_rate(self): + return random.uniform(-200, 200) + + def _inspiratory_pressure(self): + return random.uniform(0, 25) + + def _PEEP(self): + return random.uniform(2, 5) + + def _peak_pressure(self): + return random.uniform(23, 25) + + def _tidal_volume(self): + return self._tidal_volume_filter.get_datum() + + @property + def descriptors(self): + return {"Flow Rate": self._flow_rate(), + "Inspiratory Pressure": self._inspiratory_pressure(), + "PEEP": self._PEEP(), + "Peak Pressure": self._peak_pressure(), + "Tidal Volume": self._tidal_volume()} diff --git a/process_sample_data.py b/process_sample_data.py new file mode 100644 index 0000000..63639c3 --- /dev/null +++ b/process_sample_data.py @@ -0,0 +1,101 @@ +from datetime import datetime +import pytz +from pytz import timezone + + +class ProcessSampleData(): + """Parses a file with flow rate, tidal volume, and optionally + pressure data. The expected formats are + + `%f\tSLMx10:%f.2\tTidalVol:%f.2\n` + with the first number being the floating-point milliseconds since + Epoch, the second being ten times the flow rate in mL/s, and the + last being the tidal volume in mL, and + + `%H:%M:%S.%f -> SLMx10:%f.2\tTidalVol:%f.2\tPressurex10:%f.2` + with the first 11 character representing the time the datum was + recorded as if on a digital clock (assuming the date as 2020-06-09 + and timezone as US/Pacific), the %f.2 after `SLMx10:` representing + ten times the flow rate, the following %f.2 representing the tidal + volume, and the last representing ten times the pressure. + """ + + def __init__(self, path_to_data): + self._flow_data_file = open(path_to_data, "r") + self._parseData() + self._flow_data_file.close() + + def __len__(self): + return len(self.timestamps) + + @property + def timestamps(self): + """Gives the list of timestamps data were taken at in + milliseconds since Epoch + """ + + return self._timestamps + + @property + def relative_timestamps(self): + """Gives the list of timestamps data were taken at in + milliseconds since the first data point + """ + + return [timestamp - self.timestamps[0] + for timestamp in self.timestamps] + + @property + def flow_rates(self): + """Gives the list of flow rates in mL/s""" + return self._flow_rates + + @property + def tidal_volumes(self): + """Gives the list of tidal volumes in mL""" + return self._tidal_volumes + + @property + def pressures(self): + """Gives the list of pressures in cmH2O""" + return self._pressures + + def _parseData(self): + self._timestamps = [] + self._flow_rates = [] + self._tidal_volumes = [] + self._pressures = [] + flow_rate_marker = "SLMx10:" + tidal_volume_marker = "TidalVol:" + pressure_marker = "Pressurex10:" + + for datum in self._flow_data_file: + splitDatum = datum.replace(" -> ", "\t").split("\t") + try: + self._timestamps.append(float(splitDatum[0])) + except ValueError: + self._timestamps \ + .append(timezone("US/Pacific") + .localize(datetime + .strptime(splitDatum[0], + "%H:%M:%S.%f") + .replace(year=2020, + month=6, + day=9)) + .astimezone(pytz.utc) + .timestamp() * 1000.0) + + self._flow_rates.append(float(splitDatum[1] + .replace(flow_rate_marker, + "") + .strip("\n")) / 10) + self._tidal_volumes.append(float(splitDatum[2] + .replace(tidal_volume_marker, + "") + .strip("\n"))) + + if (pressure_marker in datum): + self._pressures.append(float(splitDatum[3] + .replace(pressure_marker, + "") + .strip("\n")) / 10) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..818d7c6 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,9 @@ +matplotlib +numpy +numpy_ringbuffer +behave +zmq +pytz +docker +adafruit_blinka +crcmod diff --git a/rpi_check.py b/rpi_check.py index bcd82da..aded4d1 100644 --- a/rpi_check.py +++ b/rpi_check.py @@ -1,115 +1,9 @@ -# This is almost entirely copied from -# https://github.com/adafruit/Adafruit_Python_GPIO/blob/master/Adafruit_GPIO/Platform.py -# except for the method is_on_raspberry_pi, which was added for this -# project - -import platform -import re - - -# Platform identification constants. -UNKNOWN = 0 -RASPBERRY_PI = 1 -BEAGLEBONE_BLACK = 2 -MINNOWBOARD = 3 -JETSON_NANO = 4 - - -def platform_detect(): - """Detect if running on the Raspberry Pi or Beaglebone Black and return the - platform type. Will return RASPBERRY_PI, BEAGLEBONE_BLACK, or UNKNOWN.""" - # Handle Raspberry Pi - pi = pi_version() - if pi is not None: - return RASPBERRY_PI - - # Handle Beaglebone Black - # TODO: Check the Beaglebone Black /proc/cpuinfo value instead of reading - # the platform. - plat = platform.platform() - if plat.lower().find('armv7l-with-debian') > -1: - return BEAGLEBONE_BLACK - elif plat.lower().find('armv7l-with-ubuntu') > -1: - return BEAGLEBONE_BLACK - elif plat.lower().find('armv7l-with-glibc2.4') > -1: - return BEAGLEBONE_BLACK - elif plat.lower().find('tegra-aarch64-with-ubuntu') > -1: - return JETSON_NANO - - # Handle Minnowboard - # Assumption is that mraa is installed - try: - import mraa - if mraa.getPlatformName()=='MinnowBoard MAX': - return MINNOWBOARD - except ImportError: - pass - - # Couldn't figure out the platform, just return unknown. - return UNKNOWN - - -def pi_revision(): - """Detect the revision number of a Raspberry Pi, useful for changing - functionality like default I2C bus based on revision.""" - # Revision list available at: http://elinux.org/RPi_HardwareHistory#Board_Revision_History - with open('/proc/cpuinfo', 'r') as infile: - for line in infile: - # Match a line of the form "Revision : 0002" while ignoring extra - # info in front of the revsion (like 1000 when the Pi was over-volted). - match = re.match('Revision\s+:\s+.*(\w{4})$', line, flags=re.IGNORECASE) - if match and match.group(1) in ['0000', '0002', '0003']: - # Return revision 1 if revision ends with 0000, 0002 or 0003. - return 1 - elif match: - # Assume revision 2 if revision ends with any other 4 chars. - return 2 - # Couldn't find the revision, throw an exception. - raise RuntimeError('Could not determine Raspberry Pi revision.') - - -def pi_version(): - """Detect the version of the Raspberry Pi. Returns either 1, 2 or - None depending on if it's a Raspberry Pi 1 (model A, B, A+, B+), - Raspberry Pi 2 (model B+), or not a Raspberry Pi. - """ - # Check /proc/cpuinfo for the Hardware field value. - # 2708 is pi 1 - # 2709 is pi 2 - # 2835 is pi 3 on 4.9.x kernel - # Anything else is not a pi. - with open('/proc/cpuinfo', 'r') as infile: - cpuinfo = infile.read() - # Match a line like 'Hardware : BCM2709' - match = re.search('^Hardware\s+:\s+(\w+)$', cpuinfo, - flags=re.MULTILINE | re.IGNORECASE) - if not match: - # Couldn't find the hardware, assume it isn't a pi. - return None - if match.group(1) == 'BCM2708': - # Pi 1 - return 1 - elif match.group(1) == 'BCM2709': - # Pi 2 - return 2 - elif match.group(1) == 'BCM2835': - # Pi 3 / Pi on 4.9.x kernel - return 3 - else: - # Something else, not a pi. - return None +from adafruit_platformdetect import Detector def is_on_raspberry_pi(): - """Method to determine if the current platform is a Raspberry Pi. - It's able to tell Pis from similar boards like Beaglebone Blacks. - - Adapted from https://github.com/adafruit/Adafruit_Python_GPIO/blob/master/Adafruit_GPIO/Platform.py - """ - try: - if platform_detect == RASPBERRY_PI: - return True - else: - return False - except FileNotFoundError: + """Returns true if evaluated on a Raspberry Pi, else False.""" + if Detector().get_device_model() is not None: + return True + else: return False diff --git a/sensors.py b/sensors.py index 4e842ba..1ae47ca 100644 --- a/sensors.py +++ b/sensors.py @@ -1,85 +1,185 @@ import os -import random from abc import ABC, abstractmethod +import warnings -from processsampledata import ProcessSampleData +from spl06_007 import PressureSensor +from sfm3300d import FlowSensor +from tca9548a import I2CMux +from process_sample_data import ProcessSampleData from rpi_check import is_on_raspberry_pi import constants -class SensorsDataABC(ABC): +class SensorsABC(ABC): + """A class to collect data from the sensing suit for the Tetra + Ventillator Splitter. If this class is not used on a Raspberry Pi, + Then it will return data recorded from the sensors. + """ @abstractmethod - def __init__(self, - pressure_sampling_rate, - pressure_oversampling, - temperature_sampling_rate, - temperature_oversampling): + def __init__(self, dump_communication=False): + """Initializes self.""" super().__init__() @abstractmethod - def connected_sensors(self): + def close(self): + """Closes ever sensor in the system.""" pass @abstractmethod - def calibration_pressure_sensor_connected(self): + def connected_sensors(self): + """Returns a tuple of all the sensors connected to the system. + + Returns + ------- + sensors : tuple + A tuple of tuples of strings, where a string can be + "SPL06-007" (representing the pressure sensor), "SFM3300-D" + (representing the Sensirion sensor), or "Mass Air Flow" + (representing the automotive sensor). sensors[i] gives + a tuple of all the sensors connected to port i of the + splitter. sensors[constants.NUMBER_OF_PATIENTS + 1] will + give the sensors connected for calibration of the whole + system. The output will look something like this: + (("SPLO6-007", "SFM3300-D"), ("SPL06-007", "SFM3300-D"), + ("SPLO6-007", "SFM3300-D"), ("SPLO6-007", "SFM3300-D"), + ("SPLO6-007")) + """ pass @abstractmethod - def poll(self): - pass + def tubes_with_enough_sensors(self): + """Returns a list of the ports with both a pressure sensor and + a flow sensor. + + Returns + ------- + port_list : list + A list of ints in range(constants.NUMBER_OF_PATIENTS) + representing ports that have enough sensors. + """ if is_on_raspberry_pi(): - class SensorsData(SensorsDataABC): - """Actual implementation""" + class Sensors(SensorsABC): + + def __init__(self, dump_communication=False): + self._pressure_mux = I2CMux(constants.PRESSURE_SENSOR_MUX_ADDRESS) + self._pressure_sensors = [] + for i in range(constants.NUMBER_OF_PRESSURE_SENSORS): + self._pressure_mux.select_channel(i) + self._pressure_sensors.append(PressureSensor( + dump_communication=dump_communication)) + self._pressure_sensors[i].set_sampling( + pressure_oversample=constants.PRESSURE_OVERSAMPLING, + pressure_sampling_rate=constants.PRESSURE_RATE, + temperature_oversample=constants.TEMPERATURE_OVERSAMPLING, + temperature_sampling_rate=constants.TEMPERATURE_RATE + ) + self._pressure_sensors[i].set_op_mode( + PressureSensor.OpMode.command) + + self._flow_mux = I2CMux(constants.FLOW_SENSOR_MUX_ADDRESS) + self._flow_sensors = [] + for i in range(constants.NUMBER_OF_SENSIRION_SENSORS): + self._flow_mux.select_channel(i) + # print(f"i{i} {self._flow_mux.scan()}") + self._flow_sensors.append(FlowSensor( + dump_communication=dump_communication)) + + self._mass_airflow_sensors = [] + for i in range(constants.NUMBER_OF_MASS_AIRFLOW_SENSORS): + pass - def __init__(self, - pressure_sampling_rate, - pressure_oversampling, - temperature_sampling_rate, - temperature_oversampling): - pass + def close(self): + + for i in range(constants.NUMBER_OF_PRESSURE_SENSORS): + self._pressure_mux.select_channel(i) + self._pressure_sensors[i].close() + for i in range(constants.NUMBER_OF_SENSIRION_SENSORS): + self._flow_mux.select_channel(i) + self._flow_sensors[i].close() + for mass_airflow_sensor in self._mass_airflow_sensors: + pass + self._pressure_mux.close() + self._flow_mux.close() def connected_sensors(self): - pass + def sensors_available_on_port(i): + port_i = [] + self._pressure_mux.select_channel(i) + if self._pressure_sensors[i].is_present(): + port_i.append(constants.PRESSURE_SENSOR) + if i < constants.NUMBER_OF_SENSIRION_SENSORS: + self._flow_mux.select_channel(i) + if self._flow_sensors[i].is_present(): + port_i.append(constants.SENSIRION_SENSOR) + return tuple(port_i) + + return tuple(sensors_available_on_port(i) + for i in range(constants.MAX_SENSOR_COUNT)) + + def tubes_with_enough_sensors(self): + tubes = [] + sensors = self.connected_sensors() + for i in range(len(sensors)): + if (constants.PRESSURE_SENSOR in sensors[i] + and (constants.SENSIRION_SENSOR in sensors[i] + or constants.MASS_AIRFLOW_SENSOR in sensors[i])): + tubes.append(i) + if len(tubes) != constants.NUMBER_OF_PATIENTS: + warnings.warn("Not all tubes have a flow and a " + "pressure sensor.", + NotEnoughSensors) + return tubes def calibration_pressure_sensor_connected(self): - pass + if (constants.PRESSURE_SENSOR in + self.connected_sensors()[ + constants.CALIBRATION_PRESSURE_SENSOR_INDEX]): + return True + else: + return False def poll(self): - pass + sensors = self.connected_sensors() + + def sensor_data_on_port(i): + data = [] + if constants.PRESSURE_SENSOR in sensors[i]: + data.append(self._pressure_sensors[i].pressure()) + if constants.SENSIRION_SENSOR in sensors[i]: + data.append(self._flow_sensors[i].flow()) + if constants.MASS_AIRFLOW_SENSOR in sensors[i]: + pass + return data + + return tuple(sensor_data_on_port(i) + for i in range(constants.MAX_SENSOR_COUNT)) else: - class SensorsData(SensorsDataABC): - """Dummy class while I work on the real thing""" + class Sensors(SensorsABC): - def __init__(self, - pressure_sampling_rate, - pressure_oversampling, - temperature_sampling_rate, - temperature_oversampling): - self._fake_data = \ - ProcessSampleData("TestData/20200609T2358Z_patrickData.txt") + def __init__(self, dump_communication=False): + self._fake_data = ( + ProcessSampleData("TestData/20200609T2358Z_patrickData.txt")) self._data_index = 0 - def connected_sensors(self, not_enough_sensors=False): + def close(self): + pass + + def connected_sensors(self): try: if (os.environ[constants.SENSOR_QUANTITY] == constants.NOT_ENOUGH_SENSORS): - sensors = tuple([(constants.PRESSURE_SENSOR,)] - + [(constants.PRESSURE_SENSOR, - constants.SENSIRION_SENSOR) - for _ in range(constants. - NUMBER_OF_PATIENTS-1) - ]) - raise NotEnoughSensors( - f"{len(self._tubes_with_enough_sensors(sensors))} " - "tube(s) do not have both a pressure sensor " - "and a flow sensor") + return tuple([(constants.PRESSURE_SENSOR,)] + + [(constants.PRESSURE_SENSOR, + constants.SENSIRION_SENSOR) + for _ in range(constants. + NUMBER_OF_PATIENTS-1)]) elif (os.environ[constants.SENSOR_QUANTITY] == constants.TOO_MANY_SENSORS): @@ -97,6 +197,21 @@ def connected_sensors(self, not_enough_sensors=False): constants.SENSIRION_SENSOR) for _ in range(constants.NUMBER_OF_PATIENTS)) + def tubes_with_enough_sensors(self): + tubes = [] + sensors = self.connected_sensors() + print(sensors) + for i in range(constants.NUMBER_OF_PATIENTS): + if (constants.PRESSURE_SENSOR in sensors[i] + and (constants.SENSIRION_SENSOR in sensors[i] + or constants.MASS_AIRFLOW_SENSOR in sensors[i])): + tubes.append(i) + if len(tubes) != constants.NUMBER_OF_PATIENTS: + warnings.warn("Not all tubes have a flow and a " + "pressure sensor.", + NotEnoughSensors) + return tubes + def calibration_pressure_sensor_connected(self, fail=False): if fail: return False @@ -105,53 +220,12 @@ def calibration_pressure_sensor_connected(self, fail=False): def poll(self): """Pulls data from the pressure and flow sensors""" + datum = tuple((self._fake_data.pressures[self._data_index], + self._fake_data.flow_rates[self._data_index]) + for _ in range(constants.NUMBER_OF_PATIENTS)) self._data_index += 1 - return tuple((self._fake_data.pressures[self._data_index-1], - self._fake_data.flow_rates[self._data_index-1]) - for _ in range(constants.NUMBER_OF_PATIENTS)) - - def _tubes_with_enough_sensors(self, tubes_sensors): - tubes = [] - for tube in tubes_sensors: - if (constants.PRESSURE_SENSOR in tube - and (constants.SENSIRION_SENSOR in tube - or constants.MASS_AIRFLOW_SENSOR in tube)): - tubes.append(tube) - return tubes - - -class Sensors(): - - def __init__(self, - pressure_sampling_rate, - pressure_oversampling, - temperature_sampling_rate, - temperature_oversampling): - self._sensors_data = SensorsData(pressure_sampling_rate, - pressure_oversampling, - temperature_sampling_rate, - temperature_oversampling) - - def calibrate(self): - pass - - def calibration_pressure_sensor_connected(self): - pass - - def tubes_with_enough_sensors(self): - tubes = [] - sensors = self._sensors_data.connected_sensors() - for i in range(len(sensors)): - if (constants.PRESSURE_SENSOR in sensors[i] - and (constants.SENSIRION_SENSOR in sensors[i]) - or constants.MASS_AIRFLOW_SENSOR in sensors[i]): - tubes.append(i) - - return tubes - - def poll(self): - return self._sensors_data.poll() + return datum -class NotEnoughSensors(Exception): +class NotEnoughSensors(Warning): pass diff --git a/server.py b/server.py new file mode 100644 index 0000000..61abd87 --- /dev/null +++ b/server.py @@ -0,0 +1,65 @@ +import sys +import time +import json +import random + +import zmq + +from patienttubingdescriptorcalculator \ + import PatientTubingDescriptorCalculator +from sensors import Sensors +import constants + + +class Calculator(): + + def __init__(self): + + self._calculators = ( + tuple(PatientTubingDescriptorCalculator(time.time()) + for _ in range(constants.NUMBER_OF_PATIENTS))) + + def add_datum(self, datum): + for i in range(len(self._calculators)): + self._calculators[i].add_pressure_datum(datum[i][0]) + if len(datum[i]) > 1: + self._calculators[i].add_flow_rate_datum(datum[i][1], + time.time()) + + def get_datum(self): + datum = {} + for i in range(len(self._calculators)): + datum.update({i: self._calculators[i].descriptors}) + return datum + + +class Communicator(): + + def __init__(self, port=5000): + self._socket = zmq.Context().socket(zmq.PUB) + self._socket.bind(f"tcp://*:{port}") + + def publish_message(self, message): + self._socket.send_multipart([b"", + json.dumps(message).encode("ascii")]) + + +def main(): + sensors = Sensors() + sensor_data = sensors.poll() + calculator = Calculator() + communicator = Communicator() + running = True + while running: + try: + calculator.add_datum(sensor_data) + + communicator.publish_message(calculator.get_datum()) + time.sleep(1.0) + except: + running = False + raise + + +if "__main__" == __name__: + main() diff --git a/services.conf b/services.conf new file mode 100644 index 0000000..7ce9ca5 --- /dev/null +++ b/services.conf @@ -0,0 +1,7 @@ +[program:publish_server] +directory=/src/zmq_proxy +command=python3 server.py + +[program:zmq_proxy] +directory=/src/zmq_proxy +command=./zmq_proxy \ No newline at end of file diff --git a/setup.sh b/setup.sh index c2d587e..8c1f5a0 100755 --- a/setup.sh +++ b/setup.sh @@ -1,12 +1,24 @@ #!/bin/sh +HIGHLIGHT='\033[0;33m' +NO_COLOR='\033[0m' + + if ! [ -d venv ]; then python3 -m venv venv fi +. venv/bin/activate + if [ -f requirements.txt ]; then pip3 install -r requirements.txt fi -echo $'\nrun this:' -echo source ./venv/bin/activate +deactivate + +if ! command -v docker &> /dev/null; then + printf "\n${HIGHLIGHT}Please install Docker${NO_COLOR}" +fi + +echo $'\nRun this to start the virtual environment' +printf "${HIGHLIGHT}. venv/bin/activate${NO_COLOR}\n" diff --git a/sfm3300d.py b/sfm3300d.py new file mode 100644 index 0000000..898942c --- /dev/null +++ b/sfm3300d.py @@ -0,0 +1,171 @@ +import time +import math + +import crcmod + +from i2c_interface import I2CInterface + + +class FlowSensor(): + """An interface for initizlizing and getting calibrated data from a + SFM3300-D flow sensor. The data sheet for the sensor can be found at + https://www.mouser.com/datasheet/2/682/Sensirion_Mass_Flow_Meters_SFM3300_Datasheet-1524535.pdf + """ + + def __init__(self, dump_communication=False): + """Initializes self.""" + self._calibrator = Calibrator(SensorConstants.OFFSET_FLOW, + SensorConstants.SCALE_FACTOR_FLOW) + self._communicator = Communicator( + dump_communication=dump_communication) + self._communicator.init_flow() + + def close(self): + """Deinitializes the I2C and unlocks the I2C bus.""" + if self.is_present(): + self._communicator.close() + + def is_present(self): + return self._communicator.is_present() + + def flow(self): + """Flow rate in standard liters per minute (SFM).""" + raw_flow = self._communicator.raw_flow() + if raw_flow >= 0: + return self._calibrator.flow(self._communicator.raw_flow()) + else: + return float("nan") + + def serial_number(self): + """Serial number of the particular sensor being used.""" + return self._communicator.serial_number() + + +class Calibrator(): + """Takes raw data from a SFM3300-D flow sensor and converts it + to flow rate in standard liters per minute (SFM). + """ + + def __init__(self, offset_flow=None, scale_factor_flow=None): + if offset_flow is not None: + self._offset_flow = offset_flow + else: + self._offset_flow = SensorConstants.OFFSET_FLOW + + if scale_factor_flow is not None: + self._scale_factor_flow = scale_factor_flow + else: + self._scale_factor_flow = SensorConstants.SCALE_FACTOR_FLOW + if math.isclose(self._scale_factor_flow, 0.0): + raise ZeroDivisionError("scale_factor_flow cannot be zero.") + + def flow(self, measured_value): + """Flow rate in standard liters per minute (SFM). + + Parameters + ---------- + measured_value : int + Raw flow from the sensor. + """ + return (measured_value - self._offset_flow) / self._scale_factor_flow + + +class Communicator(): + """Performs I2C communication between a Raspberry Pi and a SFM3300-D + flow sensor. The data sheet describing the I2C communication can be + found at + https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/5_Mass_Flow_Meters/Application_Notes/Sensirion_Mass_Flo_Meters_SFM3xxx_I2C_Functional_Description.pdf + + And the data sheet the describes the CRC validation used can be found + at + https://www.mouser.jp/pdfDocs/SFM3000_CRC_Checksum_Calculation.pdf + """ + + def __init__(self, dump_communication=False): + """Initializes self.""" + self._i2c = I2CInterface(SensorConstants.ADDRESS, + dump_communication=dump_communication) + if SensorConstants.ADDRESS in self._i2c.scan(): + print("reset") + self._reset() + self._sensor_available = True + else: + self._sensor_available = False + self._flow_inited = False + self._crc8 = crcmod.mkCrcFun(SensorConstants.CRC_POLYNOMIAL, + initCrc=0x00, + rev=False, + xorOut=0x00) + + def close(self): + """Deinitializes I2C and unlocks the I2C bus.""" + if self.is_present(): + self._reset() + self._i2c.close() + + def is_present(self): + return self._sensor_available + + def serial_number(self): + """The serial number of the particular sensor being used.""" + if self.is_present(): + serial_number_bytes = ( + self._i2c.read_register(SensorConstants.READ_SERIAL_NUMBER, + SensorConstants.SERIAL_NUMBER_BYTES)) + serial_number = 0 + for i in range(SensorConstants.SERIAL_NUMBER_BYTES): + serial_number |= ( + serial_number_bytes[SensorConstants.SERIAL_NUMBER_BYTES + - i - 1] << (8*i)) + return serial_number + else: + return -1 + + def init_flow(self): + """Prepares the sensor to begin reading out data. It takes about + 100ms to initialize. + """ + if self.is_present() and not self._flow_inited: + self._i2c.write_data( + SensorConstants.START_CONTINUOUS_MEASUREMENT) + self._flow_inited = True + time.sleep(0.100) # give the sensor a moment to initialize + self.raw_flow() # the first datum is garbage + + def raw_flow(self): + """The raw, uncalibrated flow data.""" + if self.is_present() and self._flow_inited: + flow_bytes = ( + self._i2c.read_data(SensorConstants.MEASUREMENT_BYTES)) + flow_measurement = bytearray(flow_bytes[0:2]) + print("I am the very model") + print(self._crc8(flow_measurement)) + print(flow_bytes[2]) + if self._crc8(flow_measurement) != flow_bytes[2]: + raise CRCError("Data fails CRC8 validation.") + else: + return int(flow_measurement.hex(), 16) + else: + return -1 + + def _reset(self): + self._i2c.write_data(SensorConstants.SOFT_RESET) + + +class CRCError(Exception): + pass + + +class SensorConstants(): + """The names and addresses of every register on the chip and codes + to write to them. + """ + ADDRESS = 0x40 + SOFT_RESET = 0x2000 + READ_SERIAL_NUMBER = 0x31AE + SERIAL_NUMBER_BYTES = 4 + START_CONTINUOUS_MEASUREMENT = 0x1000 + MEASUREMENT_BYTES = 3 + CRC_POLYNOMIAL = 0x131 # x^8 + x^5 + x^4 + 1 + SCALE_FACTOR_FLOW = 120 + OFFSET_FLOW = 32768 diff --git a/spl06_007.py b/spl06_007.py new file mode 100644 index 0000000..9d2a858 --- /dev/null +++ b/spl06_007.py @@ -0,0 +1,774 @@ +import time +import warnings +import math + +from i2c_interface import I2CInterface + + +class PressureSensor(): + """An interface for initializing and getting calibrated data from a + SPL06-007 pressure sensor. The data sheet for the sensor can be + found at + https://datasheet.lcsc.com/szlcsc/1912111437_Goertek-SPL06-007_C233787.pdf + """ + + def __init__(self, dump_communication=False): + self._communicator = Communicator( + dump_communication=dump_communication) + self._sampling_set = False + self._first_measurement_has_happened = False + + def __enter__(self): + return self._communicator.__enter__() + + def __exit__(self, exc_type, exc_val, exc_tb): + self._communicator.__exit__(exc_type, exc_val, exc_tb) + + def close(self): + """Deinitializes and unlocks the I2C bus.""" + self._communicator.close() + + def is_present(self): + return self._communicator.is_present() + + def set_sampling(self, + pressure_oversample=16, + pressure_sampling_rate=1, + temperature_oversample=1, + temperature_sampling_rate=1): + """Set the amount of oversampling and the sampling rate + + Parameters + ---------- + pressure_oversample=16 : {1, 2, 4, 8, 16, 32, 64, 128} + The SPL06-007 reads the sensor multiple times and combines + them into one result to achieve a higher precision. This + increases the current consumption and the measurement time, + which again reduces the maximum measurement rate. + The measurement times and precision for each oversample are + these values. + | Oversampling | Measurement time [ms] | Precision [PaRMS] | + |--------------|-----------------------|-------------------| + | 1 | 3.6 | 5 | + | 2 | 5.2 | | + | 4 | 8.4 | 2.5 | + | 8 | 14.8 | | + | 16 | 27.6 | 1.2 | + | 32 | 53.2 | 0.9 | + | 64 | 104.4 | 0.5 | + | 128 | 206.8 | | + pressure_sampling_rate=1 : {1, 2, 4, 8, 16, 32, 64, 128} + The sampling rate of for pressure in hertz. The sampling + rate is only relevant in Background Mode. + temperature_oversample=1 : {1, 2, 4, 8, 16, 32, 64, 128} + The SPL06-007 reads the sensor multiple times and combines + them into one result to achieve a higher precision. This + increases the current consumption and the measurement time, + which again reduces the maximum measurement rate. + Setting the oversample for temperature is optional and may + not be relevant. + The measurement time for oversample=1 is 3.6 ms. + temperature_sampling_rate=1 : {1, 2, 4, 8, 16, 32, 64, 128} + The sampling rate for temperature in hertz. The sampling + rate is only relevant in Background Mode. + """ + self._communicator.set_pressure_sampling( + oversample=pressure_oversample, + rate=pressure_sampling_rate + ) + self._communicator.set_temperature_sampling( + oversample=temperature_oversample, + rate=temperature_sampling_rate + ) + + self._calibrator = Calibrator( + self._communicator.calibration_coefficients, + self._communicator.pressure_scale_factor, + self._communicator.temperature_scale_factor + ) + + self._sampling_set = True + return self._sampling_set + + def set_op_mode(self, op_mode): + """Sets the mode in which the sensor samples data + + Parameters + ---------- + op_mode: {self.OpMode.standby, + self.OpMode.background, + self.OpMode.command} + self.OpMode.standby is the default mode after power on or + reset. No measurements are performed. All registers and + compensation coefficients are accessible. + In self.OpMode.background, pressure and/or temperature + measurements are performed continuously according to the + selected measurement precision and rate. The temperature + measurement is performed immediately after the pressure + measurement. The FIFO can be used to store 32 measurement + results and minimize the number of times the sensor must be + accessed to read out the results. + In self.OpMode.command, one temperature or pressure + measurement is performed according to the selected + precision. The sensor will return to Standby Mode when the + measurement is finished, and the measurement result will be + available in the data registers. + """ + return self._communicator.set_op_mode(op_mode) + + def pressure(self): + """Returns the currect pressure in Pa. If set_sampling() has + not been called, then it will return NaN. + """ + if self._sampling_set: + self._first_measurement_delay() + return self._calibrator.pressure( + self._communicator.raw_pressure(), + self._communicator.raw_temperature() + ) + else: + return float("nan") + + def temperature(self): + """Returns the currect temperature in degC. If set_sampling() + has not been called, then it will return NaN. + """ + if self._sampling_set: + self._first_measurement_delay() + return self._calibrator.temperature( + self._communicator.raw_temperature() + ) + else: + return float("nan") + + class OpMode(): + standby = "Standby" + background = "Background" + command = "Command" + + def _first_measurement_delay(self): + first_measurement_delay = 0.151 + if self._first_measurement_has_happened: + self._first_measurement_has_happened = True + time.sleep(first_measurement_delay) + + +class Calibrator(): + """Takes raw data from a SPL06-007 pressure sensor and converts it + to pressure data in Pa and temperature data in degC. + """ + + def __init__(self, + calibration_coefficients, + pressure_scaling_factor, + temperature_scaling_factor): + """Initializes self. + + Parameters + ---------- + calibration_coefficients : iterable + An iterable with the coefficients + (c0, c1, c00, c10, c01, c11, c20, c21, c30) as defined in the + data sheet. + pressure_scaling_factor : int + A scaling factor corresponding with the selected pressure + oversampling. + temperature_scaling_factor : int + A scaling factor corresponding with the selected temperature + oversampling + """ + self._c0 = calibration_coefficients[0] + self._c1 = calibration_coefficients[1] + self._c00 = calibration_coefficients[2] + self._c10 = calibration_coefficients[3] + self._c01 = calibration_coefficients[4] + self._c11 = calibration_coefficients[5] + self._c20 = calibration_coefficients[6] + self._c21 = calibration_coefficients[7] + self._c30 = calibration_coefficients[8] + + if (math.isclose(pressure_scaling_factor, 0.0) + or math.isclose(temperature_scaling_factor, 0.0)): + raise ZeroDivisionError("Cannot have pressure or temperature " + "scaling factor equal to 0.") + + self._pressure_scaling_factor = pressure_scaling_factor + self._temperature_scaling_factor = temperature_scaling_factor + + def pressure(self, raw_pressure, raw_temperature): + """Pressure in Pa. + + Parameters + ---------- + raw_pressure : int + Raw pressure from the sensor. + raw_temperature : int + Raw temperature from the sensor. + """ + scaled_pressure = raw_pressure / self._pressure_scaling_factor + scaled_temperature = (raw_temperature + / self._temperature_scaling_factor) + + compensated_pressure = ( + self._c00 + + scaled_pressure*(self._c10 + + scaled_pressure*(self._c20 + + scaled_pressure*self._c30) + ) + + scaled_temperature*self._c01 + + scaled_temperature*scaled_pressure*(self._c11 + + scaled_pressure*self._c21) + ) + return compensated_pressure + + def temperature(self, raw_temperature): + """Temperature in degC + + Parameters + ---------- + raw_temperature : int + Raw temperature from the sensor. + """ + scaled_temperature = (raw_temperature + / self._temperature_scaling_factor) + compensated_temperature = ( + self._c0 * 0.5 + self._c1 * scaled_temperature + ) + return compensated_temperature + + +class Communicator(): + """Performs I2C communication between a Raspberry Pi and a + SPL06-007 pressure sensor. + + Parameters + ---------- + SDO_high = True: bool + Set to false if the SDO pin on the SPL06-007 is pulled to ground + dump_communication=False: bool + For every read or write to the I2C device, the transmitted and + recieved communication will be printed alongside the time in + millis since epoch. A write will look like this, + 1594169517918.1819 TX -> 0x0C09 + and a read will look like this. + 1594169517938.8496 TX -> 0x08 + 1594169517939.2563 RX <- 0x40 + """ + + _READY_WAIT_TIME = 0.0036 + + def __init__(self, SDO_high=True, dump_communication=False): + """The sensor takes(107 + /- 8) ms to initialize.""" + if SDO_high: + self._i2c_address = SensorConstants.DEVICE_ADDRESS_SDO_HIGH + else: + self._i2c_address = SensorConstants.DEVICE_ADDRESS_SDO_LOW + self._i2c = I2CInterface(self._i2c_address, + dump_communication=dump_communication) + self._i2c.find_device() + self._reset_sensor() + self.set_op_mode(PressureSensor.OpMode.standby) + self._calculate_calibration_coefficients() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + + def close(self): + """Deinitializes and unlocks the I2C bus.""" + self._i2c.close() + + def is_present(self): + if self._i2c_address in self._i2c.scan(): + return True + else: + return False + + def set_op_mode(self, mode): + """Sets the pressure sensor into a mode for data collection + + Parameters + ---------- + mode : {PressureSensor.OpMode.standby, + PressureSensor.OpMode.command, + PressureSensor.OpMode.background} + The data output modes of the sensor + use_pressure=True : bool + Set to False if you don't want pressure data; it's + otherwise True + use_temperature=True : bool + Set to False if you don't want temperature data; + it's otherwise True + """ + + set_standby = False + if mode == PressureSensor.OpMode.command: + self._op_mode = PressureSensor.OpMode.command + return PressureSensor.OpMode.command + + elif mode == PressureSensor.OpMode.background: + self._i2c.write_register( + SensorConstants.SENSOR_OP_MODE, + SensorConstants.BACKGROUND_PRESSURE_TEMPERATURE + ) + self._op_mode = PressureSensor.OpMode.background + return PressureSensor.OpMode.background + + else: + if mode != PressureSensor.OpMode.standby: + warnings.warn("Undefined mode. Defaulting to" + "Standby Mode", + RuntimeWarning) + set_standby = True + if set_standby: + self._i2c.write_register( + SensorConstants.SENSOR_OP_MODE, SensorConstants.STANDBY) + self._op_mode = PressureSensor.OpMode.standby + return PressureSensor.OpMode.standby + + @property + def calibration_coefficients(self): + """The calibration coefficients + (c0, c1, c00, c10, c01, c11, c20, c21, c30) + """ + return self._calibration_coefficients + + def set_pressure_sampling(self, oversample=16, rate=1): + """Set the amount of oversampling and the sampling rate + + Parameters + ---------- + oversample=16 : {1, 2, 4, 8, 16, 32, 64, 128} + The SPL06-007 reads the sensor multiple times and combines + them into one result to achieve a higher precision. This + increases the current consumption and the measurement time, + which again reduces the maximum measurement rate. + The measurement times and precision for each oversample are + these values. + | Oversampling | Measurement time [ms] | Precision [Pa RMS] | + |--------------|-----------------------|--------------------| + | 1 | 3.6 | 5 | + | 2 | 5.2 | | + | 4 | 8.4 | 2.5 | + | 8 | 14.8 | | + | 16 | 27.6 | 1.2 | + | 32 | 53.2 | 0.9 | + | 64 | 104.4 | 0.5 | + | 128 | 206.8 | | + rate=1 : {1, 2, 4, 8, 16, 32, 64, 128} + The sampling rate of the sensor in hertz. The sampling rate + is only relevant in Background Mode. + """ + + try: + rate_mode = SensorConstants.PRESSURE_RATE_OPTIONS[rate] + except KeyError: + raise ValueError("Pressure sampling rate can only be " + "1, 2, 4, 8, 16, 32, 64, or 128 Hz") + try: + oversample_mode = ( + SensorConstants.PRESSURE_OVERSAMPLE_OPTIONS[oversample] + ) + self._pressure_scale_factor = ( + SensorConstants.COMPENSATION_SCALE_FACTORS[oversample] + ) + except KeyError: + raise ValueError("Pressure oversampling can only be " + "1, 2, 4, 8, 16, 32, 64, or 128X") + self._i2c.write_register(SensorConstants.PRESSURE_CONFIGURATION, + rate_mode | oversample_mode) + if oversample > 8: + self._i2c.write_register( + SensorConstants.INTERRUPT_AND_FIFO_CONFIGURATION, + SensorConstants.PRESSURE_RESULT_BIT_SHIFT + ) + else: + new_interrupt_and_fifo_config_state = ( + self._i2c.read_register( + SensorConstants.INTERRUPT_AND_FIFO_CONFIGURATION + ) & (0xff - SensorConstants.PRESSURE_RESULT_BIT_SHIFT)) + self._i2c.write_register( + SensorConstants.INTERRUPT_AND_FIFO_CONFIGURATION, + new_interrupt_and_fifo_config_state + ) + + def raw_pressure(self): + """The raw pressuring reading from the sensor. This needs to + be scaled and compensated per the data sheet to be useful. + """ + if self._op_mode == PressureSensor.OpMode.command: + self._i2c.write_register( + SensorConstants.SENSOR_OP_MODE, + SensorConstants.COMMAND_PRESSURE + ) + + def pressure_ready(): + return (self._i2c.read_register(SensorConstants.SENSOR_OP_MODE) + & SensorConstants.PRS_RDY != 0) + self._wait_for_condition_else_timeout(pressure_ready, 4) + + pressure_msb = self._i2c.read_register( + SensorConstants.PRESSURE_MSB) + pressure_lsb = self._i2c.read_register( + SensorConstants.PRESSURE_LSB) + pressure_xlsb = self._i2c.read_register( + SensorConstants.PRESSURE_XLSB) + + pressure = self._twos_complement(((pressure_msb << 16) + + (pressure_lsb << 8) + + pressure_xlsb), + 24) + return pressure + + @property + def pressure_scale_factor(self): + """A constant used for calibrating the sensor.""" + return self._pressure_scale_factor + + def set_temperature_sampling(self, oversample=1, rate=1): + """Set the amount of oversampling and the sampling rate. + + Parameters + ---------- + oversample=1 : {1, 2, 4, 8, 16, 32, 64, 128} + The SPL06-007 reads the sensor multiple times and combines + them into one result to achieve a higher precision. This + increases the current consumption and the measurement time, + which again reduces the maximum measurement rate. + Setting the oversample for temperature is optional and may + not be relevant. + The measurement time for oversample=1 is 3.6 ms. + rate=1 : {1, 2, 4, 8, 16, 32, 64, 128} + The sampling rate of the sensor in hertz. The sampling rate + is only relevant in background mode. + """ + + try: + rate_mode = SensorConstants.TEMPERATURE_RATE_OPTIONS[rate] + except KeyError: + raise ValueError("Temperature sampling rate can only be " + "1, 2, 4, 8, 16, 32, 64, or 128 Hz") + try: + oversample_mode = ( + SensorConstants.TEMPERATURE_OVERSAMPLE_OPTIONS[oversample] + ) + self._temperature_scale_factor = \ + SensorConstants.COMPENSATION_SCALE_FACTORS[oversample] + except KeyError: + raise ValueError("Temperature oversampling can only be " + "1, 2, 4, 8, 16, 32, 64, or 128X") + self._i2c.write_register(SensorConstants.TEMPERATURE_CONFIGURATION, + rate_mode | oversample_mode) + if oversample > 8: + self._i2c.write_register( + SensorConstants.INTERRUPT_AND_FIFO_CONFIGURATION, + SensorConstants.TEMPERATURE_RESULT_BIT_SHIFT + ) + else: + new_interrupt_and_fifo_config_state = ( + self._i2c.read_register( + SensorConstants.INTERRUPT_AND_FIFO_CONFIGURATION) + ) & (0xff - SensorConstants.TEMPERATURE_RESULT_BIT_SHIFT) + self._i2c.write_register( + SensorConstants.INTERRUPT_AND_FIFO_CONFIGURATION, + new_interrupt_and_fifo_config_state + ) + + def raw_temperature(self): + """The raw temperature reading from the sensor. This need to + be scaled and compensated per the data sheet to be useful. + """ + if self._op_mode == PressureSensor.OpMode.command: + self._i2c.write_register(SensorConstants.SENSOR_OP_MODE, + SensorConstants.COMMAND_TEMPERATURE) + + def temperature_ready(): + return (self._i2c.read_register(SensorConstants.SENSOR_OP_MODE) + & SensorConstants.TMP_RDY != 0) + self._wait_for_condition_else_timeout(temperature_ready, 4) + + temperature_msb = self._i2c.read_register( + SensorConstants.TEMPERATURE_MSB) + temperature_lsb = self._i2c.read_register( + SensorConstants.TEMPERATURE_LSB) + temperature_xlsb = self._i2c.read_register( + SensorConstants.TEMPERATURE_XLSB) + temperature = self._twos_complement(((temperature_msb << 16) + + (temperature_lsb << 8) + + temperature_xlsb), + 24) + return temperature + + @property + def temperature_scale_factor(self): + """A constant used for calibrating the sensor.""" + return self._temperature_scale_factor + + def _calculate_calibration_coefficients(self): + """The SPL06-007 is a calibrated sensor and contains + calibration coefficients. These are used in the + application (for instance by the host processor) to + compensate the measurement results for sensor nonlinearity’s. + + Note: The coefficients read from the coefficient register + {c00, c10, c01, c11, c20, c21, c30} are 16 bit 2´s complement + numbers. + + Note: The coefficients read from the coefficient register + {c0, c1} 12 bit 2´s complement numbers. + """ + def coefficients_ready(): + return (self._i2c.read_register(SensorConstants.SENSOR_OP_MODE) + & SensorConstants.COEF_RDY != 0) + self._wait_for_condition_else_timeout(coefficients_ready, 4) + + _c0_11_4 = self._i2c.read_register(SensorConstants.C0_11_4) + _c0_3_0_c1_11_8 = ( + self._i2c.read_register(SensorConstants.C0_3_0_C1_11_8)) + _c1_7_0 = self._i2c.read_register(SensorConstants.C1_7_0) + _c00_19_12 = self._i2c.read_register(SensorConstants.C00_19_12) + _c00_11_4 = self._i2c.read_register(SensorConstants.C00_11_4) + _c00_3_0_c10_19_16 = ( + self._i2c.read_register(SensorConstants.C00_3_0_C10_19_16)) + _c10_15_8 = self._i2c.read_register(SensorConstants.C10_15_8) + _c10_7_0 = self._i2c.read_register(SensorConstants.C10_7_0) + _c01_15_8 = self._i2c.read_register(SensorConstants.C01_15_8) + _c01_7_0 = self._i2c.read_register(SensorConstants.C01_7_0) + _c11_15_8 = self._i2c.read_register(SensorConstants.C11_15_8) + _c11_7_0 = self._i2c.read_register(SensorConstants.C11_7_0) + _c20_15_8 = self._i2c.read_register(SensorConstants.C20_15_8) + _c20_7_0 = self._i2c.read_register(SensorConstants.C20_7_0) + _c21_15_8 = self._i2c.read_register(SensorConstants.C21_15_8) + _c21_7_0 = self._i2c.read_register(SensorConstants.C21_7_0) + _c30_15_8 = self._i2c.read_register(SensorConstants.C30_15_8) + _c30_7_0 = self._i2c.read_register(SensorConstants.C30_7_0) + + def most_significant_nibble(byte): return (byte & 0xf0) >> 4 + + def least_significant_nibble(byte): return byte & 0x0f + + c0 = self._twos_complement( + (_c0_11_4 << 4) | most_significant_nibble(_c0_3_0_c1_11_8), + 12 + ) + c1 = self._twos_complement( + (least_significant_nibble(_c0_3_0_c1_11_8) << 8) | _c1_7_0, + 12 + ) + + c00 = self._twos_complement( + (_c00_19_12 << 12) | (_c00_11_4 << 4) + | most_significant_nibble(_c00_3_0_c10_19_16), + 16 + ) + c10 = self._twos_complement( + (least_significant_nibble(_c00_3_0_c10_19_16) << 16) + | (_c10_15_8 << 8) | _c10_7_0, + 16 + ) + c01 = self._twos_complement((_c01_15_8 << 8) | _c01_7_0, 16) + c11 = self._twos_complement((_c11_15_8 << 8) | _c11_7_0, 16) + c20 = self._twos_complement((_c20_15_8 << 8) | _c20_7_0, 16) + c21 = self._twos_complement((_c21_15_8 << 8) | _c21_7_0, 16) + c30 = self._twos_complement((_c30_15_8 << 8) | _c30_7_0, 16) + + self._calibration_coefficients = (c0, c1, + c00, c10, c01, c11, c20, c21, c30) + + def _reset_sensor(self): + reset_time = 0.02 + self._i2c.write_register(SensorConstants.RESET_AND_FLUSH, + SensorConstants.SOFT_RESET) + time.sleep(reset_time) + + def sensor_ready(): + return (self._i2c.read_register(SensorConstants.SENSOR_OP_MODE) + & SensorConstants.SENSOR_RDY != 0) + self._wait_for_condition_else_timeout(sensor_ready, 4) + + def _wait_for_condition_else_timeout(self, conditionFunction, timeout): + + start_time = time.time() + while not conditionFunction(): + if time.time() - start_time > timeout: + return False + time.sleep(self._READY_WAIT_TIME) + return True + + def _twos_complement(self, value, bits): + + if (value & (1 << (bits - 1))) != 0: + complement = (value & (2**bits - 1)) - (1 << bits) + else: + complement = value & (2**bits - 1) + return complement + + +class SensorConstants(): + """The names and addresses of every register on the chip and codes + to write to them + """ + DEVICE_ADDRESS_SDO_HIGH = 0x77 + DEVICE_ADDRESS_SDO_LOW = 0x76 + + # Register addresses + PRESSURE_MSB = 0x00 + PRESSURE_LSB = 0x01 + PRESSURE_XLSB = 0x02 + TEMPERATURE_MSB = 0x03 + TEMPERATURE_LSB = 0x04 + TEMPERATURE_XLSB = 0x05 + PRESSURE_CONFIGURATION = 0x06 + TEMPERATURE_CONFIGURATION = 0x07 + SENSOR_OP_MODE = 0x08 + INTERRUPT_AND_FIFO_CONFIGURATION = 0x09 + INTERRUPT_STATUS = 0x0A + FIFO_STATUS = 0x0B + RESET_AND_FLUSH = 0x0C + PRODUCT_AND_REVISION_ID = 0x0D + # Calibration Coefficient register addresses + C0_11_4 = 0x10 + C0_3_0_C1_11_8 = 0x11 + C1_7_0 = 0x12 + C00_19_12 = 0x13 + C00_11_4 = 0x14 + C00_3_0_C10_19_16 = 0x15 + C10_15_8 = 0x16 + C10_7_0 = 0x17 + C01_15_8 = 0x18 + C01_7_0 = 0x19 + C11_15_8 = 0x1A + C11_7_0 = 0x1B + C20_15_8 = 0x1C + C20_7_0 = 0x1D + C21_15_8 = 0x1E + C21_7_0 = 0x1F + C30_15_8 = 0x20 + C30_7_0 = 0x21 + + # Bitmasks to read from registers + # Read these from self._SENSOR_OP_MODE + COEF_RDY = 0b10000000 + SENSOR_RDY = 0b01000000 + TMP_RDY = 0b00100000 + PRS_RDY = 0b00010000 + # Read these from self._INTERRUPT_STATUS + INT_FIFO_FULL = 0b00000100 + INT_TMP = 0b00000010 + INT_PRS = 0b00000001 + # Read these from self._FIFO_STATUS + FIFO_FULL = 0b00000010 + FIFO_EMPTY = 0b00000001 + # Read these from self._PRODUCT_AND_REVISION_ID + PROD_ID = 0b11110000 + REV_ID = 0b00001111 + + # Codes to write to registers + # Write these to self._PRESSURE_CONFIGURATION + # The rate and oversample can bitwise-or'ed together + PRESSURE_RATE_1HZ = 0b00000000 + PRESSURE_RATE_2HZ = 0b00010000 + PRESSURE_RATE_4HZ = 0b00100000 + PRESSURE_RATE_8HZ = 0b00110000 + PRESSURE_RATE_16HZ = 0b01000000 + PRESSURE_RATE_32HZ = 0b01010000 + PRESSURE_RATE_64HZ = 0b01100000 + PRESSURE_RATE_128HZ = 0b01110000 + PRESSURE_OVERSAMPLE_1X = 0b00000000 + PRESSURE_OVERSAMPLE_2X = 0b00000001 + PRESSURE_OVERSAMPLE_4X = 0b00000010 + PRESSURE_OVERSAMPLE_8X = 0b00000011 + PRESSURE_OVERSAMPLE_16X = 0b00000100 + PRESSURE_OVERSAMPLE_32X = 0b00000101 + PRESSURE_OVERSAMPLE_64X = 0b00000110 + PRESSURE_OVERSAMPLE_128X = 0b00000111 + # Write these to self._TEMPERATURE_CONFIGURATION + # The sensor, rate, and can be bitwise-or'ed together + TEMPERATURE_SENSOR_INTERNAL = 0b10000000 + TEMPERATURE_SENSOR_EXTERNAL = 0b00000000 + TEMPERATURE_RATE_1HZ = 0b00000000 + TEMPERATURE_RATE_2HZ = 0b00010000 + TEMPERATURE_RATE_4HZ = 0b00100000 + TEMPERATURE_RATE_8HZ = 0b00110000 + TEMPERATURE_RATE_16HZ = 0b01000000 + TEMPERATURE_RATE_32HZ = 0b01010000 + TEMPERATURE_RATE_64HZ = 0b01100000 + TEMPERATURE_RATE_128HZ = 0b01110000 + TEMPERATURE_OVERSAMPLE_1X = 0b00000000 + TEMPERATURE_OVERSAMPLE_2X = 0b00000001 + TEMPERATURE_OVERSAMPLE_4X = 0b00000010 + TEMPERATURE_OVERSAMPLE_8X = 0b00000011 + TEMPERATURE_OVERSAMPLE_16X = 0b00000100 + TEMPERATURE_OVERSAMPLE_32X = 0b00000101 + TEMPERATURE_OVERSAMPLE_64X = 0b00000110 + TEMPERATURE_OVERSAMPLE_128X = 0b00000111 + # Write these to self._SENSOR_OP_MODE + STANDBY = 0b00000000 + COMMAND_PRESSURE = 0b00000001 + COMMAND_TEMPERATURE = 0b00000010 + BACKGROUND_PRESSURE = 0b00000101 + BACKGROUND_TEMPERATURE = 0b00000110 + BACKGROUND_PRESSURE_TEMPERATURE = 0b00000111 + # Read or write these to self._INTERRUPT_AND_FIFO_CONFIGURATION + # Note: temperature or pressure bit shift must be set when + # their respective oversample rates are set to > 8 + SET_INTERRUPT_ACTIVE_LEVEL = 0b10000000 + GENERATE_INTERRUPT_WHEN_FIFO_IS_FULL = 0b01000000 + GENERATE_INTERRUPT_WHEN_PRESSURE_IS_READY = 0b00100000 + GENERATE_INTERRUPT_WHEN_TEMPERATURE_IS_READY = 0b00010000 + TEMPERATURE_RESULT_BIT_SHIFT = 0b00001000 + PRESSURE_RESULT_BIT_SHIFT = 0b00000100 + ENABLE_FIFO = 0b00000010 + SET_4_WIRE_SPI = 0b00000000 + SET_3_WIRE_SPI = 0b00000001 + # Write these to self._RESET_AND_FLUSH + # They can be bitwise-or'ed together + FLUSH_FIFO = 0b10000000 + SOFT_RESET = 0b00001001 + + # For use in calibrating the sensor, taken from Table 4 of + # the data sheet + COMPENSATION_SCALE_FACTORS = {1: 524288, + 2: 1572864, + 4: 3670016, + 8: 7864320, + 16: 253952, + 32: 516096, + 64: 1040384, + 128: 2088960} + + # Some helper constants + PRESSURE_RATE_OPTIONS = {1: PRESSURE_RATE_1HZ, + 2: PRESSURE_RATE_2HZ, + 4: PRESSURE_RATE_4HZ, + 8: PRESSURE_RATE_8HZ, + 16: PRESSURE_RATE_16HZ, + 32: PRESSURE_RATE_32HZ, + 64: PRESSURE_RATE_64HZ, + 128: PRESSURE_RATE_128HZ} + PRESSURE_OVERSAMPLE_OPTIONS = {1: PRESSURE_OVERSAMPLE_1X, + 2: PRESSURE_OVERSAMPLE_2X, + 4: PRESSURE_OVERSAMPLE_4X, + 8: PRESSURE_OVERSAMPLE_8X, + 16: PRESSURE_OVERSAMPLE_16X, + 32: PRESSURE_OVERSAMPLE_32X, + 64: PRESSURE_OVERSAMPLE_64X, + 128: PRESSURE_OVERSAMPLE_128X} + TEMPERATURE_RATE_OPTIONS = {1: TEMPERATURE_RATE_1HZ, + 2: TEMPERATURE_RATE_2HZ, + 4: TEMPERATURE_RATE_4HZ, + 8: TEMPERATURE_RATE_8HZ, + 16: TEMPERATURE_RATE_16HZ, + 32: TEMPERATURE_RATE_32HZ, + 64: TEMPERATURE_RATE_64HZ, + 128: TEMPERATURE_RATE_128HZ} + TEMPERATURE_OVERSAMPLE_OPTIONS = {1: TEMPERATURE_OVERSAMPLE_1X, + 2: TEMPERATURE_OVERSAMPLE_2X, + 4: TEMPERATURE_OVERSAMPLE_4X, + 8: TEMPERATURE_OVERSAMPLE_8X, + 16: TEMPERATURE_OVERSAMPLE_16X, + 32: TEMPERATURE_OVERSAMPLE_32X, + 64: TEMPERATURE_OVERSAMPLE_64X, + 128: TEMPERATURE_OVERSAMPLE_128X} diff --git a/tca9548a.py b/tca9548a.py new file mode 100644 index 0000000..209adcb --- /dev/null +++ b/tca9548a.py @@ -0,0 +1,19 @@ +from i2c_interface import I2CInterface + + +class I2CMux(): + + def __init__(self, mux_address): + self._i2c = I2CInterface(mux_address) + + def close(self): + self._i2c.close() + + def select_channel(self, channel): + if channel > 7: + raise ValueError("Multiplexor channel must be an integer 0-7") + else: + self._i2c.write_data(1 << channel) + + def scan(self): + return self._i2c.scan()