|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #######################################  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Module  : Tissue.pm  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Author  : Jaap Voets  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Date    : 04-05-2006   | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $Revision$  | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #######################################  | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Deco::Tissue;  | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
9
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
920
 | 
 use strict;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
182
 | 
    | 
| 
10
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
25
 | 
 use warnings;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
150
 | 
    | 
| 
11
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
25
 | 
 use Carp;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
306
 | 
    | 
| 
12
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
4184
 | 
 use POSIX qw( pow );  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39803
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
    | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '0.5';  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # water vapor at 37 degrees celsius (i.e. our lungs)  | 
| 
16
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
6301
 | 
 use constant WATER_VAPOR_PRESSURE => 0.0627;   | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
373
 | 
    | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # carbon dioxide pressure for normal persons  | 
| 
19
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
24
 | 
 use constant CO2_PRESSURE => 0.0534;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12871
 | 
    | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # properties of the object that can be set by the user  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @PROPERTIES = ('halftime','m0', 'deltam', 'o2fraction', 'waterfactor','topsidepressure','offgasfactor','RQ', 'nr');  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # supported GASES, with fractions in breathing mix  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our %GASES = ( 'o2' => 0.21,  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	       'n2' => 0.78,  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	       'he' => 0);  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Constructor  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
31
 | 
179
 | 
 
 | 
 
 | 
  
179
  
 | 
  
1
  
 | 
9258
 | 
     my $class = shift;  | 
| 
32
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
754
 | 
     my %args  = @_;  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
34
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
296
 | 
     my $self = {};  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # defaults  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # O2 fraction  | 
| 
38
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
566
 | 
     $self->{o2}->{fraction} = 0.21;  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # N2 fraction  | 
| 
41
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
411
 | 
     $self->{n2}->{fraction} = 0.78;  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # pressure at start of dive, normally 1 bar sea level  | 
| 
44
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
283
 | 
     $self->{topsidepressure} = 1; #bar  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   	  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # specific weight for the type of water, fresh = 1.000, salt = 1.030  | 
| 
47
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
255
 | 
     $self->{waterfactor} = 1.000;  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # offgassing might be slower than ongassing  | 
| 
50
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
237
 | 
     $self->{offgasfactor} = 1;  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # respiratory quotient RQ. This is the amount of CO2 produced per O2  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # schreiner uses 0.8 (more conservative), US Navy 0.9 , Buhlmann 1.0  | 
| 
54
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
250
 | 
     $self->{RQ} = 0.8;  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
56
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
247
 | 
     $self->{nr} = 0;  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # we need a few things for a valid tissue  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # half time (in minutes)  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # M0 and deltaM value (in bar)  | 
