[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