Skip to content

Commit ee40200

Browse files
authored
Merge pull request #229 from MideTechnology/feature/ES-803_pressure_to_altitude
feature/ES-803 pressure to altitude
2 parents a75ced3 + 5e1bc05 commit ee40200

16 files changed

+355
-5
lines changed

endaq/calc/utils.py

Lines changed: 119 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from __future__ import annotations
44

55
import typing
6-
from typing import Optional, Union
6+
from typing import Optional, Union, Literal
77
import warnings
88

99
import numpy as np
@@ -161,9 +161,9 @@ def resample(df: pd.DataFrame, sample_rate: Optional[float] = None) -> pd.DataFr
161161
index=resampled_time.astype(df.index.dtype),
162162
columns=df.columns,
163163
)
164-
164+
165165
resampled_df.index.name = df.index.name
166-
166+
167167
return resampled_df
168168

169169

@@ -343,3 +343,119 @@ def convert_units(
343343
for i, c in enumerate(df.columns):
344344
converted_df[c] = vals[:, i]
345345
return converted_df
346+
347+
348+
def to_altitude(df: pd.DataFrame,
349+
base_press: Optional[float] = 101325,
350+
base_temp: Optional[float] = 15,
351+
temp_col_index: Optional[int] = None,
352+
press_col_index: Optional[int] = None,
353+
units: Literal['m', 'ft'] = 'm') -> pd.DataFrame:
354+
"""
355+
Converts pressure (Pascals) to altitude (feet or meters) up to 50km.
356+
357+
:param df: pandas DataFrame of one of the temperature/pressure channels.
358+
A pressure column should be present, if not, raise an error
359+
:param base_press: P_b; reference pressure (pressure at sea level) in
360+
Pascals (Pa). If set to None, use the first pressure measurement
361+
included in the dataframe (df)
362+
:param base_temp: T_b reference temperature (temperature at sea level) in
363+
Celsius (C). If set to None and a Temperature column exists in the
364+
dataframe (df), use the first listed temperature value. If set to None
365+
and no temperature column exists, error out
366+
:param temp_col_index: the index (starting at 0) in the dataframe (df) of
367+
the temperature column to pull data from.
368+
:param press_col_index: the index (starting at 0) in the dataframe (df) of
369+
the pressure column to pull data from
370+
:param units: determines if altitude is represented in meters ('m') or feet
371+
('ft') in both the input and output dataframes
372+
:returns: a pandas DataFrame with the same Index values as the
373+
input, and an added column of “Altitude (m)” or “Altitude (ft)” data
374+
"""
375+
# Column Name Placeholders
376+
temp_col = None
377+
press_col = None
378+
379+
# Conversion Constants
380+
C_K = 273.15 # Celsius to Kelvin Constant (C + 273.15 = K)
381+
ft_m = 0.3048 # Feet to Meters Constant (ft * 0.3048 = m) & (m / 0.3048 = ft)
382+
383+
# Constants
384+
h_b = 0 # Reference Height of Sea Level (m)
385+
h_sb = 11000 # Height at the Base of the Stratosphere (meters)
386+
h_st = 50000 # Height at the Top of the Stratosphere (meters)
387+
L_b = -0.0065 # Standard Temperature Lapse Rate [K/m]
388+
g_0 = 9.80665 # Gravitational Acceleration Constant [m/s^2]
389+
R = 8.31432 # Universal Gas Constant [N*m/mol*K]
390+
M = 0.0289644 # Molar Mass of Earth's Air [kg/mol]
391+
top_stratosphere_pressure = 100 # Air Pressure at Stratopause (1mb)=[100 Pa]
392+
393+
# Finding pressure column
394+
if press_col_index is None:
395+
for col in df.columns:
396+
if "press" in col.lower():
397+
press_col = col
398+
press_col_index = df.columns.get_loc(press_col)
399+
break
400+
if press_col is None:
401+
raise ValueError("Pressure column not found.")
402+
else:
403+
press_col = df.columns[press_col_index]
404+
405+
# Checking for base temp and converting to K
406+
if base_temp == None:
407+
if temp_col_index is None:
408+
for col in df.columns:
409+
if "temp" in col.lower():
410+
temp_col = col
411+
temp_col_index = df.columns.get_loc(temp_col)
412+
break
413+
if temp_col is None:
414+
raise ValueError('Temperature column not found.')
415+
T_b = df.iloc[0, temp_col_index] + C_K # Standard Temperature in Kelvin
416+
T_bS = T_b -71.5 # Temperature at start of Stratosphere
417+
else:
418+
T_b = base_temp + C_K # Standard Temperature in Kelvin
419+
T_bS = T_b -71.5 # Temperature at start of Stratosphere
420+
421+
# Checking for base pressure
422+
if base_press == None:
423+
# Set to first pressure recording in the dataframe
424+
P_b = df.iloc[0, press_col_index] # Static Pressure in Pascals
425+
else:
426+
P_b = base_press # Static Pressure in Pascals
427+
428+
# Pressure at base of Stratosphere
429+
base_stratosphere_pressure = (P_b * (1 + (L_b / T_b) * (h_sb - h_b)) **
430+
((-g_0 * M) / (R * L_b)))
431+
432+
# List of Altitudes to be added to Dataframe
433+
altitude_column = []
434+
435+
# Calculate Altitude for the DataFrame
436+
for index, row in df.iterrows():
437+
P = row[press_col]
438+
if P > base_stratosphere_pressure:
439+
h = h_b + (T_b / L_b) * (((P / P_b) ** ((-R * L_b) / (g_0 * M))) - 1)
440+
altitude_column.append(h)
441+
elif top_stratosphere_pressure < P < base_stratosphere_pressure:
442+
h = h_sb + ((R * T_bS * np.log(P / base_stratosphere_pressure)) /
443+
(-g_0 * M))
444+
altitude_column.append(h)
445+
else:
446+
raise ValueError("Altitudes above stratosphere not supported.")
447+
448+
# Convert Altitude back to feet if specified
449+
if units == 'ft':
450+
altitude_column = [x / ft_m for x in altitude_column]
451+
# Add "Altitude (ft)" Column to Copy of Original Dataframe
452+
alt_df = df.copy()
453+
alt_df["Altitude (ft)"] = altitude_column
454+
455+
# Add "Altitude (m)" Column to Copy of Original Dataframe
456+
if units == 'm':
457+
alt_df = df.copy()
458+
alt_df["Altitude (m)"] = altitude_column
459+
460+
# Return DataFrame with New Altitude Column
461+
return alt_df

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def get_version(rel_path):
2626
"ebmlite>=3.2.0",
2727
"idelib>=3.2.8",
2828
"jinja2",
29-
"numpy>=1.19.5",
29+
"numpy>1.19.5",
3030
"pandas>=1.3",
3131
"plotly>=5.3.1",
3232
"pynmeagps",

tests/batch/test_core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ def assert_output_is_valid(output: endaq.batch.core.OutputStruct):
292292
@pytest.mark.filterwarnings("ignore:no acceleration channel in:UserWarning")
293293
@pytest.mark.filterwarnings(
294294
"ignore"
295-
":nperseg .* is greater than input length .*, using nperseg .*"
295+
":.*nperseg.* is greater than (signal|input) length.*, using nperseg .*"
296296
":UserWarning"
297297
)
298298
def test_aggregate_data(getdata_builder):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Pressure (Pa),Temperature (C)
2+
25,15
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Pressure (Pa),Temperature (C)
2+
101325,15
3+
100000,
4+
95000,
5+
90000,
6+
85000,
7+
80000,
8+
75000,
9+
70000,
10+
65000,
11+
60000,
12+
55000,
13+
50000,
14+
45000,
15+
40000,
16+
35000,
17+
30000,
18+
25000,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Key,base settings = None
2+
0.00
3+
110.88
4+
540.34
5+
988.50
6+
1457.30
7+
1948.99
8+
2466.23
9+
3012.18
10+
3590.69
11+
4206.43
12+
4865.22
13+
5574.44
14+
6343.62
15+
7185.44
16+
8117.27
17+
9163.96
18+
10362.95
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Key,settings are default
2+
0.00
3+
110.88
4+
540.34
5+
988.50
6+
1457.30
7+
1948.99
8+
2466.23
9+
3012.18
10+
3590.69
11+
4206.43
12+
4865.22
13+
5574.44
14+
6343.62
15+
7185.44
16+
8117.27
17+
9163.96
18+
10362.95
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Key,the base pressure is not set to the default value
2+
-111.16
3+
0
4+
430.53
5+
879.82
6+
1349.79
7+
1842.71
8+
2361.25
9+
2908.57
10+
3488.53
11+
4105.81
12+
4766.26
13+
5477.25
14+
6248.37
15+
7092.29
16+
8026.46,
17+
9075.77
18+
10277.77
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Key,the base temperature is not set to the default value
2+
0.00
3+
116.66
4+
568.47
5+
1039.96
6+
1533.16
7+
2050.45
8+
2594.61
9+
3168.99
10+
3777.61
11+
4425.40
12+
5118.48
13+
5864.62
14+
6673.85
15+
7559.48
16+
8539.82
17+
9641.00
18+
10902.40
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Key,the base temperature and pressure are not set to default values
2+
-116.95
3+
0.00
4+
452.94
5+
925.62
6+
1420.06
7+
1938.64
8+
2484.17
9+
3059.98
10+
3670.13
11+
4319.54
12+
5014.37
13+
5762.38
14+
6573.63
15+
7461.49
16+
8444.29
17+
9548.22
18+
10812.79

0 commit comments

Comments
 (0)