Hi, I was trying to to plot the extracted field lines in a 3D figure, but it didn't succeed. Could you please take a look?
I transformed the points of the field line from the polar coordinates to the cartesian coordinates, but it didn't show up in the 3D figure. The scale of the polar plot is in AU, while the scale in the 3D figure is in solar radii unit.
Here's the code and the output figures:
from solarmach import SolarMACH
import astropy.constants as aconst
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sunpy.sun import constants as const
body_list = ['STEREO-A', 'Earth', 'PSP']
vsw_list = [400, 400, 400]
date = '2022-07-22 13:40:00'
coord_sys = 'Stonyhurst' # 'Carrington' (default) or 'Stonyhurst'
reference_long = -10 # longitude of reference (None to omit)
reference_lat = 32 # latitude of reference (None to omit)
reference_vsw = 400 # define solar wind speed at reference
long_offset = 270 # longitudinal offset for polar plot; defines where Earth's longitude is (by default 270, i.e., at "6 o'clock")
plot_spirals = True # plot Parker spirals for each body
plot_sun_body_line = False # plot straight line between Sun and body
return_plot_object = True # figure and axis object of matplotib are returned, allowing further adjustments to the figure
transparent = False # make output figure background transparent
numbered_markers = True # plot each body with a numbered marker
# initialize
sm = SolarMACH(date, body_list, vsw_list, reference_long, reference_lat, coord_sys)
# make plot
fig, ax = sm.plot(
plot_spirals=plot_spirals,
plot_sun_body_line=plot_sun_body_line,
reference_vsw=reference_vsw,
transparent=transparent,
numbered_markers=numbered_markers,
long_offset=long_offset,
return_plot_object=return_plot_object
)
# Adding another field line info
new_reference_long = 120
new_reference_lat = 7
new_reference_vsw = 400
# add anther arrow
arrow_dist = min([sm.max_dist/3.2, 2.])
ax.arrow(np.deg2rad(new_reference_long), 0.01, 0, arrow_dist, head_width=0.2, head_length=0.07,
edgecolor='dodgerblue', facecolor='dodgerblue', lw=1.8, zorder=5, overhang=0.2)
#add another dashed Parker spiral at arrow
AU = (const.au/1000).value # km
r_array = np.arange(0.007, (sm.max_dist+0.1)/np.cos(np.deg2rad(sm.max_dist_lat)) + 3.0, 0.001)
omega_ref = sm.solar_diff_rot(new_reference_lat)
alpha_ref = np.deg2rad(new_reference_long) + omega_ref / (reference_vsw / AU) * (sm.target_solar_radius*aconst.R_sun.to(u.AU).value - r_array) * np.cos(np.deg2rad(new_reference_lat))
ax.plot(alpha_ref, r_array * np.cos(np.deg2rad(new_reference_lat)), '--', color='dodgerblue',
label='Second filed line')
# reset max. radius for plot
ax.set_rmax(sm.max_dist + 0.3)
# extract the field lines
xfl1, yfl1 = ax.get_children()[10].get_data()
xfl2, yfl2 = ax.get_children()[19].get_data()
fig
# make the 3D figure
fig = plt.figure(figsize=[8,8])
ax = fig.add_subplot(111, projection='3d', computed_zorder=False)
# draw the Sun
theta, phi = np.mgrid[0:np.pi:100j, 0:2*np.pi:100j]
x = np.sin(theta)*np.cos(phi)
y = np.sin(theta)*np.sin(phi)
z = np.cos(theta)
ax.plot_surface(x, y, z, color='orange', zorder=0)
# draw the field lines from solarmach
r = xfl1 # Radial distance (r) from polar plot
theta = yfl1 # Angular coordinate (theta) from polar plot
# Convert polar coordinates to Cartesian coordinates
x_3d = r * np.cos(theta)
y_3d = r * np.sin(theta)
# make the 3rd axis as a 1D array of points similar to the given latitute
z_3d = np.full(len(x_3d), reference_lat)
ax.plot3D(x_3d, y_3d, z_3d, zorder=10)
# plot settings
axes_limit = 3
ax.set_xlim(-axes_limit, axes_limit)
ax.set_ylim(-axes_limit, axes_limit)
ax.set_zlim(-axes_limit, axes_limit)
ax.set_box_aspect([axes_limit, axes_limit, axes_limit])
for axis in 'xyz':
getattr(ax, 'set_{}label'.format(axis))(axis+' [R$_\odot]$')
plt.show()