<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Analysis of neonatal ventilator alarms
Author
Step1:  Import modules containing own functions
Step2:  List and set the working directory and the directories to write out data
Step3:  List of the  recordings
Step4:  Import clinical details
Step5:  Import ventilator parameters retrieved with 1/sec frequency
Step6:  Calculating parameters / body weight kg
Step7:  Resampling to remove half-empty rows
Step8:  Save processed slow_measurements DataFrames to pickle archive
Step9:  Import processed 'slow_measurements' data from pickle archive
Calculate recording durations
Step10:  Visualising recording durations
Step11:  Write recording times out into files
Step12:  Import ventilator modes and settings
Import ventilation settings
Step13:  Import ventilation modes
Step14:  Save ventilation modes and settings into Excel files
Step15:  Import alarm settings
Step16:  Import alarm states
Step17:  Calculate the total and average time of all recordings
Step18:  Generate alarm events from alarm states
Step19:  Using the files containing the alarm states, for each alarm category in each recording create a DataFrame with the timestamps the alarm went off and the duration of the alarm and store them in a dictionary of dictionaries
Step20:  Calculate descriptive statistics for each alarm in each recording and write them to file
Step21:  Visualise alarm statistics for the individual alarms in the individual recording
Step22:  Example plots
Step23:  Write all graphs to files
Generate cumulative descriptive statistics of all alarms combined in each recording
For each recording, what was the total number of alarm events and the number of events normalized for 24 hour periods
Step24:  In each recording, what was the mean, median, sd, mad, min, 25pc, 75pc, max of alarm durations
Step25:  Visualize cumulative statistics of recordings
Step26:  Generate cumulative statistics of each alarm in all recordings combined
Step27:  For each alarm, what was number of alarm events across all recordings and the number of events normalized per 24 hour recording time
Step28:  For each alarm, what was the total duration of alarm events across all recordings and normalized per 24 hour recording time
Step29:  For each alarm what was the mean, median, sd, mad, min, 25pc, 75pc, max of alarm durations
Step30:  Visualising cumulative statistics of alarms
Step31:  Calculate cumulative descriptive statistics of all alarms in all recording together
Step32:  Visualise the duration of all alarm events as histogram
Step33:  How many short alarms did occur?
Step34:  Check which are the longest alarms
Step35:  How many alarm events are longer than 10 minutes but shorter than 1 hour?¶
Step36:  how many alarm events are longer than 1 minutes?¶
Step37:  Check which are the most frequent alarms
Step38:  Visualise MV and RR limit alarms
Generate dictionaries with the alarm counts (absolute and per 24H recording period) for MV low and high alarms and RR high alarms for those recordings where this occurs
Step39:  Investigate the relationship of MV and RR parameter readings, ventilation settings and alarm settings
Step40:  Create the tables and figures of the paper
Table 1
Step41:  Figure 1
Step42:  Figure 2
Step43:  Figure 3
<ASSISTANT_TASK:>
Python Code:
import IPython
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import os
import sys
import pickle
import scipy as sp
from scipy import stats
from pandas import Series, DataFrame
from datetime import datetime, timedelta
%matplotlib inline
matplotlib.style.use('classic')
matplotlib.rcParams['figure.facecolor'] = 'w'
pd.set_option('display.max_rows', 100)
pd.set_option('display.max_columns', 100)
pd.set_option('mode.chained_assignment', None)
print("Python version: {}".format(sys.version))
print("IPython version: {}".format(IPython.__version__))
print("pandas version: {}".format(pd.__version__))
print("matplotlib version: {}".format(matplotlib.__version__))
print("NumPy version: {}".format(np.__version__))
print("SciPy version: {}".format(sp.__version__))
Explanation: Analysis of neonatal ventilator alarms
Author: Dr Gusztav Belteki
This Notebook contains the code used for data processing, statistical analysis and 
visualization described in the following paper: 
Belteki G, Morley CJ. Frequency, duration and cause of ventilator alarms on a
neonatal intensive care unit. Arch Dis Child Fetal Neonatal Ed.
2018 Jul;103(4):F307-F311. doi: 10.1136/archdischild-2017-313493.
Epub 2017 Oct 27. PubMed PMID: 29079651.
Link to the paper: https://fn.bmj.com/content/103/4/F307.long
Contact: gusztav.belteki@addenbrookes.nhs.uk; gbelteki@aol.com
Importing the required libraries and setting options
End of explanation
from gb_loader import *
from gb_stats import *
from gb_transform import *
Explanation: Import modules containing own functions
End of explanation
# Topic of the Notebook which will also be the name of the subfolder containing results
TOPIC = 'alarms_2'
# Name of the external hard drive
DRIVE = 'GUSZTI'
# Directory containing clinical and blood gas data
CWD = '/Users/guszti/ventilation_data'
# Directory on external drive to read the ventilation data from
DIR_READ = '/Volumes/%s/ventilation_data' % DRIVE
# Directory to write results and selected images to 
if not os.path.isdir('%s/%s/%s' % (CWD, 'Analyses', TOPIC)):
    os.makedirs('%s/%s/%s' % (CWD, 'Analyses', TOPIC))
DIR_WRITE = '%s/%s/%s' % (CWD, 'Analyses', TOPIC)
# Images and raw data will be written on an external hard drive
if not os.path.isdir('/Volumes/%s/data_dump/%s' % (DRIVE, TOPIC)):
    os.makedirs('/Volumes/%s/data_dump/%s' % (DRIVE, TOPIC))
DATA_DUMP = '/Volumes/%s/data_dump/%s' % (DRIVE, TOPIC)
os.chdir(CWD)
os.getcwd()
DIR_READ
DIR_WRITE
DATA_DUMP
Explanation: List and set the working directory and the directories to write out data
End of explanation
# One recording from each patient, all of them 24 hours old or longer
# The sub folders containing the individual recordings have the same names within cwd
recordings = ['DG001', 'DG002_1', 'DG003', 'DG004', 'DG005_1', 'DG006_2',  'DG007', 'DG008', 'DG009', 'DG010',
              'DG011',  'DG013', 'DG014', 'DG015', 'DG016', 'DG017', 'DG018_1', 'DG020',
              'DG021', 'DG022', 'DG023',  'DG025', 'DG026', 'DG027', 'DG028', 'DG029', 'DG030',
              'DG031',  'DG032_2', 'DG033', 'DG034', 'DG035',  'DG037', 'DG038_1', 'DG039', 'DG040_1', 'DG041', 
              'DG042', 'DG043', 'DG044', 'DG045', 'DG046_2', 'DG047', 'DG048', 'DG049', 'DG050']
Explanation: List of the  recordings
End of explanation
clinical_details = pd.read_excel('%s/data_grabber_patient_data_combined.xlsx' % CWD)
clinical_details.index = clinical_details['Recording']
clinical_details.info()
current_weights = {}
for recording in recordings:
    current_weights[recording] = clinical_details.loc[recording, 'Current weight' ] / 1000
Explanation: Import clinical details
End of explanation
slow_measurements = {}
for recording in recordings:
    flist = os.listdir('%s/%s' % (DIR_READ, recording))
    flist = [file for file in flist if not file.startswith('.')] # There are some hidden 
    # files on the hard drive starting with '.'; this step is necessary to ignore them
    files = slow_measurement_finder(flist)
    print('Loading recording %s' % recording)
    print(files)
    fnames = ['%s/%s/%s' % (DIR_READ, recording, filename) for filename in files]
    slow_measurements[recording] =  data_loader(fnames)
# 46 recordings from 46 patients (4 recordings excluded as they were < 24 hours lon)
len(slow_measurements)
Explanation: Import ventilator parameters retrieved with 1/sec frequency
End of explanation
for recording in recordings:
    try:
        a = slow_measurements[recording]
        a['VT_kg']       = a['5001|VT [mL]'] / current_weights[recording]
        a['VTi_kg']      = a['5001|VTi [mL]'] / current_weights[recording]
        a['VTe_kg']      = a['5001|VTe [mL]'] / current_weights[recording]
        a['VTmand_kg']   = a['5001|VTmand [mL]'] / current_weights[recording]
        a['VTspon_kg']   = a['5001|VTspon [mL]'] / current_weights[recording]
        a['VTimand_kg']  = a['5001|VTimand [mL]'] / current_weights[recording]
        a['VTemand_kg']  = a['5001|VTemand [mL]'] / current_weights[recording]
        a['VTispon_kg']  = a['5001|VTispon [mL]'] / current_weights[recording]
        a['VTespon_kg']  = a['5001|VTespon [mL]'] / current_weights[recording]
    except KeyError:
        # print('%s does not have all of the parameters' % recording)
        pass
for recording in recordings:
    try:
        a = slow_measurements[recording]
        a['VThf_kg']      = a['5001|VThf [mL]'] / current_weights[recording]
        a['DCO2_corr_kg'] = a['5001|DCO2 [10*mL^2/s]'] * 10 / (current_weights[recording]) ** 2
    except KeyError:
        # print('%s does not have all of the parameters' % recording)
        pass
