<jupyter_start><jupyter_text>Visualization  OverviewVisualization poses a significant challenge for the space weather community: output from models and data are very domain-specific, both in content (coordinate systems, units) and in representation (file formats and data structures). On the other hand, science users also have their preferred context for analyzing these results - for instance, they may only want simulation results interpolated on a satellite trajectory and in a specific coordinate system with their own prefered units.Kamodo aims to strike a balance between the intent of the model (or data) provider and the goals of the user, by making it easy for developers to provide context for their output and for users to easily change that context. It accomplishes this in two ways:* By leveraging default arguments given by model and data providers * By mapping the shape of function inputs and output to certain registered plot typesThis strategy allows Kamodo to automatically generate plots for arbitrary model output and data sources, while still allowing for customization by the end user.  Available Plot TypesKamodo keeps a registry of plotting functions, indexed by argument shape and output shape.<jupyter_code>from kamodo.plotting import plot_types
plot_types<jupyter_output><empty_output><jupyter_text>When a user tries to plot a given variable, a lookup is made into the table above and the corresponding plotting function is used to generate the output. Examples below demonstrate the intended workflow.  1-Dimensional line plots<jupyter_code>from kamodo import Kamodo, kamodofy
kamodo = Kamodo('g_N[kg] = x_N**2')
kamodo['f[g]'] = 'g_N'
kamodo<jupyter_output><empty_output><jupyter_text>Here we have defined a function $g_N$ which returns an array of shape $N$. As input, it takes one argument $x_N$ which also has size $N$. We also generate a function $f$ which is the same as $g_N$ but with a different units.!!! note    We could have named the function $g$ instead of $g_N$. The variable names have no bearing on the resulting plots - only the argument input shapes and output shapes matter. When we call Kamodo's plot function, we define which variable we are plotting and domain over which the arguments are applied:<jupyter_code>import numpy as np
import plotly.io as pio

fig = kamodo.plot(f = dict(x_N = np.linspace(-4, 3, 30)))
# pio.write_image(fig, 'images/1d-line.svg')<jupyter_output><empty_output><jupyter_text>![1d](images/1d-line.svg?1) This is the graph $f(x_n)$ for $x_N \in [-4,3]$.  Time series dataThe process for time series data is the same, except we use a pandas datetime index for the input argument.<jupyter_code>import pandas as pd
t_N = pd.date_range('Nov 9, 2018', 'Nov 20, 2018', freq = 'H')
@kamodofy(units = 'kg/m**3')
def rho_N(t_N = t_N):
    dt_days = (t_N - t_N[0]).total_seconds()/(24*3600)
    return 1+np.sin(dt_days) + .1*np.random.random(len(dt_days))

kamodo = Kamodo(rho_N = rho_N, verbose = False)
kamodo
fig = kamodo.plot('rho_N')<jupyter_output><empty_output><jupyter_text>In this case, we only need to name the variable we wish to plot, because we have already defined a function $rho_N(t_N)$ with a default parameter for $t_N$.<jupyter_code># pio.write_image(fig, 'images/1d-time-series.svg')<jupyter_output><empty_output><jupyter_text>![timeseries](images/1d-time-series.svg) !!! note    By providing default parameters, the function author can insure that anyone plotting the variable will not need to know where to place resolution!  2-D Parametric chartsFor 2-D Plots, the output function must have input shape $(N,1)$ and output shape $(N,2)$.<jupyter_code>from kamodo import Kamodo
@kamodofy(units = 'cm')
def x_Ncomma2(theta_N = np.linspace(0,6*np.pi, 200)):
    r = theta_N
    x = r*np.cos(theta_N)
    y = r*np.sin(theta_N)
    return np.array(list(zip(x,y)))

kamodo = Kamodo(x_Ncomma2 = x_Ncomma2)
kamodo<jupyter_output><empty_output><jupyter_text>Here, we again provide a default array for $\theta_N$ so the end user does not need to:<jupyter_code>fig = kamodo.plot('x_Ncomma2')
# pio.write_image(fig, 'images/fig-2d.svg')<jupyter_output><empty_output><jupyter_text>![param2d](images/fig-2d.svg)  3-Dimensional parametric curves For 3-D parametric curves, the output function must have input shape $(N,1)$ and output shape $(N,3)$.<jupyter_code>@kamodofy(units = 'km')
def x_Ncomma3(t_N = pd.date_range('Nov 12, 2018', 'Dec 30, 2018', freq = '4 H')):
    dt_days = (t_N - t_N[0]).total_seconds()/(24*3600)
    theta = dt_days*np.pi/5
    r = theta
    x = r*np.cos(theta)
    y = r*np.sin(theta)
    z = r
    return np.array(list(zip(x,y,z)))

