Exemplo n.º 1
0
    def contains_points(
        self,
        x: Union[float, np.ndarray],
        y: Union[float, np.ndarray],
    ) -> np.ndarray:
        """
        Returns a boolean array of whether or not some (x, y) point(s) are contained within the Polygon.

        Args:
            x: x-coordinate(s) of the query points.
            y: y-coordinate(s) of the query points.

        Returns: A boolean array of the same size as x and y.

        """
        x = np.array(x)
        y = np.array(y)
        try:
            input_shape = (x + y).shape
        except ValueError as e:  # If arrays are not broadcastable
            raise ValueError(
                "Inputs x and y could not be broadcast together!") from e

        x = x.reshape(-1, 1)
        y = y.reshape(-1, 1)

        points = np.hstack((x, y))

        contained = path.Path(
            vertices=self.coordinates).contains_points(points)
        contained = np.array(contained).reshape(input_shape)

        return contained
Exemplo n.º 2
0
    def contains_points(
        self,
        x,
        y,
    ):
        x = np.array(x)
        y = np.array(y)
        try:
            input_shape = (x + y).shape
        except ValueError as e:  # If arrays are not broadcastable
            raise ValueError(
                "Inputs x and y could not be broadcast together!") from e

        x = x.reshape(-1, 1)
        y = y.reshape(-1, 1)

        points = np.hstack((x, y))

        contained = path.Path(
            vertices=self.coordinates).contains_points(points)
        contained = np.array(contained).reshape(input_shape)

        return contained
import aerosandbox.numpy as np

np.random.seed(0)  # Fix a seed for reproducibility

### Create some data (some fictional system where temperature is a function of time, and we're measuring it)
n = 20

time = 100 * np.random.rand(n)

actual_temperature = 2 * time + 20  # True physics of the system

noise = 10 * np.random.randn(n)
measured_temperature = actual_temperature + noise  # Measured temperature of the system

### Add in a dropout measurement (say, the sensor wire randomly came loose and gave us a 0 reading)
time = np.hstack((time, 90))
measured_temperature = np.hstack((measured_temperature, 0))

if __name__ == '__main__':
    from aerosandbox.tools.pretty_plots import plt, sns, mpl, show_plot
    fig, ax = plt.subplots()
    plt.plot(time, measured_temperature, ".")
    show_plot(xlabel="Time", ylabel="Measured Temperature")
Exemplo n.º 4
0
#             (3, 1, 1)
#         ),
#         winds_95_world
#     ),
#     axis=0
# )

# Downsample
latitudes_world = latitudes_world[::5]
winds_95_world = winds_95_world[:, ::5, :]

# Extend boundaries so that cubic spline interpolates around day_of_year appropriately.
extend_bounds = 3
day_of_year_world = np.hstack((
    day_of_year_world[-extend_bounds:] - 365,
    day_of_year_world,
    day_of_year_world[:extend_bounds] + 365
))
winds_95_world = np.dstack((
    winds_95_world[:, :, -extend_bounds:],
    winds_95_world,
    winds_95_world[:, :, :extend_bounds]
))

