[CCR PATCH] Calculate appropriate po2 values
Dirk Hohndel
dirk at hohndel.org
Fri Jun 20 15:54:49 PDT 2014
Willem,
I haven't had enough time looking at your patches and thinking through
them.
Could someone else do a code review and provide feedback - maybe some of
the long time contributors (Lubomir, Miika, Henrik)?
Thanks
/D
On Fri, Jun 20, 2014 at 06:44:28PM +0200, Willem Ferguson wrote:
> Calculate appropriate O2 partial pressures for CCR dives
>
> Files affected: profile.h, profile.c
>
> This patch ensures an appropriate representation of oxygen partial
> pressures
> for CCR equipment with one or more oxygen partial pressure sensors. The
> calculated po2 is stored in the po2 variable of the plot_data structure.
> The
> following changes were made:
> 1) In profile.h adapt plot_data with variables to accommodate the
> partial
> pressure values by creating fo2, o2sensor[3] and o2setpoint.
> 2) In profile.c change function calculate_gas_information_new:
> a) Add a dc parameter in the function call.
> b) Perform PO2 calculations using the following rules:
> For 2 PO2 sensors, calculate the mean of the two and store in po2.
> For 3 sensors: diff_limit is the critical limit indicating large
> sensor
> difference (default = 100 mbar)
> a) If all three readings are within a range of diff_limit, then
> take the
> mean value. This includes the case where reading 1 is within
> diff_limit of reading 2; and reading 2 is within diff_limit of
> reading 3, but readings 1 and 3 differ by more than diff_limit.
> b) If one sensor differs by more than diff-limit from the other
> two,
> then take the mean if the closer two sensors and disregard the
> 3rd
> sensor, considered as an outlier.
> c) If all 3 sensors differ by more than diff_limit then take the
> mean
> of the 3 readings.
>
> Signed-off-by: Willem Ferguson <willemferguson at zoology.up.ac.za>
>
>
> In terms of C code files this patch is independent of the previous CCR patch
> (dealing with xml and git I/O) since this one only affects profile.c and
> profile.h
> which were not involved in the previous patch.
> However, in execution it is dependent on the initialisation if the dive data
> structure (o2 sensor data) which is done in that patch.
> From 12f83036736c58170f1a8c7da97be9e2825d0be3 Mon Sep 17 00:00:00 2001
> From: Willem Ferguson <willemferguson at zoology.up.ac.za>
> Date: Fri, 20 Jun 2014 18:00:00 +0200
> Subject: [PATCH] Calculate appropriate O2 partial pressures for CCR dives
>
> This patch ensures an appropriate representation of oxygen partial pressures
> for CCR equipment with one or more oxygen partial pressure sensors. The
> following changes were made:
> 1) In profile.h adapt plot_data with variables to accommodate the partial
> pressure values by creating fo2, o2sensor[3] and o2setpoint.
> 2) In profile.c change function calculate_gas_information_new:
> a) Add a dc parameter in the function call.
> b) Perform PO2 calculations using the following rules:
> For 2 PO2 sensors, calculate the mean of the two and store in po2.
> For 3 sensors: diff_limit is the critical limit indicating large sensor
> difference (default = 100 mbar)
> a) If all three readings are within a range of diff_limit, then take the
> mean value. This includes the case where reading 1 is within
> diff_limit of reading 2; and reading 2 is within diff_limit of
> reading 3, but readings 1 and 3 differ by more than diff_limit.
> b) If one sensor differs by more than diff-limit from the other two,
> then take the mean if the closer two sensors and disregard the 3rd
> sensor, considered as an outlier.
> c) If all 3 sensors differ by more than diff_limit then take the mean
> of the 3 readings.
>
> Signed-off-by: Willem Ferguson <willemferguson at zoology.up.ac.za>
> ---
> profile.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
> profile.h | 4 +++-
> 2 files changed, 63 insertions(+), 8 deletions(-)
>
> diff --git a/profile.c b/profile.c
> index b40ef62..09057f7 100644
> --- a/profile.c
> +++ b/profile.c
> @@ -1126,12 +1126,16 @@ void calculate_deco_information(struct dive *dive, struct divecomputer *dc, stru
> #endif
> }
>
> -static void calculate_gas_information_new(struct dive *dive, struct plot_info *pi)
> +static void calculate_gas_information_new(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
> {
> - int i;
> + int i, j;
> double amb_pressure;
> + double sensordifference[3]; // The differences between the ogygen partial pressure measurements
> + double diff_limit = 100; // The limit beyond which O2 sensor differences are considered significant (default = 100 mbar)
> + int num_of_diffs; // The number of significant differences between the ogygen partial pressure measurements
>
> for (i = 1; i < pi->nr; i++) {
> + int s1 = 0, s2 = 1;
> int fo2, fhe;
> struct plot_data *entry = pi->entry + i;
> int cylinderindex = entry->cylinderindex;
> @@ -1140,11 +1144,59 @@ static void calculate_gas_information_new(struct dive *dive, struct plot_info *p
> fo2 = get_o2(&dive->cylinder[cylinderindex].gasmix);
> fhe = get_he(&dive->cylinder[cylinderindex].gasmix);
>
> + if (dc->dctype == CCR) { // for rebreathers..
> + // Estimate the most reliable PO2, given the different oxygen partial pressure values from the O2 sensors
> + switch(dc->no_o2sensors) {
> + case 2: { // For 2 sensors: take the mean value of the two partial pressure sensors.
> + entry->po2 = (entry->o2sensor[0] + entry->o2sensor[1]) * 0.5;
> + break;
> + }
> + case 3: { /* For 3 sensors: diff_limit is the critical limit indicating large sensor difference (default = 100 mbar).
> + * a) If all three readings are within a range of diff_limit, then take the mean value. This
> + * includes the case where reading 1 is within diff_limit of reading 2; and reading 2 is
> + * within diff_limit of reading 3, but readings 1 and 3 differ by more than diff_limit.
> + * b) If one sensor differs by more than diff-limit from the other two, then take the mean
> + * if the closer two sensors and disregard the 3rd sensor, considered as an outlier.
> + * c) If all 3 sensors differ by more than diff_limit then take the mean of the 3 readings. */
> +
> + sensordifference[0] = abs(entry->o2sensor[0] - entry->o2sensor[1]);
> + sensordifference[1] = abs(entry->o2sensor[1] - entry->o2sensor[2]);
> + sensordifference[2] = abs(entry->o2sensor[0] - entry->o2sensor[2]);
> +
> + for (num_of_diffs = 0, j = 0; j < 3; j++) // determine how many sensordifferences are larger than the diff_limit
> + if (sensordifference[j] > diff_limit) num_of_diffs++;
> +
> + if (num_of_diffs == 2) { // Case b) above: there is one clear outlier. Find this outlier.
> + if ((sensordifference[0] > diff_limit) && (sensordifference[1] > diff_limit)) {
> + s1 = 0;
> + s2 = 2;
> + } else if ((sensordifference[1] > diff_limit) && (sensordifference[2] > diff_limit)) {
> + s1 = 0;
> + s2 = 1;
> + } else {
> + s1 = 1;
> + s2 = 2;
> + }
> + entry->po2 = (entry->o2sensor[s1] + entry->o2sensor[s2]) * 0.5; // Disregard the outlier
> + } else // Cases a) and c) above. Not one clear outlier.
> + entry->po2 = (entry->o2sensor[0] + entry->o2sensor[1] + entry->o2sensor[2]) / 3.0;
> + break;
> + }
> + default: // if # of sensors is unknown, simply take the value of the first sensor
> + if (entry->o2sensor[0])
> + entry->po2 = entry->o2sensor[0];
> + else
> + entry->po2 = 0; // if no sensor value found, then go to next section, esimating PO2 using depth.
> + }
> + entry->fo2 = 1000 * entry->po2 / amb_pressure; // remember, it should be in permille
> + fo2 = entry->fo2;
> + } // dc->type == CCR
> +
> if (entry->po2) {
> /* we have an O2 partial pressure in the sample - so this
> - * is likely a CC dive... use that instead of the value
> + * is likely a CCR dive... use that instead of the value
> * from the cylinder info */
> - if (entry->po2 >= amb_pressure || fo2 == 1000) {
> + if (entry->po2 >= amb_pressure || fo2 == 1000) {
> entry->po2 = amb_pressure;
> entry->phe = 0;
> entry->pn2 = 0;
> @@ -1155,11 +1207,11 @@ static void calculate_gas_information_new(struct dive *dive, struct plot_info *p
> } else {
> entry->po2 = fo2 / 1000.0 * amb_pressure;
> entry->phe = fhe / 1000.0 * amb_pressure;
> - entry->pn2 = (1000 - fo2 - fhe) / 1000.0 * amb_pressure;
> + entry->pn2 = (1000 - fo2 - fhe) / 1000.0 * amb_pressure;
> }
>
> /* Calculate MOD, EAD, END and EADD based on partial pressures calculated before
> - * so there is no difference in calculating between OC and CC
> + * so there is no difference in calculating between OC and CCR
> * END takes O2 + N2 (air) into account ("Narcotic" for trimix dives)
> * EAD just uses N2 ("Air" for nitrox dives) */
> pressure_t modppO2 = { .mbar = (int) (prefs.modppO2 * 1000) };
> @@ -1181,6 +1233,7 @@ static void calculate_gas_information_new(struct dive *dive, struct plot_info *p
> entry->eadd = 0;
> }
> }
> +
> /*
> * Create a plot-info with smoothing and ranged min/max
> *
> @@ -1209,7 +1262,7 @@ void create_plot_info_new(struct dive *dive, struct divecomputer *dc, struct plo
> populate_pressure_information(dive, dc, pi); /* .. calculate missing pressure entries */
> calculate_sac(dive, pi); /* Calculate sac */
> calculate_deco_information(dive, dc, pi, false);
> - calculate_gas_information_new(dive, pi); /* And finaly calculate gas partial pressures */
> + calculate_gas_information_new(dive, dc, pi); /* And finaly calculate gas partial pressures */
> pi->meandepth = dive->dc.meandepth.mm;
> analyze_plot_info(pi);
> }
> diff --git a/profile.h b/profile.h
> index 54d250a..793bce7 100644
> --- a/profile.h
> +++ b/profile.h
> @@ -34,7 +34,9 @@ struct plot_data {
> int cns;
> int smoothed;
> int sac;
> - double po2, pn2, phe;
> + double fo2, po2, pn2, phe;
> + double o2sensor[3];
> + double o2setpoint;
> double mod, ead, end, eadd;
> velocity_t velocity;
> int speed;
> --
> 1.7.10.4
>
> _______________________________________________
> subsurface mailing list
> subsurface at hohndel.org
> http://lists.hohndel.org/cgi-bin/mailman/listinfo/subsurface
More information about the subsurface
mailing list