for recording in recordings:
    try:
        a = slow_measurements[recording]
        a['MV_kg'] =      a['5001|MV [L/min]'] / current_weights[recording]
        a['MVi_kg'] =     a['5001|MVi [L/min]'] / current_weights[recording]
        a['MVe_kg'] =     a['5001|MVe [L/min]'] / current_weights[recording]
        a['MVemand_kg'] = a['5001|MVemand [L/min]'] / current_weights[recording]
        a['MVespon_kg'] = a['5001|MVespon [L/min]'] / current_weights[recording]
        a['MVleak_kg'] =  a['5001|MVleak [L/min]'] / current_weights[recording]
    except KeyError:
        # print('%s does not have all of the parameters' % recording)
        pass
Explanation: Calculating parameters / body weight kg
End of explanation
# 1/sec data are retrieved in two parts which need to be joined
# This resampling steps combines the two parts
for recording in recordings:
    slow_measurements[recording] = slow_measurements[recording].resample('1S').mean()
# Example
slow_measurements['DG003'].head();
Explanation: Resampling to remove half-empty rows
End of explanation
len(recordings)
rec1 = recordings[:15]; rec2 = recordings[15:30]; rec3 = recordings[30:40]; rec4 = recordings[40:] 
Explanation: Save processed slow_measurements DataFrames to pickle archive
End of explanation
# Time stamps are obtained from 'slow measurements' 
recording_duration = {}
for recording in recordings:
    recording_duration[recording] = slow_measurements[recording].index[-1] - slow_measurements[recording].index[0]
recording_duration_seconds = {}
recording_duration_hours = {}
for recording in recordings:
    temp = recording_duration[recording]
    recording_duration_seconds[recording] = temp.total_seconds()
    recording_duration_hours[recording] = temp.total_seconds() / 3600
Explanation: Import processed 'slow_measurements' data from pickle archive
Calculate recording durations
End of explanation
v = list(range(1, len(recordings)+1))
w = [value for key, value in sorted(recording_duration_hours.items()) if key in recordings]
fig = plt.figure()
fig.set_size_inches(20, 10)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
ax1 = fig.add_subplot(1, 1, 1);
ax1.bar(v, w, color = 'blue')
plt.xlabel("Recordings", fontsize  = 22)
plt.ylabel("Hours", fontsize  = 22)
plt.title("Recording periods" , fontsize = 22)
plt.yticks(fontsize = 22)
plt.xticks([i+1.5  for i, _ in enumerate(recordings)], recordings, fontsize = 22, rotation = 'vertical');
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'recording_durations.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)    
Explanation: Visualising recording durations
End of explanation
recording_times_frame = DataFrame([recording_duration, recording_duration_hours, recording_duration_seconds],
                            index = ['days', 'hours', 'seconds'])
recording_times_frame
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'recording_periods.xlsx'))
recording_times_frame.to_excel(writer,'rec_periods')
writer.save()
Explanation: Write recording times out into files
End of explanation
vent_settings = {}
for recording in recordings:
    flist = os.listdir('%s/%s' % (DIR_READ, recording))
    flist = [file for file in flist if not file.startswith('.')] # There are some hidden 
    # files on the hard drive starting with '.'; this step is necessary to ignore them
    files = slow_setting_finder(flist)
    # print('Loading recording %s' % recording)
    # print(files)
    fnames = ['%s/%s/%s' % (DIR_READ, recording, filename) for filename in files]
    vent_settings[recording] =  data_loader(fnames)
# remove less important ventilator settings to simplify the table
vent_settings_selected = {}
for recording in recordings:
    vent_settings_selected[recording] = vent_settings_cleaner(vent_settings[recording])
# Create a another dictionary of Dataframes wit some of the ventilation settings (set VT, set RR, set Pmax)
lsts = [(['VT_weight'], ['VTi', 'VThf']), (['RR_set'], ['RR']), (['Pmax'], ['Pmax', 'Ampl hf max'])]
vent_settings_2 = {}
                                                            
for recording in recordings:
    frmes = []                                                       
    for name, pars in lsts:
        if pars in [['VTi', 'VThf']]:
            ind = []
            val = []
            for index, row in vent_settings_selected[recording].iterrows():
                if row['Id'] in pars:
                    ind.append(index)
                    val.append(row['Value New'] / current_weights[recording])
                frmes.append(DataFrame(val, index = ind, columns = name))
        else:
            ind = []
            val = []
            for index, row in vent_settings_selected[recording].iterrows():
                if row['Id'] in pars:
                    ind.append(index)
                    val.append(row['Value New'])
                frmes.append(DataFrame(val, index = ind, columns = name))
    vent_settings_2[recording] = pd.concat(frmes)
    vent_settings_2[recording].drop_duplicates(inplace = True)
Explanation: Import ventilator modes and settings
Import ventilation settings
End of explanation
vent_modes = {}
for recording in recordings:
    flist = os.listdir('%s/%s' % (DIR_READ, recording))
    flist = [file for file in flist if not file.startswith('.')] # There are some hidden 
    # files on the hard drive starting with '.'; this step is necessary to ignore them
    files = slow_text_finder(flist)
    # print('Loading recording %s' % recording)
    # print(files)
    fnames = ['%s/%s/%s' % (DIR_READ, recording, filename) for filename in files]
    vent_modes[recording] =  data_loader(fnames)
# remove less important ventilator mode settings to simplify the table
vent_modes_selected = {}
for recording in recordings:
    vent_modes_selected[recording] = vent_mode_cleaner(vent_modes[recording])
Explanation: Import ventilation modes
End of explanation
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'ventilator_settings.xlsx'))
for recording in recordings:
    vent_settings[recording].to_excel(writer,'%s' % recording)
writer.save()
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'ventilator_settings_selected.xlsx'))
for recording in recordings:
    vent_settings_selected[recording].to_excel(writer,'%s' % recording)
writer.save()
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'ventilator_settings_2.xlsx'))
for recording in recordings:
    vent_settings_2[recording].to_excel(writer,'%s' % recording)
writer.save()
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'ventilator_modes.xlsx'))
for recording in recordings:
    vent_modes[recording].to_excel(writer,'%s' % recording)
writer.save()
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'ventilator_modes_selected.xlsx'))
for recording in recordings:
    vent_modes_selected[recording].to_excel(writer,'%s' % recording)
writer.save()
Explanation: Save ventilation modes and settings into Excel files
End of explanation
alarm_settings = {}
for recording in recordings:
    flist = os.listdir('%s/%s' % (DIR_READ, recording))
    flist = [file for file in flist if not file.startswith('.')] # There are some hidden 
    # files on the hard drive starting with '.'; this step is necessary to ignore them
    files = alarm_setting_finder(flist)
    # print('Loading recording %s' % recording)
    # print(files)
    fnames = ['%s/%s/%s' % (DIR_READ, recording, filename) for filename in files]
    alarm_settings[recording] =  data_loader(fnames)
# Remove etCO2 limits which were not used
alarm_settings_selected = {}
for recording in recordings:
    alarm_settings_selected[recording] = alarm_setting_cleaner(alarm_settings[recording])
# Create a another dictionary of Dataframes with some of the alarm settings 
lsts = [(['MV_high_weight'], ['MVe_HL']), (['MV_low_weight'], ['MVe_LL']), 
        (['PIP_high'], ['PIP_HL']), (['RR_high'], ['RR_HL'])]
alarm_settings_2 = {}
                                                            
for recording in recordings:
    frmes = []                                                       
    for name, pars in lsts:
        if pars in [['MVe_HL'], ['MVe_LL']]:
            ind = []
            val = []
            for index, row in alarm_settings_selected[recording].iterrows():
                if row['Id'] in pars:
                    ind.append(index)
                    val.append(row['Value New'] / current_weights[recording])
                frmes.append(DataFrame(val, index = ind, columns = name))
        else:
            ind = []
            val = []
            for index, row in alarm_settings_selected[recording].iterrows():
                if row['Id'] in pars:
                    ind.append(index)
                    val.append(row['Value New'])
                frmes.append(DataFrame(val, index = ind, columns = name))
    alarm_settings_2[recording] = pd.concat(frmes)
    alarm_settings_2[recording].drop_duplicates(inplace = True)
# Write DataFrames containing alarm settings to a multisheet Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'alarm_settings.xlsx'))
for recording in recordings:
    alarm_settings[recording].to_excel(writer,'%s' % recording)
writer.save()
# Write DataFrames containing alarm settings to a multisheet Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'alarm_settings_2.xlsx'))
for recording in recordings:
    alarm_settings_2[recording].to_excel(writer,'%s' % recording)
writer.save()
Explanation: Import alarm settings
End of explanation
alarm_states = {}
for recording in recordings:
    flist = os.listdir('%s/%s' % (DIR_READ, recording))
    flist = [file for file in flist if not file.startswith('.')] # There are some hidden 
    # files on the hard drive starting with '.'; this step is necessary to ignore them
    files = alarm_state_finder(flist)
    # print('Loading recording %s' % recording)
    # print(files)
    fnames = ['%s/%s/%s' % (DIR_READ, recording, filename) for filename in files]
    alarm_states[recording] =  data_loader(fnames)
# Write DataFrames containing alarm states to a multisheet Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'alarm_states.xlsx'))
for recording in recordings:
    alarm_states[recording].to_excel(writer,'%s' % recording)
writer.save()
Explanation: Import alarm states
End of explanation
total_recording_time = timedelta(0)
for recording in recordings:
    total_recording_time += recording_duration[recording] 