# Make the model
winds_95_world_model = InterpolatedModel(
    x_data_coordinates={
        "altitude"   : altitudes_world,
        "latitude"   : latitudes_world,
        "day of year": day_of_year_world,
    },
Exemplo n.º 5
0
    def repanel(
        self,
        n_points_per_side: int = 100,
    ) -> 'Airfoil':
        """
        Returns a repaneled version of the airfoil with cosine-spaced coordinates on the upper and lower surfaces.
        :param n_points_per_side: Number of points per side (upper and lower) of the airfoil [int]
            Notes: The number of points defining the final airfoil will be n_points_per_side*2-1,
            since one point (the leading edge point) is shared by both the upper and lower surfaces.
        :return: Returns the new airfoil.
        """

        upper_original_coors = self.upper_coordinates(
        )  # Note: includes leading edge point, be careful about duplicates
        lower_original_coors = self.lower_coordinates(
        )  # Note: includes leading edge point, be careful about duplicates

        # Find distances between coordinates, assuming linear interpolation
        upper_distances_between_points = (
            (upper_original_coors[:-1, 0] - upper_original_coors[1:, 0])**2 +
            (upper_original_coors[:-1, 1] - upper_original_coors[1:, 1])**
            2)**0.5
        lower_distances_between_points = (
            (lower_original_coors[:-1, 0] - lower_original_coors[1:, 0])**2 +
            (lower_original_coors[:-1, 1] - lower_original_coors[1:, 1])**
            2)**0.5
        upper_distances_from_TE = np.hstack(
            (0, np.cumsum(upper_distances_between_points)))
        lower_distances_from_LE = np.hstack(
            (0, np.cumsum(lower_distances_between_points)))
        upper_distances_from_TE_normalized = upper_distances_from_TE / upper_distances_from_TE[
            -1]
        lower_distances_from_LE_normalized = lower_distances_from_LE / lower_distances_from_LE[
            -1]

        distances_from_TE_normalized = np.hstack(
            (upper_distances_from_TE_normalized,
             1 + lower_distances_from_LE_normalized[1:]))

        # Generate a cosine-spaced list of points from 0 to 1
        cosspaced_points = np.cosspace(0, 1, n_points_per_side)
        s = np.hstack((
            cosspaced_points,
            1 + cosspaced_points[1:],
        ))

        # Check that there are no duplicate points in the airfoil.
        if np.any(np.diff(distances_from_TE_normalized) == 0):
            raise ValueError(
                "This airfoil has a duplicated point (i.e. two adjacent points with the same (x, y) coordinates), so you can't repanel it!"
            )

        x = interp1d(
            distances_from_TE_normalized,
            self.x(),
            kind="cubic",
        )(s)
        y = interp1d(
            distances_from_TE_normalized,
            self.y(),
            kind="cubic",
        )(s)

        return Airfoil(name=self.name, coordinates=stack_coordinates(x, y))
Exemplo n.º 6
0
def get_NACA_coordinates(
        name: str = 'naca2412',
        n_points_per_side: int = _default_n_points_per_side) -> np.ndarray:
    """
    Returns the coordinates of a specified 4-digit NACA airfoil.
    Args:
        name: Name of the NACA airfoil.
        n_points_per_side: Number of points per side of the airfoil (top/bottom).

    Returns: The coordinates of the airfoil as a Nx2 ndarray [x, y]

    """
    name = name.lower().strip()

    if not "naca" in name:
        raise ValueError("Not a NACA airfoil!")

    nacanumber = name.split("naca")[1]
    if not nacanumber.isdigit():
        raise ValueError("Couldn't parse the number of the NACA airfoil!")

    if not len(nacanumber) == 4:
        raise NotImplementedError(
            "Only 4-digit NACA airfoils are currently supported!")

    # Parse
    max_camber = int(nacanumber[0]) * 0.01
    camber_loc = int(nacanumber[1]) * 0.1
    thickness = int(nacanumber[2:]) * 0.01

    # Referencing https://en.wikipedia.org/wiki/NACA_airfoil#Equation_for_a_cambered_4-digit_NACA_airfoil
    # from here on out

    # Make uncambered coordinates
    x_t = np.cosspace(0, 1,
                      n_points_per_side)  # Generate some cosine-spaced points
    y_t = 5 * thickness * (
        +0.2969 * x_t**0.5 - 0.1260 * x_t - 0.3516 * x_t**2 + 0.2843 * x_t**3 -
        0.1015 * x_t**4  # 0.1015 is original, #0.1036 for sharp TE
    )

    if camber_loc == 0:
        camber_loc = 0.5  # prevents divide by zero errors for things like naca0012's.

    # Get camber
    y_c = np.where(
        x_t <= camber_loc,
        max_camber / camber_loc**2 * (2 * camber_loc * x_t - x_t**2),
        max_camber / (1 - camber_loc)**2 *
        ((1 - 2 * camber_loc) + 2 * camber_loc * x_t - x_t**2))

    # Get camber slope
    dycdx = np.where(x_t <= camber_loc,
                     2 * max_camber / camber_loc**2 * (camber_loc - x_t),
                     2 * max_camber / (1 - camber_loc)**2 * (camber_loc - x_t))
    theta = np.arctan(dycdx)

    # Combine everything
    x_U = x_t - y_t * np.sin(theta)
    x_L = x_t + y_t * np.sin(theta)
    y_U = y_c + y_t * np.cos(theta)
    y_L = y_c - y_t * np.cos(theta)

    # Flip upper surface so it's back to front
    x_U, y_U = x_U[::-1], y_U[::-1]

    # Trim 1 point from lower surface so there's no overlap
    x_L, y_L = x_L[1:], y_L[1:]

    x = np.hstack((x_U, x_L))
    y = np.hstack((y_U, y_L))

    return stack_coordinates(x, y)
lats_v = data["lats"].flatten()
alts_v = data["alts"].flatten()
speeds = data["speeds"].reshape(len(alts_v), len(lats_v)).T.flatten()

lats, alts = np.meshgrid(lats_v, alts_v, indexing="ij")
lats = lats.flatten()
alts = alts.flatten()

# %%

lats_scaled = (lats - 37.5) / 11.5
alts_scaled = (alts - 24200) / 24200
speeds_scaled = (speeds - 7) / 56

alt_diff = np.diff(alts_v)
alt_diff_aug = np.hstack((alt_diff[0], alt_diff, alt_diff[-1]))
weights_1d = (alt_diff_aug[:-1] + alt_diff_aug[1:]) / 2
weights_1d = weights_1d / np.mean(weights_1d)
# region_of_interest = np.logical_and(
#     alts_v > 10000,
#     alts_v < 40000
# )
# true_weights = np.where(
#     region_of_interest,
#     2,
#     1
# )
weights = np.tile(weights_1d, (93, 1)).flatten()

# %%