Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tst/testing suite reestructuring #498

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1916956
Merge pull request #487 from RocketPy-Team/master
Gui-FernandesBR Nov 27, 2023
657ae95
ENH: set Function operation prioritary with ufunc.
phmbressan Nov 28, 2023
b82810f
TST: test result type of reverse Function arithmetic.
phmbressan Nov 28, 2023
ac6f3b3
ENH: lowercase trigger comparison in parachute.py
Gui-FernandesBR Nov 28, 2023
990df21
MNT: Refactor Parachute trigger function handling
Gui-FernandesBR Nov 28, 2023
83bcd02
MNT: update CHANGELOG.md
Gui-FernandesBR Nov 28, 2023
c1e43ec
MNT: Fix typo in parachute trigger error message
Gui-FernandesBR Nov 28, 2023
f4437d3
MNT: Add __repr__ method to Parachute class
Gui-FernandesBR Nov 28, 2023
622439b
DOC: add tests to git style
lucasfourier Nov 28, 2023
214e4c2
Merge pull request #491 from RocketPy-Team/doc/adding-tst-to-docs
lucasfourier Nov 28, 2023
63881c4
FIX: include numpy numeric types in Function arithmetic.
phmbressan Nov 28, 2023
9162921
TST: expand testing of data type priorities.
phmbressan Nov 28, 2023
beb22ab
MNT: update CHANGELOG.
phmbressan Nov 28, 2023
191ab9f
Merge pull request #488 from RocketPy-Team/enh/function-reverse-arith
phmbressan Nov 28, 2023
fcea30a
GIT: Set code owners as @RocketPy-Team/code-owners
giovaniceotto Nov 29, 2023
58637d3
Merge pull request #493 from RocketPy-Team/git/code-owners
MateusStano Nov 29, 2023
a6dfea3
MNT: Fix typo in parachute trigger string
Gui-FernandesBR Nov 30, 2023
ae45abe
Merge pull request #489 from RocketPy-Team/enh/case-sensitive-triggers
Gui-FernandesBR Nov 30, 2023
daa2dd6
MNT: Update parachute __repr__ method 2 convention
Gui-FernandesBR Nov 30, 2023
72ca940
MNT: Update CHANGELOG.md
Gui-FernandesBR Nov 30, 2023
8def7ad
Merge branch 'develop' into mnt/parachute-repr-method
Gui-FernandesBR Nov 30, 2023
a9ac31c
Merge pull request #490 from RocketPy-Team/mnt/parachute-repr-method
Gui-FernandesBR Nov 30, 2023
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
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ straightforward as possible.

### 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)

### Fixed

-
- ENH: Parachute trigger doesn't work if "Apogee" is used instead of "apogee" [#489](https://github.com/RocketPy-Team/RocketPy/pull/489)

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

Expand Down
3 changes: 2 additions & 1 deletion CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# These owners will be the default owners for everything in
# the repo.
* @giovaniceotto
* @RocketPy-Team/code-owners

2 changes: 2 additions & 0 deletions docs/development/style_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ So here are a couple of **guidelines** to help you when creating new branches to
#. ``enh``: when you add new features and enhancements
#. ``maint``: when your branch is all about refactoring, fixing typos, etc.
#. ``rel``: when your branch makes changes related to creating new releases
#. ``tst``: when your branch makes changes related to tests

* Use ``-`` instead of spaces for the description text.
* Keep branch names with lowercase letters.
Expand All @@ -80,6 +81,7 @@ Here are a couple of example branch names:
- ``bug/issue-98-upside-down-rockets``
- ``enh/hybrid-motor-feature``
- ``maint/typos-flight-class``
- ``tst/refactor-tests-flight-class``