total_recording_time
mean_recording_time = total_recording_time / len(recordings)
mean_recording_time
Explanation: Calculate the total and average time of all recordings
End of explanation
# Define function to retrieve alarm events from alarm timing data
def alarm_events_calculator(dframe, al):
    
    '''
    DataFrame, str -> DataFrame
    
    dframe: DataFrame containing alarm states
    al:  alarm category (string)
    
    Returns a pd.DataFrame object with the time stamps when the alarm went off and the duration (in seconds)
    of the alarm for alarm 'al' in recording 'rec'
    '''
    
    alarms = dframe
    alarm = alarms[alarms.Name == al]
    length = len(alarm)
    delta = np.array([(alarm.Date_Time[i] - alarm.Date_Time[i-1]).total_seconds() 
            for i in range(1, length) if alarm['State New'][i] == 'NotActive' and alarm['State New'][i-1] == 'Active'])
    stamp = np.array([alarm.index[i-1] 
            for i in range(1, length) if alarm['State New'][i] == 'NotActive' and alarm['State New'][i-1] == 'Active'])
    data = {'duration_seconds': delta, 'time_went_off': stamp,}
    alarm_t = DataFrame(data, columns = ['time_went_off', 'duration_seconds'])
    return alarm_t
Explanation: Generate alarm events from alarm states
End of explanation
# Create a list of alarms occurring during each recording
alarm_list = {}
for recording in recordings:
    alarm_list[recording] = sorted(set(alarm_states[recording].Name))
alarm_events = {}
for recording in recordings:
    alarm_events[recording] = {}
    for alarm in alarm_list[recording]:
        alarm_events[recording][alarm] = alarm_events_calculator(alarm_states[recording], alarm) 
# Write Dataframes containing the alarm events in Excel files,
# one Excel file for each recording
for recording in recordings:
    writer = pd.ExcelWriter('%s/%s%s' % (DIR_WRITE, recording, '_alarm_events.xlsx'))
    for alarm in alarm_list[recording]:
        alarm_events[recording][alarm].to_excel(writer, alarm[:20])
    
    writer.save()
Explanation: Using the files containing the alarm states, for each alarm category in each recording create a DataFrame with the timestamps the alarm went off and the duration of the alarm and store them in a dictionary of dictionaries
End of explanation
def alarm_stats_calculator(dframe, rec, al):
    '''
    dframe: DataFrame containing alarm events 
    rec: recording (string)
    al: alarm (string)
    
    Returns detailed statistics about a particular alarm (al) in a particular recording (rec);
    - number of times alarm went off and its value normalized to 24 hour periods
    - mean, median, standard deviation, mean absolute deviation, minimum, 25th centile, 75th centile, maximum
    time period when the alarm was off
    - the total amount of time the alarm was off and its relative value in percent as the total recording time 
    '''
    alarm = dframe[al].duration_seconds
    return  (alarm.size, round((alarm.size / (recording_duration_hours[rec] / 24)), 1), 
            round(alarm.mean() , 1), round(alarm.median(), 1), round(alarm.std(), 1), round(alarm.min() , 1), 
            round(alarm.quantile(0.25), 1), round(alarm.quantile(0.75), 1), round(alarm.max(), 1),
            round(alarm.sum(), 1), round(alarm.sum() * 100 / recording_duration_seconds[rec] ,3))
alarm_stats = {}
for recording in recordings:
    alarm_stats[recording] = {}
    for alarm in alarm_list[recording]:
        data = alarm_stats_calculator(alarm_events[recording], recording, alarm)
        frame = DataFrame([data], columns = ['number of events', 'number of event per 24h', 
                                             'mean duration (s)', 'median duration (s)', 'SD duration (s)', 
                                             'miminum duration (s)', 
                                             'duration 25th centile (s)', 'duration 75th centile (s)', 
                                             'maximum duration (s)', 'cumulative duration (s)', 
                                             'percentage of recording length (%)'], index = [alarm])
        alarm_stats[recording][alarm] = frame
# Write descriptive statistics in a multisheet Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'alarm_stats.xlsx'))
for recording in recordings:
    stats = []
    for alarm in alarm_stats[recording]:
        stats.append(alarm_stats[recording][alarm])
    stats_all = pd.concat(stats)
    stats_all.to_excel(writer, recording)
