最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - remove extra coordinate - Stack Overflow

programmeradmin0浏览0评论

I have a program simulating the movement of a ball inside a box, and tracking it using matplotlib:

def track_bouncing_charge():
    fig, (ax, ax_dist) = plt.subplots(1, 2, figsize=(14, 6))
    ax = fig.add_subplot(121, projection='3d')  # 3D plot

    sensor_labels = [f"Sensor {i + 1}" for i in range(len(sensors))]
    time_steps = []
    distance_history = [[] for _ in range(len(sensors))]
    time_counter = 0

    # Initial charge position and velocity
    charge_pos = np.array([0.5, 0.5, 0.5])
    velocity = np.array([0.02, 0.03, 0.01])
    dt = 0.1  # Time step

    while True:
        # Update charge position (simulate bouncing off walls)
        charge_pos += velocity * dt
        for i in range(3):
            if charge_pos[i] <= 0 or charge_pos[i] >= 1:
                velocity[i] = -velocity[i]  # Reverse direction on collision
                charge_pos[i] = max(0, min(1, charge_pos[i]))  # Keep within bounds

        # Generate synthetic electric field data
        sensor_readings = np.array([compute_electric_field(sensor, charge_pos) for sensor in sensors])

        # Solve for charge position using least squares optimization
        initial_guess = np.array([0.5, 0.5, 0.5])
        result = least_squares(error_function, initial_guess, args=(sensor_readings,))
        estimated_position = result.x

        # Compute distances
        distances = [np.linalg.norm(sensor - estimated_position) for sensor in sensors]
        time_steps.append(time_counter)
        time_counter += dt

        for i in range(len(sensors)):
            distance_history[i].append(distances[i])

        # Clear and redraw 3D plot
        ax.clear()
        ax.scatter(sensors[:, 0], sensors[:, 1], sensors[:, 2], c='b', marker='o', label='Sensors')
        ax.scatter(charge_pos[0], charge_pos[1], charge_pos[2], c='g', s=200, label='True Charge Position')

        # Draw lines connecting sensors to the estimated charge position with varying color intensity based on distance
        for sensor in sensors:
            distance = np.linalg.norm(sensor - estimated_position)
            ax.plot([sensor[0], estimated_position[0]],
                    [sensor[1], estimated_position[1]],
                    [sensor[2], estimated_position[2]],
                    'r.-.', lw=min(20, 2 / distance), alpha=min(0.5, 0.5 / distance))

        ax.set_xlabel('X Position (m)', fontsize=24, fontname='Arial', labelpad=20)
        ax.set_ylabel('Y Position (m)', fontsize=24, fontname='Arial', labelpad=20)
        ax.set_zlabel('Z Position (m)', fontsize=24, fontname='Arial', labelpad=20)
        ax.tick_params(axis='both', which='major', labelsize=24)

        # Remove bounding box lines while keeping the grid
        for axis in [ax.xaxis, ax.yaxis, ax.zaxis]:
            axis._axinfo["grid"].update(linewidth=0.5)  # Keep grid lines but make them subtle
            axis._axinfo["grid"].update(color=(0.7, 0.7, 0.7, 0.7))  # Light grey grid

        # Hide the extra bounding box lines
        ax.xaxis._axinfo["grid"].update(linewidth=0)
        ax.yaxis._axinfo["grid"].update(linewidth=0)
        ax.zaxis._axinfo["grid"].update(linewidth=0)
        ax.xaxis._axinfo['tick']['outward_factor'] = 0  # Remove extra tick lines
        ax.yaxis._axinfo['tick']['outward_factor'] = 0
        ax.zaxis._axinfo['tick']['outward_factor'] = 0
        ax.grid(True)

        # Clear and redraw distance vs. time plot
        ax_dist.clear()
        for i in range(len(sensors)):
            ax_dist.plot(time_steps, distance_history[i], label=f'Sensor {i + 1}')

        ax_dist.set_xlabel('Time (s)', fontsize=24, fontname='Arial', labelpad=15)
        ax_dist.set_ylabel('Distance to Charge (m)', fontsize=24, fontname='Arial', labelpad=15)
        ax_dist.tick_params(axis='both', which='major', labelsize=24)

        plt.pause(0.01)  # Pause to allow real-time update
        plt.tight_layout()


# Run the real-time tracking simulation
track_bouncing_charge()

The output looks like:

The left image shows how the ball moves, and the right shows the distance of the ball to the corners.

My question is : How to remove the extra 2D coordinate axes around the 3D plot? This is a simulation of a ball moving inside a box.

I have a program simulating the movement of a ball inside a box, and tracking it using matplotlib:

