예제 #1
0
def top_view_bridge(
    config: Config,
    abutments: bool = False,
    edges: bool = False,
    piers: bool = False,
    lanes: bool = False,
    lane_fill: bool = False,
    landscape: bool = True,
    compass: bool = False,
):
    """Plot the top view of a bridge's geometry.

    Args:
        bridge: the bridge top to plot.
        landscape: orient the plot in landscape (16 x 10) ?
        abutments: plot the bridge's abutments?
        edges: plot the longitudinal edges?
        piers: plot where the piers connect to the deck?
        lanes: plot lanes on the bridge?
        lane_fill: plot fill or only outline?
        compass: plot a compass rose?

    """
    bridge = config.bridge
    if landscape:
        plt.landscape()
    plt.axis("equal")
    if edges:
        plt.hlines([bridge.z_min, bridge.z_max], 0, bridge.length)
    if abutments:
        plt.vlines([0, bridge.length], bridge.z_min, bridge.z_max)
    if piers:
        for pier in bridge.supports:
            z_min_top, z_max_top = pier.z_min_max_top()
            x_min, x_max = pier.x_min_max_top()
            plt.vlines([x_min, x_max], z_min_top, z_max_top)
    if lanes:
        for lane in bridge.lanes:
            plt.gca().add_patch(
                matplotlib.patches.Rectangle(
                    (0, lane.z_min),
                    bridge.length,
                    lane.z_max - lane.z_min,
                    facecolor="black" if lane_fill else "none",
                    edgecolor="black",
                )
            )
    if compass:
        ax = plt.gca()  # Reference to the original axis.
        dir_path = os.path.dirname(os.path.abspath(__file__))
        compass_img = plt.imread(os.path.join(dir_path, "compass-rose.png"))
        c_len = max(bridge.width, bridge.length) * 0.2
        ax_c = ax.inset_axes(
            [0, bridge.z_max + (c_len * 0.05), c_len, c_len], transform=ax.transData,
        )
        ax_c.imshow(compass_img)
        ax_c.axis("off")
        plt.sca(ax)  # Return control to the original axis.
    plt.xlabel("X position")
    plt.ylabel("Z position")
예제 #2
0
def wagen1_plot(c: Config):
    """Plot of wagen1 compared to given specification."""
    plt.landscape()

    wheel_print = (0.31, 0.25)
    wheel_prints = []
    for w_i in range(len(truck1.axle_distances) + 1):
        if w_i in [1, 2]:
            wheel_prints.append([wheel_print, wheel_print])
        else:
            wheel_prints.append([wheel_print])

    plt.subplot(1, 2, 1)
    xlim, ylim = topview_vehicle(truck1, wheel_prints=wheel_prints)
    plt.title("Truck 1 specification")
    plt.xlabel("Width (m)")
    plt.ylabel("Length (m)")

    plt.subplot(1, 2, 2)
    topview_vehicle(truck1, xlim=xlim, ylim=ylim)
    plt.title("Truck 1 in simulation")
    plt.xlabel("Width (m)")
    plt.ylabel("Length (m)")

    plt.savefig(c.get_image_path("vehicles", "wagen-1", bridge=False) + ".pdf")
    plt.close()
예제 #3
0
def make_boundary_plot(c: Config):
    """Top view of bridge with boundary conditions."""
    plt.landscape()
    top_view_bridge(c.bridge, abutments=True, piers=True, compass=False)
    plt.vlines(
        [0, c.bridge.length],
        c.bridge.z_min,
        c.bridge.z_max,
        lw=5,
        color="orange",
        label="     Y = 1, Z = 1",
    )
    for p_i, pier in enumerate(c.bridge.supports):
        z_min_top, z_max_top = pier.z_min_max_bottom()
        x_min, x_max = pier.x_min_max_top()
        x_center = x_min + ((x_max - x_min) / 2)
        plt.vlines(
            [x_center],
            z_min_top,
            z_max_top,
            lw=5,
            color="red" if (8 <= p_i <= 15) else "orange",
            label="X = 1, Y = 1, Z = 1" if p_i == 8 else None,
        )
    legend_marker_size(plt.legend(), 50)
    plt.title("Bridge 705 boundary conditions of nodal supports")
    plt.tight_layout()
    plt.savefig(c.get_image_path("sensors", "boundary.pdf"))
    plt.close()