writer.save()
Explanation: Calculate descriptive statistics for each alarm in each recording and write them to file
End of explanation
# Generates a plot with the cumulative times (in seconds) of the various alarm occurring during recording (rec).
# Displays the plot
def alarm_plot_1(rec):
    fig = plt.figure()
    fig.set_size_inches(25, 8)
    fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1)
    xs = [i + 0.1 for i, _ in enumerate(alarm_list[rec])]
    stats = []
    for alarm in alarm_list[rec]:
        stats.append(alarm_stats[rec][alarm]['cumulative duration (s)'])
    stats_all = pd.concat(stats)
    plt.barh(xs, stats_all, color = 'red')
    plt.xlabel("seconds", fontsize  = 24)
    plt.title("Recording %s : How long was the alarm active over the %d seconds of recording?" % (rec, 
                recording_duration_seconds[rec]), fontsize = 22)
    plt.yticks([i + 0.5 for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 22)
    plt.xticks(fontsize = 20)
# Generates a plot with the cumulative times (in seconds) of the various alarm occurring during recording (rec).
# Does not displays the plot but write it into a jpg file.
# NB: the resolution of the image is only 100 dpi - for publication quality higher is needed
def alarm_plot_1_write(rec):
    fig = plt.figure()
    fig.set_size_inches(25, 8)
    fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1)
    xs = [i + 0.1 for i, _ in enumerate(alarm_list[rec])]
    stats = []
    for alarm in alarm_list[rec]:
        stats.append(alarm_stats[rec][alarm]['cumulative duration (s)'])
    stats_all = pd.concat(stats)
    plt.barh(xs, stats_all, color = 'red')
    plt.xlabel("seconds", fontsize  = 24)
    plt.title("Recording %s : How long was the alarm active over the %d seconds of recording?" % (rec, 
                recording_duration_seconds[rec]), fontsize = 22)
    plt.yticks([i + 0.5 for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 22)
    plt.xticks(fontsize = 20)
    
    fig.savefig('%s/%s_%s.jpg' % (dir_write, 'alarm_durations_1', rec), dpi=100, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
    plt.close(fig)
# Generates a plot with the cumulative times (expressed as percentage of the total recording time) 
# of the various alarm occurring during recording (rec).
# Displays the plot
def alarm_plot_2(rec):
    fig = plt.figure()
    fig.set_size_inches(25, 8)
    fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1)
    xs = [i + 0.1 for i, _ in enumerate(alarm_list[rec])]
    stats = []
    for alarm in alarm_list[rec]:
        stats.append(alarm_stats[rec][alarm]['percentage of recording length (%)'])
    stats_all = pd.concat(stats)
    plt.barh(xs, stats_all, color = 'red')
    plt.xlabel("% of total recording time", fontsize  = 24)
    plt.title("Recording %s: How long the alarm active over the %s hours of recording?" % (rec, 
            str(recording_duration[rec])), fontsize = 22)
    plt.yticks([i + 0.5 for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 22)
    plt.xticks(fontsize = 20)
# Generates a plot with the cumulative times (expressed as percentage of the total recording time) 
# of the various alarm occurring during recording (rec).
# Does not displays the plot but write it into a jpg file.
# NB: the resolution of the image is only 100 dpi - for publication quality higher is needed
def alarm_plot_2_write(rec):
    fig = plt.figure()
    fig.set_size_inches(25, 8)
    fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1)
    xs = [i + 0.1 for i, _ in enumerate(alarm_list[rec])]
    stats = []
    for alarm in alarm_list[rec]:
        stats.append(alarm_stats[rec][alarm]['percentage of recording length (%)'])
    stats_all = pd.concat(stats)
    plt.barh(xs, stats_all, color = 'red')
    plt.xlabel("% of total recording time", fontsize  = 24)
    plt.title("Recording %s: How long the alarm active over the %s hours of recording?" % (rec, 
            str(recording_duration[rec])), fontsize = 22)
    plt.yticks([i + 0.5 for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 22)
    plt.xticks(fontsize = 20)
    
    fig.savefig('%s/%s_%s.jpg' % (dir_write, 'alarm_durations_2', rec), dpi=100, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
    plt.close(fig)
# Displays the individual alarm events of the recording (rec) along the time axis
# Displays the plot
def alarm_plot_3(rec):
    alarm_state = alarm_states[rec]
    numbered = Series(np.zeros(len(alarm_state)), index = alarm_state.index)
    for i in range(1, len(alarm_state)):
        if alarm_state.iloc[i]['State New'] == 'Active':
            numbered[i] = alarm_list[rec].index(alarm_state.iloc[i]['Id']) + 1
    
    fig = plt.figure()
    fig.set_size_inches(17, 8)
    fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1);
    ax1.plot(alarm_state.index,  numbered, '|', color = 'red', markersize = 16, markeredgewidth = 1 )
    plt.xlabel("Time", fontsize  = 20)
    plt.title("Alarm events during recording %s" % rec , fontsize = 24)
    plt.yticks([i+1  for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 18);
    plt.xticks(fontsize = 14, rotation = 30)
    plt.ylim(0.5, len(alarm_list[rec]) + 0.5);
# Displays the individual alarm events of recording (rec) along the time axis
# Does not displays the plot but write it into a jpg file.
# NB: the resolution of the image is only 100 dpi - for publication quality higher is needed
def alarm_plot_3_write(rec):
    alarm_state = alarm_states[rec]
    numbered = Series(np.zeros(len(alarm_state)), index = alarm_state.index)
    for i in range(1, len(alarm_state)):
        if alarm_state.iloc[i]['State New'] == 'Active':
            numbered[i] = alarm_list[rec].index(alarm_state.iloc[i]['Id']) + 1
    
    fig = plt.figure()
    fig.set_size_inches(17, 8)
    fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1);
    ax1.plot(alarm_state.index,  numbered, '|', color = 'red', markersize = 16, markeredgewidth = 1 )
    plt.xlabel("Time", fontsize  = 20)
    plt.title("Alarm events during recording %s" % rec , fontsize = 24)
    plt.yticks([i+1  for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 18);
    plt.xticks(fontsize = 14, rotation = 30)
    plt.ylim(0.5, len(alarm_list[rec]) + 0.5)
    
    fig.savefig('%s/%s_%s.pdf' % (dir_write, 'individual_alarms', rec), dpi=100, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='pdf',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
    plt.close(fig)
Explanation: Visualise alarm statistics for the individual alarms in the individual recording
End of explanation
alarm_plot_1('DG032_2')
alarm_plot_2('DG032_2')
alarm_plot_3('DG032_2')
Explanation: Example plots
End of explanation
total_alarm_number_recordings = {} # dictionary containing the total number of alarm events in each recording
for recording in recordings:
    total = 0
    for alarm in alarm_list[recording]:
        total += len(alarm_events[recording][alarm].index)
    total_alarm_number_recordings[recording] = total
total_alarm_number_recordings_24H = {} # dictionary containing the total number of alarm events in each recording
                                       # corrected for 24 hour period
for recording in recordings:
    total_alarm_number_recordings_24H[recording] = (total_alarm_number_recordings[recording] / 
                                                    (recording_duration[recording].total_seconds() / 86400))
Explanation: Write all graphs to files
Generate cumulative descriptive statistics of all alarms combined in each recording
For each recording, what was the total number of alarm events and the number of events normalized for 24 hour periods
End of explanation
alarm_durations_recordings = {} # a dictionary of Series. Each series contains all the alarm durations of a recording
for recording in recordings:
    durations = []
    for alarm in alarm_list[recording]:
        durations.append(alarm_events[recording][alarm]['duration_seconds'])
    durations = pd.concat(durations)
    alarm_durations_recordings[recording] = durations
# Dictionaries containing various descriptive statistics for each recording
mean_alarm_duration_recordings = {}
median_alarm_duration_recordings = {}
sd_alarm_duration_recordings = {}
mad_alarm_duration_recordings = {}
min_alarm_duration_recordings = {}
pc25_alarm_duration_recordings = {}
pc75_alarm_duration_recordings = {}
max_alarm_duration_recordings = {}
for recording in recordings:
    mean_alarm_duration_recordings[recording] = round(alarm_durations_recordings[recording].mean(), 4)
    median_alarm_duration_recordings[recording] = round(alarm_durations_recordings[recording].median(), 4)
    sd_alarm_duration_recordings[recording] = round(alarm_durations_recordings[recording].std(), 4)
    mad_alarm_duration_recordings[recording] = round(alarm_durations_recordings[recording].mad(), 4)
    min_alarm_duration_recordings[recording] = round(alarm_durations_recordings[recording].min(), 4)
    pc25_alarm_duration_recordings[recording] = round(alarm_durations_recordings[recording].quantile(0.25), 4)
    pc75_alarm_duration_recordings[recording] = round(alarm_durations_recordings[recording].quantile(0.75), 4)
    max_alarm_duration_recordings[recording] = round(alarm_durations_recordings[recording].max(), 4)
# Create DataFrame containing cumulative alarm statistics for each recording
alarm_stats_cum_rec = DataFrame([total_alarm_number_recordings, 
                                 total_alarm_number_recordings_24H,
                                 mean_alarm_duration_recordings,  
                                 median_alarm_duration_recordings,
                                 sd_alarm_duration_recordings,
                                 mad_alarm_duration_recordings,
                                 min_alarm_duration_recordings,
                                 pc25_alarm_duration_recordings,
                                 pc75_alarm_duration_recordings,
                                 max_alarm_duration_recordings],
    index = ['count', 'count per 24h', 'mean duration (sec)', 'median duration (sec)', 'sd duration (sec)', 
             'mad duration (sec)', 'min duration (sec)', '25th cent duration (sec)', '75th cent duration (sec)',
             'max duration (sec)'])
alarm_stats_cum_rec.round(2)
# Write statistics to Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'alarm_stats_cum_rec.xlsx'))
alarm_stats_cum_rec.round(2).to_excel(writer, 'cumulative_stats')
writer.save()
Explanation: In each recording, what was the mean, median, sd, mad, min, 25pc, 75pc, max of alarm durations
End of explanation
# Plot the absolute number of alarm events for each recording
fig = plt.figure()
fig.set_size_inches(12, 12)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(recordings)+1)), alarm_stats_cum_rec.loc['count', :], color = 'blue')
plt.ylabel("Recordings", fontsize  = 22)
plt.xlabel("", fontsize  = 22)
plt.title("Number of alarm events" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(recordings)], recordings, rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'number_events_rec.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Plot the number of alarm events in each recording normalised for 24 hour periods
fig = plt.figure()
fig.set_size_inches(12, 12)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(recordings)+1)), alarm_stats_cum_rec.loc['count per 24h', :], color = 'blue')
plt.ylabel("Recordings", fontsize  = 22)
plt.xlabel("", fontsize  = 22)
plt.title("Number of alarm events per 24 hours" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(recordings)], recordings, rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'number_events_24H_rec.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Median duration of alarm events
fig = plt.figure()
fig.set_size_inches(12, 12)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(recordings)+1)), alarm_stats_cum_rec.loc['mean duration (sec)', :], color = 'blue')
plt.ylabel("Recordings", fontsize  = 22)
plt.xlabel("seconds", fontsize  = 22)
plt.title("Median duration of alarm events" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(recordings)], recordings,  rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'median_duration_rec.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
Explanation: Visualize cumulative statistics of recordings
End of explanation
# Create a list of all alarms occurring in any recording
total_alarm_list = set()
for recording in recordings:
    total_alarm_list.update(alarm_list[recording])
total_alarm_list = sorted(total_alarm_list)
# A list of all alarms occurring during the service evaluation
total_alarm_list
# Write alarm list to Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'total_alarm_list.xlsx'))
DataFrame(total_alarm_list, columns = ['alarm categories']).to_excel(writer, 'total_alarm_list')
writer.save()
Explanation: Generate cumulative statistics of each alarm in all recordings combined
End of explanation
total_alarm_number_alarms = {} # dictionary containing the number of alarm events in all recordings for the 
                               # various alarm categories
for alarm in total_alarm_list:
    total = 0
    for recording in recordings:
        if alarm in alarm_list[recording]:
            total += len(alarm_events[recording][alarm].index)
    total_alarm_number_alarms[alarm] = total
# Write alarm list to Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'total_alarm_list_numbers.xlsx'))
DataFrame([total_alarm_number_alarms]).T.to_excel(writer, 'total_alarm_list')
writer.save()
total_alarm_number_alarms_24H = {} # dictionary containing the number of alarm events in all recordings for the 
                                   # various alarm categories normalized for 24 hour recording periods
for alarm in total_alarm_list:
    total_alarm_number_alarms_24H[alarm] = round(((total_alarm_number_alarms[alarm] / 
                                                    (total_recording_time.total_seconds() / 86400))), 4)
Explanation: For each alarm, what was number of alarm events across all recordings and the number of events normalized per 24 hour recording time
End of explanation
alarm_durations_alarms = {} # a dictionary of Series. Each Series contains all durations of a particular alarm
                            # in all recordings
for alarm in total_alarm_list:
    durations = []
    for recording in recordings:
        if alarm in alarm_list[recording]:
            durations.append(alarm_events[recording][alarm]['duration_seconds'])
    durations = pd.concat(durations)
    alarm_durations_alarms[alarm] = durations
cum_alarm_duration_alarms = {} # dictionary containing the total duration of alarms in all recordings for the 
                               # various alarm categories 
for alarm in total_alarm_list:
    cum_alarm_duration_alarms[alarm] = round(alarm_durations_alarms[alarm].sum(), 4)
cum_alarm_duration_alarms_24H = {} # dictionary containing the total duration of alarms in all recordings for the 
                                   # various alarm categories normalized for 24 hour recording periods
for alarm in total_alarm_list:
    cum_alarm_duration_alarms_24H[alarm] = round(((cum_alarm_duration_alarms[alarm] / 
                                                    (total_recording_time.total_seconds() / 86400))), 4)
