diff --git a/double_pendula/double_pendula.py b/double_pendula/double_pendula.py index 8b1df57..4588d43 100644 --- a/double_pendula/double_pendula.py +++ b/double_pendula/double_pendula.py @@ -1,6 +1,4 @@ """Model of a double pendulum""" -# Author: Chris Greening -# Date: 2019-07-15 from typing import Tuple, List @@ -51,35 +49,123 @@ def __init__(self, L1: int = 1, L2: int = 1, m1: int = 1, m2: int = 1, self.max_length = self.pendulum1.L + self.pendulum2.L def get_frame_x(self, i: int) -> Tuple[int]: - """Return x coordinates of the system of a specific index""" + """Return x coordinates of the system of a specific index. + + Parameters + ---------- + i : int + The index of the frame for which to return x coordinates. + + Returns + ------- + Tuple[int] + A tuple containing the x coordinates of the system at the specified index. + The first element is always 0, followed by the x coordinate of `pendulum1` and + the x coordinate of `pendulum2`. + """ return (0, self.pendulum1.x[i], self.pendulum2.x[i]) def get_frame_y(self, i: int) -> Tuple[int]: - """Return y coordinates of the system of a specific index""" + """ + Return y coordinates of the system of a specific index. + + Parameters + ---------- + i : int + The index of the frame for which to return y coordinates. + + Returns + ------- + Tuple[int] + A tuple containing the y coordinates of the system at the specified index. + The first element is always 0, followed by the y coordinate of `pendulum1` and + the y coordinate of `pendulum2`. + """ return (0, self.pendulum1.y[i],self.pendulum2.y[i]) def get_frame_coordinates(self, i: int) -> Tuple[Tuple[int]]: - """Return the x,y coordinates at a given frame""" + """Return the x,y coordinates at a given frame. + + Parameters + ---------- + i : int + The index of the frame for which to return x,y coordinates. + + Returns + ------- + Tuple[Tuple[int]] + A tuple containing two tuples: the first one is the x coordinates + and the second one is the y coordinates of the system at the specified + index. Each inner tuple follows the format: + (coordinate of origin, coordinate of `pendulum1`, coordinate of `pendulum2`). + """ return (self.get_frame_x(i), self.get_frame_y(i)) def get_max_x(self) -> float: - """Return the maximum x-coord of the double pendulum""" + """ + Return the maximum x-coordinate of the double pendulum. + + Returns + ------- + float + The maximum x-coordinate that the double pendulum reaches. + """ return self.pendulum2.get_max_x() def get_max_y(self) -> float: - """Return the maximum y-coord of the double pendulum""" + """ + Return the maximum y-coordinate of the double pendulum. + + Returns + ------- + float + The maximum y-coordinate that the double pendulum reaches. + """ return self.pendulum2.get_max_y() def get_max_coordinates(self) -> float: - """Return the maximum coordinates the overall system reaches""" + """ + Return the maximum coordinates the overall system reaches. + + Returns + ------- + float + The maximum distance from the origin that the overall double pendulum system reaches. + """ return self.pendulum2.get_max_coordinates() @classmethod def create_multiple_double_pendula( cls, num_pendula: int = 1, L1: float = 1.0, L2: float = 1.0, m1: float = 1.0, m2: float = 1.0, - initial_theta: float = 90, dtheta: float = .05) -> List["DoublePendulum"]: - """Returns a list of DoublePendulum's each offset slightly from each other""" + initial_theta: float = 90, dtheta: float = .05) -> List["DoublePendula"]: + """ + Creates and returns a list of DoublePendula objects with initial + conditions offset by dtheta. + + Parameters + ---------- + num_pendula : int, optional + Number of DoublePendula objects to create, default is 1. + L1 : float, optional + Length of the first pendulum arm, default is 1.0. + L2 : float, optional + Length of the second pendulum arm, default is 1.0. + m1 : float, optional + Mass of the first pendulum bob, default is 1.0. + m2 : float, optional + Mass of the second pendulum bob, default is 1.0. + initial_theta : float, optional + Initial angle in degrees of the first pendulum, default is 90. + dtheta : float, optional + Offset in initial angle in degrees for each subsequent pendulum, + default is 0.05. + + Returns + ------- + List["DoublePendula"] + A list containing the created DoublePendula objects. + """ # pylint: disable=too-many-arguments pendula = [] created_pendula = 0 @@ -129,4 +215,4 @@ def _calculate_system(self) -> None: def __repr__(self): # pylint: disable=line-too-long - return f"< DoublePendulum: L1={self.pendulum1.L} m1={self.pendulum1.m} L2={self.pendulum2.L} m2={self.pendulum2.m} y0={self.y0} >" + return f"< DoublePendula: L1={self.pendulum1.L} m1={self.pendulum1.m} L2={self.pendulum2.L} m2={self.pendulum2.m} y0={self.y0} >" diff --git a/double_pendula/equations.py b/double_pendula/equations.py index d4a6609..b60f398 100644 --- a/double_pendula/equations.py +++ b/double_pendula/equations.py @@ -1,6 +1,4 @@ """Module for storing equations relevant to calculating the double pendulum's movement""" -# Author: Chris Greening -# Date: 2022-10-29 import numpy as np import scipy.integrate diff --git a/double_pendula/pendulum.py b/double_pendula/pendulum.py index 4b35ba8..e5273d6 100644 --- a/double_pendula/pendulum.py +++ b/double_pendula/pendulum.py @@ -1,6 +1,4 @@ """Model of a single pendulum""" -# Author: Chris Greening -# Date: 2022-10-29 from typing import Tuple @@ -46,17 +44,42 @@ def calculate_path(self, theta: float, dtheta: float, x0: float = 0, y0: float = self.dtheta = dtheta self.x = self.L*np.sin(self.theta) + x0 self.y = self.L*np.cos(self.theta) + y0 - self.df = pd.DataFrame({"theta": self.theta, "dtheta": self.dtheta, - "x": self.x, "y": self.y}) + self.df = pd.DataFrame({ + "theta": self.theta, + "dtheta": self.dtheta, + "x": self.x, + "y": self.y + }) def get_max_x(self) -> float: - """Return the maximum x-value that this pendulum reaches""" + """ + Return the maximum x-coordinate of the pendulum. + + Returns + ------- + float + The maximum x-coordinate that the pendulum reaches. + """ return max(self.x) def get_max_y(self) -> float: - """Return the maximum y-value that this pendulum reaches""" + """ + Return the maximum y-coordinate of the double pendulum. + + Returns + ------- + float + The maximum y-coordinate that the double pendulum reaches. + """ return max(self.y) def get_max_coordinates(self) -> Tuple[float, float]: - """Return maximum cartesian coordinate that this system reaches""" + """ + Return the maximum coordinates the overall system reaches. + + Returns + ------- + float + The maximum distance from the origin that the overall double pendulum system reaches. + """ return (self.get_max_x(), self.get_max_y()) diff --git a/setup.py b/setup.py index 13badbf..532e321 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setuptools.setup( name="double-pendula", - version="0.1.4", + version="0.1.5", author="Chris Greening", author_email="chris@christophergreening.com", description="Library for animating double pendula in Python",