예제 #4
0
def temperature_effect_date(c: Config, month: str, vert: bool):
    temp = __init__.load(name=month)
    point = Point(x=51, y=0, z=-8.4)
    plt.landscape()

    def plot_hours():
        if not vert:
            return
        label_set = False
        for dt in temp["datetime"]:
            if np.isclose(float(dt.hour + dt.minute), 0):
                label = None
                if not label_set:
                    label = "Time at vertical line = 00:00"
                    label_set = True
                plt.axvline(x=dt, linewidth=1, color="black", label=label)

    # Plot the temperature.
    plt.subplot(2, 1, 1)
    plot_hours()
    plt.scatter(
        temp["datetime"],
        temp["temp"],
        c=temp["missing"],
        cmap=mpl.cm.get_cmap("bwr"),
        s=1,
    )
    plt.ylabel("Temperature (°C)")
    plt.xlabel("Date")
    plt.gcf().autofmt_xdate()
    plt.title(f"Temperature in {str(month[0]).upper()}{month[1:]}")
    plt.legend()
    # Plot the effect at a point.
    response_type = ResponseType.YTranslation
    plt.subplot(2, 1, 2)
    plot_hours()
    effect = __init__.effect(
        c=c, response_type=response_type, points=[point], temps=temp["temp"]
    )[0]
    plt.scatter(
        temp["datetime"],
        effect * 1000,
        c=temp["missing"],
        cmap=mpl.cm.get_cmap("bwr"),
        s=1,
    )
    plt.ylabel(f"{response_type.name()} (mm)")
    plt.xlabel("Date")
    plt.gcf().autofmt_xdate()
    plt.title(f"{response_type.name()} to unit thermal loading in {month}")
    # Save.
    plt.tight_layout()
    plt.savefig(c.get_image_path("classify/temperature", f"{month}.png"))
    plt.savefig(c.get_image_path("classify/temperature", f"{month}.pdf"))
    plt.close()
예제 #5
0
def angles_3d(
    xs: List[float],
    ys: List[float],
    zs: List[float],
    angles: Optional[List[float]] = None,
    elev: Optional[float] = None,
):
    """Rotate a plot in 3D, yielding the axis and angle.

    TODO: Deprecate.

    Args:
        angles: Optional[List[float]], angles to plot at, if None use default
            angle.
        elev: Optional[float], elevation used if 'angles' is given.

    """
    xs, ys, zs = np.array(xs), np.array(ys), np.array(zs)

    # Determine values for scaling axes.
    max_range = (np.array(
        [xs.max() - xs.min(),
         ys.max() - ys.min(),
         zs.max() - zs.min()]).max() / 2.0)
    mid_x = (xs.max() + xs.min()) * 0.5
    mid_y = (ys.max() + ys.min()) * 0.5
    mid_z = (zs.max() + zs.min()) * 0.5

    # Ensure at least one angle in default case.
    if angles is None:
        angles = [None]

    # Plot for different angles.
    for ii in angles:
        plt.landscape()
        fig = plt.figure()
        # ax = fig.add_subplot(111, projection="3d", proj_type="ortho")
        ax = Axes3D(fig)
        ax.set_xlim(mid_x - max_range, mid_x + max_range)
        ax.set_ylim(mid_y - max_range, mid_y + max_range)
        ax.set_zlim(mid_z - max_range, mid_z + max_range)
        if ii is not None:
            ax.view_init(elev=elev, azim=ii)
        yield fig, ax, ii
예제 #6
0
def ax_3d(
    xs: List[float],
    ys: List[float],
    zs: List[float],
):
    """Return a new figure and 3D axis scaled to given data."""
    xs, ys, zs = np.array(xs), np.array(ys), np.array(zs)
    max_range = (np.array(
        [xs.max() - xs.min(),
         ys.max() - ys.min(),
         zs.max() - zs.min()]).max() / 2.0)
    mid_x = (xs.max() + xs.min()) * 0.5
    mid_y = (ys.max() + ys.min()) * 0.5
    mid_z = (zs.max() + zs.min()) * 0.5
    plt.landscape()
    fig = plt.figure()
    ax = fig.add_subplot(111, projection="3d", proj_type="ortho")
    ax.set_xlim(mid_x - max_range, mid_x + max_range)
    ax.set_ylim(mid_y - max_range, mid_y + max_range)
    ax.set_zlim(mid_z - max_range, mid_z + max_range)
    return fig, ax