Explanation: For each alarm, what was the total duration of alarm events across all recordings and normalized per 24 hour recording time
End of explanation
# libraries containing various descriptive statistics for each recording
mean_alarm_duration_alarms = {}
median_alarm_duration_alarms = {}
sd_alarm_duration_alarms = {}
mad_alarm_duration_alarms = {}
min_alarm_duration_alarms = {}
pc25_alarm_duration_alarms = {}
pc75_alarm_duration_alarms = {}
max_alarm_duration_alarms = {}
for alarm in total_alarm_list:
    mean_alarm_duration_alarms[alarm] = round(alarm_durations_alarms[alarm].mean(), 4)
    median_alarm_duration_alarms[alarm] = round(alarm_durations_alarms[alarm].median(), 4)
    sd_alarm_duration_alarms[alarm] = round(alarm_durations_alarms[alarm].std(), 4)
    mad_alarm_duration_alarms[alarm] = round(alarm_durations_alarms[alarm].mad(), 4)
    min_alarm_duration_alarms[alarm] = round(alarm_durations_alarms[alarm].min(), 4)
    pc25_alarm_duration_alarms[alarm] = round(alarm_durations_alarms[alarm].quantile(0.25), 4)
    pc75_alarm_duration_alarms[alarm] = round(alarm_durations_alarms[alarm].quantile(0.75), 4)
    max_alarm_duration_alarms[alarm] = round(alarm_durations_alarms[alarm].max(), 4)
# Create DataFrame containing cumulative alarm statistics for each alarm
alarm_stats_cum_al = DataFrame([total_alarm_number_alarms, 
                                 total_alarm_number_alarms_24H,
                                 cum_alarm_duration_alarms,
                                 cum_alarm_duration_alarms_24H,
                                 mean_alarm_duration_alarms,  
                                 median_alarm_duration_alarms,
                                 sd_alarm_duration_alarms,
                                 mad_alarm_duration_alarms,
                                 min_alarm_duration_alarms,
                                 pc25_alarm_duration_alarms,
                                 pc75_alarm_duration_alarms,
                                 max_alarm_duration_alarms],
    index = ['count', 'count per 24h', 'total alarm duration (sec)', 'total alarm duration per 24 hours (sec)', 
             'mean duration (sec)', 'median duration (sec)', 'sd duration (sec)', 'mad duration (sec)', 
             'min duration (sec)', '25th cent duration (sec)', '75th cent duration (sec)',
             'max duration (sec)'])
# Dataframe containing cumulative alarm statistics for each alarm
alarm_stats_cum_al.round(2)
# Write Dataframe containing cumulative alarm statistics for each alarm to Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'alarm_stats_cum_al.xlsx'))
alarm_stats_cum_al.round(2).to_excel(writer, 'cumulative_stats')
writer.save()
Explanation: For each alarm what was the mean, median, sd, mad, min, 25pc, 75pc, max of alarm durations
End of explanation
# Reduce a too long alarm name
total_alarm_list[0] = 'A setting, alarm limit or vent...'
# Total number of alarm events in all recordings
fig = plt.figure()
fig.set_size_inches(17, 12)
fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(total_alarm_list)+1)), alarm_stats_cum_al.loc['count', :], color = 'blue')
plt.ylabel("Alarms", fontsize  = 22)
plt.xlabel("", fontsize  = 22)
plt.title("Number of alarm events" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(total_alarm_list)], total_alarm_list, rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'number_events_al.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Total number of alarm events in all recordings normalized for 24 hour periods
fig = plt.figure()
fig.set_size_inches(17, 12)
fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(total_alarm_list)+1)), alarm_stats_cum_al.loc['count per 24h', :], color = 'blue')
plt.ylabel("Alarms", fontsize  = 22)
plt.xlabel("", fontsize  = 22)
plt.title("Number of alarm events per 24 hour" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(total_alarm_list)], total_alarm_list, rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'number_events_24H_al.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Median duration of alarm events in all recordings
fig = plt.figure()
fig.set_size_inches(17, 12)
fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(total_alarm_list)+1)), alarm_stats_cum_al.loc['median duration (sec)', :], color = 'blue')
plt.ylabel("Alarms", fontsize  = 22)
plt.xlabel("seconds", fontsize  = 22)
plt.title("Median duration of alarm events" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(total_alarm_list)], total_alarm_list,  rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'median_events_al.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
Explanation: Visualising cumulative statistics of alarms
End of explanation
all_durations = [] # Series containing durations of all alarm events in all the recording
for recording in recordings:
    for alarm in alarm_list[recording]:
        all_durations.append(alarm_events[recording][alarm]['duration_seconds'])
all_durations = pd.concat(all_durations)
# The total number of alarm events in all the recordings
total_count = len(all_durations)
total_count
# The total number of alarm events in all the recordings per 24 hour
total_count_24H = total_count / (total_recording_time.total_seconds() / 86400)
total_count_24H
# Calculate descriptive statistics (expressed in seconds)
mean_duration_total     = round(all_durations.mean(), 4)
median_duration_total   = round(all_durations.median(), 4)
sd_duration_total       = round(all_durations.std(), 4)
mad_duration_total      = round(all_durations.mad(), 4)
min_duration_total      = round(all_durations.min(), 4)
pc25_duration_total     = round(all_durations.quantile(0.25), 4)
pc75_duration_total     = round(all_durations.quantile(0.75), 4)
max_duration_total      = round(all_durations.max(), 4)
alarm_stats_cum_total = DataFrame([ total_count, total_count_24H,
                                    mean_duration_total, median_duration_total,
                                    sd_duration_total, mad_duration_total, min_duration_total,      
                                    pc25_duration_total, pc75_duration_total, max_duration_total], 
                                  
                                  columns = ['all alarms in all recordings'],
                                  index =  ['total alarm events', 'total alarm events per 24 hours',
                                          'mean alarm duration (sec)', 'median alarm duration (sec)',
                                          'sd alarm duration (sec)', 'mad alarm duration (sec)',
                                          'min alarm duration (sec)', '25 centile alarm duration (sec)',
                                          '75 centile alarm duration (sec)', 'max alarm duration (sec)'])