kamodo = Kamodo(x_Ncomma3 = x_Ncomma3)
kamodo
fig = kamodo.plot('x_Ncomma3')
# pio.write_image(fig, 'images/3d-line.svg')<jupyter_output><empty_output><jupyter_text>![3d-line](images/3d-line.svg) Functions of three N-d arrays are also interpreted as 3D parametric plots, but with an additonal color component.<jupyter_code>s = np.linspace(0, 8*np.pi, 100)
x = 10*np.sin(s/8)
y = 10*np.sin(s)
z = s

@kamodofy(units = 'kg')
def f_N(x_N = x, y_N = y, z_N = z):
    return x_N**2+y_N**2+z_N**2

kamodo = Kamodo(f_N = f_N)
kamodo
fig = kamodo.plot('f_N')
# pio.write_image(fig, 'images/3d-points.svg')<jupyter_output><empty_output><jupyter_text>![3d-points](images/3d-points.svg)  Vector fieldsKamodo generates a 2-d vector (quiver) plot for functions of one variable, if both the input and output have shape (N,2). The input positions are assumed to be $x$,$y$ and the output vectors are assumed to be $v_x$, $v_y$<jupyter_code>theta_N = np.linspace(0,6*np.pi, 200)
r = theta_N
x = r*np.cos(theta_N)
y = r*np.sin(theta_N)
points = np.array(list(zip(x,y)))

@kamodofy(units = 'cm')
def fvec_Ncomma2(rvec_Ncomma2 = points):
    return rvec_Ncomma2

kamodo = Kamodo(fvec_Ncomma2 = fvec_Ncomma2)
kamodo
fig = kamodo.plot('fvec_Ncomma2')
# pio.write_image(fig, 'images/fig2d-vector.svg')<jupyter_output><empty_output><jupyter_text>![fig2dvec](images/fig2d-vector.svg) If we wish to represent a grid of vectors, we must first unravel the grid as a string of points.<jupyter_code>x = np.linspace(-np.pi, np.pi, 25)
y = np.linspace(-np.pi, np.pi, 30)
xx, yy = np.meshgrid(x,y)
points = np.array(list(zip(xx.ravel(), yy.ravel())))

def fvec_Ncomma2(rvec_Ncomma2 = points):
    ux = np.sin(rvec_Ncomma2[:,0])
    uy = np.cos(rvec_Ncomma2[:,1])
    return np.vstack((ux,uy)).T
    
kamodo = Kamodo(fvec_Ncomma2 = fvec_Ncomma2)
kamodo
fig = kamodo.plot('fvec_Ncomma2')
# pio.write_image(fig, 'images/fig2d-vector-field.svg')<jupyter_output><empty_output><jupyter_text>![fig2dvec](images/fig2d-vector-field.svg)  3D vector fieldsFunctions representing 3D vector fields should have one argument of shape (N,3) and an output shape of (N,3)<jupyter_code>x, y, z = np.meshgrid(np.linspace(-2,2,4),
                      np.linspace(-3,3,6),
                      np.linspace(-5,5,10))
points = np.array(list(zip(x.ravel(), y.ravel(), z.ravel())))
def fvec_Ncomma3(rvec_Ncomma3 = points):
    return rvec_Ncomma3

kamodo = Kamodo(fvec_Ncomma3 = fvec_Ncomma3)
kamodo
fig = kamodo.plot('fvec_Ncomma3')
# pio.write_image(fig, 'images/fig3d-vector.svg')<jupyter_output><empty_output><jupyter_text>![fig3dvec](images/fig3d-vector.svg)  Contour plotsScalar functions of two variables of size (N) and (M) and output size (N,M) will generate contour plots. Kamodo can handle both ```ij``` indexing and ```xy``` indexing.<jupyter_code>from kamodo import Kamodo
@kamodofy(units = 'cm^2')
def f_NcommaM(x_N = np.linspace(0, 8*np.pi,100), y_M = np.linspace(0, 5, 90)):
    x, y = np.meshgrid(x_N, y_M, indexing = 'xy')
    return np.sin(x)*y

