Skip to content

Commit

Permalink
Merge branch 'develop' into enh/shepard-multiple-opt
Browse files Browse the repository at this point in the history
  • Loading branch information
phmbressan authored Jan 25, 2024
2 parents 1de49c9 + 2ebed8d commit 48e4f5d
Show file tree
Hide file tree
Showing 15 changed files with 423 additions and 42 deletions.
3 changes: 3 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ function-naming-style=snake_case
# Good variable names which should always be accepted, separated by a comma.
good-names=FlightPhases,
WindroseAxes,
barometric_height_ISA,


# Good variable names regexes, separated by a comma. If names match any regex,
Expand Down Expand Up @@ -435,6 +436,8 @@ disable=raw-checker-failed,
use-implicit-booleaness-not-comparison-to-zero,
no-else-return,
inconsistent-return-statements,
unspecified-encoding,
no-member, # because we use funcify_method decorator

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
Expand Down
18 changes: 16 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,34 @@ straightforward as possible.
### Added

- ENH: Shepard Optimized Interpolation - Multiple Inputs Support [#515](https://github.com/RocketPy-Team/RocketPy/pull/515)
- ENH: adds new Function.savetxt method [#514](https://github.com/RocketPy-Team/RocketPy/pull/514)
- ENH: Argument for Optional Mutation on Function Discretize [#519](https://github.com/RocketPy-Team/RocketPy/pull/519)

### Changed

- MNT: Add repr method to Parachute class [#490](https://github.com/RocketPy-Team/RocketPy/pull/490)
- ENH: Function Reverse Arithmetic Priority [#488](https://github.com/RocketPy-Team/RocketPy/pull/488)
- DOC: Update Header Related Docs
- ENH Precalculate Barometric Height [#511](https://github.com/RocketPy-Team/RocketPy/pull/511)
- MNT: Encapsulate quaternion conversions [#537](https://github.com/RocketPy-Team/RocketPy/pull/537)
- MNT: improve the low pass filter and document an example [#538](https://github.com/RocketPy-Team/RocketPy/pull/538)


### Fixed

- ENH: Parachute trigger doesn't work if "Apogee" is used instead of "apogee" [#489](https://github.com/RocketPy-Team/RocketPy/pull/489)
- BUG: fin_flutter_analysis doesn't find any fin set [#510](https://github.com/RocketPy-Team/RocketPy/pull/510)
- FIX: EmptyMotor is breaking the Rocket.draw() method [#516](https://github.com/RocketPy-Team/RocketPy/pull/516)
- BUG: 3D trajectory plot not labeling axes [#533](https://github.com/RocketPy-Team/RocketPy/pull/533)
-

## [v1.1.5] - 2024-01-21

You can install this version by running `pip install rocketpy==1.1.5`

### Fixed

- BUG: Parachute Pressures not being Set before All Info. [#534](https://github.com/RocketPy-Team/RocketPy/pull/534)
- BUG: Invalid Arguments on Two Dimensional Discretize. [#521](https://github.com/RocketPy-Team/RocketPy/pull/521)

## [v1.1.4] - 2023-12-07
Expand All @@ -64,8 +78,8 @@ You can install this version by running `pip install rocketpy==1.1.3`

### Fixed

- FIX: Broken Function.get_value_opt for N-Dimensional Functions [#492](https://github.com/RocketPy-Team/RocketPy/pull/492)
- FIX: Never ending Flight simulations when using a GenericMotor [#497](https://github.com/RocketPy-Team/RocketPy/pull/497)
- FIX: Broken Function.get_value_opt for N-Dimensional Functions [#492](https://github.com/RocketPy-Team/RocketPy/pull/492)
- FIX: Never ending Flight simulations when using a GenericMotor [#497](https://github.com/RocketPy-Team/RocketPy/pull/497)

## [v1.1.2] - 2023-11-25

Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
author = "RocketPy Team"

# The full version, including alpha/beta/rc tags
release = "1.1.4"
release = "1.1.5"


# -- General configuration ---------------------------------------------------
Expand Down
56 changes: 56 additions & 0 deletions docs/user/function.rst
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,62 @@ Here we have shown that we can integrate the gaussian function over a defined in
# Compare the function with the integral
Function.compare_plots([f, f_int], lower=-4, upper=4)

e. Export to a text file (CSV or TXT)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Since rocketpy version 1.2.0, the ``Function`` class supports exporting the
source data to a CSV or TXT file. This is accomplished by the method
:meth:`rocketpy.Function.savetxt` and allows for easy data exportation for
further analysis.

Let's export the gaussian function to a CSV file:

.. jupyter-execute::

# Define the gaussian function
def gaussian(x):
return 1 / np.sqrt(2*np.pi) * np.exp(-x**2/2)

f = Function(gaussian, inputs="x", outputs="f(x)")

# Export to CSV
f.savetxt("gaussian.csv", lower=-4, upper=4, samples=20, fmt="%.2f")

# Read the CSV file
import pandas as pd
pd.read_csv("gaussian.csv")


.. jupyter-execute::

# Delete the CSV file
import os
os.remove("gaussian.csv")

f. Filter data
~~~~~~~~~~~~~~

Since rocketpy version 1.2.0, the ``Function`` class supports filtering the
source data. This is accomplished by the method :meth:`rocketpy.Function.low_pass_filter`
and allows for easy data filtering for further analysis.

Let's filter an example function:

.. jupyter-execute::

x = np.linspace(-4, 4, 1000)
y = np.sin(x) + np.random.normal(0, 0.1, 1000)

f = Function(list(zip(x, y)), inputs="x", outputs="f(x)")

# Filter the function
f_filtered = f.low_pass_filter(0.5)

# Compare the function with the filtered function
Function.compare_plots(
[(f, "Original"), (f_filtered, "Filtered")], lower=-4, upper=4
)

........

This guide shows some of the capabilities of the ``Function`` class, but there are many other functionalities to enhance your analysis. Do not hesitate in tanking a look at the documentation :class:`rocketpy.Function`.
2 changes: 1 addition & 1 deletion docs/user/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ If you want to choose a specific version to guarantee compatibility, you may ins

.. code-block:: shell
pip install rocketpy==1.1.4
pip install rocketpy==1.1.5
Optional Installation Method: ``conda``
Expand Down
67 changes: 66 additions & 1 deletion rocketpy/environment/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ class Environment:
Environment.pressure : Function
Air pressure in Pa as a function of altitude. Can be accessed as regular
array, or called as a Function. See Function for more information.
Environment.barometric_height : Function
Geometric height above sea level in m as a function of pressure. Can be
accessed as regular array, or called as a Function. See Function for
more information.
Environment.temperature : Function
Air temperature in K as a function of altitude. Can be accessed as
regular array, or called as a Function. See Function for more
Expand Down Expand Up @@ -1315,6 +1319,8 @@ def process_standard_atmosphere(self):

# Save temperature, pressure and wind profiles
self.pressure = self.pressure_ISA
self.barometric_height = self.barometric_height_ISA

self.temperature = self.temperature_ISA
self.wind_direction = Function(
0,
Expand Down Expand Up @@ -1433,6 +1439,7 @@ def process_custom_atmosphere(
if pressure is None:
# Use standard atmosphere
self.pressure = self.pressure_ISA
self.barometric_height = self.barometric_height_ISA
else:
# Use custom input
self.pressure = Function(
Expand All @@ -1441,6 +1448,11 @@ def process_custom_atmosphere(
outputs="Pressure (Pa)",
interpolation="linear",
)
self.barometric_height = self.pressure.inverse_function().set_discrete(
0, max_expected_height, 100, extrapolation="constant"
)
self.barometric_height.set_inputs("Pressure (Pa)")
self.barometric_height.set_outputs("Height Above Sea Level (m)")
# Check maximum height of custom pressure input
if not callable(self.pressure.source):
max_expected_height = max(self.pressure[-1, 0], max_expected_height)
Expand Down Expand Up @@ -1605,6 +1617,15 @@ def process_windy_atmosphere(self, model="ECMWF"):
outputs="Pressure (Pa)",
interpolation="linear",
)
# Linearly extrapolate pressure to ground level
bar_height = data_array[:, (0, 1)]
self.barometric_height = Function(
bar_height,
inputs="Pressure (Pa)",
outputs="Height Above Sea Level (m)",
interpolation="linear",
extrapolation="natural",
)
self.temperature = Function(
data_array[:, (1, 2)],
inputs="Height Above Sea Level (m)",
Expand Down Expand Up @@ -1732,6 +1753,15 @@ def process_wyoming_sounding(self, file):
outputs="Pressure (Pa)",
interpolation="linear",
)
# Linearly extrapolate pressure to ground level
bar_height = data_array[:, (0, 1)]
self.barometric_height = Function(
bar_height,
inputs="Pressure (Pa)",
outputs="Height Above Sea Level (m)",
interpolation="linear",
extrapolation="natural",
)

# Retrieve temperature from data array
data_array[:, 2] = data_array[:, 2] + 273.15 # Converts C to K
Expand Down Expand Up @@ -1845,6 +1875,7 @@ def process_noaaruc_sounding(self, file):

# Extract pressure as a function of height
pressure_array = []
barometric_height_array = []
for line in lines:
# Split line into columns
columns = re.split(" +", line)[1:]
Expand All @@ -1858,7 +1889,9 @@ def process_noaaruc_sounding(self, file):
if max(columns) != 99999:
# Save value
pressure_array.append(columns)
barometric_height_array.append([columns[1], columns[0]])
pressure_array = np.array(pressure_array)
barometric_height_array = np.array(barometric_height_array)

# Extract temperature as a function of height
temperature_array = []
Expand Down Expand Up @@ -1905,6 +1938,15 @@ def process_noaaruc_sounding(self, file):
outputs="Pressure (Pa)",
interpolation="linear",
)
# Converts 10*hPa to Pa and save values
barometric_height_array[:, 0] = 10 * barometric_height_array[:, 0]
self.barometric_height = Function(
barometric_height_array,
inputs="Pressure (Pa)",
outputs="Height Above Sea Level (m)",
interpolation="linear",
extrapolation="natural",
)

# Convert 10*C to K and save values
temperature_array[:, 1] = (
Expand Down Expand Up @@ -2274,6 +2316,15 @@ def process_forecast_reanalysis(self, file, dictionary):
outputs="Pressure (Pa)",
interpolation="linear",
)
# Linearly extrapolate pressure to ground level
bar_height = data_array[:, (0, 1)]
self.barometric_height = Function(
bar_height,
inputs="Pressure (Pa)",
outputs="Height Above Sea Level (m)",
interpolation="linear",
extrapolation="natural",
)
self.temperature = Function(
data_array[:, (1, 2)],
inputs="Height Above Sea Level (m)",
Expand Down Expand Up @@ -2803,6 +2854,15 @@ def select_ensemble_member(self, member=0):
outputs="Pressure (Pa)",
interpolation="linear",
)
# Linearly extrapolate pressure to ground level
bar_height = data_array[:, (0, 1)]
self.barometric_height = Function(
bar_height,
inputs="Pressure (Pa)",
outputs="Height Above Sea Level (m)",
interpolation="linear",
extrapolation="natural",
)
self.temperature = Function(
data_array[:, (1, 2)],
inputs="Height Above Sea Level (m)",
Expand Down Expand Up @@ -2965,7 +3025,12 @@ def pressure_function(h):
outputs="Pressure (Pa)",
)

return None
# Discretize Function to speed up the trajectory simulation.
self.barometric_height_ISA = self.pressure_ISA.inverse_function().set_discrete(
pressure[-1], pressure[0], 100, extrapolation="constant"
)
self.barometric_height_ISA.set_inputs("Pressure (Pa)")
self.barometric_height_ISA.set_outputs("Height Above Sea Level (m)")

def calculate_density_profile(self):
"""Compute the density of the atmosphere as a function of
Expand Down
Loading

0 comments on commit 48e4f5d

Please sign in to comment.