Once you are ready to create a Pull Request for your branch, we advise you to merge with the ``develop`` branch instead of the default ``master`` branch.
This way, we keep the ``master`` branch stable and use the ``develop`` branch to test out new features!
Expand Down
27 changes: 21 additions & 6 deletions rocketpy/mathutils/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
extrapolation, plotting and algebra.
"""

# Arithmetic priority
__array_ufunc__ = None

def __init__(
self,
source,
Expand Down Expand Up @@ -207,8 +210,8 @@
except ValueError:
# If an error occurs, headers are present
source = np.loadtxt(source, delimiter=",", dtype=float, skiprows=1)
except Exception as e:
raise ValueError(

Check warning on line 214 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L213-L214

Added lines #L213 - L214 were not covered by tests
"The source file is not a valid csv or txt file."
) from e

Expand Down Expand Up @@ -1837,7 +1840,9 @@
return Function(lambda x: (self.get_value(x) + other(x)))
# If other is Float except...
except AttributeError:
if isinstance(other, (float, int, complex)):
if isinstance(
other, (float, int, complex, np.ndarray, np.integer, np.floating)
):
# Check if Function object source is array or callable
if isinstance(self.source, np.ndarray):
# Operate on grid values
Expand Down Expand Up @@ -1967,7 +1972,9 @@
return Function(lambda x: (self.get_value(x) * other(x)))
# If other is Float except...
except AttributeError:
if isinstance(other, (float, int, complex)):
if isinstance(
other, (float, int, complex, np.ndarray, np.integer, np.floating)
):
# Check if Function object source is array or callable
if isinstance(self.source, np.ndarray):
# Operate on grid values
Expand Down Expand Up @@ -2056,7 +2063,9 @@
return Function(lambda x: (self.get_value_opt(x) / other(x)))
# If other is Float except...
except AttributeError:
if isinstance(other, (float, int, complex)):
if isinstance(
other, (float, int, complex, np.ndarray, np.integer, np.floating)
):
# Check if Function object source is array or callable
if isinstance(self.source, np.ndarray):
# Operate on grid values
Expand Down Expand Up @@ -2095,7 +2104,9 @@
A Function object which gives the result of other(x)/self(x).
"""
# Check if Function object source is array and other is float
if isinstance(other, (float, int, complex)):
if isinstance(
other, (float, int, complex, np.ndarray, np.integer, np.floating)
):
if isinstance(self.source, np.ndarray):
# Operate on grid values
ys = other / self.y_array
Expand Down Expand Up @@ -2163,7 +2174,9 @@
return Function(lambda x: (self.get_value_opt(x) ** other(x)))
# If other is Float except...
except AttributeError:
if isinstance(other, (float, int, complex)):
if isinstance(
other, (float, int, complex, np.ndarray, np.integer, np.floating)
):
# Check if Function object source is array or callable
if isinstance(self.source, np.ndarray):
# Operate on grid values
Expand Down Expand Up @@ -2202,7 +2215,9 @@
A Function object which gives the result of other(x)**self(x).
"""
# Check if Function object source is array and other is float
if isinstance(other, (float, int, complex)):
if isinstance(
other, (float, int, complex, np.ndarray, np.integer, np.floating)
):
if isinstance(self.source, np.ndarray):
# Operate on grid values
ys = other**self.y_array
Expand Down Expand Up @@ -2869,8 +2884,8 @@
# Skip header
source = np.loadtxt(source, delimiter=",", dtype=float, skiprows=1)
except Exception as e:
raise ValueError(
"The source file is not a valid csv or txt file."

Check warning on line 2888 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L2887-L2888

Added lines #L2887 - L2888 were not covered by tests
) from e

else:
Expand Down
32 changes: 25 additions & 7 deletions rocketpy/rocket/parachute.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
case, the parachute will be ejected when the rocket reaches this height
above ground level.

- The string "apogee," which triggers the parachute at apogee, i.e.,
- The string "apogee" which triggers the parachute at apogee, i.e.,
when the rocket reaches its highest point and starts descending.

Note: The function will be called according to the sampling rate
Expand Down Expand Up @@ -126,7 +126,7 @@
case, the parachute will be ejected when the rocket reaches this
height above ground level.

- The string "apogee," which triggers the parachute at apogee, i.e.,
- The string "apogee" which triggers the parachute at apogee, i.e.,
when the rocket reaches its highest point and starts descending.

Note: The function will be called according to the sampling rate
Expand Down Expand Up @@ -171,11 +171,17 @@

self.prints = _ParachutePrints(self)

# evaluate the trigger
self.__evaluate_trigger_function(trigger)

def __evaluate_trigger_function(self, trigger):
"""This is used to set the triggerfunc attribute that will be used to
interact with the Flight class.
"""
if callable(trigger):
self.triggerfunc = trigger

elif isinstance(trigger, (int, float)):
# trigger is interpreted as the absolute height at which the parachute will be ejected
# The parachute is deployed at a given height
def triggerfunc(p, h, y):
# p = pressure considering parachute noise signal
# h = height above ground level considering parachute noise signal
Expand All @@ -184,8 +190,8 @@

self.triggerfunc = triggerfunc

elif trigger == "apogee":
# trigger for apogee
elif trigger.lower() == "apogee":
# The parachute is deployed at apogee
def triggerfunc(p, h, y):
# p = pressure considering parachute noise signal
# h = height above ground level considering parachute noise signal
Expand All @@ -194,7 +200,12 @@

self.triggerfunc = triggerfunc

return None
else:
raise ValueError(

Check warning on line 204 in rocketpy/rocket/parachute.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/rocket/parachute.py#L204

Added line #L204 was not covered by tests
f"Unable to set the trigger function for parachute '{self.name}'. "
+ "Trigger must be a callable, a float value or the string 'apogee'. "
+ "See the Parachute class documentation for more information."
)

def __str__(self):
"""Returns a string representation of the Parachute class.
Expand All @@ -209,6 +220,13 @@
self.cd_s,
)