kamodo = Kamodo(f_NcommaM = f_NcommaM)
kamodo
fig = kamodo.plot('f_NcommaM')
# pio.write_image(fig, 'images/fig2d-contour.svg')<jupyter_output><empty_output><jupyter_text>![contour](images/fig2d-contour.svg) Since $x_N$ and $y_M$ have differnt sizes, we could have used ```indexing=ij``` as an argument to meshgrid and kamodo would have produced the same figure - Kamodo swaps the ordering where appropriate. In the event that *both* arguments have the same size, we can pass an ```indexing``` argument as an option to the plot function.<jupyter_code>@kamodofy(units = 'cm**2')
def f_NN(x_N = np.linspace(0, 8*np.pi, 90), y_N = np.linspace(0, 5, 90)):
    x, y = np.meshgrid(x_N, y_N, indexing = 'xy')
    return np.sin(x)*y

kamodo = Kamodo(f_NN = f_NN)
kamodo
fig = kamodo.plot(f_NN = dict(indexing = 'xy'))
# pio.write_image(fig, 'images/fig2d-contour-xy.svg')<jupyter_output><empty_output><jupyter_text>![fig2dcontourxy](images/fig2d-contour-xy.svg)  Skew (Carpet) PlotsFunctions of two arguments each having shape (N,M) matching the output shape will produce skewed contour plots, whereby the x and y components of the grid are independent.<jupyter_code>r = np.linspace(1, 3, 20)
theta = np.linspace(0, np.pi, 14)
r_, theta_ = np.meshgrid(r,theta)
XX = r_*np.cos(theta_)
YY = r_*np.sin(theta_)

@kamodofy(units = 'cm**2')
def f_NM(x_NM = XX, y_NM = YY):
    return np.sin(x_NM)+y_NM

kamodo = Kamodo(f_NM = f_NM)
kamodo
fig = kamodo.plot('f_NM')
# pio.write_image(fig, 'images/fig2d-skew.svg')<jupyter_output><empty_output><jupyter_text>![fig2dskew](images/fig2d-skew.svg)  Parametric surfaces To generate a purely geometrical parametric surface, supply a functions of three variables, each of size (N,M) and of output shape (1).<jupyter_code>from kamodo import Kamodo
u = np.linspace(-2, 2, 40)
v = np.linspace(-2, 2, 50)
uu, vv = np.meshgrid(u,v)

@kamodofy(units = 'cm')
def parametric(x_NM = uu*np.sin(vv*np.pi), 
               y_NM = vv, 
               z_NM = np.exp(-uu**2-vv**2)):
    return np.array([1])
kamodo = Kamodo(p = parametric)
kamodo
fig = kamodo.plot('p')
# pio.write_image(fig, 'images/3d-parametric.svg')<jupyter_output><empty_output><jupyter_text>![3dparametric](images/3d-parametric.svg) To control the color of the parametric surface, have the output shape be (N,M).<jupyter_code>R = 1
theta = np.linspace(.2*np.pi, .8*np.pi, 40)
phi = np.linspace(0, 2*np.pi, 50)
theta_, phi_ = np.meshgrid(theta, phi)
r = (R +.1*(np.cos(10*theta_)*np.sin(14*phi_)))

xx = r*np.sin(theta_)*np.cos(phi_)
yy = r*np.sin(theta_)*np.sin(phi_)
zz = r*np.cos(theta_)

@kamodofy(units = 'cm')
def spherelike(x_NM = xx, y_NM = yy, z_NM = zz):
    return .1*x_NM + x_NM**2 + y_NM**2 + z_NM**2

kamodo = Kamodo(h_NM = spherelike)
kamodo
fig = kamodo.plot('h_NM')
# pio.write_image(fig, 'images/3d-parametric-color.svg')<jupyter_output><empty_output><jupyter_text>![parametric3dcolor](images/3d-parametric-color.svg)  Map-to-planeWe often need to produce slices through a volumetric grid of data. This may be accomplished through the use of volumetric grid interpolators equipped with default values for each of the input arguments. Suppose such a function has default input arguments of size (L), (M), (N), and output shape (L,M,N), then a cartesian plane will be generated if the user overrides one of these defaults (e.g. setting $L = 1$).<jupyter_code>@kamodofy(units = 'g/cm**3')
def f_LMN(
      x_L = np.linspace(-5, 5, 50), 
      y_M = np.linspace(0, 10, 75), 
      z_N = np.linspace(-20, 20, 100)):
    xx, yy, zz = np.meshgrid(x_L,y_M,z_N, indexing = 'xy')
    return xx + yy + zz

