Loading Vlasiator Data Into VDFpy

import requests
import os.path

file = "parallel_shock_1d_t100s.vlsv"

if not os.path.isfile(file):
    url = f"https://raw.githubusercontent.com/henry2004y/vlsv_data/master/{file}"
    testfiles = url.rsplit("/", 1)[1]
    r = requests.get(url, allow_redirects=True)
    open(testfiles, "wb").write(r.content)

Vlasiator works in the phase space directly, therefore, there is no concept of particles. Here we are collecting the moments computed from integrals of the phase space and performing the clustering.

import vdfpy

from pyvlasiator.vlsv import Vlsv
import pyvlasiator.plot

import matplotlib.pyplot as plt
import numpy as np


ds = Vlsv(file)
df = vdfpy.collect_moments(file)

method = "GMM"
labels = vdfpy.cluster(df, n_clusters=4, method=method)
labels = labels[::20]

xrange = np.linspace(ds.coordmin[0]+1, ds.coordmax[0]-1, labels.size)
ylocs = np.zeros(labels.size)

fig, ax = plt.subplots(figsize=(10, 2), layout="constrained")

for g in np.unique(labels):
    ix = np.where(labels == g)
    ax.scatter(xrange[ix], ylocs[ix], label=g, s=30)

ax.get_yaxis().set_visible(False)
ax.legend(loc="upper center", fancybox=True, shadow=True, ncol=4, fontsize=16)
ax.set_title("1D Shock, 4-class GMM", fontsize=14)

plt.show()
# clusters: 4; # samples: 5200; # features: 3
_images/9bf4b434810229481c2c5ab422ea849f3d577bbc5b448dcb64eab30713698004.png
import matplotlib as mpl
from cycler import cycler
custom_cycler = (cycler(color=["tab:purple","tab:cyan","tab:olive","tomato"]))

# Create a figure with two subfigures
fig = plt.figure(figsize=(12, 7), layout="constrained")
subfigs = fig.subfigures(2, 1, wspace=0.02, height_ratios=[1, 1.8])

axsTop = subfigs[0].subplots(2, 1, sharex=True, height_ratios=[1, 3.5])
axsTop[0].set_prop_cycle(custom_cycler)
xrange = np.linspace(ds.coordmin[0]*1e-3+1, ds.coordmax[0]*1e-3-1, labels.size)

for g in np.unique(labels):
    ix = np.where(labels == g)
    yloc = np.zeros_like(ix)
    axsTop[0].scatter(xrange[ix], yloc, label=g, s=30)

axsTop[0].legend(loc=(0.4, 0.0), fancybox=True, shadow=True, ncol=4, fontsize=8)
axsTop[0].set_title("1D Shock, 4-class GMM", fontsize=14)
axsTop[0].axis("off")

x = np.linspace(ds.coordmin[0] * 1e-3, ds.coordmax[0] * 1e-3, ds.ncells[0])
w = ds.read_variable("proton/vg_rho") * 1e-6
axsTop[1].plot(x, w)
axsTop[1].set_xlabel("x [km]", fontsize=14)
axsTop[1].set_ylabel(r"$n_p$ [/cc]", fontsize=14)

nVDF = 5
vdfrange = [[-2000, 2000], [-2000, 2000]]
xrange = np.linspace(ds.coordmin[0]+1, ds.coordmax[0]-1, nVDF)
cmap = mpl.colormaps["turbo"] # pyvlasiator 0.1.4

axsBot = subfigs[1].subplots(2, nVDF, sharex=True, sharey=True)
for i in range(nVDF):
    ax1 = axsBot[0,i]
    ax2 = axsBot[1,i]
    loc = (xrange[i], 0, 0)
    ds.vdfslice(loc, ax=ax1, range=vdfrange, addcolorbar=False, cmap=cmap)
    ds.vdfslice(loc, ax=ax2, range=vdfrange, addcolorbar=False, slicetype="xy", cmap=cmap)

    cidReq = ds.getcell(loc)
    cidNearest = ds.getnearestcellwithvdf(cidReq)
    l = ds.getcellcoordinates(cidNearest) * 1e-3
    ax1.set_xlim(vdfrange[0])
    ax1.set_ylim(vdfrange[1])
    ax2.set_xlim(vdfrange[0])
    ax2.set_ylim(vdfrange[1])
    ax1.set_title(f"x={l[0]:.1e} km")
    ax2.set_title("")
    axsTop[1].axvline(l[0], color="k", linestyle="--")

plt.show()
_images/ca329104ab82f323f5d66f8db9e674cb697a9171b9bb759cda3bc7c6108d107d.png