Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 119 additions & 3 deletions endaq/calc/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

import typing
from typing import Optional, Union
from typing import Optional, Union, Literal
import warnings

import numpy as np
Expand Down Expand Up @@ -161,9 +161,9 @@ def resample(df: pd.DataFrame, sample_rate: Optional[float] = None) -> pd.DataFr
index=resampled_time.astype(df.index.dtype),
columns=df.columns,
)

resampled_df.index.name = df.index.name

return resampled_df


Expand Down Expand Up @@ -343,3 +343,119 @@ def convert_units(
for i, c in enumerate(df.columns):
converted_df[c] = vals[:, i]
return converted_df


def to_altitude(df: pd.DataFrame,
base_press: Optional[float] = 101325,
base_temp: Optional[float] = 15,
temp_col_index: Optional[int] = None,
press_col_index: Optional[int] = None,
units: Literal['m', 'ft'] = 'm') -> pd.DataFrame:
"""
Converts pressure (Pascals) to altitude (feet or meters) up to 50km.

:param df: pandas DataFrame of one of the temperature/pressure channels.
A pressure column should be present, if not, raise an error
:param base_press: P_b; reference pressure (pressure at sea level) in
Pascals (Pa). If set to None, use the first pressure measurement
included in the dataframe (df)
:param base_temp: T_b reference temperature (temperature at sea level) in
Celsius (C). If set to None and a Temperature column exists in the
dataframe (df), use the first listed temperature value. If set to None
and no temperature column exists, error out
:param temp_col_index: the index (starting at 0) in the dataframe (df) of
the temperature column to pull data from.
:param press_col_index: the index (starting at 0) in the dataframe (df) of
the pressure column to pull data from
:param units: determines if altitude is represented in meters ('m') or feet
('ft') in both the input and output dataframes
:returns: a pandas DataFrame with the same Index values as the
input, and an added column of “Altitude (m)” or “Altitude (ft)” data
"""
# Column Name Placeholders
temp_col = None
press_col = None

# Conversion Constants
C_K = 273.15 # Celsius to Kelvin Constant (C + 273.15 = K)
ft_m = 0.3048 # Feet to Meters Constant (ft * 0.3048 = m) & (m / 0.3048 = ft)

# Constants
h_b = 0 # Reference Height of Sea Level (m)
h_sb = 11000 # Height at the Base of the Stratosphere (meters)
h_st = 50000 # Height at the Top of the Stratosphere (meters)
L_b = -0.0065 # Standard Temperature Lapse Rate [K/m]
g_0 = 9.80665 # Gravitational Acceleration Constant [m/s^2]
R = 8.31432 # Universal Gas Constant [N*m/mol*K]
M = 0.0289644 # Molar Mass of Earth's Air [kg/mol]
top_stratosphere_pressure = 100 # Air Pressure at Stratopause (1mb)=[100 Pa]

# Finding pressure column
if press_col_index is None:
for col in df.columns:
if "press" in col.lower():
press_col = col
press_col_index = df.columns.get_loc(press_col)
break
if press_col is None:
raise ValueError("Pressure column not found.")
else:
press_col = df.columns[press_col_index]

# Checking for base temp and converting to K
if base_temp == None:
if temp_col_index is None:
for col in df.columns:
if "temp" in col.lower():
temp_col = col
temp_col_index = df.columns.get_loc(temp_col)
break
if temp_col is None:
raise ValueError('Temperature column not found.')
T_b = df.iloc[0, temp_col_index] + C_K # Standard Temperature in Kelvin
T_bS = T_b -71.5 # Temperature at start of Stratosphere
else:
T_b = base_temp + C_K # Standard Temperature in Kelvin
T_bS = T_b -71.5 # Temperature at start of Stratosphere

# Checking for base pressure
if base_press == None:
# Set to first pressure recording in the dataframe
P_b = df.iloc[0, press_col_index] # Static Pressure in Pascals
else:
P_b = base_press # Static Pressure in Pascals

# Pressure at base of Stratosphere
base_stratosphere_pressure = (P_b * (1 + (L_b / T_b) * (h_sb - h_b)) **
((-g_0 * M) / (R * L_b)))

# List of Altitudes to be added to Dataframe
altitude_column = []

# Calculate Altitude for the DataFrame
for index, row in df.iterrows():
P = row[press_col]
if P > base_stratosphere_pressure:
h = h_b + (T_b / L_b) * (((P / P_b) ** ((-R * L_b) / (g_0 * M))) - 1)
altitude_column.append(h)
elif top_stratosphere_pressure < P < base_stratosphere_pressure:
h = h_sb + ((R * T_bS * np.log(P / base_stratosphere_pressure)) /
(-g_0 * M))
altitude_column.append(h)
else:
raise ValueError("Altitudes above stratosphere not supported.")

# Convert Altitude back to feet if specified
if units == 'ft':
altitude_column = [x / ft_m for x in altitude_column]
# Add "Altitude (ft)" Column to Copy of Original Dataframe
alt_df = df.copy()
alt_df["Altitude (ft)"] = altitude_column

# Add "Altitude (m)" Column to Copy of Original Dataframe
if units == 'm':
alt_df = df.copy()
alt_df["Altitude (m)"] = altitude_column

# Return DataFrame with New Altitude Column
return alt_df
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def get_version(rel_path):
"ebmlite>=3.2.0",
"idelib>=3.2.8",
"jinja2",
"numpy>=1.19.5",
"numpy>1.19.5",
"pandas>=1.3",
"plotly>=5.3.1",
"pynmeagps",
Expand Down
2 changes: 1 addition & 1 deletion tests/batch/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def assert_output_is_valid(output: endaq.batch.core.OutputStruct):
@pytest.mark.filterwarnings("ignore:no acceleration channel in:UserWarning")
@pytest.mark.filterwarnings(
"ignore"
":nperseg .* is greater than input length .*, using nperseg .*"
":.*nperseg.* is greater than (signal|input) length.*, using nperseg .*"
":UserWarning"
)
def test_aggregate_data(getdata_builder):
Expand Down
2 changes: 2 additions & 0 deletions tests/calc/csv_to_df/beyond_stratosphere.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Pressure (Pa),Temperature (C)
25,15
18 changes: 18 additions & 0 deletions tests/calc/csv_to_df/default_sea_lvl.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Pressure (Pa),Temperature (C)
101325,15
100000,
95000,
90000,
85000,
80000,
75000,
70000,
65000,
60000,
55000,
50000,
45000,
40000,
35000,
30000,
25000,
18 changes: 18 additions & 0 deletions tests/calc/csv_to_df/keys/base_values_none.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Key,base settings = None
0.00
110.88
540.34
988.50
1457.30
1948.99
2466.23
3012.18
3590.69
4206.43
4865.22
5574.44
6343.62
7185.44
8117.27
9163.96
10362.95
18 changes: 18 additions & 0 deletions tests/calc/csv_to_df/keys/default_settings.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Key,settings are default
0.00
110.88
540.34
988.50
1457.30
1948.99
2466.23
3012.18
3590.69
4206.43
4865.22
5574.44
6343.62
7185.44
8117.27
9163.96
10362.95
18 changes: 18 additions & 0 deletions tests/calc/csv_to_df/keys/diff_base_pressure.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Key,the base pressure is not set to the default value
-111.16
0
430.53
879.82
1349.79
1842.71
2361.25
2908.57
3488.53
4105.81
4766.26
5477.25
6248.37
7092.29
8026.46,
9075.77
10277.77
18 changes: 18 additions & 0 deletions tests/calc/csv_to_df/keys/diff_base_temp.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Key,the base temperature is not set to the default value
0.00
116.66
568.47
1039.96
1533.16
2050.45
2594.61
3168.99
3777.61
4425.40
5118.48
5864.62
6673.85
7559.48
8539.82
9641.00
10902.40
18 changes: 18 additions & 0 deletions tests/calc/csv_to_df/keys/diff_temp_and_pressure.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Key,the base temperature and pressure are not set to default values
-116.95
0.00
452.94
925.62
1420.06
1938.64
2484.17
3059.98
3670.13
4319.54
5014.37
5762.38
6573.63
7461.49
8444.29
9548.22
10812.79
12 changes: 12 additions & 0 deletions tests/calc/csv_to_df/keys/stratosphere.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Key,altitude is in the stratosphere
11784.05
12452.21
13199.14
14045.95
15023.51
16179.72
17594.82
19419.19
21990.49
26386.17
35177.52
18 changes: 18 additions & 0 deletions tests/calc/csv_to_df/keys/units_feet.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Key,units are set to feet ('ft')
0.00
363.79
1772.76
3243.11
4781.17
6394.32
8091.29
9882.49
11780.47
13800.61
15962.0
18288.84
20812.4,
23574.27
26631.46
30065.48
33999.16
2 changes: 2 additions & 0 deletions tests/calc/csv_to_df/press_error.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Temperature (C)
15
12 changes: 12 additions & 0 deletions tests/calc/csv_to_df/stratosphere.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Pressure (Pa),Temperature (C)
20000,-55
18000
16000
14000
12000
10000
8000
6000
4000
2000
500
18 changes: 18 additions & 0 deletions tests/calc/csv_to_df/temp_error.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Pressure (Pa),
101325,
100000,
95000,
90000,
85000,
80000,
75000,
70000,
65000,
60000,
55000,
50000,
45000,
40000,
35000,
30000,
25000,
Loading
Loading