cpmech / plotpy

Rust plotting library using Python (Matplotlib)
MIT License
65 stars 6 forks source link

Can plotpy be used with barplot? #50

Closed supernova4869 closed 1 month ago

supernova4869 commented 1 month ago

I only found Curve, Surface and Histogram in the plotpy cargo. How could I plot barplot with plotpy?

cpmech commented 1 month ago

Hi, can you give a Python example of the plot you are trying to make? Then I can see if we can wrap it in Rust. Thanks.

supernova4869 commented 1 month ago

Thank you. I have tried to modify from the python script generated from the Line plot mission.

### file generated by the 'plotpy' Rust crate

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tck
import matplotlib.patches as pat
import matplotlib.path as pth
import matplotlib.patheffects as pff
import matplotlib.lines as lns
import matplotlib.transforms as tra
import mpl_toolkits.mplot3d

# Width for bar
width = 0.8

# Variable to handle NaN values coming from Rust
NaN = np.nan

# List of additional objects to calculate bounding boxes
EXTRA_ARTISTS = []

# Adds an entity to the EXTRA_ARTISTS list to calculate bounding boxes
def add_to_ea(obj):
    if obj!=None: EXTRA_ARTISTS.append(obj)

# Is a dictionary of mplot3d objects (one for each subplot_3d)
THREE_D = dict()

# Is a tuple holding the key to the current THREE_D object (defines the subplot_3d)
THREE_D_ACTIVE = (1,1,1)

# Creates or returns the mplot3d object with the current subplot_3d definition specified by THREE_D_ACTIVE
def ax3d():
    global THREE_D
    global THREE_D_ACTIVE
    if not THREE_D_ACTIVE in THREE_D:
        a, b, c = THREE_D_ACTIVE
        THREE_D[THREE_D_ACTIVE] = plt.gcf().add_subplot(a,b,c,projection='3d')
        THREE_D[THREE_D_ACTIVE].set_xlabel('x')
        THREE_D[THREE_D_ACTIVE].set_ylabel('y')
        THREE_D[THREE_D_ACTIVE].set_zlabel('z')
        add_to_ea(THREE_D[THREE_D_ACTIVE])
    return THREE_D[THREE_D_ACTIVE]

# Specifies the THREE_D_ACTIVE parameters to define a subplot_3d
def subplot_3d(a,b,c):
    global THREE_D_ACTIVE
    THREE_D_ACTIVE = (a,b,c)
    ax3d()

# Transforms data limits to axis limits
def data_to_axis(coords):
    plt.axis() # must call this first
    return plt.gca().transLimits.transform(coords)

# Transforms axis limits to data limits
def axis_to_data(coords):
    plt.axis() # must call this first
    return plt.gca().transLimits.inverted().transform(coords)

# Configures the aspect of axes with a same scaling from data to plot units for x, y and z.
def set_equal_axes():
    global THREE_D
    if len(THREE_D) == 0:
        ax = plt.gca()
        ax.axes.set_aspect('equal')
        return
    try:
        ax = ax3d()
        ax.set_box_aspect([1,1,1])
        limits = np.array([ax.get_xlim3d(), ax.get_ylim3d(), ax.get_zlim3d()])
        origin = np.mean(limits, axis=1)
        radius = 0.5 * np.max(np.abs(limits[:, 1] - limits[:, 0]))
        x, y, z = origin
        ax.set_xlim3d([x - radius, x + radius])
        ax.set_ylim3d([y - radius, y + radius])
        ax.set_zlim3d([z - radius, z + radius])
    except:
        import matplotlib
        print('VERSION of MATPLOTLIB = {}'.format(matplotlib.__version__))
        print('ERROR: set_box_aspect is missing in this version of Matplotlib')

################## plotting commands follow after this line ############################

x=np.array([0,1,2,3,4,5,6,7,8,9,],dtype=float)
y=np.array([5,4,3,2,1,0,1,2,3,4,],dtype=float)
plt.bar(x, y, width=width)

fn=r'example_main.png'
plt.savefig(fn,bbox_inches='tight',bbox_extra_artists=EXTRA_ARTISTS)
cpmech commented 1 month ago

Hi,

Sorry for the delay, but I had to implement a new struct (Barplot; available on version 1.2).

The example below replicates your case.

See also https://docs.rs/plotpy/1.2.1/plotpy/struct.Barplot.html

// data
let xx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let yy = [5, 4, 3, 2, 1, 0, 1, 2, 3, 4];

// barplot object and options
let mut bar = Barplot::new();
bar.draw(&xx, &yy);

// save figure
let mut plot = Plot::new();
plot.add(&bar).save("/tmp/my_bar_plot.svg")?;

my_bar_plot

supernova4869 commented 1 month ago

Hi. Thank you for the update! This crate is really useful and I could plot specific figure with my data now. Thank you again for your work. my_bar_plot