magpylib / magpylib

Python package for computation of magnetic fields of magnets, currents and moments.
https://magpylib.readthedocs.io/en/latest/
BSD 2-Clause "Simplified" License
218 stars 34 forks source link

add "customizable animation" to docs #766

Open OrtnerMichael opened 1 month ago

OrtnerMichael commented 1 month ago

some minimal example that can be used for copy-pasting whenever we want to customize animations to make nice figures.

from plotly.subplots import make_subplots
import plotly.graph_objects as go
import numpy as np
import magpylib as magpy

fig1 = make_subplots(
    rows=1, cols=2,
    specs=[[{"type": "xy"}, {"type":"scatter3d"}]])

# setting up a system with a path
n = 10
verfahrweg = 2
xs = np.linspace(-verfahrweg/2, verfahrweg/2, n)
path = np.linspace((-verfahrweg/2,0,0), (verfahrweg/2,0,0), n)

cube = magpy.magnet.Cuboid(
    dimension=(1,1,1),
    polarization=(0,0,1),
    position=path
)
sensor = magpy.Sensor(position=(0,0,1))
coll = magpy.Collection(cube, sensor)

# compute and plot B-traces
COLORS = ['palevioletred','palegoldenrod','rebeccapurple']
B0 = coll.getB()
for col,i,lab in zip(COLORS, [0,1,2], ['Bx', 'By', 'Bz']):
    fig1.add_trace(
        go.Scatter(x=xs, y=B0[:,i], line_color=col, name=lab),
        row=1, col=1)

# plot location marker
for x0,y0 in zip(xs,B0):
    fig1.add_trace(
        go.Scatter(
            visible=False,
            x=[x0]*3,
            y=y0,
            marker_size=10,
            marker_color=COLORS,
            marker_line_color='black',
            marker_line_width=1,
            name='cart position'
            ),
        row=1,
        col=1,
        )
# set visibility of initial frame true
fig1.data[3].visible=True 

# add 3D-plot to fig (compute for every instance)
for i in range(n):
    fig0 = go.Figure()
    magpy.show(
        coll,
        backend='plotly',
        canvas=fig0,
        style_path_show=False,
        style_path_frames=[i],
        markers=[[-3]*3,[3]*3],      # keep view window fixed
        style_marker_size=0.0001,
        )
    for dat in fig0.data:
        dat.visible=False
        fig1.add_trace(dat, row=1, col=2)
m = len(fig0.data)

# set initial visibility
for i in range(m):
    fig1.data[3+n+i].visible=True

# add slider
steps1=[]
for i in range(n):
    viz = [True]*3 + [False]*n + [False]*n*m
    viz[3+i]=True
    for j in range(m):
        viz[3+n+m*i+j]=True
    step = dict(
        method="update",
        args=[dict(visible=viz)],
        label=f"{xs[i]:.0f}"
        )
    steps1.append(step)

slider1 = dict(
    active=0,
    currentvalue_prefix="cart position [mm]: ",
    pad=dict(t=50),
    steps=steps1,
    )

# figure styling
fig1.update_layout(
    xaxis_title='position (mm)',
    yaxis_title='B field (T)',
    xaxis_range=(-verfahrweg/1.8, verfahrweg/1.8),
    yaxis_range=(-.5,.5),
    sliders=[slider1],
    scene= dict(
        xaxis = dict(range=[-3,3]),
        yaxis = dict(range=[-3,3]),
        zaxis = dict(range=[-3,3]),
        aspectratio=dict(x=1,y=1,z=1),
    )
)

fig1.show()
Alexboiboi commented 3 weeks ago

I'll see if there is a nice way to do this, may take some time

OrtnerMichael commented 3 weeks ago

🥇