| 
61
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
473
 | 
     foreach my $arg (keys %args) {  | 
| 
62
 | 
709
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1032
 | 
 	if ( grep {/$arg/i} @PROPERTIES) {  | 
| 
 
 | 
6381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18534
 | 
    | 
| 
63
 | 
709
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2128
 | 
 	    $self->{ lc($arg) } = $args{ $arg };  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
65
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    carp "Argument $arg is not valid";  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
69
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
493
 | 
     bless $self, $class;  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # additional properties, these are for finetuning  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # current internal pressure for N2, assumes equilibrium at current level (sea or higher)  | 
| 
75
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
411
 | 
     $self->{n2}->{pressure} = $self->_alveolarPressure( depth=>0 , gas=>'n2');  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # defaults to sea level in bar  | 
| 
78
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
359
 | 
     $self->{ambientpressure} = $self->{topsidepressure};  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # current depth in meters  | 
| 
81
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
246
 | 
     $self->{depth} = 0;  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # previous depth  | 
| 
84
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
228
 | 
     $self->{previousdepth} = 0;  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # some timestamps in seconds  | 
| 
87
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
413
 | 
     $self->{time}->{current}  = 0;  | 
| 
88
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
284
 | 
     $self->{time}->{previous} = 0;  | 
| 
89
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
247
 | 
     $self->{time}->{lastdepthchange} = 0;  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # oxygen exposure tracking through OTU's  | 
| 
92
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
264
 | 
     $self->{otu}   = 0;  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # haldane formula for current parameters, returns a ref to a sub  | 
| 
95
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
358
 | 
     $self->{haldane} = $self->_haldanePressure();  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
97
 | 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1152
 | 
     return $self;  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # get the tissue nr  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub nr {  | 
| 
102
 | 
666
 | 
 
 | 
 
 | 
  
666
  
 | 
  
1
  
 | 
1281
 | 
     my $self = shift;  | 
| 
103
 | 
666
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1515
 | 
     croak "Tissue numbers not set yet" unless ($self->{nr});  | 
| 
104
 | 
666
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5381
 | 
     return $self->{nr};  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # return the current internal for requested gas pressure  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub internalpressure {  | 
| 
109
 | 
1099
 | 
 
 | 
 
 | 
  
1099
  
 | 
  
1
  
 | 
2532
 | 
     my $self = shift;  | 
| 
110
 | 
1099
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1971
 | 
     my %opt  = @_;  | 
| 
111
 | 
1099
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
29746
 | 
     my $gas  = lc($opt{gas}) || 'n2';  | 
| 
112
 | 
1099
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3302
 | 
     croak "Asking for unsupported gas $gas" unless exists $GASES{$gas};  | 
| 
113
 | 
1099
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6604
 | 
     return $self->{$gas}->{pressure};  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # percentage of tissue pressure compared to allowed M0  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub percentage {  | 
| 
118
 | 
549
 | 
 
 | 
 
 | 
  
549
  
 | 
  
1
  
 | 
681
 | 
     my $self = shift;  | 
| 
119
 | 
549
 | 
 
 | 
 
 | 
 
 | 
 
 | 
758
 | 
     my %opt  = @_;  | 
| 
120
 | 
549
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
30573
 | 
     my $gas  = lc($opt{gas}) || 'n2';  | 
| 
121
 | 
549
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2105
 | 
     return ( 100 * $self->internalpressure( gas => $gas) / $self->{m0}) ;  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # return the current OTU (Oxygen Toxicity Unit)  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub otu {  | 
| 
126
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
1
  
 | 
11
 | 
     my $self = shift;  | 
| 
127
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     return $self->{otu};  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # calculate otu's, should be called after changing depth/time  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # if pO2 > 0.5 then OTU = minutes x ( ( pO2 -0.5 ) / 0.5) ^ 0.83  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub calculate_otu {  | 
| 
133
 | 
552
 | 
 
 | 
 
 | 
  
552
  
 | 
  
1
  
 | 
652
 | 
     my $self = shift;  | 
| 
134
 | 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1372
 | 
     my $minutes = ($self->{time}->{current} - $self->{time}->{previous} ) / 60;  | 
| 
135
 | 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
604
 | 
     my $otu = 0;  | 
| 
136
 | 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
993
 | 
     my $pO2 = $self->ambientpressure() * $self->{o2}->{fraction};  | 
| 
137
 | 
552
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1185
 | 
     if ($pO2 > 0.5) {  | 
| 
138
 | 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1132
 | 
 	$otu = $minutes * POSIX::pow( 2 * $pO2 - 1,  0.83);  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
140
 | 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1708
 | 
     $self->{otu} += $otu;  | 
| 
141
 | 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3719
 | 
     return $self->{otu};  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # set time, depth combination  | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # this way we control the order of time/depth changes  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # during descent, we want to change depth first, the time  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # during ascent we want to change the time first then the depth  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # this way we calculate the 'outer' profile in rectangles of the real profile  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # and thus we are more conservative  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub point {  | 
| 
151
 | 
710
 | 
 
 | 
 
 | 
  
710
  
 | 
  
1
  
 | 
3400
 | 
     my $self = shift;  | 
| 
152
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1109
 | 
     my ($time, $depth) = @_;  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
154
 | 
710
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2270
 | 
     if ( $depth > $self->{previousdepth} ) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# descending, so depth first   | 
| 
156
 | 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
950
 | 
 	$self->depth( $depth );  | 
| 
157
 | 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1033
 | 
 	$self->time( $time );  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ( $depth < $self->{previousdepth} ) {  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# ascending, so time first  | 
| 
161
 | 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
501
 | 
 	$self->time( $time );  | 
| 
162
 | 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
483
 | 
 	$self->depth( $depth );  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# same depth, only time change  | 
| 
165
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
 	$self->time( $time );  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
168
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1693
 | 
     return 1;  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # set gas fractions  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub gas {  | 
| 
173
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
  
1
  
 | 
186
 | 
     my $self = shift;  | 
| 
174
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
     my %gaslist = @_;  | 
| 
175
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
     foreach my $keygas (keys %gaslist) {  | 
| 
176
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
 	my $gas = lc($keygas);  | 
| 
177
 | 
22
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
63
 | 
 	if (! exists $GASES{$gas} ) {  | 
| 
178
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
48
 | 
 	    croak "Can't use gas $gas";  | 
| 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
180
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
 	my $fraction = $gaslist{$keygas};  | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# if using percentage, convert to fractions  | 
| 
182
 | 
20
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
52
 | 
 	if ($fraction > 1) {  | 
| 
183
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
 	    $fraction = $fraction / 100;  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
186
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
 	$self->{$gas}->{fraction} = $fraction;  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
188
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
44
 | 
     return 1;  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # set new depth point  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub depth {  | 
| 
193
 | 
698
 | 
 
 | 
 
 | 
  
698
  
 | 
  
1
  
 | 
1256
 | 
     my $self = shift;  | 
| 
194
 | 
698
 | 
 
 | 
 
 | 
 
 | 
 
 | 
898
 | 
     my $depth = shift;  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
196
 | 
698
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1339
 | 
     croak "Depth can not be negative" unless($depth >= 0);  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
198
 | 
697
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1492
 | 
     if ($depth != $self->{depth} ) {  | 
| 
199
 | 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
890
 | 
 	$self->{previousdepth} = $self->{depth};  | 
| 
200
 | 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
738
 | 
         $self->{depth}         = $depth;  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# remember this depthchange on the time scale  | 
| 
203
 | 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1331
 | 
 	$self->{time}->{lastdepthchange} = $self->{time}->{current};  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	#print "Time of last depth change is: " . $self->{time}->{lastdepthchange} ."\n";  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# when depth changes we need to recalculate the Haldane formula  | 
| 
207
 | 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1094
 | 
 	$self->{haldane} = $self->_haldanePressure();  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
210
 | 
697
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2968
 | 
     return $self->{depth};  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # set new timestamp in seconds  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub time {  | 
| 
216
 | 
711
 | 
 
 | 
 
 | 
  
711
  
 | 
  
1
  
 | 
2143
 | 
     my $self = shift;  | 
| 
217
 | 
711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
832
 | 
     my $time = shift;  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
219
 | 
711
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1851
 | 
     croak "Time can not be negative" unless($time >= 0);  | 
| 
220
 | 
710
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2195
 | 
     if ($time != $self->{time}->{current} ) {  | 
| 
221
 | 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
908
 | 
 	$self->{time}->{previous} = $self->{time}->{current};  | 
| 
222
 | 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
662
 | 
 	$self->{time}->{current}  = $time;  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# when time changes, we need to recalculate the internal pressure  | 
| 
225
 | 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1025
 | 
 	my $minutes = ($time - $self->{time}->{lastdepthchange}) / 60;  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	#print "Minutes passed since last depth change: $minutes\n";  | 
| 
227
 | 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
514
 | 
 	$self->{n2}->{pressure} = &{ $self->{haldane} }( $minutes );  | 
| 
 
 | 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1169
 | 
    | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	#print "So internal N2 is now: " . $self->{n2}->{pressure} . "\n";  | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
231
 | 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1892
 | 
     return $self->{time}->{current};  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # set or get halftime  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub halftime {  | 
| 
237
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
1
  
 | 
5
 | 
     my $self = shift;  | 
| 
238
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     my $newvalue = shift;  | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
240
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     if ($newvalue) {  | 
| 
241
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 	croak "Halftimes need to be entered in positives minutes" unless($newvalue >= 1);  | 
| 
242
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	$self->{halftime} = $newvalue;  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
245
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     return $self->{halftime};  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # set or get Respiratory Quotient (RQ)  | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub rq {  | 
| 
250
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
3
 | 
     my $self = shift;  | 
| 
251
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     my $newvalue = shift;  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
253
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     if ($newvalue) {  | 
| 
254
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
9
 | 
 	croak "RQ (Respiratory Quotient) needs to be entered in the range 0.7 - 1.1" unless($newvalue >= 0.7 and $newvalue <= 1.1);  | 
| 
255
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	$self->{RQ} = $newvalue;  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
258
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     return $self->{RQ};  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # get the K value = ln(2) / halftime  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub k {  | 
| 
263
 | 
1594
 | 
 
 | 
 
 | 
  
1594
  
 | 
  
1
  
 | 
1777
 | 
     my $self = shift;  | 
| 
264
 | 
1594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4378
 | 
     return log(2) / $self->{halftime};	  | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # give ambient total pressure  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub ambientpressure {  | 
| 
269
 | 
2613
 | 
 
 | 
 
 | 
  
2613
  
 | 
  
1
  
 | 
3009
 | 
     my $self = shift;  | 
| 
270
 | 
2613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2897
 | 
     my $depth = shift;  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
272
 | 
2613
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
5004
 | 
     $depth = $self->{depth} unless defined $depth;  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
274
 | 
2613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5305
 | 
     my $press = $self->{topsidepressure} + $self->_depth2pressure( $depth );  | 
| 
275
 | 
2613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3760
 | 
     $self->{ambientpressure} = $press;  | 
| 
276
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
277
 | 
2613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6886
 | 
     return $press;  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # print info about tissue  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub info {  | 
| 
282
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
3
 | 
 	my $self = shift;  | 
| 
283
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my $gaslist = '';  | 
| 
284
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	foreach my $gas (keys %GASES) {  | 
| 
285
 | 
3
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
13
 | 
 	    my $fraction = $self->{$gas}->{fraction} || 0;  | 
| 
286
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
 	    $gaslist .= " $gas at " . sprintf("%.1f", 100 * $fraction) . "%  ";   | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
289
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 	my $info = "============================================================  | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =   TISSUE INFO  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = Halftime (min)     : " . $self->{halftime} ."  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = k  (min^-1)        : " . $self->k ."  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = RQ                 : " . $self->{RQ} ."  | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = M0 (bar)           : " . $self->{m0} ."  | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = delta M (bar/m)    : " . $self->{deltam} ."  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = Ambient (bar)      : " . $self->ambientpressure() ."  | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = Depth (m)          : " . $self->{depth} ."  | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = Total time (s)     : " . $self->{time}->{current} ."  | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = Tissue N2 (bar)    : " . $self->{n2}->{pressure} . "  | 
| 
301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = Alveo. N2 (bar)    : " . $self->_alveolarPressure( gas => 'n2', depth => $self->{depth} ) ."  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = M (bar)            : " . $self->M( depth => $self->{depth}) ."  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = Safe depth (m)     : " . $self->safe_depth( gas => 'n2') ."  | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = No deco time (min) : " . $self->nodeco_time( gas => 'n2') ."  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = OTU's              : " . $self->{otu} ."  | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 = Gas list           : $gaslist    | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ===========================================================\n";  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
309
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	return $info;  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # get the current M-values  | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub M {  | 
| 
314
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
1
  
 | 
5
 | 
     my $self = shift;  | 
| 
315
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     my %opt = @_;  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      | 
| 
317
 | 
3
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
23
 | 
     my $depth = $opt{depth} || $self->{depth};  # meters  | 
| 
318
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     my $M = $self->{m0} + $self->{deltam} * $depth / ( 10 * $self->{waterfactor} );  # bar  | 
| 
319
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     $self->{M} = $M;  | 
| 
320
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     return $M;  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # calculate the minimal depth to which we can safely ascend  | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # without exceeding the M0 value for the tissue  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub safe_depth {  | 
| 
327
 | 
550
 | 
 
 | 
 
 | 
  
550
  
 | 
  
1
  
 | 
659
 | 
 	my $self = shift;  | 
| 
328
 | 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
777
 | 
 	my %opt  = @_;  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
330
 | 
550
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
30376
 | 
 	my $gas = lc($opt{gas}) || 'n2';	  | 
| 
331
 | 
550
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2091
 | 
 	croak "The Delta M value has not been set for this tissue" unless ($self->{deltam} > 0);  | 
| 
332
 | 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1449
 | 
 	my $safe_depth = ( $self->{$gas}->{pressure} - $self->{m0} ) / $self->{deltam};  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# negative values mean we can go to the surface  | 
| 
335
 | 
550
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1150
 | 
 	if ($safe_depth < 0 ) {  | 
| 
336
 | 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
664
 | 
 		$safe_depth = 0;  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
339
 | 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1782
 | 
 	return $safe_depth;  | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # calculate how long this tissue is allowed to stay at the current depth  | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # without getting into Deco  | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # note: time is returned in minutes  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub nodeco_time {  | 
| 
346
 | 
733
 | 
 
 | 
 
 | 
  
733
  
 | 
  
1
  
 | 
925
 | 
     my $self = shift;  | 
| 
347
 | 
733
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1087
 | 
     my %opt = @_;  | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
349
 | 
733
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
39937
 | 
     my $gas = lc($opt{gas}) || 'n2';  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # shortcut: take P_no_deco to be M0 (instant go to surface)  | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # unless a specific pressure was specified (for time_until function)  | 
| 
353
 | 
733
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2451
 | 
     my $p_end = $self->{m0};  | 
| 
354
 | 
733
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1725
 | 
     my $time = $self->time_until_pressure( pressure => $p_end, gas => $gas );  | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
356
 | 
733
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2329
 | 
     return $time;  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # calculate how many minutes this tissue  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # can stay at the present depth until the  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # given pressure (in bar) will be reached  | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # a special case of this function is d  | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # this is practically the same as the no_deco_time function  | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # but there we take some surfacing pressure   | 
| 
367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub time_until_pressure {  | 
| 
368
 | 
1095
 | 
 
 | 
 
 | 
  
1095
  
 | 
  
1
  
 | 
2790
 | 
     my $self = shift;  | 
| 
369
 | 
1095
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2906
 | 
     my %opt = @_;  | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
371
 | 
1095
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
25491
 | 
     my $gas = lc($opt{gas}) || 'n2';  | 
| 
372
 | 
1095
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1685
 | 
     my $pressure = $opt{pressure};  | 
| 
373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # alveolar pressure  | 
| 
375
 | 
1095
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2654
 | 
     my $p_alv = $self->_alveolarPressure( gas => $gas , depth => $self->{depth} );  | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
377
 | 
1095
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2123
 | 
     my $k = $self->k();  | 
| 
378
 | 
1095
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1387
 | 
     my $time_until = '-';  | 
| 
379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
380
 | 
1095
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1365
 | 
     my $depth = $self->{'depth'};  | 
| 
381
 | 
1095
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1614
 | 
     my $current_pressure = $self->{$gas}->{pressure};  | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
383
 | 
1095
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2240
 | 
     if ($current_pressure >= $pressure) {  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		# already at or over the wanted pressure  | 
| 
385
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$time_until = 0;  | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
387
 | 
1095
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1262
 | 
 		my $denominator = $current_pressure - $p_alv;  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      | 
| 
389
 | 
1095
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1976
 | 
 		if ( $denominator ) {  | 
| 
390
 | 
1077
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1118
 | 
 			my $nominator = $pressure - $p_alv;  | 
| 
391
 | 
1077
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1175
 | 
 			my $fraction = $nominator / $denominator;  | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
393
 | 
1077
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2214
 | 
 			if ($fraction > 0 ) {  | 
| 
394
 | 
639
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1309
 | 
 			    $time_until = -1 / $k * log( $fraction );  | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			    # round it to whole minutes  | 
| 
396
 | 
639
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1375
 | 
 			    $time_until = sprintf('%.0f', $time_until);  | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }   | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
401
 | 
1095
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3244
 | 
     return $time_until;  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ##########################################  | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # PRIVATE FUNCTIONS  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ##########################################  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # convert meters to bar  | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # this does NOT include the starting pressure  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # so 0 meters = 0 bar water pressure  | 
| 
412
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _depth2pressure {  | 
| 
413
 | 
2615
 | 
 
 | 
 
 | 
  
2615
  
 | 
 
 | 
2703
 | 
     my $self = shift;  | 
| 
414
 | 
2615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2756
 | 
     my $depth = shift;  | 
| 
415
 | 
2615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4784
 | 
     my $press =  $depth  * $self->{waterfactor} / 10;  | 
| 
416
 | 
2615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5949
 | 
     return $press;  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # use haldanian formula to solve the current pressure in tissue  | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # as long as the depth remains constant, this formula is still valid  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _haldanePressure {  | 
| 
422
 | 
781
 | 
 
 | 
 
 | 
  
781
  
 | 
 
 | 
995
 | 
     my $self = shift;  | 
| 
423
 | 
781
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
45453
 | 
     my $gas  = lc(shift) || 'n2';  | 
| 
424
 | 
781
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2668
 | 
     croak "Asking for unsupported gas $gas" unless exists $GASES{$gas};  | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # we need the current tissure pressure, at t=0 for the depth  | 
| 
427
 | 
781
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1696
 | 
     my $tissue_press0 = $self->{$gas}->{pressure};  | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #print "recalculating haldane formula. tissue pressure at t0 = $tissue_press0\n";  | 
| 
429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # and the alveolar pressure  | 
| 
431
 | 
781
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1885
 | 
     my $alveolar = $self->_alveolarPressure( depth => $self->{depth} );  | 
| 
432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # the time in minutes we have been at this depth, note that internal times are in seconds!  | 
| 
434
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return sub {  | 
| 
435
 | 
497
 | 
 
 | 
 
 | 
  
497
  
 | 
 
 | 
586
 | 
 		my $t = shift;  | 
| 
436
 | 
497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1106
 | 
 		$alveolar + ($tissue_press0 - $alveolar ) * exp( -1 * $self->k() * $t );  | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
439
 | 
781
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6387
 | 
 }  | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # return alvealor pressure for N2 (or other inert gas specified)  | 
| 
442
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # see the Deco.pdf document for explanation on this calculation  | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _alveolarPressure {  | 
| 
444
 | 
2058
 | 
 
 | 
 
 | 
  
2058
  
 | 
 
 | 
2452
 | 
     my $self = shift;  | 
| 
445
 | 
2058
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6151
 | 
     my %opt  = @_;  | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
447
 | 
2058
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
5235
 | 
     my $depth = $opt{depth} || 0;  | 
| 
448
 | 
2058
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
46440
 | 
     my $gas  = lc($opt{gas}) || 'n2';  | 
| 
449
 | 
2058
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5521
 | 
     croak "Asking for unsupported gas $gas" unless exists $GASES{$gas};  | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
451
 | 
2058
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5305
 | 
     my $press = $self->{$gas}->{fraction} * ( $self->ambientpressure( $depth ) - WATER_VAPOR_PRESSURE +  ( ( 1 - $self->{RQ} ) / $self->{RQ} ) * CO2_PRESSURE );  | 
| 
452
 | 
2058
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5062
 | 
     return $press;	  | 
| 
453
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
454
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
455
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
456
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |