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

ENH: Implement optional plot saving #597

Merged
merged 22 commits into from
Nov 10, 2024
Merged
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
388c2d7
ENH: Add filename option to most plot functions
nalquas Apr 19, 2024
63017f2
MNT: Use f-strings in plot_helpers.py
nalquas May 20, 2024
5586e72
MNT: Run isort
nalquas May 20, 2024
6ae38c3
DOC: Make docstring fit into 80 columns and reference matplotlib formats
nalquas May 20, 2024
848475e
MNT: Run black
nalquas May 20, 2024
906c337
MNT: Move get_matplotlib_supported_file_endings into tools
nalquas May 20, 2024
eb8cb8e
Apply suggestions from code review
nalquas Jun 7, 2024
67e9c0f
Fix function/__call__ check
nalquas Jun 25, 2024
11bf3a1
Change plot_helpers warnings from UserWarning to ValueError
nalquas Jun 25, 2024
d182c87
Update docstrings
nalquas Jul 5, 2024
fa9a2b3
Fix issues from rebase
nalquas Jul 5, 2024
1062ccd
Merge branch 'enh/save-graphs' of https://github.com/nalquas/RocketPy…
phmbressan Aug 23, 2024
c5264a2
MNT: post merge fixes regarding plots.
phmbressan Aug 23, 2024
a5938c5
Merge remote-tracking branch 'origin/develop' into enh/save-graphs
phmbressan Nov 8, 2024
9d7e04d
MNT: post merge fixes and linting.
phmbressan Nov 8, 2024
dcde26a
Merge branch 'develop' into enh/save-graphs
phmbressan Nov 8, 2024
f68a4af
TST: implement testing of show or save plots.
phmbressan Nov 8, 2024
fece299
Merge branch 'develop' into enh/save-graphs
phmbressan Nov 8, 2024
0042991
Merge branch 'develop' into enh/save-graphs
phmbressan Nov 9, 2024
bd0400a
MNT: Correct CHANGELOG file.
phmbressan Nov 9, 2024
d90831f
MNT: Improve error handling of unsupported file endings.
phmbressan Nov 9, 2024
28c2ed5
DOC: add doc section for plot saving.
phmbressan Nov 9, 2024
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Attention: The newest changes should be on top -->

### Added

-
- ENH: Implement optional plot saving [#597](https://github.com/RocketPy-Team/RocketPy/pull/597)

### Changed

Expand Down
39 changes: 39 additions & 0 deletions docs/user/first_simulation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,45 @@ Finally, the :meth:`rocketpy.Flight.export_data` method also provides a convenie
os.remove("calisto_flight_data.csv")


Saving and Storing Plots
------------------------

Here we show how to save the plots and drawings generated by RocketPy.
For instance, we can save our rocket drawing as a ``.png`` file:

.. jupyter-execute::

calisto.draw(filename="calisto_drawing.png")

Also, if you want to save a specific rocketpy plot, every RocketPy
attribute of type :class:`rocketpy.Function` is capable of saving its plot
as an image file. For example, we can save our rocket's speed plot and the
trajectory plot as ``.jpg`` files:

.. jupyter-execute::

test_flight.speed.plot(filename="speed_plot.jpg")
test_flight.plots.trajectory_3d(filename="trajectory_plot.jpg")

The supported file formats are ``.eps``, ``.jpg``, ``.jpeg``, ``.pdf``,
``.pgf``, ``.png``, ``.ps``, ``.raw``, ``.rgba``, ``.svg``, ``.svgz``,
``.tif``, ``.tiff`` and ``.webp``. More details on manipulating data and
results can be found in the :ref:`Function Class Usage <functionusage>`.

.. note::

The ``filename`` argument is optional. If not provided, the plot will be
shown instead. If the provided filename is in a directory that does not
exist, the directory will be created.

.. jupyter-execute::
:hide-code:
:hide-output:

os.remove("calisto_drawing.png")
os.remove("speed_plot.jpg")
os.remove("trajectory_plot.jpg")

Further Analysis
----------------

Expand Down
40 changes: 34 additions & 6 deletions rocketpy/mathutils/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
RBFInterpolator,
)

from ..plots.plot_helpers import show_or_save_plot
Gui-FernandesBR marked this conversation as resolved.
Show resolved Hide resolved

nalquas marked this conversation as resolved.
Show resolved Hide resolved
# Numpy 1.x compatibility,
# TODO: remove these lines when all dependencies support numpy>=2.0.0
if np.lib.NumpyVersion(np.__version__) >= "2.0.0b1":
Expand Down Expand Up @@ -1378,7 +1380,7 @@
)

# Define all presentation methods
def __call__(self, *args):
def __call__(self, *args, filename=None):
"""Plot the Function if no argument is given. If an
argument is given, return the value of the function at the desired
point.
Expand All @@ -1392,13 +1394,18 @@
evaluated at all points in the list and a list of floats will be
returned. If the function is N-D, N arguments must be given, each
one being an scalar or list.
filename : str | None, optional
The path the plot should be saved to. By default None, in which case
the plot will be shown instead of saved. Supported file endings are:
eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff
and webp (these are the formats supported by matplotlib).

Returns
-------
ans : None, scalar, list
"""
if len(args) == 0:
return self.plot()
return self.plot(filename=filename)
else:
return self.get_value(*args)

Expand Down Expand Up @@ -1459,8 +1466,11 @@
Function.plot_2d if Function is 2-Dimensional and forward arguments
and key-word arguments."""
if isinstance(self, list):
# Extract filename from kwargs
filename = kwargs.get("filename", None)

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

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L1470

Added line #L1470 was not covered by tests

# Compare multiple plots
Function.compare_plots(self)
Function.compare_plots(self, filename)

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

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L1473

Added line #L1473 was not covered by tests
else:
if self.__dom_dim__ == 1:
self.plot_1d(*args, **kwargs)
Expand Down Expand Up @@ -1488,6 +1498,7 @@
force_points=False,
return_object=False,
equal_axis=False,
filename=None,
):
"""Plot 1-Dimensional Function, from a lower limit to an upper limit,
by sampling the Function several times in the interval. The title of
Expand Down Expand Up @@ -1518,6 +1529,11 @@
Setting force_points to True will plot all points, as a scatter, in
which the Function was evaluated in the dataset. Default value is
False.
filename : str | None, optional
The path the plot should be saved to. By default None, in which case
the plot will be shown instead of saved. Supported file endings are:
eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff
and webp (these are the formats supported by matplotlib).

Returns
-------
Expand Down Expand Up @@ -1558,7 +1574,7 @@
plt.title(self.title)
plt.xlabel(self.__inputs__[0].title())
plt.ylabel(self.__outputs__[0].title())
plt.show()
show_or_save_plot(filename)
if return_object:
return fig, ax

Expand All @@ -1581,6 +1597,7 @@
disp_type="surface",
alpha=0.6,
cmap="viridis",
filename=None,
):
"""Plot 2-Dimensional Function, from a lower limit to an upper limit,
by sampling the Function several times in the interval. The title of
Expand Down Expand Up @@ -1620,6 +1637,11 @@
cmap : string, optional
Colormap of plotted graph, which can be any of the color maps
available in matplotlib. Default value is viridis.
filename : str | None, optional
The path the plot should be saved to. By default None, in which case
the plot will be shown instead of saved. Supported file endings are:
eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff
and webp (these are the formats supported by matplotlib).

Returns
-------
Expand Down Expand Up @@ -1692,7 +1714,7 @@
axes.set_xlabel(self.__inputs__[0].title())
axes.set_ylabel(self.__inputs__[1].title())
axes.set_zlabel(self.__outputs__[0].title())
plt.show()
show_or_save_plot(filename)

@staticmethod
def compare_plots( # pylint: disable=too-many-statements
Expand All @@ -1707,6 +1729,7 @@
force_points=False,
return_object=False,
show=True,
filename=None,
):
"""Plots N 1-Dimensional Functions in the same plot, from a lower
limit to an upper limit, by sampling the Functions several times in
Expand Down Expand Up @@ -1751,6 +1774,11 @@
False.
show : bool, optional
If True, shows the plot. Default value is True.
filename : str | None, optional
The path the plot should be saved to. By default None, in which case
the plot will be shown instead of saved. Supported file endings are:
eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff
and webp (these are the formats supported by matplotlib).

Returns
-------
Expand Down Expand Up @@ -1826,7 +1854,7 @@
plt.ylabel(ylabel)

if show:
plt.show()
show_or_save_plot(filename)

if return_object:
return fig, ax
Expand Down
29 changes: 16 additions & 13 deletions rocketpy/motors/hybrid_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,16 +601,19 @@
)
reset_funcified_methods(self)

def draw(self):
"""Draws a representation of the HybridMotor."""
self.plots.draw()

def info(self):
"""Prints out basic data about the Motor."""
self.prints.all()
self.plots.thrust()

def all_info(self):
"""Prints out all data and graphs available about the Motor."""
self.prints.all()
self.plots.all()
Gui-FernandesBR marked this conversation as resolved.
Show resolved Hide resolved
def draw(self, filename=None):
"""Draws a representation of the HybridMotor.

Parameters
----------
filename : str | None, optional
The path the plot should be saved to. By default None, in which case
the plot will be shown instead of saved. Supported file endings are:
eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff
and webp (these are the formats supported by matplotlib).

Returns
-------
None
"""
self.plots.draw(filename)

Check warning on line 619 in rocketpy/motors/hybrid_motor.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/hybrid_motor.py#L619

Added line #L619 was not covered by tests
26 changes: 12 additions & 14 deletions rocketpy/motors/liquid_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,21 +463,19 @@
self.positioned_tanks.append({"tank": tank, "position": position})
reset_funcified_methods(self)

def draw(self):
"""Draw a representation of the LiquidMotor."""
self.plots.draw()
def draw(self, filename=None):
"""Draw a representation of the LiquidMotor.

def info(self):
"""Prints out basic data about the Motor."""
self.prints.all()
self.plots.thrust()

def all_info(self):
"""Prints out all data and graphs available about the Motor.
Gui-FernandesBR marked this conversation as resolved.
Show resolved Hide resolved
Parameters
----------
filename : str | None, optional
The path the plot should be saved to. By default None, in which case
the plot will be shown instead of saved. Supported file endings are:
eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff
and webp (these are the formats supported by matplotlib).

Return
------
Returns
-------
None
"""
self.prints.all()
self.plots.all()
self.plots.draw(filename)

Check warning on line 481 in rocketpy/motors/liquid_motor.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/liquid_motor.py#L481

Added line #L481 was not covered by tests
17 changes: 14 additions & 3 deletions rocketpy/motors/motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1083,15 +1083,26 @@ def get_attr_value(obj, attr_name, multiplier=1):
# Write last line
file.write(f"{self.thrust.source[-1, 0]:.4f} {0:.3f}\n")

def info(self):
def info(self, filename=None):
"""Prints out a summary of the data and graphs available about the
Motor.

Parameters
----------
filename : str | None, optional
The path the plot should be saved to. By default None, in which case
the plot will be shown instead of saved. Supported file endings are:
eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff
and webp (these are the formats supported by matplotlib).

Returns
-------
None
"""
# Print motor details
self.prints.all()
self.plots.thrust()
self.plots.thrust(filename=filename)

@abstractmethod
def all_info(self):
"""Prints out all data and graphs available about the Motor."""
self.prints.all()
Expand Down
29 changes: 16 additions & 13 deletions rocketpy/motors/solid_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,16 +727,19 @@
def propellant_I_23(self):
return 0

def draw(self):
"""Draw a representation of the SolidMotor."""
self.plots.draw()

def info(self):
"""Prints out basic data about the SolidMotor."""
self.prints.all()
self.plots.thrust()

def all_info(self):
"""Prints out all data and graphs available about the SolidMotor."""
self.prints.all()
self.plots.all()
def draw(self, filename=None):
"""Draw a representation of the SolidMotor.

Parameters
----------
filename : str | None, optional
The path the plot should be saved to. By default None, in which case
the plot will be shown instead of saved. Supported file endings are:
eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff
and webp (these are the formats supported by matplotlib).

Returns
-------
None
"""
self.plots.draw(filename)

Check warning on line 745 in rocketpy/motors/solid_motor.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/solid_motor.py#L745

Added line #L745 was not covered by tests
19 changes: 16 additions & 3 deletions rocketpy/motors/tank.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,9 +476,22 @@
elif (height < bottom_tolerance).any():
underfill_height_exception(name, height)

def draw(self):
"""Draws the tank geometry."""
self.plots.draw()
def draw(self, filename=None):
"""Draws the tank geometry.

Parameters
----------
filename : str | None, optional
The path the plot should be saved to. By default None, in which case
the plot will be shown instead of saved. Supported file endings are:
eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff
and webp (these are the formats supported by matplotlib).

Returns
-------
None
"""
self.plots.draw(filename)

Check warning on line 494 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L494

Added line #L494 was not covered by tests


class MassFlowRateBasedTank(Tank):
Expand Down
Loading
Loading