# Cumulative statistics of the whole datasett
alarm_stats_cum_total.round(2)
# Write cumulative statistics to Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'alarm_stats_cum_total.xlsx'))
alarm_stats_cum_total.to_excel(writer, 'cumulative_stats')
writer.save()
Explanation: Calculate cumulative descriptive statistics of all alarms in all recording together
End of explanation
# Histogram showing the number of alarms which were shorter than 1 minute
fig = plt.figure()
fig.set_size_inches(12, 6)
fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1)
n, bins, patches = plt.hist(all_durations, bins = range(0, 60))
plt.grid(True)
plt.xlabel('Alarm duration (seconds)', fontsize = 20)
plt.ylabel('Number of events', fontsize = 20)
plt.xticks(range(0,60,2), fontsize = 10)
plt.yticks(fontsize = 10)
plt.title('Histogram of alarm durations', fontsize = 20)
fig.savefig('%s/%s' % (DIR_WRITE, 'alarm_duration_hist_1.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Histogram showing the number of alarms which were shorter than 10 minutes
fig = plt.figure()
fig.set_size_inches(12, 6)
fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1)
n, bins, patches = plt.hist(all_durations, bins = range(0, 600))
plt.grid(True)
plt.xlabel('Alarm duration (seconds)', fontsize = 20)
plt.ylabel('Number of events', fontsize = 20)
plt.xticks(range(0, 600, 60), fontsize = 10)
plt.yticks(fontsize = 10)
plt.title('Histogram of alarm durations', fontsize = 20)
fig.savefig('%s/%s' % (DIR_WRITE, 'alarm_duration_hist_2.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Histogram showing all data with a bin size of 1minutes and log X axis
fig = plt.figure()
fig.set_size_inches(12, 6)
fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1)
n, bins, patches = plt.hist(all_durations, bins = range(0, 50000, 60))
plt.grid(True)
plt.xlabel('Alarm duration (seconds)', fontsize = 20)
plt.ylabel('Number of events', fontsize = 20)
plt.xticks(range(0, 50000, 600), fontsize = 10)
plt.yticks(fontsize = 10)
plt.xscale('log')
plt.yscale('log')
plt.title('Histogram of alarm durations', fontsize = 20)
fig.savefig('%s/%s' % (DIR_WRITE, 'alarm_duration_hist_3.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
Explanation: Visualise the duration of all alarm events as histogram
End of explanation
under_10_sec =  sorted([al for al in all_durations if al < 10])
len(under_10_sec)
under_1_min =  sorted([al for al in all_durations if al <= 60])
len(under_1_min)
under_10_sec_MV_low = sorted([al for al in alarm_durations_alarms['Minute volume < low limit'] if al < 10])
under_10_sec_MV_high = sorted([al for al in alarm_durations_alarms['Minute volume > high limit'] if al < 10])
under_10_sec_RR_high = sorted([al for al in alarm_durations_alarms['Respiratory rate > high limit'] if al < 10])
len(under_10_sec_MV_low), len(under_10_sec_MV_high), len(under_10_sec_RR_high)
# Short alarms (<10 sec) in the categories where the user sets the limits
len(under_10_sec_MV_low) + len(under_10_sec_MV_high) + len(under_10_sec_RR_high)
Explanation: How many short alarms did occur?
End of explanation
# How many alarm events are longer than 1 hour?
over_1_hour =  sorted([al for al in all_durations if al > 3600]) 
len(over_1_hour)
# Which alarms were longer than one hour?
alarms_over_1_hour = []
for recording in recordings:
    for alarm in alarm_list[recording]:
        for event in alarm_events[recording][alarm]['duration_seconds']:
            if event > 3600:
                alarms_over_1_hour.append((recording, alarm, event))
alarms_over_1_hour = DataFrame(sorted(alarms_over_1_hour, key = lambda x: x[2], reverse = True), 
                               columns = ['recording', 'alarm', 'duration (seconds)'])
alarms_over_1_hour
alarms_over_1_hour.groupby('alarm').count()
Explanation: Check which are the longest alarms
End of explanation
over_10_minutes =  sorted([al for al in all_durations if al > 600 and al <= 3600])
len(over_10_minutes)
alarms_over_10_min = []
# which alarms were longer than 10 minutes but shorter than 1 hour
for recording in recordings:
    for alarm in alarm_list[recording]:
        for event in alarm_events[recording][alarm]['duration_seconds']:
            if event > 600 and event <= 3600:
                alarms_over_10_min.append((recording, alarm, event))
alarms_over_10_min = DataFrame(sorted(alarms_over_10_min, key = lambda x: x[2], reverse = True), 
                               columns = ['recording', 'alarm', 'duration (seconds)'])
alarms_over_10_min.groupby('alarm').count()
Explanation: How many alarm events are longer than 10 minutes but shorter than 1 hour?¶
End of explanation
over_1_minutes =  sorted([al for al in all_durations if al > 60 and al <= 600])
len(over_1_minutes)
alarms_over_1_min = []
# which alarms were longer than 1 minutes but shorter than 10 minutes
for recording in recordings:
    for alarm in alarm_list[recording]:
        for event in alarm_events[recording][alarm]['duration_seconds']:
            if event > 60 and event <= 600:
                alarms_over_1_min.append((recording, alarm, event))
                
alarms_over_1_min = DataFrame(sorted(alarms_over_1_min, key = lambda x: x[2], reverse = True), 
                               columns = ['recording', 'alarm', 'duration (seconds)'])
alarms_over_1_min.groupby('alarm').count()
# Write long alarms into a multisheet Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'long_alarms.xlsx'))
alarms_over_1_hour.to_excel(writer, 'over_1hour')
alarms_over_10_min.to_excel(writer, '10min_to_1hour')
alarms_over_1_min.to_excel(writer, '1min_to_10min')
writer.save()
Explanation: how many alarm events are longer than 1 minutes?¶
End of explanation
# Identify the most frequent alarm events
frequent_alarms = alarm_stats_cum_al.loc['count'].sort_values(inplace = False, ascending = False)
# The eight most frequent alarms
frequent_alarms[:8]
# How many percent of all alarms were these 8 frequent alarms?
round(frequent_alarms[:8].sum() / frequent_alarms.sum(), 3) * 100
# Write frequent alarm in an Excel file
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'frequent_alarms.xlsx'))
DataFrame(frequent_alarms[:8]).to_excel(writer, 'frequent_alarms')
writer.save()
# Number of alarms where the user sets the limits
user_set_alarms = (frequent_alarms['Minute volume < low limit'] + frequent_alarms['Minute volume > high limit'] + 
                frequent_alarms['Respiratory rate > high limit'])
int(user_set_alarms)
# What proportion of all alarms were these 3 user-set alarms?
print('%.3f' % (user_set_alarms / frequent_alarms.sum()))
# Frequent alarms related to VT not achieved
other_frequent_alarms = (frequent_alarms['Tidal volume < low Limit'] + frequent_alarms['Volume not constant'] + 
                frequent_alarms['Tube obstructed'])
int(other_frequent_alarms)
# What proportion of all alarms were alarms related to VT not achieved?
print('%.3f' % (other_frequent_alarms / frequent_alarms.sum()))
Explanation: Check which are the most frequent alarms
End of explanation
MV_low_count = {}
for recording in recordings:
    try:
        MV_low_count[recording] = alarm_stats[recording]['Minute volume < low limit']['number of events'].iloc[0]
    except KeyError:
        # print('No "MV_low" alarm in recording %s' % recording)
        pass
MV_low_count_24H = {}
for recording in recordings:
    try:
        MV_low_count_24H[recording] = \
            alarm_stats[recording]['Minute volume < low limit']['number of event per 24h'].iloc[0]
    except KeyError:
        # print('No "MV_low" alarm in recording %s' % recording)
        pass
MV_high_count = {}
for recording in recordings:
    try:
        MV_high_count[recording] = alarm_stats[recording]['Minute volume > high limit']['number of events'].iloc[0]
    except KeyError:
        # print('No "MV_high" alarm in recording %s' % recording)
        pass
MV_high_count_24H = {}
for recording in recordings:
    try:
        MV_high_count_24H[recording] = alarm_stats[recording]['Minute volume > high limit']['number of event per 24h'].iloc[0]
    except KeyError:
        # print('No "MV_high" alarm in recording %s' % recording)
        pass
RR_high_count = {}
for recording in recordings:
    try:
        RR_high_count[recording] = alarm_stats[recording]['Respiratory rate > high limit']['number of events'].iloc[0]
    except KeyError:
        # print('No "RR_high" alarm in recording %s' % recording)
        pass
RR_high_count_24H = {}
for recording in recordings:
    try:
        RR_high_count_24H[recording] = alarm_stats[recording]['Respiratory rate > high limit']['number of event per 24h'].iloc[0]
    except KeyError:
        # print('No "RR_high" alarm in recording %s' % recording)
        pass
# Plot the number of MV < low limit alarm events and write graph to file
fig = plt.figure()
fig.set_size_inches(17, 12)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(MV_low_count)+1)), MV_low_count.values(), color = 'blue')
plt.ylabel("Recordings", fontsize  = 16)
plt.xlabel("number of alarm events", fontsize  = 16)
plt.title("MV < low limit" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(MV_low_count.keys())], MV_low_count.keys(),
        rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'MV_low.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Plot the number of MV < low limit alarm events normalized for 24 hours and write graph to file
fig = plt.figure()
fig.set_size_inches(17, 12)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(MV_low_count_24H)+1)), MV_low_count_24H.values(), color = 'blue')
plt.ylabel("Recordings", fontsize  = 16)
plt.xlabel("number of alarm events per 24 hours", fontsize  = 16)
plt.title("MV < low limit" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(MV_low_count_24H.keys())], MV_low_count_24H.keys(),
        rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'MV_low_24H.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Plot the number of MV > low limit alarm events and write graph to file
fig = plt.figure()
fig.set_size_inches(17, 12)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(MV_high_count)+1)), MV_high_count.values(), color = 'blue')
plt.ylabel("Recordings", fontsize  = 16)
plt.xlabel("number of alarm events", fontsize  = 16)
plt.title("MV > high limit" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(MV_high_count.keys())], MV_high_count.keys(),
           rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'MV_high.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Plot the number of MV > low limit alarm events and write graph to file
fig = plt.figure()
fig.set_size_inches(17, 12)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(MV_high_count_24H)+1)), MV_high_count_24H.values(), color = 'blue')
plt.ylabel("Recordings", fontsize  = 16)
plt.xlabel("number of alarm events per 24 hours", fontsize  = 16)
plt.title("MV > high limit" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(MV_high_count_24H.keys())], MV_high_count_24H.keys(),
           rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'MV_high_24H.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Plot the number of RR > high limit alarm events and write graph to file
fig = plt.figure()
fig.set_size_inches(17, 12)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(RR_high_count)+1)), RR_high_count.values(), color = 'blue')
plt.ylabel("Recordings", fontsize  = 16)
plt.xlabel("number of alarm events", fontsize  = 16)
plt.title("RR > high limit" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(RR_high_count.keys())], RR_high_count.keys(),
           rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'RR_high.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
# Plot the number of RR > high limit alarm events normalized for 24 hours and write graph to file
fig = plt.figure()
fig.set_size_inches(17, 12)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
ax1.barh(list(range(1, len(RR_high_count_24H)+1)), RR_high_count_24H.values(), color = 'blue')
plt.ylabel("Recordings", fontsize  = 16)
plt.xlabel("number of alarm events per 24 hours", fontsize  = 16)
plt.title("RR > high limit" , fontsize = 26)
ax1.tick_params(which = 'both', labelsize=14)
plt.yticks([i+1.5  for i, _ in enumerate(RR_high_count_24H.keys())], 
           RR_high_count_24H.keys(), rotation = 'horizontal')