kamodo = Kamodo(f_LMN = f_LMN)
kamodo
fig = kamodo.plot(f_LMN = dict(z_N = -5))
# pio.write_image(fig,'images/fig2d-map-to-plane.svg')<jupyter_output><empty_output><jupyter_text>![maptoplane](images/fig2d-map-to-plane.svg) !!!tip    By providing appropriate defaults for the undelying grid structure, the interpolator author can ensure that the user can generate figures with optimal resolution!  Multiple traces Kamodo supports multiple traces in the same figure. Simply provide ```plot``` with multiple function-argument pairs.<jupyter_code>from kamodo import Kamodo
t_N = pd.date_range('Nov 9, 2018', 'Nov 20, 2018', freq = 'H')

@kamodofy(units = 'kg/m**3')
def rho_N(t_N = t_N):
    dt_days = (t_N - t_N[0]).total_seconds()/(24*3600)
    return 1+np.sin(dt_days) + .1*np.random.random(len(dt_days))

@kamodofy(units = 'nPa')
def p_N(t_N = t_N):
    dt_days = (t_N - t_N[0]).total_seconds()/(24*3600)
    return 1+np.sin(2*dt_days) + .1*np.random.random(len(dt_days))


kamodo = Kamodo(rho_N = rho_N, p_N = p_N, verbose = False)
kamodo
fig = kamodo.plot('p_N','rho_N')
# pio.write_image(fig, 'images/multi-trace.svg')<jupyter_output><empty_output><jupyter_text>![multitrace](images/multi-trace.svg) !!! note    Plot types must be compatible for kamodo to plot different variables on the same axes. Kamodo can also handle multiple traces in 3D<jupyter_code>from kamodo import Kamodo, kamodofy

@kamodofy(units = 'g/cm**3')
def f_LMN(
      x_L = np.linspace(-5, 5, 50), 
      y_M = np.linspace(0, 10, 75), 
      z_N = np.linspace(-20, 20, 100)):
    xx, yy, zz = np.meshgrid(x_L,y_M,z_N, indexing = 'xy')
    return xx + yy + zz

kamodo = Kamodo(f_LMN = f_LMN, g_LMN = f_LMN)
kamodo
fig = kamodo.plot(f_LMN = dict(z_N = 0), 
                  g_LMN = dict(y_M = 5))
# pio.write_image(fig, 'images/multi-trace3d.svg')<jupyter_output><empty_output><jupyter_text>![multi3d](images/multi-trace3d.svg?1) !!! bug    Multiple traces results in different colorbars which may overlap. More control over the layout will be available in future updates.   Interactive Plotting For interactive 3d plots, we take advantage of Plotly's in-browser plotting library.<jupyter_code>from plotly.offline import iplot, plot, init_notebook_mode<jupyter_output><empty_output><jupyter_text>To generate a separate interactive html page, use `iplot` instead of `plot`:<jupyter_code># plot(fig, filename = 'sample_plot.html') #uncomment to render 3D interactive plot in this cell<jupyter_output><empty_output><jupyter_text>navigate to the 3d interactive plot: [sample_plot.html](sample_plot.html). Alternatively, you may work with interactive plots directly in jupyter notebooks:<jupyter_code># init_notebook_mode() # uncomment to initialize plotly for notebook
# iplot(fig) #uncomment to render 3D interactive plot in this cell<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12849836624520528, 'fraction_numerical': 0.02173604205142776, 'mean_word_length': 5.07639188605956, 'pattern_counts': {'":': 0, '<': 93, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '23', 'dir': 'jupyter-structured-clean-dedup', 'id': '82927', 'license': 'NASA-1.3', 'n_tokens_mistral': 5458, 'n_tokens_neox': 5272, 'n_words': 1439, 'path': 'docs/notebooks/Visualization.ipynb', 'repo_name': 'EnsembleGovServices/Kamodo-ccmc-readers', 'size': '14078'}