def __repr__(self):
"""Representation method for the class, useful when debugging."""
return (

Check warning on line 225 in rocketpy/rocket/parachute.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/rocket/parachute.py#L225

Added line #L225 was not covered by tests
f"<Parachute {self.name} "
+ f"(cd_s = {self.cd_s:.4f} m2, trigger = {self.trigger})>"
)

def info(self):
"""Prints information about the Parachute class."""
self.prints.all()
Expand Down
2 changes: 1 addition & 1 deletion rocketpy/rocket/rocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ def add_parachute(
case, the parachute will be ejected when the rocket reaches this height
above ground level.

- The string "apogee," which triggers the parachute at apogee, i.e.,
- The string "apogee" which triggers the parachute at apogee, i.e.,
when the rocket reaches its highest point and starts descending.

Note: The function will be called according to the sampling rate
Expand Down
80 changes: 80 additions & 0 deletions tests/test_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,83 @@ def test_shepard_interpolation(x, y, z_expected):
func = Function(source=source, inputs=["x", "y"], outputs=["z"])
z = func(x, y)
assert np.isclose(z, z_expected, atol=1e-8).all()


@pytest.mark.parametrize("other", [1, 0.1, np.int_(1), np.float_(0.1), np.array([1])])
def test_sum_arithmetic_priority(other):
"""Test the arithmetic priority of the add operation of the Function class,
specially comparing to the numpy array operations.
"""
func_lambda = Function(lambda x: x**2)
func_array = Function([(0, 0), (1, 1), (2, 4)])

assert isinstance(func_lambda + func_array, Function)
assert isinstance(func_array + func_lambda, Function)
assert isinstance(func_lambda + other, Function)
assert isinstance(other + func_lambda, Function)
assert isinstance(func_array + other, Function)
assert isinstance(other + func_array, Function)


@pytest.mark.parametrize("other", [1, 0.1, np.int_(1), np.float_(0.1), np.array([1])])
def test_sub_arithmetic_priority(other):
"""Test the arithmetic priority of the sub operation of the Function class,
specially comparing to the numpy array operations.
"""
func_lambda = Function(lambda x: x**2)
func_array = Function([(0, 0), (1, 1), (2, 4)])

assert isinstance(func_lambda - func_array, Function)
assert isinstance(func_array - func_lambda, Function)
assert isinstance(func_lambda - other, Function)
assert isinstance(other - func_lambda, Function)
assert isinstance(func_array - other, Function)
assert isinstance(other - func_array, Function)


@pytest.mark.parametrize("other", [1, 0.1, np.int_(1), np.float_(0.1), np.array([1])])
def test_mul_arithmetic_priority(other):
"""Test the arithmetic priority of the mul operation of the Function class,
specially comparing to the numpy array operations.
"""
func_lambda = Function(lambda x: x**2)
func_array = Function([(0, 0), (1, 1), (2, 4)])

assert isinstance(func_lambda * func_array, Function)
assert isinstance(func_array * func_lambda, Function)
assert isinstance(func_lambda * other, Function)
assert isinstance(other * func_lambda, Function)
assert isinstance(func_array * other, Function)
assert isinstance(other * func_array, Function)


@pytest.mark.parametrize("other", [1, 0.1, np.int_(1), np.float_(0.1), np.array([1])])
def test_truediv_arithmetic_priority(other):
"""Test the arithmetic priority of the truediv operation of the Function class,
specially comparing to the numpy array operations.
"""
func_lambda = Function(lambda x: x**2)
func_array = Function([(1, 1), (2, 4)])

assert isinstance(func_lambda / func_array, Function)
assert isinstance(func_array / func_lambda, Function)
assert isinstance(func_lambda / other, Function)
assert isinstance(other / func_lambda, Function)
assert isinstance(func_array / other, Function)
assert isinstance(other / func_array, Function)


@pytest.mark.parametrize("other", [1, 0.1, np.int_(1), np.float_(0.1), np.array([1])])
def test_pow_arithmetic_priority(other):
"""Test the arithmetic priority of the pow operation of the Function class,
specially comparing to the numpy array operations.
"""
func_lambda = Function(lambda x: x**2)
func_array = Function([(0, 0), (1, 1), (2, 4)])

assert isinstance(func_lambda**func_array, Function)
assert isinstance(func_array**func_lambda, Function)
assert isinstance(func_lambda**other, Function)
assert isinstance(other**func_lambda, Function)
assert isinstance(func_array**other, Function)
assert isinstance(other**func_array, Function)
Loading