예제 #7
0
def number_of_uls_plot(c: Config):
    """Plot error as a function of number of unit load simulations."""
    if not c.shorten_paths:
        raise ValueError("This plot requires --shorten-paths true")
    response_type = ResponseType.YTranslation
    num_ulss = np.arange(100, 2000, 10)
    chosen_uls = 600
    point = Point(x=c.bridge.x_max - (c.bridge.length / 2), y=0, z=-8.4)
    wagen1_time = truck1.time_at(x=point.x, bridge=c.bridge)
    print_i(f"Wagen 1 time at x = {point.x:.3f} is t = {wagen1_time:.3f}")

    # Determine the reference value.
    truck_loads = flatten(
        truck1.to_point_load_pw(time=wagen1_time, bridge=c.bridge), PointLoad)
    print_i(f"Truck loads = {truck_loads}")
    sim_responses = load_fem_responses(
        c=c,
        response_type=response_type,
        sim_runner=OSRunner(c),
        sim_params=SimParams(ploads=truck_loads,
                             response_types=[response_type]),
    )
    ref_value = sim_responses.at_deck(point, interp=True) * 1000
    print_i(f"Reference value = {ref_value}")

    # Collect the data.
    total_load = []
    num_loads = []
    responses = []
    for num_uls in num_ulss:
        c.il_num_loads = num_uls
        # Nested in here because it depends on the setting of 'il_num_loads'.
        truck_loads = flatten(
            truck1.to_wheel_track_loads(c=c, time=wagen1_time), PointLoad)
        num_loads.append(len(truck_loads))
        total_load.append(sum(map(lambda l: l.kn, truck_loads)))
        sim_responses = load_fem_responses(
            c=c,
            response_type=response_type,
            sim_runner=OSRunner(c),
            sim_params=SimParams(ploads=truck_loads,
                                 response_types=[response_type]),
        )
        responses.append(sim_responses.at_deck(point, interp=True) * 1000)

    # Plot the raw fem, then error on the second axis.
    plt.landscape()
    # plt.plot(num_ulss, fem)
    # plt.ylabel(f"{response_type.name().lower()} (mm)")
    plt.xlabel("ULS")
    error = np.abs(np.array(responses) - ref_value).flatten() * 100
    # ax2 = plt.twinx()
    plt.plot(num_ulss, error)
    plt.ylabel("Error (%)")
    plt.title(
        f"Error in {response_type.name()} to Truck 1 as a function of ULS")
    # Plot the chosen number of ULS.
    chosen_error = np.interp([chosen_uls], num_ulss, error)[0]
    plt.axhline(
        chosen_error,
        label=f"At {chosen_uls} ULS, error = {np.around(chosen_error, 2)} %",
        color="black",
    )
    plt.axhline(0,
                color="red",
                label="Response from direct simulation (no wheel tracks)")
    plt.legend()
    plt.tight_layout()
    plt.savefig(c.get_image_path("paramselection", "uls.pdf"))
    plt.close()
    # Additional verification plots.
    plt.plot(num_ulss, total_load)
    plt.savefig(c.get_image_path("paramselection",
                                 "uls-verify-total-load.pdf"))
    plt.close()
    plt.plot(num_ulss, num_loads)
    plt.savefig(c.get_image_path("paramselection", "uls-verify-num-loads.pdf"))
    plt.close()
예제 #8
0
def pairwise_sensors(c: Config, dist_measure=ks_no_outliers):
    """Compare distribution of pairs of sensors under HealthyScenario."""
    normal_traffic_array, traffic_scenario = load_normal_traffic_array(c)
    response_type = ResponseType.YTranslation
    points = [
        Point(x=x, y=0, z=z)
        for x, z in itertools.product(
            np.linspace(c.bridge.x_min, c.bridge.x_max, 50),
            np.linspace(c.bridge.z_min, c.bridge.z_max, 4),
        )
    ]

    bridge_scenario = HealthyScenario()
    responses = responses_to_traffic_array(
        c=c,
        traffic_array=normal_traffic_array,
        response_type=response_type,
        bridge_scenario=bridge_scenario,
        points=points,
        sim_runner=OSRunner,
    ).T
    assert len(responses) == len(points)

    ks_values_healthy = []
    for p0, point0 in enumerate(points):
        print_i(f"Point {p0 + 1} / {len(points)}")
        ks_values_healthy.append([])
        for p1, point1 in enumerate(points):
            ks = dist_measure(responses[p0], responses[p1])
            ks_values_healthy[-1].append(ks)

    plt.landscape()
    plt.imshow(ks_values_healthy)
    plt.savefig(c.get_image_path("joint-clustering", "healthy-bridge"))
    plt.close()

    bridge_scenario = each_pier_scenarios(c)[0]
    responses = responses_to_traffic_array(
        c=c,
        traffic_array=normal_traffic_array,
        response_type=response_type,
        bridge_scenario=bridge_scenario,
        points=points,
        sim_runner=OSRunner,
    ).T
    assert len(responses) == len(points)

    ks_values_damage = []
    for p0, point0 in enumerate(points):
        print_i(f"Point {p0 + 1} / {len(points)}")
        ks_values_damage.append([])
        for p1, point1 in enumerate(points):
            ks = dist_measure(responses[p0], responses[p1])
            ks_values_damage[-1].append(ks)

    plt.imshow(ks_values_damage)
    plt.savefig(c.get_image_path("joint-clustering", "scenarios-bridge"))
    plt.close()

    ks_values_comp = []
    for p0, point0 in enumerate(points):
        ks_values_comp.append([])
        for p1, point1 in enumerate(points):
            comp = abs(ks_values_healthy[p0][p1] - ks_values_damage[p0][p1])
            ks_values_comp[-1].append(comp)

    plt.landscape()
    plt.imshow(ks_values_comp)
    plt.savefig(c.get_image_path("joint-clustering", "scenarios-bridge-comp"))
    plt.close()

    responses = Responses.from_responses(
        response_type=response_type,
        responses=[(sum(ks_values_comp[p]), point) for p, point in enumerate(points)],
    )
    top_view_bridge(c.bridge, abutments=True, piers=True)
    plot_contour_deck(c=c, responses=responses)
    plt.savefig(c.get_image_path("joint-clustering", "scenarios-bridge-comp-contour"))
    plt.close()