def track_bouncing_charge():
    fig, (ax, ax_dist) = plt.subplots(1, 2, figsize=(14, 6))
    ax = fig.add_subplot(121, projection='3d')  # 3D plot

    sensor_labels = [f"Sensor {i + 1}" for i in range(len(sensors))]
    time_steps = []
    distance_history = [[] for _ in range(len(sensors))]
    time_counter = 0

    # Initial charge position and velocity
    charge_pos = np.array([0.5, 0.5, 0.5])
    velocity = np.array([0.02, 0.03, 0.01])
    dt = 0.1  # Time step

    while True:
        # Update charge position (simulate bouncing off walls)
        charge_pos += velocity * dt
        for i in range(3):
            if charge_pos[i] <= 0 or charge_pos[i] >= 1:
                velocity[i] = -velocity[i]  # Reverse direction on collision
                charge_pos[i] = max(0, min(1, charge_pos[i]))  # Keep within bounds

        # Generate synthetic electric field data
        sensor_readings = np.array([compute_electric_field(sensor, charge_pos) for sensor in sensors])

        # Solve for charge position using least squares optimization
        initial_guess = np.array([0.5, 0.5, 0.5])
        result = least_squares(error_function, initial_guess, args=(sensor_readings,))
        estimated_position = result.x

        # Compute distances
        distances = [np.linalg.norm(sensor - estimated_position) for sensor in sensors]
        time_steps.append(time_counter)
        time_counter += dt

        for i in range(len(sensors)):
            distance_history[i].append(distances[i])

        # Clear and redraw 3D plot
        ax.clear()
        ax.scatter(sensors[:, 0], sensors[:, 1], sensors[:, 2], c='b', marker='o', label='Sensors')
        ax.scatter(charge_pos[0], charge_pos[1], charge_pos[2], c='g', s=200, label='True Charge Position')

        # Draw lines connecting sensors to the estimated charge position with varying color intensity based on distance
        for sensor in sensors:
            distance = np.linalg.norm(sensor - estimated_position)
            ax.plot([sensor[0], estimated_position[0]],
                    [sensor[1], estimated_position[1]],
                    [sensor[2], estimated_position[2]],
                    'r.-.', lw=min(20, 2 / distance), alpha=min(0.5, 0.5 / distance))

        ax.set_xlabel('X Position (m)', fontsize=24, fontname='Arial', labelpad=20)
        ax.set_ylabel('Y Position (m)', fontsize=24, fontname='Arial', labelpad=20)
        ax.set_zlabel('Z Position (m)', fontsize=24, fontname='Arial', labelpad=20)
        ax.tick_params(axis='both', which='major', labelsize=24)

        # Remove bounding box lines while keeping the grid
        for axis in [ax.xaxis, ax.yaxis, ax.zaxis]:
            axis._axinfo["grid"].update(linewidth=0.5)  # Keep grid lines but make them subtle
            axis._axinfo["grid"].update(color=(0.7, 0.7, 0.7, 0.7))  # Light grey grid

        # Hide the extra bounding box lines
        ax.xaxis._axinfo["grid"].update(linewidth=0)
        ax.yaxis._axinfo["grid"].update(linewidth=0)
        ax.zaxis._axinfo["grid"].update(linewidth=0)
        ax.xaxis._axinfo['tick']['outward_factor'] = 0  # Remove extra tick lines
        ax.yaxis._axinfo['tick']['outward_factor'] = 0
        ax.zaxis._axinfo['tick']['outward_factor'] = 0
        ax.grid(True)

        # Clear and redraw distance vs. time plot
        ax_dist.clear()
        for i in range(len(sensors)):
            ax_dist.plot(time_steps, distance_history[i], label=f'Sensor {i + 1}')

        ax_dist.set_xlabel('Time (s)', fontsize=24, fontname='Arial', labelpad=15)
        ax_dist.set_ylabel('Distance to Charge (m)', fontsize=24, fontname='Arial', labelpad=15)
        ax_dist.tick_params(axis='both', which='major', labelsize=24)

        plt.pause(0.01)  # Pause to allow real-time update
        plt.tight_layout()


# Run the real-time tracking simulation
track_bouncing_charge()

The output looks like:

The left image shows how the ball moves, and the right shows the distance of the ball to the corners.

My question is : How to remove the extra 2D coordinate axes around the 3D plot? This is a simulation of a ball moving inside a box.

Share Improve this question edited Mar 16 at 10:33 Jenny 6833 silver badges16 bronze badges asked Mar 13 at 9:05 Renyun ZhangRenyun Zhang 273 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

The issue here is that you are first creating two 2D Axes with plt.subplots, referenced respectively by ax and ax_dist. Then you create a new 3D Axes with fig.add_subplot, which you place over the first set of 2D Axes (which still exists), and replace the ax reference by this new Axes. The solution is to not create the first of the two 2D Axes.

Replacing:

fig, (ax, ax_dist) = plt.subplots(1, 2, figsize=(14, 6)) # Creates 2 2D Axes
ax = fig.add_subplot(121, projection='3d')  # Creates a 3D Axes over the first 2D Axes

by:

fig = plt.figure(figsize=(14,6)) # Creates the figure
ax = fig.add_subplot(121, projection='3d') # Creates the 3D Axes
ax_dist = fig.add_subplot(122) # Creates the distance 2D Axes

does the trick.

发布评论

评论列表(0)

  1. 暂无评论