plt.grid()
fig.savefig('%s/%s' % (DIR_WRITE, 'RR_high_24H.jpg'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
Explanation: Visualise MV and RR limit alarms
Generate dictionaries with the alarm counts (absolute and per 24H recording period) for MV low and high alarms and RR high alarms for those recordings where this occurs
End of explanation
for recording in recordings:
    slow_measurements[recording] = pd.concat([slow_measurements[recording],
            vent_settings_2[recording], alarm_settings_2[recording]], axis = 0, join = 'outer')
    slow_measurements[recording].sort_index(inplace = True)
for recording in recordings:
    slow_measurements[recording] = slow_measurements[recording].fillna(method = 'pad')
def minute_volume_plotter(rec, ylim = False):
    '''
    Plots the total minute volumme (using the data obtained with 1/sec sampling rate) 
    together with the "MV low" and "MV high" alarm limits
    Displays the plot
    
    '''
    if ylim:
        ymax =  ylim
    else:
        ymax = slow_measurements[rec]['MV_high_weight'].max() + 0.3
    
    fig = plt.figure()
    fig.set_size_inches(12, 8)
    fig.subplots_adjust(left=None, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1);
    slow_measurements[rec]['MV_kg'].plot(ax = ax1, color = 'blue', ylim = [0, ymax] );
    slow_measurements[rec]['MV_low_weight'].plot(ax = ax1, color = 'green', linewidth = 3, ylim = [0, ymax] );
    slow_measurements[rec]['MV_high_weight'].plot(ax = ax1, color = 'red', linewidth = 3, ylim = [0, ymax] );
    ax1.set_title('Minute volume - %s' % rec, size = 22, color = 'black')
    ax1.set_xlabel('Time', size = 22, color = 'black')
    ax1.set_ylabel('L/kg/min', size = 22, color = 'black')
    ax1.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
    ax1.legend(['MV_kg', 'alarm_low', 'alarm_high']);
minute_volume_plotter('DG003')
def minute_volume_plotter_2(rec, ylim = False, version = ''):
    '''
    Plots the total minute volumme (using the data obtained with 1/sec sampling rate) 
    together with the "MV low" and "MV high" alarm limits
    Writes the plot to file (does not display the plot)
    
    '''
    if ylim:
        ymax =  ylim
    else:
        ymax = slow_measurements[rec]['alarm_MV_high_weight'].max() + 0.3
    
    fig = plt.figure()
    fig.set_size_inches(12, 8)
    fig.subplots_adjust(left=None, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1);
    slow_measurements[rec]['MV_kg'].plot(ax = ax1, color = 'blue', ylim = [0, ymax] );
    slow_measurements[rec]['alarm_MV_low_weight'].plot(ax = ax1, color = 'green', linewidth = 3, ylim = [0, ymax] );
    slow_measurements[rec]['alarm_MV_high_weight'].plot(ax = ax1, color = 'red', linewidth = 3,  ylim = [0, ymax] );
    ax1.set_title('Minute volume - %s' % rec, size = 22, color = 'black')
    ax1.set_xlabel('Time', size = 22, color = 'black')
    ax1.set_ylabel('L/kg/min', size = 22, color = 'black')
    ax1.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
    ax1.legend(['MV_kg', 'alarm_low', 'alarm_high']);
    fig.savefig('%s/%s_%s%s.jpg' % (dir_write, 'minute_volume', rec, version), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
    plt.close(fig)
def resp_rate_plotter(rec, ylim = False):
    '''
    Plots the total reapiratory rate (using the data obtained with 1/sec sampling rate) 
    together with the set backup rate and "RR high" alarm limits
    Displays the plot
    
    '''
    if ylim:
        ymax =  ylim
    else:
        ymax = slow_measurements[rec]['5001|RR [1/min]'].max() + 10
    
    fig = plt.figure()
    fig.set_size_inches(12, 8)
    fig.subplots_adjust(left=None, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1);
    slow_measurements[rec]['5001|RR [1/min]'].plot(ax = ax1, color = 'blue', ylim = [0, ymax] );
    slow_measurements[rec]['RR_high'].plot(ax = ax1, color = 'red', linewidth = 3, ylim = [0, ymax] );
    slow_measurements[rec]['RR_set'].plot(ax = ax1, color = 'green', linewidth = 3, ylim = [0, ymax] );
    ax1.set_title('Respiratory rate - %s' % rec, size = 22, color = 'black')
    ax1.set_xlabel('Time', size = 22, color = 'black')
    ax1.set_ylabel('1/min', size = 22, color = 'black')
    ax1.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
    ax1.legend(['RR', 'alarm_high', 'RR_set']);
resp_rate_plotter('DG003')
def resp_rate_plotter_2(rec, ylim = False, version = ''):
    '''
    Plots the total reapiratory rate (using the data obtained with 1/sec sampling rate) 
    together with the set backup rate and "RR high" alarm limits
    Writes the plots to files (does not display the plot)
    
    '''
    if ylim:
        ymax =  ylim
    else:
        ymax = slow_measurements[rec]['5001|RR [1/min]'].max() + 10
    
    fig = plt.figure()
    fig.set_size_inches(12, 8)
    fig.subplots_adjust(left=None, bottom=None, right=None, top=None,
    wspace=None, hspace=0.7)
    ax1 = fig.add_subplot(1, 1, 1);
    slow_measurements[rec]['5001|RR [1/min]'].plot(ax = ax1, color = 'blue', ylim = [0, ymax] );
    slow_measurements[rec]['alarm_RR_high'].plot(ax = ax1, color = 'red', linewidth = 3, ylim = [0, ymax] );
    slow_measurements[rec]['RR_set'].plot(ax = ax1, color = 'green', linewidth = 3, ylim = [0, ymax] );
    ax1.set_title('Respiratory rate - %s' % rec, size = 22, color = 'black')
    ax1.set_xlabel('Time', size = 22, color = 'black')
    ax1.set_ylabel('1/min', size = 22, color = 'black')
    ax1.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
    ax1.legend(['RR', 'alarm_high', 'RR_set'])
    
    fig.savefig('%s/%s_%s%s.jpg' % (dir_write, 'resp_rate', rec, version), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='jpg',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
    plt.close(fig)
Explanation: Investigate the relationship of MV and RR parameter readings, ventilation settings and alarm settings
End of explanation
clinical_details_for_paper = clinical_details[['Gestation', 'Birth weight', 'Current weight', 'Main diagnoses']]
clinical_details_for_paper = clinical_details_for_paper.loc[recordings]
# clinical_details_for_paper
vent_modes_all = {}
for recording in recordings:
    vent_modes_all[recording] = vent_modes_selected[recording].Text.unique()
    vent_modes_all[recording] = [mode[5:] for mode in vent_modes_all[recording] if mode.startswith(' Mode')]
    
vent_modes_all = DataFrame([vent_modes_all]).T
vent_modes_all.columns = ['Ventilation modes']
vent_modes_all = vent_modes_all.loc[recordings]
# vent_modes_all
recording_duration_hours_all = DataFrame([recording_duration_hours]).T
recording_duration_hours_all.columns = ['Recording duration (hours)']
Table_1 = recording_duration_hours_all.join([clinical_details_for_paper, vent_modes_all])
Table_1
writer = pd.ExcelWriter('%s/%s' % (DIR_WRITE, 'Table_1.xlsx'))
Table_1.to_excel(writer)
writer.save()
Explanation: Create the tables and figures of the paper
Table 1
End of explanation
rec = 'DG032_2'
filetype = 'jpg'
dpi = 300
alarm_state = alarm_states[rec]
numbered = Series(np.zeros(len(alarm_state)), index = alarm_state.index)
for i in range(1, len(alarm_state)):
    if alarm_state.iloc[i]['State New'] == 'Active':
        numbered[i] = alarm_list[rec].index(alarm_state.iloc[i]['Id']) + 1
    
fig = plt.figure()
fig.set_size_inches(10, 4)
fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None, wspace=None, hspace=None)
ax1 = fig.add_subplot(1, 1, 1);
ax1.plot(alarm_state.index,  numbered, '|', color = 'red', markersize = 14, markeredgewidth = 0.5 )
plt.xlabel("Time", fontsize  = 14)
plt.title(rec)
plt.yticks([i+1  for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 14);
plt.xticks(fontsize = 8)
                                                     
plt.ylim(0.5, len(alarm_list[rec]) + 0.5)
    
fig.savefig('%s/%s.jpg' % (DIR_WRITE, 'Figure_1a'), dpi=dpi, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format= filetype,
        transparent=False, bbox_inches=None, pad_inches=0.1, frameon=True)
rec = 'DG032_2'
filetype = 'jpg'
dpi = 300
fig = plt.figure()
fig.set_size_inches(8, 4)
fig.subplots_adjust(left=0.5, bottom=None, right=None, top=None, wspace=None, hspace= None)
ax1 = fig.add_subplot(1, 1, 1)
xs = [i + 0.1 for i, _ in enumerate(alarm_list[rec])]
stats = []
for alarm in alarm_list[rec]:
    stats.append(alarm_stats[rec][alarm]['percentage of recording length (%)'])
stats_all = pd.concat(stats)
plt.barh(xs, stats_all, color = 'red')
plt.xlabel("% of total recording time", fontsize  = 14)
plt.title(rec)
plt.yticks([i + 0.5 for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 14)
plt.xticks(fontsize = 14);
    
fig.savefig('%s/%s.jpg' % (DIR_WRITE, 'Figure_1b'), dpi=dpi, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format= filetype,
        transparent=False, bbox_inches=None, pad_inches=0.1, frameon=True)
rec = 'DG032_2'
filetype = 'tiff'
dpi = 300
alarm_state = alarm_states[rec]
numbered = Series(np.zeros(len(alarm_state)), index = alarm_state.index)
for i in range(1, len(alarm_state)):
    if alarm_state.iloc[i]['State New'] == 'Active':
        numbered[i] = alarm_list[rec].index(alarm_state.iloc[i]['Id']) + 1
    
fig = plt.figure()
fig.set_size_inches(9, 7)
fig.subplots_adjust(left=0.4, bottom=None, right=None, top=None, wspace=None, hspace=0.3)
ax1 = fig.add_subplot(2, 1, 1);
ax1.plot(alarm_state.index,  numbered, '|', color = 'red', markersize = 10, markeredgewidth = 0.5 )
plt.xlabel("Time", fontsize  = 12)
plt.title(rec)
plt.yticks([i+1  for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 12);
plt.xticks(fontsize = 8)
plt.ylim(0.5, len(alarm_list[rec]) + 0.5)
ax1 = fig.add_subplot(2, 1, 2)
xs = [i + 0.1 for i, _ in enumerate(alarm_list[rec])]
stats = []
for alarm in alarm_list[rec]:
    stats.append(alarm_stats[rec][alarm]['percentage of recording length (%)'])
stats_all = pd.concat(stats)
plt.barh(xs, stats_all, color = 'red')
plt.xlabel("% of total recording time", fontsize  = 12)
plt.title(rec)
plt.yticks([i + 0.5 for i, _ in enumerate(alarm_list[rec])], alarm_list[rec], fontsize = 12)
plt.xticks(fontsize = 8);
    
fig.savefig('%s/%s.tiff' % (DIR_WRITE, 'Figure_1'), dpi=dpi, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format= filetype,
        transparent=False, bbox_inches=None, pad_inches=0.1, frameon=True)
Explanation: Figure 1
End of explanation
rec = 'DG003'
filetype = 'jpg'
dpi = 300
ymax = slow_measurements[rec]['MV_high_weight'].max() + 0.3
    
fig = plt.figure()
fig.set_size_inches(8, 6)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None,
    wspace=None, hspace=None)
ax1 = fig.add_subplot(1, 1, 1);
slow_measurements[rec]['MV_kg'].plot(ax = ax1, color = 'blue', ylim = [0, ymax] );
slow_measurements[rec]['MV_low_weight'].plot(ax = ax1, color = 'green', linewidth = 3, ylim = [0, ymax] );
slow_measurements[rec]['MV_high_weight'].plot(ax = ax1, color = 'red', linewidth = 3,  ylim = [0, ymax] );
ax1.set_title(rec, size = 14, color = 'black')
ax1.set_xlabel('Time', size = 14, color = 'black')
ax1.set_ylabel('L/min/kg', size = 14, color = 'black')
ax1.tick_params(which = 'both', labelsize=12)
ax1.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
ax1.legend(['MV_kg', 'alarm_low', 'alarm_high']);
fig.savefig('%s/%s.jpg' % (DIR_WRITE, 'Figure_2a_color'), dpi=dpi, facecolor='w', edgecolor='w',
    orientation='portrait', papertype=None, format= filetype,
    transparent=False, bbox_inches=None, pad_inches=0.1, frameon=True)
rec = 'DG003'
filetype = 'jpg'
dpi = 300
ymax = slow_measurements[rec]['MV_high_weight'].max() + 0.3
    
fig = plt.figure()
fig.set_size_inches(8, 6)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None,
    wspace=None, hspace=None)
ax1 = fig.add_subplot(1, 1, 1);
slow_measurements[rec]['MV_kg'].plot(ax = ax1, color = 'black', alpha = 0.6, ylim = [0, ymax] );
slow_measurements[rec]['MV_low_weight'].plot(ax = ax1, color = 'black', linewidth = 3, ylim = [0, ymax] );
slow_measurements[rec]['MV_high_weight'].plot(ax = ax1, color = 'black', linewidth = 3,  ylim = [0, ymax] );
ax1.set_title(rec, size = 14, color = 'black')
ax1.set_xlabel('Time', size = 14, color = 'black')
ax1.set_ylabel('L/min/kg', size = 14, color = 'black')
ax1.tick_params(which = 'both', labelsize=12)
ax1.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
ax1.legend(['MV_kg', 'alarm_low', 'alarm_high']);
fig.savefig('%s/%s.jpg' % (DIR_WRITE, 'Figure_2a_bw'), dpi=dpi, facecolor='w', edgecolor='w',
    orientation='portrait', papertype=None, format= filetype,
    transparent=False, bbox_inches=None, pad_inches=0.1, frameon=True)
rec = 'DG041'
filetype = 'jpg'
dpi = 300
ymax = slow_measurements[rec]['5001|RR [1/min]'].max() + 15
    
fig = plt.figure()
fig.set_size_inches(8, 6)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None,
wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
    
slow_measurements[rec]['5001|RR [1/min]'].plot(ax = ax1, color = 'blue', ylim = [0, ymax] );
slow_measurements[rec]['RR_high'].plot(ax = ax1, color = 'red', linewidth = 3, ylim = [0, ymax] );
slow_measurements[rec]['RR_set'].plot(ax = ax1, color = 'green', linewidth = 3, ylim = [0, ymax] );
ax1.set_title(rec, size = 14, color = 'black')
ax1.set_xlabel('Time', size = 14, color = 'black')
ax1.set_ylabel('1/min', size = 14, color = 'black')
ax1.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
ax1.legend(['RR', 'alarm_high', 'RR_set'])
    
fig.savefig('%s/%s.jpg' % (DIR_WRITE, 'Figure_2b_color'), dpi=dpi, facecolor='w', edgecolor='w',
    orientation='portrait', papertype=None, format= filetype,
    transparent=False, bbox_inches=None, pad_inches=0.1, frameon=True)
rec = 'DG041'
filetype = 'jpg'
dpi = 300
ymax = slow_measurements[rec]['5001|RR [1/min]'].max() + 15
    
fig = plt.figure()
fig.set_size_inches(8, 6)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None,
wspace=None, hspace=0.7)
ax1 = fig.add_subplot(1, 1, 1);
    
slow_measurements[rec]['5001|RR [1/min]'].plot(ax = ax1, color = 'black', alpha = 0.6, ylim = [0, ymax] );
slow_measurements[rec]['RR_high'].plot(ax = ax1, color = 'black', linewidth = 3, ylim = [0, ymax] );
slow_measurements[rec]['RR_set'].plot(ax = ax1, color = 'black', linewidth = 3, ylim = [0, ymax] );
ax1.set_title(rec, size = 14, color = 'black')
ax1.set_xlabel('Time', size = 14, color = 'black')
ax1.set_ylabel('1/min', size = 14, color = 'black')
ax1.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
ax1.legend(['RR', 'alarm_high', 'RR_set'])
    
fig.savefig('%s/%s.jpg' % (DIR_WRITE, 'Figure_2b_bw'), dpi=dpi, facecolor='w', edgecolor='w',
    orientation='portrait', papertype=None, format= filetype,
    transparent=False, bbox_inches=None, pad_inches=0.1, frameon=True)
rec0 = 'DG003'
rec1 = 'DG041'
filetype = 'tiff'
dpi = 300
ymax0 = slow_measurements[rec0]['MV_high_weight'].max() + 0.3
ymax1 = slow_measurements[rec1]['5001|RR [1/min]'].max() + 15
fig = plt.figure()
fig.set_size_inches(6, 9)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.3)
ax0 = fig.add_subplot(2, 1, 1);
slow_measurements[rec0]['MV_kg'].plot(ax = ax0, color = 'blue', ylim = [0, ymax0] );
slow_measurements[rec0]['MV_low_weight'].plot(ax = ax0, color = 'green', linewidth = 3, ylim = [0, ymax0] );
slow_measurements[rec0]['MV_high_weight'].plot(ax = ax0, color = 'red', linewidth = 3,  ylim = [0, ymax0] );
ax0.set_title(rec0, size = 12, color = 'black')
ax0.set_xlabel('', size = 12, color = 'black')
ax0.set_ylabel('L/min/kg', size = 12, color = 'black')
ax0.tick_params(which = 'both', labelsize=10)
ax0.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
ax0.legend(['MV_kg', 'alarm_low', 'alarm_high']);
ax1 = fig.add_subplot(2, 1, 2);    
slow_measurements[rec1]['5001|RR [1/min]'].plot(ax = ax1, color = 'blue', ylim = [0, ymax1] );
slow_measurements[rec1]['RR_high'].plot(ax = ax1, color = 'red', linewidth = 3, ylim = [0, ymax1] );
slow_measurements[rec1]['RR_set'].plot(ax = ax1, color = 'green', linewidth = 3, ylim = [0, ymax1] );
ax1.set_title(rec1, size = 12, color = 'black')
ax1.set_xlabel('Time', size = 12, color = 'black')
ax1.set_ylabel('1/min', size = 12, color = 'black')
ax1.tick_params(which = 'both', labelsize=10)
ax1.grid('on', linestyle='-', linewidth=0.5, color = 'gray')
ax1.legend(['RR', 'alarm_high', 'RR_set'], loc = 4)
    
fig.savefig('%s/%s.tiff' % (DIR_WRITE, 'Figure_2'), dpi=dpi, facecolor='w', edgecolor='w',
    orientation='portrait', papertype=None, format= filetype,
    transparent=False, bbox_inches=None, pad_inches=0.1, frameon=True)
Explanation: Figure 2
End of explanation
# Histogram showing the number of alarms which were shorter than 1 minute
fig = plt.figure()
fig.set_size_inches(7, 5)
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
ax1 = fig.add_subplot(1, 1, 1)
n, bins, patches = plt.hist(all_durations, bins = range(0, 60))
plt.grid(True)
plt.xlabel('Alarm duration (seconds)', fontsize = 12)
plt.ylabel('Number of alarm events', fontsize = 12)
plt.xticks(range(0,60,4), fontsize = 12)
plt.yticks(fontsize = 12)
plt.title('Histogram of alarm durations', fontsize = 12)
fig.savefig('%s/%s' % (DIR_WRITE, 'Figure_3.tiff'), dpi=300, facecolor='w', edgecolor='w',
        orientation='portrait', papertype=None, format='tiff',
        transparent=False, bbox_inches=None, pad_inches=0.1,
        frameon=True)
Explanation: Figure 3
End of explanation
<END_TASK>