예제 #9
0
def plot_mmm_strain_convergence(
    c: Config,
    pier: int,
    df: pd.DataFrame,
    all_strains: Dict[float, Responses],
    title: str,
    without: Optional[Callable[[Point], bool]] = None,
    append: Optional[str] = None,
):
    """Plot convergence of given fem as model size grows."""
    # A grid of points 1m apart, over which to calculate fem.
    grid = [
        Point(x=x, y=0, z=z)
        for x, z in itertools.product(
            np.linspace(c.bridge.x_min, c.bridge.x_max, int(c.bridge.length)),
            np.linspace(c.bridge.z_min, c.bridge.z_max, int(c.bridge.width)),
        )
    ]
    # If requested, remove some values from the fem.
    if without is not None:
        grid = [point for point in grid if not without(point)]
        for msl, strains in all_strains.items():
            print(f"Removing points from strains with max_shell_len = {msl}")
            all_strains[msl] = strains.without(without)
    # Collect fem over all fem, and over the grid. Iterate by
    # decreasing max_shell_len.
    mins, maxes, means = [], [], []
    gmins, gmaxes, gmeans = [], [], []
    max_shell_lens = []
    for msl, strains in sorted(all_strains.items(), key=lambda kv: -kv[0]):
        max_shell_lens.append(msl)
        print_i(f"Gathering strains with max_shell_len = {msl}", end="\r")
        grid_strains = np.array([strains.at_deck(point, interp=True) for point in grid])
        gmins.append(scalar(np.min(grid_strains)))
        gmaxes.append(scalar(np.max(grid_strains)))
        gmeans.append(scalar(np.mean(grid_strains)))
        strains = np.array(list(strains.values()))
        mins.append(scalar(np.min(strains)))
        maxes.append(scalar(np.max(strains)))
        means.append(scalar(np.mean(strains)))
    print()
    # Normalize and plot the mins, maxes, and means.
    def normalize(ys):
        print(ys)
        return ys / np.mean(ys[-5:])

    mins, maxes, means = normalize(mins), normalize(maxes), normalize(means)
    gmins, gmaxes, gmeans = normalize(gmins), normalize(gmaxes), normalize(gmeans)
    deck_nodes = [df.at[msl, "deck-nodes"] for msl in max_shell_lens]
    pier_nodes = [df.at[msl, "pier-nodes"] for msl in max_shell_lens]
    num_nodes = np.array(deck_nodes) + np.array(pier_nodes)
    print(f"MSLs = {max_shell_lens}")
    print(f"num_nodes = {num_nodes}")
    # Plot all lines, for debugging.
    plt.landscape()
    plt.plot(num_nodes, mins, label="mins")
    plt.plot(num_nodes, maxes, label="maxes")
    plt.plot(num_nodes, means, label="means")
    plt.plot(num_nodes, gmins, label="gmins")
    plt.plot(num_nodes, gmaxes, label="gmaxes")
    plt.plot(num_nodes, gmeans, label="gmeans")
    plt.grid(axis="y")
    plt.xlabel("Nodes in FEM")
    plt.ylabel("Strain")
    plt.title(title)
    plt.tight_layout()
    plt.legend()
    plt.savefig(
        c.get_image_path("convergence-pier-strain", f"mmm-{append}-all.pdf", acc=False)
    )
    plt.close()
    # Only plot some lines, for the thesis.
    plt.landscape()
    plt.plot(num_nodes, gmins, label="Minimum")
    plt.plot(num_nodes, gmaxes, label="Maximum")
    plt.plot(num_nodes, gmeans, label="Mean")
    plt.grid(axis="y")
    plt.title(title)
    plt.xlabel("Nodes in FEM")
    plt.ylabel("Strain")
    plt.legend()
    plt.tight_layout()
    plt.savefig(
        c.get_image_path("convergence-pier-strain", f"mmm-{append}.pdf", acc=False)
    )
    plt.close()