SlideShare a Scribd company logo
1
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Using Python, PHP, JQuery and Linux to
visualize the heartrate and blood oxygen
saturation level of my stepdaughter
Jeroen Baten
T-DOSE 2015
2
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
TOC
Who am I
Who is Anouschka?
What happened
What I did
How it worked out
The end...
3
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Who am I?
●
Jeroen Baten
●
Open Source geek since 1997
●
Sofar 9 books and 2 columns
●
Job title : all-round IT problem fixer
●
(former) Volunteer Firefighter
●
Scouting
4
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Who am I ? (in pics)
5
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Who the f*ck is this Anouschka?
Name: Anouschka van G.
DOB: 18-1-1997
Current age: 18 years
Diagnosis:
Spina Bifida Aperta L3-L5
Arnold Chiari Malformation
Hydrocephalus
Number of surgeries till today: 43
Number of hospital sessions: stopped counting
6
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Hospital life….
7
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Some surgery examples
8
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
The surgery session where our journey starts
Reason: chronic pain in hip joint
Cause: insufficient joint development
Post surgery:
Low oxygen levels during sleep
Questions:
Source/origin?
How severe?
How to fix?
9
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Actions taken by pediatrician at WKZ
Polysomnografy at AMC. This takes 24 hours.
Result: varying (85-90%) O2-levels at night.
Values found are in “grey” area.
Oxygen measures introduced at home.
Pediatrician: “If only we had more data….”
“But please not a huge table with data.”
10
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Oxygen concentrator + saturation measurement
Oxygen concentrator for producing O2:
Philips Everflo oxygen concentrator
No matter what people say: these
things are loud at night!
Saturation measurement for correct level
feedback + alarm:
Masimo RAD-8 saturation
measurement device.
And so we begin
But what is that I see on the back of the
Rad-8?
11
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
RS-232!
That looks like….
No, it IS an RS-232 port!
Google….
Masimo-Rad-8-User-Manual.pdf
12
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Manual adventures
What does the manual say?
09/01/14 04:01:41 SN=0000051252 SPO2=092% BPM=086 PI=01.03%
SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000800
What do we get….?
13
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Step 1: make database
Use simple database: MySQL
Make simple table:
CREATE TABLE `data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tijd` datetime DEFAULT NULL,
`data` varchar(150) DEFAULT NULL,
`spo2` int(11) DEFAULT NULL,
`bpm` int(11) DEFAULT NULL,
`session` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`tijd3` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `id` (`id`),
KEY `session_index` (`session`),
KEY `tijd_index` (`tijd`),
KEY `spo2_index` (`spo2`)
)
14
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Step 2: python
#!/usr/bin/python
print "Loading libraries"
import serial, time, os
import logging
import logging.handlers
import MySQLdb
import datetime
version="1.0"
def log(msg):
print msg
my_logger.debug(os.path.basename(__file__)+":"+msg)
print "Initialising logging"
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address = '/dev/log')
my_logger.addHandler(handler)
log("Log-RAD-8 version "+version)
log("Copyright 2014 J. Baten")
log("")
log("Logging serial data from Masimo RAD-8 serial port")
log("Note: Works only with RAD-8 serial port set to 'ASC1'")
log("")
#my_logger.debug('this is debug')
#my_logger.critical('this is critical')
log("Initialising database connection")
#setting up database connection
#create table data (id int auto_increment, tijd timestamp, data varchar(150), key(id) );
#+-------+--------------+------+-----+-------------------+-----------------------------+
#| Field | Type | Null | Key | Default | Extra |
#+-------+--------------+------+-----+-------------------+-----------------------------+
#| id | int(11) | NO | MUL | NULL | auto_increment |
#| tijd | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
#| data | varchar(150) | YES | | NULL | |
#+-------+--------------+------+-----+-------------------+-----------------------------+
try:
conn = MySQLdb.connect(host= "10.1.1.1", user="lograd8", passwd="lograd8", db="lograd8")
except MySQLdb.Error, e:
log( "ERROR %d IN CONNECTION: %s" % (e.args[0], e.args[1]))
#except MySQLdb.Error:
#log("ERROR IN CONNECTION")
exit(2)
x = conn.cursor()
#x.execute("SELECT * FROM anooog1")
#x.execute (" INSERT INTO anooog1 VALUES ('%s','%s') ", (188,90))
#row = x.fetchall()
now = datetime.datetime.now()
#print now
log("Program started at "+str(now))
#today8am = now.replace(hour=8, minute=0, second=0, microsecond=0)
today = datetime.datetime.today()
#print today
one_day = datetime.timedelta(days=1)
tomorrow = today + one_day
#print 'Tomorrow :', tomorrow
endtime= tomorrow.replace(hour=8, minute=0, second=0, microsecond=0)
log("Logging should stop at "+ str(endtime))
#initialization and open the port
#possible timeout values:
# 1. None: wait forever, block call
# 2. 0: non-blocking mode, return immediately
# 3. x, x is bigger than 0, float allowed, timeout block call
log( "Initializing port")
ser = serial.Serial()
#ser.port = "/dev/ttyUSB0"
ser.port = "/dev/ttyS0"
#ser.port = "/dev/ttyS2"
ser.baudrate = 9600
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
#ser.timeout = None #block read
ser.timeout = 1 #non-block read
#ser.timeout = 2 #timeout block read
ser.xonxoff = False #disable software flow control
ser.rtscts = False #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 2 #timeout for write
try:
log( "Trying to open serial port")
ser.open()
except Exception, e:
log( "error open serial port: " + str(e))
exit(1)
if ser.isOpen():
log( "Port succesfully opened")
try:
log( "Flushing port data")
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput()#flush output buffer, aborting current output
#and discard all that is in buffer
#write data
#ser.write("AT+CSQ")
#time.sleep(0.5) #give the serial port sometime to receive the data
while True:
response = ser.readline()
print response
response = MySQLdb.escape_string(response)
print(response)
if (len(response)>5):
try:
x.execute ("INSERT INTO data (tijd,data) VALUES (now(),%s) ", response)
conn.commit()
except MySQLdb.Error, e:
log( "ERROR %d IN CONNECTION: %s" % (e.args[0], e.args[1]))
log( "Last query was: "+ x._last_executed )
# Is it time to stop yet?
#endtime= now+ datetime.timedelta(seconds=5)
now = datetime.datetime.now()
if (now > endtime):
break
ser.close()
except Exception, e1:
log( "error communicating...: " + str(e1))
else:
log( "cannot open serial port ")
conn.close()
15
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Step 3:
What do we have?
MySQL [(none)]> use lograd8
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MySQL [lograd8]> show tables;
+-------------------+
| Tables_in_lograd8 |
+-------------------+
| data |
+-------------------+
1 row in set (0.00 sec)
MySQL [lograd8]> select count(*) from data;
+----------+
| count(*) |
+----------+
| 717298 |
+----------+
1 row in set (0.68 sec)
MySQL [lograd8]>
select * from data limit 5;
+----+---------------------+-----------------------------------------------------------------------------------------------------------------------------------+------+------+---------------------+---------------------+
| id | tijd | data | spo2 | bpm | session | tijd3 |
+----+---------------------+-----------------------------------------------------------------------------------------------------------------------------------+------+------+---------------------+---------------------+
| 9 | 2014-09-02 15:00:18 | 00/00/00 00:00:03 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:18 | 0000-00-00 00:00:00 |
| 10 | 2014-09-02 15:00:19 | 09/02/14 04:58:09 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:19 | 0000-00-00 00:00:00 |
| 11 | 2014-09-02 15:00:20 | 09/02/14 04:58:10 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:20 | 0000-00-00 00:00:00 |
| 12 | 2014-09-02 15:00:21 | 09/02/14 04:58:11 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:21 | 0000-00-00 00:00:00 |
| 13 | 2014-09-02 15:00:22 | 09/02/14 04:58:12 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:22 | 0000-00-00 00:00:00 |
+----+---------------------+-----------------------------------------------------------------------------------------------------------------------------------+------+------+---------------------+---------------------+
5 rows in set (0.02 sec)
MySQL [lograd8]>
MySQL [lograd8]> select count(*),date_format(session,"%d/%m/%Y") from data group
by date(session);
+----------+---------------------------------+
| count(*) | date_format(session,"%d/%m/%Y") |
+----------+---------------------------------+
| 181711 | 00/00/0000 |
| 11200 | 02/09/2014 |
| 36399 | 03/09/2014 |
| 34166 | 04/09/2014 |
| 42495 | 05/09/2014 |
| 38313 | 09/09/2014 |
| 37392 | 10/09/2014 |
| 37279 | 11/09/2014 |
| 35972 | 12/09/2014 |
| 35467 | 13/09/2014 |
| 35761 | 14/09/2014 |
| 34845 | 15/09/2014 |
| 36510 | 16/09/2014 |
| 38400 | 17/09/2014 |
| 37797 | 18/09/2014 |
| 23 | 23/09/2014 |
| 43568 | 26/09/2014 |
+----------+---------------------------------+
17 rows in set (0.65 sec)
MySQL [lograd8]>
16
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Step 4: turn raw data into usefull data
Need to get BPM and O2 from string.
And fix the date!
update data set spo2=substring(data,38,3);
update data set bpm=substring(data,47,3);
update data set session=DATE_SUB(tijd, INTERVAL 12 HOUR);
17
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Step 4: visualize quick and dirty => PHP!
Use PHP and Jquery (for date selection)
Find easy PHP visualisation lib...
JpGraph?
No longer leading.
Google Charts javascript lib can't be wrong right?
Wrong!
DyGraph! Send it CSV formatted data. Done!
Including zoom functionality. Yay!
18
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
The result
First results...
19
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Results: DyGraph to the rescue
Working with small range averages
20
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Results: graphing ALL data...
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Saturatie weergave</title>
<link rel="stylesheet" href="jquery/jquery-ui.min.css">
<link rel="stylesheet" href="get-sat.css">
<script type="text/javascript" src="dygraph-combined.js"></script>
</head>
<body>
<div class="box" id="spo2_div" style="width:95%">
<h3>SPO2</h3>
</div>
<div class="box" id="bpm_div" style="width:95%">
<h3>SPO2</h3>
</div>
<script>
<!-- console.log(startdate); -->
g = new Dygraph(
document.getElementById("spo2_div"),
"get-data3spo.php", // path to CSV file
{ // rollPeriod: 7,
legend: 'always',
animatedZooms: true,
showRoller: true
//errorBars: true,
//valueRange: [40,100]} // options
}
);
g = new Dygraph(
document.getElementById("bpm_div"),
"get-data3bpm.php", // path to CSV file
{ // rollPeriod: 7,
legend: 'always',
animatedZooms: true,
showRoller: true
//errorBars: true,
//valueRange: [40,100]} // options
}
);
</script>
</body>
</html>
<?php
ini_set("error_reporting",E_ALL);
syslog(LOG_DEBUG,"Start get-data.php");
# set db connection parameters
$dbhost="10.1.1.1";
#$dbhost="127.0.0.1";
$dblogin="lograd8";
$dbpwd="secret";
$dbname="lograd8";
$db = mysql_connect($dbhost,$dblogin,$dbpwd);
mysql_select_db($dbname);
$rows = "DatumTijd,gem_SPO2,spreiding_SPO2,max_SPO2,min_SPO2n";
#$startdate = $_POST['startdate'];
$former=0;
$query = "select date_format(tijd,'%Y/%m/%d %H:00') as datum, avg(spo2)
as gem_spo2, std(spo2) as spreiding_spo2, max(spo2) as max_spo2,
min(spo2) as min_spo2 from data group by date_format(session,'%d/%m/%Y
%H');";
# +---------------+----------+----------------+----------+----------+
# | datum_uur | gem_spo2 | spreiding_spo2 | max_spo2 | min_spo2 |
# +---------------+----------+----------+----------------+----------+
syslog(LOG_DEBUG,"$query");
$result = mysql_query($query);
while($r = mysql_fetch_array($result)){
#syslog(LOG_DEBUG,print_r($r,TRUE));
$rij="";
# vervangen min=0 door min=avg bij spo2 en bpm
if ($r[4]==0) $r[4]=$r[1];
for ($i=0;$i<=4;$i++) {
$rij = $rij.$r[$i].",";
}
$rij=substr($rij,0,strlen($rij)-1);
$rows = $rows.$rij."n";
}
#syslog(LOG_DEBUG,print_r($rows,TRUE));
#syslog(LOG_DEBUG,print_r($rows,TRUE));
#echo $cols . '"rows":[',$google_JSON_row ."]}";
# output off json string to caller.
echo $rows;
# saving of cvs string for debugging purposes
#$fh=fopen("/tmp/get-data.cvs","w");
#fwrite($fh,$rows);
#fclose($fh);
mysql_close($db);
syslog(LOG_DEBUG,"Einde get-data.phpnn");
?>
<?php
ini_set("error_reporting",E_ALL);
syslog(LOG_DEBUG,"Start get-data.php");
# set db connection parameters
$dbhost="10.1.1.1";
#$dbhost="127.0.0.1";
$dblogin="lograd8";
$dbpwd="secret";
$dbname="lograd8";
$db = mysql_connect($dbhost,$dblogin,$dbpwd);
mysql_select_db($dbname);
$rows = "DatumTijd,gem_BPM,spreiding_BPM,max_BPM,min_BPMn";
$former=0;
$query = "select date_format(tijd,'%Y/%m/%d %H:00') as datum, avg(bpm)
as gem_bpm, std(bpm) as spreiding_bpm, max(bpm) as max_bpm, min(bpm)
as min_bpm from data group by date_format(session,'%d/%m/%Y %H');";
# +---------------+----------+---------------+---------+---------+
# | datum_uur | gem_bpm | spreiding_bpm | max_bpm | min_bpm |
# +---------------+----------+---------------+---------+---------+
syslog(LOG_DEBUG,"$query");
$result = mysql_query($query);
while($r = mysql_fetch_array($result)){
#syslog(LOG_DEBUG,print_r($r,TRUE));
#syslog(LOG_DEBUG,print_r($tijd,TRUE));
$rij="";
# replace min=0 by min=avg for spo2 and bpm
if ($r[4]==0) $r[4]=$r[1];
for ($i=0;$i<=4;$i++) {
$rij = $rij.$r[$i].",";
}
$rij=substr($rij,0,strlen($rij)-1);
$rows = $rows.$rij."n";
}
#syslog(LOG_DEBUG,print_r($rows,TRUE));
#syslog(LOG_DEBUG,print_r($rows,TRUE));
#echo $cols . '"rows":[',$google_JSON_row ."]}";
# output off json string to caller.
echo $rows;
# saving of cvs string for debugging purposes
#$fh=fopen("/tmp/get-data2.cvs","w");
#fwrite($fh,$rows);
#fclose($fh);
mysql_close($db);
syslog(LOG_DEBUG,"Einde get-data.phpnn");
?>
Index.php
oxygen.php bpm.php
21
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
New result
Can you see the problem?
22
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
New result
Let me show you...
23
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Findings
Medical:
When not connected to O2 during the night the minimum
rates will continue to drop during several days.
Ergo: O2 always needed.
Techical:
Next time make a stored procedure and a trigger to update
records upon creation.
24
Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels
Anouschka thanks you …
Thanks for your attention.
Any questions?

More Related Content

What's hot

Plugins by tagomoris #fluentdcasual
Plugins by tagomoris #fluentdcasualPlugins by tagomoris #fluentdcasual
Plugins by tagomoris #fluentdcasual
SATOSHI TAGOMORI
 
The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185
Mahmoud Samir Fayed
 
Using New Web APIs For Your Own Pleasure – How I Wrote New Features For My Vi...
Using New Web APIs For Your Own Pleasure – How I Wrote New Features For My Vi...Using New Web APIs For Your Own Pleasure – How I Wrote New Features For My Vi...
Using New Web APIs For Your Own Pleasure – How I Wrote New Features For My Vi...
GeilDanke
 
JavaFX, because you're worth it
JavaFX, because you're worth itJavaFX, because you're worth it
JavaFX, because you're worth it
Thierry Wasylczenko
 
Introduction to JavaFX 2
Introduction to JavaFX 2Introduction to JavaFX 2
Introduction to JavaFX 2
Thierry Wasylczenko
 
Ejemplo radio
Ejemplo radioEjemplo radio
Ejemplo radio
lupe ga
 
Euro python2011 High Performance Python
Euro python2011 High Performance PythonEuro python2011 High Performance Python
Euro python2011 High Performance Python
Ian Ozsvald
 
The Ring programming language version 1.7 book - Part 12 of 196
The Ring programming language version 1.7 book - Part 12 of 196The Ring programming language version 1.7 book - Part 12 of 196
The Ring programming language version 1.7 book - Part 12 of 196
Mahmoud Samir Fayed
 
Quiniela
QuinielaQuiniela
Quiniela
jbersosa
 
XTW_Import
XTW_ImportXTW_Import
XTW_Import
Luther Quinn
 
Remote Notifications
Remote NotificationsRemote Notifications
Remote Notifications
Josef Cacek
 
Commit ускоривший python 2.7.11 на 30% и новое в python 3.5
Commit ускоривший python 2.7.11 на 30% и новое в python 3.5Commit ускоривший python 2.7.11 на 30% и новое в python 3.5
Commit ускоривший python 2.7.11 на 30% и новое в python 3.5
PyNSK
 
Java programs
Java programsJava programs
Java programs
jojeph
 
Using Flow-based programming to write tools and workflows for Scientific Comp...
Using Flow-based programming to write tools and workflows for Scientific Comp...Using Flow-based programming to write tools and workflows for Scientific Comp...
Using Flow-based programming to write tools and workflows for Scientific Comp...
Samuel Lampa
 
Dagger & rxjava & retrofit
Dagger & rxjava & retrofitDagger & rxjava & retrofit
Dagger & rxjava & retrofit
Ted Liang
 
Don't do this
Don't do thisDon't do this
Don't do this
Richard Jones
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101
Ankur Gupta
 
Python and sysadmin I
Python and sysadmin IPython and sysadmin I
Python and sysadmin I
Guixing Bai
 
The Ring programming language version 1.5.3 book - Part 26 of 184
The Ring programming language version 1.5.3 book - Part 26 of 184The Ring programming language version 1.5.3 book - Part 26 of 184
The Ring programming language version 1.5.3 book - Part 26 of 184
Mahmoud Samir Fayed
 
Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010
Qiangning Hong
 

What's hot (20)

Plugins by tagomoris #fluentdcasual
Plugins by tagomoris #fluentdcasualPlugins by tagomoris #fluentdcasual
Plugins by tagomoris #fluentdcasual
 
The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185
 
Using New Web APIs For Your Own Pleasure – How I Wrote New Features For My Vi...
Using New Web APIs For Your Own Pleasure – How I Wrote New Features For My Vi...Using New Web APIs For Your Own Pleasure – How I Wrote New Features For My Vi...
Using New Web APIs For Your Own Pleasure – How I Wrote New Features For My Vi...
 
JavaFX, because you're worth it
JavaFX, because you're worth itJavaFX, because you're worth it
JavaFX, because you're worth it
 
Introduction to JavaFX 2
Introduction to JavaFX 2Introduction to JavaFX 2
Introduction to JavaFX 2
 
Ejemplo radio
Ejemplo radioEjemplo radio
Ejemplo radio
 
Euro python2011 High Performance Python
Euro python2011 High Performance PythonEuro python2011 High Performance Python
Euro python2011 High Performance Python
 
The Ring programming language version 1.7 book - Part 12 of 196
The Ring programming language version 1.7 book - Part 12 of 196The Ring programming language version 1.7 book - Part 12 of 196
The Ring programming language version 1.7 book - Part 12 of 196
 
Quiniela
QuinielaQuiniela
Quiniela
 
XTW_Import
XTW_ImportXTW_Import
XTW_Import
 
Remote Notifications
Remote NotificationsRemote Notifications
Remote Notifications
 
Commit ускоривший python 2.7.11 на 30% и новое в python 3.5
Commit ускоривший python 2.7.11 на 30% и новое в python 3.5Commit ускоривший python 2.7.11 на 30% и новое в python 3.5
Commit ускоривший python 2.7.11 на 30% и новое в python 3.5
 
Java programs
Java programsJava programs
Java programs
 
Using Flow-based programming to write tools and workflows for Scientific Comp...
Using Flow-based programming to write tools and workflows for Scientific Comp...Using Flow-based programming to write tools and workflows for Scientific Comp...
Using Flow-based programming to write tools and workflows for Scientific Comp...
 
Dagger & rxjava & retrofit
Dagger & rxjava & retrofitDagger & rxjava & retrofit
Dagger & rxjava & retrofit
 
Don't do this
Don't do thisDon't do this
Don't do this
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101
 
Python and sysadmin I
Python and sysadmin IPython and sysadmin I
Python and sysadmin I
 
The Ring programming language version 1.5.3 book - Part 26 of 184
The Ring programming language version 1.5.3 book - Part 26 of 184The Ring programming language version 1.5.3 book - Part 26 of 184
The Ring programming language version 1.5.3 book - Part 26 of 184
 
Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010
 

Similar to T-DOSE 2015: Using Python, PHP, JQuery and Linux to visualize the heartrate and blood oxygen saturation level of my stepdaughter

Cluj.py Meetup: Extending Python in C
Cluj.py Meetup: Extending Python in CCluj.py Meetup: Extending Python in C
Cluj.py Meetup: Extending Python in C
Steffen Wenz
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
Wim Godden
 
Sq lite python tutorial sqlite programming in python
Sq lite python tutorial   sqlite programming in pythonSq lite python tutorial   sqlite programming in python
Sq lite python tutorial sqlite programming in python
Martin Soria
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
Wim Godden
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
Alexander Granin
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
Wim Godden
 
PythonBrasil[8] - CPython for dummies
PythonBrasil[8] - CPython for dummiesPythonBrasil[8] - CPython for dummies
PythonBrasil[8] - CPython for dummies
Tatiana Al-Chueyr
 
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
DRVaibhavmeshram1
 
MySQL JSON Functions
MySQL JSON FunctionsMySQL JSON Functions
MySQL JSON Functions
Sveta Smirnova
 
Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8
Nikita Popov
 
XML-RPC vs Psycopg2
XML-RPC vs Psycopg2XML-RPC vs Psycopg2
XML-RPC vs Psycopg2
Associazione Odoo Italia
 
pcDuino Presentation at SparkFun
pcDuino Presentation at SparkFunpcDuino Presentation at SparkFun
pcDuino Presentation at SparkFun
Jingfeng Liu
 
Managing MariaDB Server operations with Percona Toolkit
Managing MariaDB Server operations with Percona ToolkitManaging MariaDB Server operations with Percona Toolkit
Managing MariaDB Server operations with Percona Toolkit
Sveta Smirnova
 
The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202
Mahmoud Samir Fayed
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
Wim Godden
 
Beyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeBeyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the code
Wim Godden
 
sonam Kumari python.ppt
sonam Kumari python.pptsonam Kumari python.ppt
sonam Kumari python.ppt
ssuserd64918
 
Windbg랑 친해지기
Windbg랑 친해지기Windbg랑 친해지기
Windbg랑 친해지기
Ji Hun Kim
 
Python programming Workshop SITTTR - Kalamassery
Python programming Workshop SITTTR - KalamasseryPython programming Workshop SITTTR - Kalamassery
Python programming Workshop SITTTR - Kalamassery
SHAMJITH KM
 
Best Practices in Handling Performance Issues
Best Practices in Handling Performance IssuesBest Practices in Handling Performance Issues
Best Practices in Handling Performance Issues
Odoo
 

Similar to T-DOSE 2015: Using Python, PHP, JQuery and Linux to visualize the heartrate and blood oxygen saturation level of my stepdaughter (20)

Cluj.py Meetup: Extending Python in C
Cluj.py Meetup: Extending Python in CCluj.py Meetup: Extending Python in C
Cluj.py Meetup: Extending Python in C
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
 
Sq lite python tutorial sqlite programming in python
Sq lite python tutorial   sqlite programming in pythonSq lite python tutorial   sqlite programming in python
Sq lite python tutorial sqlite programming in python
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
 
PythonBrasil[8] - CPython for dummies
PythonBrasil[8] - CPython for dummiesPythonBrasil[8] - CPython for dummies
PythonBrasil[8] - CPython for dummies
 
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
Introduction to Python 01-08-2023.pon by everyone else. . Hence, they must be...
 
MySQL JSON Functions
MySQL JSON FunctionsMySQL JSON Functions
MySQL JSON Functions
 
Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8
 
XML-RPC vs Psycopg2
XML-RPC vs Psycopg2XML-RPC vs Psycopg2
XML-RPC vs Psycopg2
 
pcDuino Presentation at SparkFun
pcDuino Presentation at SparkFunpcDuino Presentation at SparkFun
pcDuino Presentation at SparkFun
 
Managing MariaDB Server operations with Percona Toolkit
Managing MariaDB Server operations with Percona ToolkitManaging MariaDB Server operations with Percona Toolkit
Managing MariaDB Server operations with Percona Toolkit
 
The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
 
Beyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeBeyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the code
 
sonam Kumari python.ppt
sonam Kumari python.pptsonam Kumari python.ppt
sonam Kumari python.ppt
 
Windbg랑 친해지기
Windbg랑 친해지기Windbg랑 친해지기
Windbg랑 친해지기
 
Python programming Workshop SITTTR - Kalamassery
Python programming Workshop SITTTR - KalamasseryPython programming Workshop SITTTR - Kalamassery
Python programming Workshop SITTTR - Kalamassery
 
Best Practices in Handling Performance Issues
Best Practices in Handling Performance IssuesBest Practices in Handling Performance Issues
Best Practices in Handling Performance Issues
 

More from Jeroen Baten

2012: Gastcollege hogeschool utrecht
2012: Gastcollege hogeschool utrecht2012: Gastcollege hogeschool utrecht
2012: Gastcollege hogeschool utrecht
Jeroen Baten
 
T-DOSE 2015: The current state of the LibrePlan project
T-DOSE 2015: The current state of the LibrePlan projectT-DOSE 2015: The current state of the LibrePlan project
T-DOSE 2015: The current state of the LibrePlan project
Jeroen Baten
 
T-DOSE 2016: Keynote "Why we are all going to shit in 30 years due to computers"
T-DOSE 2016: Keynote "Why we are all going to shit in 30 years due to computers"T-DOSE 2016: Keynote "Why we are all going to shit in 30 years due to computers"
T-DOSE 2016: Keynote "Why we are all going to shit in 30 years due to computers"
Jeroen Baten
 
Running your mainframe on linux (for fun and profit)
Running your mainframe on linux (for fun and profit)Running your mainframe on linux (for fun and profit)
Running your mainframe on linux (for fun and profit)
Jeroen Baten
 
The case for a Dutch ANBS foundation
The case for a Dutch ANBS foundationThe case for a Dutch ANBS foundation
The case for a Dutch ANBS foundation
Jeroen Baten
 
A new document_workflow_for_the_government
A new document_workflow_for_the_governmentA new document_workflow_for_the_government
A new document_workflow_for_the_government
Jeroen Baten
 

More from Jeroen Baten (6)

2012: Gastcollege hogeschool utrecht
2012: Gastcollege hogeschool utrecht2012: Gastcollege hogeschool utrecht
2012: Gastcollege hogeschool utrecht
 
T-DOSE 2015: The current state of the LibrePlan project
T-DOSE 2015: The current state of the LibrePlan projectT-DOSE 2015: The current state of the LibrePlan project
T-DOSE 2015: The current state of the LibrePlan project
 
T-DOSE 2016: Keynote "Why we are all going to shit in 30 years due to computers"
T-DOSE 2016: Keynote "Why we are all going to shit in 30 years due to computers"T-DOSE 2016: Keynote "Why we are all going to shit in 30 years due to computers"
T-DOSE 2016: Keynote "Why we are all going to shit in 30 years due to computers"
 
Running your mainframe on linux (for fun and profit)
Running your mainframe on linux (for fun and profit)Running your mainframe on linux (for fun and profit)
Running your mainframe on linux (for fun and profit)
 
The case for a Dutch ANBS foundation
The case for a Dutch ANBS foundationThe case for a Dutch ANBS foundation
The case for a Dutch ANBS foundation
 
A new document_workflow_for_the_government
A new document_workflow_for_the_governmentA new document_workflow_for_the_government
A new document_workflow_for_the_government
 

Recently uploaded

Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
Jason Packer
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
MichaelKnudsen27
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
Tatiana Kojar
 
Webinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data WarehouseWebinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data Warehouse
Federico Razzoli
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
Project Management Semester Long Project - Acuity
Project Management Semester Long Project - AcuityProject Management Semester Long Project - Acuity
Project Management Semester Long Project - Acuity
jpupo2018
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
akankshawande
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
Jakub Marek
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
Hiroshi SHIBATA
 
Mariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceXMariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceX
Mariano Tinti
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
SitimaJohn
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
Zilliz
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
Postman
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
IndexBug
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
Zilliz
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
shyamraj55
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
kumardaparthi1024
 

Recently uploaded (20)

Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
 
Webinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data WarehouseWebinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data Warehouse
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
Project Management Semester Long Project - Acuity
Project Management Semester Long Project - AcuityProject Management Semester Long Project - Acuity
Project Management Semester Long Project - Acuity
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
 
Mariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceXMariano G Tinti - Decoding SpaceX
Mariano G Tinti - Decoding SpaceX
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
 

T-DOSE 2015: Using Python, PHP, JQuery and Linux to visualize the heartrate and blood oxygen saturation level of my stepdaughter

  • 1. 1 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Using Python, PHP, JQuery and Linux to visualize the heartrate and blood oxygen saturation level of my stepdaughter Jeroen Baten T-DOSE 2015
  • 2. 2 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels TOC Who am I Who is Anouschka? What happened What I did How it worked out The end...
  • 3. 3 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Who am I? ● Jeroen Baten ● Open Source geek since 1997 ● Sofar 9 books and 2 columns ● Job title : all-round IT problem fixer ● (former) Volunteer Firefighter ● Scouting
  • 4. 4 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Who am I ? (in pics)
  • 5. 5 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Who the f*ck is this Anouschka? Name: Anouschka van G. DOB: 18-1-1997 Current age: 18 years Diagnosis: Spina Bifida Aperta L3-L5 Arnold Chiari Malformation Hydrocephalus Number of surgeries till today: 43 Number of hospital sessions: stopped counting
  • 6. 6 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Hospital life….
  • 7. 7 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Some surgery examples
  • 8. 8 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels The surgery session where our journey starts Reason: chronic pain in hip joint Cause: insufficient joint development Post surgery: Low oxygen levels during sleep Questions: Source/origin? How severe? How to fix?
  • 9. 9 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Actions taken by pediatrician at WKZ Polysomnografy at AMC. This takes 24 hours. Result: varying (85-90%) O2-levels at night. Values found are in “grey” area. Oxygen measures introduced at home. Pediatrician: “If only we had more data….” “But please not a huge table with data.”
  • 10. 10 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Oxygen concentrator + saturation measurement Oxygen concentrator for producing O2: Philips Everflo oxygen concentrator No matter what people say: these things are loud at night! Saturation measurement for correct level feedback + alarm: Masimo RAD-8 saturation measurement device. And so we begin But what is that I see on the back of the Rad-8?
  • 11. 11 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels RS-232! That looks like…. No, it IS an RS-232 port! Google…. Masimo-Rad-8-User-Manual.pdf
  • 12. 12 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Manual adventures What does the manual say? 09/01/14 04:01:41 SN=0000051252 SPO2=092% BPM=086 PI=01.03% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000800 What do we get….?
  • 13. 13 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Step 1: make database Use simple database: MySQL Make simple table: CREATE TABLE `data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `tijd` datetime DEFAULT NULL, `data` varchar(150) DEFAULT NULL, `spo2` int(11) DEFAULT NULL, `bpm` int(11) DEFAULT NULL, `session` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `tijd3` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY `id` (`id`), KEY `session_index` (`session`), KEY `tijd_index` (`tijd`), KEY `spo2_index` (`spo2`) )
  • 14. 14 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Step 2: python #!/usr/bin/python print "Loading libraries" import serial, time, os import logging import logging.handlers import MySQLdb import datetime version="1.0" def log(msg): print msg my_logger.debug(os.path.basename(__file__)+":"+msg) print "Initialising logging" my_logger = logging.getLogger('MyLogger') my_logger.setLevel(logging.DEBUG) handler = logging.handlers.SysLogHandler(address = '/dev/log') my_logger.addHandler(handler) log("Log-RAD-8 version "+version) log("Copyright 2014 J. Baten") log("") log("Logging serial data from Masimo RAD-8 serial port") log("Note: Works only with RAD-8 serial port set to 'ASC1'") log("") #my_logger.debug('this is debug') #my_logger.critical('this is critical') log("Initialising database connection") #setting up database connection #create table data (id int auto_increment, tijd timestamp, data varchar(150), key(id) ); #+-------+--------------+------+-----+-------------------+-----------------------------+ #| Field | Type | Null | Key | Default | Extra | #+-------+--------------+------+-----+-------------------+-----------------------------+ #| id | int(11) | NO | MUL | NULL | auto_increment | #| tijd | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | #| data | varchar(150) | YES | | NULL | | #+-------+--------------+------+-----+-------------------+-----------------------------+ try: conn = MySQLdb.connect(host= "10.1.1.1", user="lograd8", passwd="lograd8", db="lograd8") except MySQLdb.Error, e: log( "ERROR %d IN CONNECTION: %s" % (e.args[0], e.args[1])) #except MySQLdb.Error: #log("ERROR IN CONNECTION") exit(2) x = conn.cursor() #x.execute("SELECT * FROM anooog1") #x.execute (" INSERT INTO anooog1 VALUES ('%s','%s') ", (188,90)) #row = x.fetchall() now = datetime.datetime.now() #print now log("Program started at "+str(now)) #today8am = now.replace(hour=8, minute=0, second=0, microsecond=0) today = datetime.datetime.today() #print today one_day = datetime.timedelta(days=1) tomorrow = today + one_day #print 'Tomorrow :', tomorrow endtime= tomorrow.replace(hour=8, minute=0, second=0, microsecond=0) log("Logging should stop at "+ str(endtime)) #initialization and open the port #possible timeout values: # 1. None: wait forever, block call # 2. 0: non-blocking mode, return immediately # 3. x, x is bigger than 0, float allowed, timeout block call log( "Initializing port") ser = serial.Serial() #ser.port = "/dev/ttyUSB0" ser.port = "/dev/ttyS0" #ser.port = "/dev/ttyS2" ser.baudrate = 9600 ser.bytesize = serial.EIGHTBITS #number of bits per bytes ser.parity = serial.PARITY_NONE #set parity check: no parity ser.stopbits = serial.STOPBITS_ONE #number of stop bits #ser.timeout = None #block read ser.timeout = 1 #non-block read #ser.timeout = 2 #timeout block read ser.xonxoff = False #disable software flow control ser.rtscts = False #disable hardware (RTS/CTS) flow control ser.dsrdtr = False #disable hardware (DSR/DTR) flow control ser.writeTimeout = 2 #timeout for write try: log( "Trying to open serial port") ser.open() except Exception, e: log( "error open serial port: " + str(e)) exit(1) if ser.isOpen(): log( "Port succesfully opened") try: log( "Flushing port data") ser.flushInput() #flush input buffer, discarding all its contents ser.flushOutput()#flush output buffer, aborting current output #and discard all that is in buffer #write data #ser.write("AT+CSQ") #time.sleep(0.5) #give the serial port sometime to receive the data while True: response = ser.readline() print response response = MySQLdb.escape_string(response) print(response) if (len(response)>5): try: x.execute ("INSERT INTO data (tijd,data) VALUES (now(),%s) ", response) conn.commit() except MySQLdb.Error, e: log( "ERROR %d IN CONNECTION: %s" % (e.args[0], e.args[1])) log( "Last query was: "+ x._last_executed ) # Is it time to stop yet? #endtime= now+ datetime.timedelta(seconds=5) now = datetime.datetime.now() if (now > endtime): break ser.close() except Exception, e1: log( "error communicating...: " + str(e1)) else: log( "cannot open serial port ") conn.close()
  • 15. 15 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Step 3: What do we have? MySQL [(none)]> use lograd8 Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed MySQL [lograd8]> show tables; +-------------------+ | Tables_in_lograd8 | +-------------------+ | data | +-------------------+ 1 row in set (0.00 sec) MySQL [lograd8]> select count(*) from data; +----------+ | count(*) | +----------+ | 717298 | +----------+ 1 row in set (0.68 sec) MySQL [lograd8]> select * from data limit 5; +----+---------------------+-----------------------------------------------------------------------------------------------------------------------------------+------+------+---------------------+---------------------+ | id | tijd | data | spo2 | bpm | session | tijd3 | +----+---------------------+-----------------------------------------------------------------------------------------------------------------------------------+------+------+---------------------+---------------------+ | 9 | 2014-09-02 15:00:18 | 00/00/00 00:00:03 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:18 | 0000-00-00 00:00:00 | | 10 | 2014-09-02 15:00:19 | 09/02/14 04:58:09 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:19 | 0000-00-00 00:00:00 | | 11 | 2014-09-02 15:00:20 | 09/02/14 04:58:10 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:20 | 0000-00-00 00:00:00 | | 12 | 2014-09-02 15:00:21 | 09/02/14 04:58:11 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:21 | 0000-00-00 00:00:00 | | 13 | 2014-09-02 15:00:22 | 09/02/14 04:58:12 SN=0000051252 SPO2=---% BPM=--- PI=--.--% SPCO=--.-% SPMET=--.-% DESAT=-- PIDELTA=+-- ALARM=0000 EXC=000000rn | 0 | 0 | 2014-09-02 03:00:22 | 0000-00-00 00:00:00 | +----+---------------------+-----------------------------------------------------------------------------------------------------------------------------------+------+------+---------------------+---------------------+ 5 rows in set (0.02 sec) MySQL [lograd8]> MySQL [lograd8]> select count(*),date_format(session,"%d/%m/%Y") from data group by date(session); +----------+---------------------------------+ | count(*) | date_format(session,"%d/%m/%Y") | +----------+---------------------------------+ | 181711 | 00/00/0000 | | 11200 | 02/09/2014 | | 36399 | 03/09/2014 | | 34166 | 04/09/2014 | | 42495 | 05/09/2014 | | 38313 | 09/09/2014 | | 37392 | 10/09/2014 | | 37279 | 11/09/2014 | | 35972 | 12/09/2014 | | 35467 | 13/09/2014 | | 35761 | 14/09/2014 | | 34845 | 15/09/2014 | | 36510 | 16/09/2014 | | 38400 | 17/09/2014 | | 37797 | 18/09/2014 | | 23 | 23/09/2014 | | 43568 | 26/09/2014 | +----------+---------------------------------+ 17 rows in set (0.65 sec) MySQL [lograd8]>
  • 16. 16 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Step 4: turn raw data into usefull data Need to get BPM and O2 from string. And fix the date! update data set spo2=substring(data,38,3); update data set bpm=substring(data,47,3); update data set session=DATE_SUB(tijd, INTERVAL 12 HOUR);
  • 17. 17 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Step 4: visualize quick and dirty => PHP! Use PHP and Jquery (for date selection) Find easy PHP visualisation lib... JpGraph? No longer leading. Google Charts javascript lib can't be wrong right? Wrong! DyGraph! Send it CSV formatted data. Done! Including zoom functionality. Yay!
  • 18. 18 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels The result First results...
  • 19. 19 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Results: DyGraph to the rescue Working with small range averages
  • 20. 20 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Results: graphing ALL data... <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Saturatie weergave</title> <link rel="stylesheet" href="jquery/jquery-ui.min.css"> <link rel="stylesheet" href="get-sat.css"> <script type="text/javascript" src="dygraph-combined.js"></script> </head> <body> <div class="box" id="spo2_div" style="width:95%"> <h3>SPO2</h3> </div> <div class="box" id="bpm_div" style="width:95%"> <h3>SPO2</h3> </div> <script> <!-- console.log(startdate); --> g = new Dygraph( document.getElementById("spo2_div"), "get-data3spo.php", // path to CSV file { // rollPeriod: 7, legend: 'always', animatedZooms: true, showRoller: true //errorBars: true, //valueRange: [40,100]} // options } ); g = new Dygraph( document.getElementById("bpm_div"), "get-data3bpm.php", // path to CSV file { // rollPeriod: 7, legend: 'always', animatedZooms: true, showRoller: true //errorBars: true, //valueRange: [40,100]} // options } ); </script> </body> </html> <?php ini_set("error_reporting",E_ALL); syslog(LOG_DEBUG,"Start get-data.php"); # set db connection parameters $dbhost="10.1.1.1"; #$dbhost="127.0.0.1"; $dblogin="lograd8"; $dbpwd="secret"; $dbname="lograd8"; $db = mysql_connect($dbhost,$dblogin,$dbpwd); mysql_select_db($dbname); $rows = "DatumTijd,gem_SPO2,spreiding_SPO2,max_SPO2,min_SPO2n"; #$startdate = $_POST['startdate']; $former=0; $query = "select date_format(tijd,'%Y/%m/%d %H:00') as datum, avg(spo2) as gem_spo2, std(spo2) as spreiding_spo2, max(spo2) as max_spo2, min(spo2) as min_spo2 from data group by date_format(session,'%d/%m/%Y %H');"; # +---------------+----------+----------------+----------+----------+ # | datum_uur | gem_spo2 | spreiding_spo2 | max_spo2 | min_spo2 | # +---------------+----------+----------+----------------+----------+ syslog(LOG_DEBUG,"$query"); $result = mysql_query($query); while($r = mysql_fetch_array($result)){ #syslog(LOG_DEBUG,print_r($r,TRUE)); $rij=""; # vervangen min=0 door min=avg bij spo2 en bpm if ($r[4]==0) $r[4]=$r[1]; for ($i=0;$i<=4;$i++) { $rij = $rij.$r[$i].","; } $rij=substr($rij,0,strlen($rij)-1); $rows = $rows.$rij."n"; } #syslog(LOG_DEBUG,print_r($rows,TRUE)); #syslog(LOG_DEBUG,print_r($rows,TRUE)); #echo $cols . '"rows":[',$google_JSON_row ."]}"; # output off json string to caller. echo $rows; # saving of cvs string for debugging purposes #$fh=fopen("/tmp/get-data.cvs","w"); #fwrite($fh,$rows); #fclose($fh); mysql_close($db); syslog(LOG_DEBUG,"Einde get-data.phpnn"); ?> <?php ini_set("error_reporting",E_ALL); syslog(LOG_DEBUG,"Start get-data.php"); # set db connection parameters $dbhost="10.1.1.1"; #$dbhost="127.0.0.1"; $dblogin="lograd8"; $dbpwd="secret"; $dbname="lograd8"; $db = mysql_connect($dbhost,$dblogin,$dbpwd); mysql_select_db($dbname); $rows = "DatumTijd,gem_BPM,spreiding_BPM,max_BPM,min_BPMn"; $former=0; $query = "select date_format(tijd,'%Y/%m/%d %H:00') as datum, avg(bpm) as gem_bpm, std(bpm) as spreiding_bpm, max(bpm) as max_bpm, min(bpm) as min_bpm from data group by date_format(session,'%d/%m/%Y %H');"; # +---------------+----------+---------------+---------+---------+ # | datum_uur | gem_bpm | spreiding_bpm | max_bpm | min_bpm | # +---------------+----------+---------------+---------+---------+ syslog(LOG_DEBUG,"$query"); $result = mysql_query($query); while($r = mysql_fetch_array($result)){ #syslog(LOG_DEBUG,print_r($r,TRUE)); #syslog(LOG_DEBUG,print_r($tijd,TRUE)); $rij=""; # replace min=0 by min=avg for spo2 and bpm if ($r[4]==0) $r[4]=$r[1]; for ($i=0;$i<=4;$i++) { $rij = $rij.$r[$i].","; } $rij=substr($rij,0,strlen($rij)-1); $rows = $rows.$rij."n"; } #syslog(LOG_DEBUG,print_r($rows,TRUE)); #syslog(LOG_DEBUG,print_r($rows,TRUE)); #echo $cols . '"rows":[',$google_JSON_row ."]}"; # output off json string to caller. echo $rows; # saving of cvs string for debugging purposes #$fh=fopen("/tmp/get-data2.cvs","w"); #fwrite($fh,$rows); #fclose($fh); mysql_close($db); syslog(LOG_DEBUG,"Einde get-data.phpnn"); ?> Index.php oxygen.php bpm.php
  • 21. 21 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels New result Can you see the problem?
  • 22. 22 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels New result Let me show you...
  • 23. 23 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Findings Medical: When not connected to O2 during the night the minimum rates will continue to drop during several days. Ergo: O2 always needed. Techical: Next time make a stored procedure and a trigger to update records upon creation.
  • 24. 24 Using Python, PHP, JQuery and Linux to visualize oxygen saturation levels Anouschka thanks you … Thanks for your attention. Any questions?