Note: This page was generated from a Jupyter notebook which can be found at docs/tutorial_notebooks/7_orbital_distributions.ipynb in your DYNAMITE directory. —-

7. Orbit Distributions

In this notebook we’ll take a closer look at orbit distributions. To run this notebook, you will already need to have created some models for the example galaxy NGC6278. To do this, first run the notebook 2_quickstart and/or 3_model_iterations_and_plots.

[1]:
import dynamite as dyn

import numpy as np
import matplotlib.pyplot as plt

print('DYNAMITE version', dyn.__version__)
#print('    installed at ', dyn.__path__)  # Uncomment to print the complete DYNAMITE installation path

fname = 'NGC6278_config.yaml'
c = dyn.config_reader.Configuration(fname, reset_logging=True)
[INFO] 11:01:59 - dynamite.config_reader.Configuration - Config file NGC6278_config.yaml read.
[INFO] 11:01:59 - dynamite.config_reader.Configuration - io_settings...
[INFO] 11:01:59 - dynamite.config_reader.Configuration - Output directory tree: NGC6278_output/.
[INFO] 11:01:59 - dynamite.config_reader.Configuration - system_attributes...
[INFO] 11:01:59 - dynamite.config_reader.Configuration - model_components...
[INFO] 11:01:59 - dynamite.config_reader.Configuration - system_parameters...
[INFO] 11:01:59 - dynamite.config_reader.Configuration - orblib_settings...
[INFO] 11:01:59 - dynamite.config_reader.Configuration - weight_solver_settings...
[INFO] 11:01:59 - dynamite.config_reader.Configuration - Will attempt to recover partially run models.
[INFO] 11:01:59 - dynamite.config_reader.Configuration - parameter_space_settings...
[INFO] 11:01:59 - dynamite.config_reader.Configuration - multiprocessing_settings...
[INFO] 11:01:59 - dynamite.config_reader.Configuration - ... using 4 CPUs for orbit integration.
[INFO] 11:01:59 - dynamite.config_reader.Configuration - ... using 4 CPUs for weight solving.
[INFO] 11:01:59 - dynamite.config_reader.Configuration - legacy_settings...
[INFO] 11:01:59 - dynamite.config_reader.Configuration - System assembled
[INFO] 11:01:59 - dynamite.config_reader.Settings - No value given for orblib setting quad_nr - set to its default 10.
[INFO] 11:01:59 - dynamite.config_reader.Settings - No value given for orblib setting quad_nth - set to its default 6.
[INFO] 11:01:59 - dynamite.config_reader.Settings - No value given for orblib setting quad_nph - set to its default 6.
[INFO] 11:01:59 - dynamite.config_reader.Configuration - Configuration validated
[INFO] 11:01:59 - dynamite.config_reader.Configuration - Instantiated parameter space
[INFO] 11:01:59 - dynamite.model.AllModels - Previous models have been found: Reading NGC6278_output/all_models.ecsv into AllModels.table
[INFO] 11:01:59 - dynamite.config_reader.Configuration - Instantiated AllModels object
[INFO] 11:01:59 - dynamite.model.AllModels - No all_models table update required.
DYNAMITE version 4.3.0

1. Get the dynamite Model object

First let’s pick a model whose orbit distribution we want to construct. Let’s look at a list of all models:

[2]:
c.all_models.table
[2]:
Table length=5
m-bha-bhc-dhf-dhq-starsp-starsu-starsmlchi2kinchi2kinmapchi2time_modifiedorblib_doneweights_doneall_donewhich_iterdirectory
float64float64float64float64float64float64float64float64float64float64float64str256boolboolboolint64str256
100000.00.0018.010.00.540.990.99995.033649.3908688462315917.0668608276921307.674259422582024-12-13T08:56:22.000TrueTrueTrue0orblib_000_000/ml05.00/
100000.00.0018.03.16227766016837950.540.990.99995.030991.11762762292317598.73085193283622813.539219131662024-12-13T08:56:21.000TrueTrueTrue1orblib_001_000/ml05.00/
100000.00.0018.031.6227766016837930.540.990.99995.040173.1757447688716959.4279065864422195.9159799470652024-12-13T08:56:22.000TrueTrueTrue1orblib_001_001/ml05.00/
100000.00.0018.010.00.540.990.99991.0497022.2219649834362170.4757700884189079.408046342842024-12-13T08:56:31.000TrueTrueTrue1orblib_000_000/ml01.00/
100000.00.0018.010.00.540.990.99999.054888.8600240343136551.1847769270175313.140503205872024-12-13T08:56:31.000TrueTrueTrue1orblib_000_000/ml09.00/

Find the row index of the best model,

[3]:
best_model_idx = c.all_models.get_best_n_models_idx(1)[0]
print(f'Index of best model: {best_model_idx}')
Index of best model: 0

and then get a dynamite Model object corresponding to that row:

[4]:
mod = c.all_models.get_model_from_row(best_model_idx)
mod
[4]:
<dynamite.model.Model at 0x1116f4e10>

Let’s then load the orbit library and (already solved for) orbit weights for this model

[5]:
orblib = mod.get_orblib()

weight_solver = mod.get_weights(orblib)
weights = mod.weights
[INFO] 11:02:00 - dynamite.weight_solvers.NNLS - Using WeightSolver: NNLS/scipy
[INFO] 11:02:02 - dynamite.weight_solvers.NNLS - NNLS solution read from existing output

3. Orbit distribution plots

Let’s run the plotting routine to make the orbit distribution plot:

[6]:
plotter = dyn.plotter.Plotter(c)

# define settings
minr, maxr = 0.1, 10. # radius limits in kpc (to be binned in log r)
nr, nl = 6, 7 # use 6 bins in radius, 7 bins in circularity lambda

fig = plotter.orbit_distribution(mod, nr=nr, nl=nl, minr=minr, maxr=maxr)
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification:
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary -     - 26.9% box
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary -     - 9.7% x-tubes
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary -     - 3.9% y-tubes
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary -     - 59.4% z-tubes
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% other types
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary - Amongst tubes, % with only one nonzero component of L:
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary -     - 22.9% of x-tubes
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary -     - 35.7% of y-tubes
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary -     - 72.0% of z-tubes
[INFO] 11:02:02 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification DONE.
[INFO] 11:02:03 - dynamite.weight_solvers.NNLS - Using WeightSolver: NNLS/scipy
[INFO] 11:02:06 - dynamite.weight_solvers.NNLS - NNLS solution read from existing output
[INFO] 11:02:07 - dynamite.plotter.Plotter - Plotting orbit distribution for orbit classes all: 4 subplot(s).
[INFO] 11:02:07 - dynamite.plotter.Plotter - fig_size=15.0.
[INFO] 11:02:07 - dynamite.plotter.Plotter - Plot NGC6278_output/plots/orbit_distribution.png saved in NGC6278_output/plots/
../_images/tutorial_notebooks_7_orbital_distributions_12_1.png

This plot shows the orbit-distributions split into four panels corresponding to four orbit-types. Each distribution shows a density in log radius (y-axis) against a circularity parameter \(\lambda\) (x-axis). Which component of the circularity is shown depends on the orbit type: - long-axis tube: \(\lambda_x\) - intermediate-axis tube: \(\lambda_y\) - short-axis tube: \(\lambda_z\) - box: \(\lambda_\mathrm{tot}\), using the total angular momentum (which should be zero for box orbits).

The main difference between this orbit-distribution plot and previous ones, which showed all orbit types in \((r,\lambda_z)\) space, is that by splitting by orbit-type we can distinguish long-axis tubes from box orbits. Restricting to \((r,\lambda_z)\) space overlays these two orbit-types since they both have \(\lambda_z=0\). Intermediate-axis orbits are unstable, and therefore should form a negligible contribution; they are left in this plot mainly as a diagnostic for the orbit classification, more details of which are given below.

Finally, note that if you want to limit which orbit types are shown, you can use the subsetkeyword argument of plotter.orbit_distribution along with many other options to change its behaivour.

3. Recreating orbit distributions using orblib.projection_tensor

To make the orbit distribution plot, when we call plotter.orbit_distribution, a method called orblib.get_projection_tensor is run internally. Let’s run this ourselves in order to get access to the orblib.projection_tensor object which we can use to recreate the orbit distributions shown in the plots above:

[7]:
orblib.get_projection_tensor(nr=nr, nl=nl, minr=minr, maxr=maxr)  # use same settings as before
orblib.projection_tensor
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification:
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 26.9% box
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 9.7% x-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 3.9% y-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 59.4% z-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% other types
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary - Amongst tubes, % with only one nonzero component of L:
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 22.9% of x-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 35.7% of y-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 72.0% of z-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification DONE.
[7]:
Formatcoo
Data Typefloat64
Shape(4, 6, 7, 360)
nnz279
Density0.004613095238095238
Read-onlyTrue
Size10.9K
Storage ratio0.02

The orblib.projection_tensor is stored as a sparse object array to speed up some calculations. For simplicity, let’s convert it to a regular numpy array using the todense() method:

[8]:
projection_tensor = orblib.projection_tensor.todense()
projection_tensor.shape
[8]:
(4, 6, 7, 360)

The projection_tensor has dimension 4 and shape (4, 6, 7, 360). These 4 dimensions correspond to:

  • 4: orbit-types \(t\) (long-axis tube, intermediate-axis tube, short-axis tube, box)

  • 6: bins in radius \(r\)

  • 7: bins in circularity (aka lambda) \(l\)

  • 360: orbit bundles \(b\)

We’ll refer to this tensor as \(P_{trlb}\) where \((t,r,l,b)\) index over these four dimensions. \(P_{trlb}\) is defined as the fraction of orbit bundle \(b\) that is of orbit-type \(t\) and that resides in radius bin \(r\) and lambda bin \(l\).

To demonstrate how we might use this object, say we want to know the fraction of different orbit-types per orbit-bundle. To do this, we can sum over all radius and lambda bins,

[9]:
orbit_fractions = np.sum(projection_tensor, (1,2))
orbit_fractions.shape
[9]:
(4, 360)

then plot the resulting fractions:

[10]:
fig, ax = plt.subplots(1, 4, figsize=(9,3), sharey=True)
titles = ['long-axis tube', 'int-axis tube', 'short-axis tube', 'box']
for i, (ax0, tit0) in enumerate(zip(ax, titles)):
    ax0.plot(orbit_fractions[i], '.')
    ax0.set_title(tit0)
    ax0.set_xlabel('Orbit Bundle Index')
ax[0].set_ylabel('Fraction')
fig.tight_layout()
../_images/tutorial_notebooks_7_orbital_distributions_20_0.png

In this test example (with dithering=1) each bundle is entirely made up of one orbit type i.e. all orbit fractions are 0 or 1. For dithering>1, note that this isn’t the case: you can have orbit-bundles with mixtures of different types of orbits within them.

To get the orbit distributions in (radius, lambda) space, we take the dot product of the projection tensor with the orbit weights,

[11]:
orbit_distributions = orblib.projection_tensor.dot(weights)
orbit_distributions.shape # (orbit types, radius bins, lambda bins)
[11]:
(4, 6, 7)

We could then re-create the short-axis distribution plot as follows:

[12]:
plt.imshow(
    orbit_distributions[2], # use index 2 for short axis tubes
    origin='lower',
    extent=(-1, 1, np.log10(minr), np.log10(maxr)),
    aspect='auto'
    )
plt.gca().set_xlabel('Circularity $\lambda_z$')
plt.gca().set_ylabel('log (radius / kpc)')
plt.gca().set_title('Short-axis tube distribution')
[12]:
Text(0.5, 1.0, 'Short-axis tube distribution')
../_images/tutorial_notebooks_7_orbital_distributions_24_1.png

4. Orbit classification

To do the orbit classification, orblib.get_projection_tensor internally runs the method orblib.classify_orbits. To see what this does let’s run this ourselves, now with the make_diagnostic_plots option set,

[13]:
orblib.classify_orbits(make_diagnostic_plots=True)
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification:
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 26.9% box
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 9.7% x-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 3.9% y-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 59.4% z-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% other types
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary - Amongst tubes, % with only one nonzero component of L:
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 22.9% of x-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 35.7% of y-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary -     - 72.0% of z-tubes
[INFO] 11:02:08 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification DONE.
../_images/tutorial_notebooks_7_orbital_distributions_26_1.png

This shows the distribution of angular momenta of the orbits in the orbit library. This is shown for the three components of angular momentum \((L_x, L_y, L_z)\) represented by the three coloured histrograms. The dotted vertical lines show a threshold angular momentum \(dL\) which is used for orbit classification. By default, this is set to a (somewhat arbitrary!) choice of \(dL= 10^{17}\).

Given this choice of \(dL\), the classification is done as follows: - if \(L_x < dL\), \(L_y < dL\) and \(L_z < dL\), then it’s a box orbit - otherwise, it’s a tube orbit, with the largest component of \(L\) determining the axis (e.g. if \(L_z\) is largest then it’s a short-axis tube orbit)

In theory, for tube-orbits we expect one and only one component of the time-averaged angular momentum to be non-zero. The output which is printed when we ran orblib.classify_orbits tells us what fraction of tube-orbits this is actually true for, when \(dL\) is used as a threshold for “non-zero”. Copying the relevant lines here:

[INFO] 23:46:28 - dynamite.orblib.LegacyOrbitLibrary - Amongst tubes, % with only one nonzero component of L:
[INFO] 23:46:28 - dynamite.orblib.LegacyOrbitLibrary -     - 22.9% of x-tubes
[INFO] 23:46:28 - dynamite.orblib.LegacyOrbitLibrary -     - 35.7% of y-tubes
[INFO] 23:46:28 - dynamite.orblib.LegacyOrbitLibrary -     - 72.0% of z-tubes

e.g. this says that only 72% of orbits we have classified as short-axis tubes have both \(L_x<dL\) and \(L_y\) below \(dL\).

You may need to play around with the threshold \(dL\) for your particular situation. This can be done by passing the optional dL keyword to any of: - plotter.orbit_distribution - orblib.get_projection_tensor - orblib.classify_orbits e.g. if we increase it from the default value of \(10^{17}\) to \(3\times10^{17}\), then the orbit distrubution changes as follows,

[14]:
fig = plotter.orbit_distribution(mod, nr=nr, nl=nl, minr=minr, dL=3e17)
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification:
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary -     - 35.0% box
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary -     - 8.3% x-tubes
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary -     - 2.2% y-tubes
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary -     - 54.4% z-tubes
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% other types
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary - Amongst tubes, % with only one nonzero component of L:
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary -     - 53.3% of x-tubes
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% of y-tubes
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary -     - 83.7% of z-tubes
[INFO] 11:02:09 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification DONE.
[INFO] 11:02:09 - dynamite.weight_solvers.NNLS - Using WeightSolver: NNLS/scipy
[INFO] 11:02:11 - dynamite.weight_solvers.NNLS - NNLS solution read from existing output
[INFO] 11:02:11 - dynamite.plotter.Plotter - Plotting orbit distribution for orbit classes all: 4 subplot(s).
[INFO] 11:02:11 - dynamite.plotter.Plotter - fig_size=15.0.
[INFO] 11:02:12 - dynamite.plotter.Plotter - Plot NGC6278_output/plots/orbit_distribution.png saved in NGC6278_output/plots/
../_images/tutorial_notebooks_7_orbital_distributions_28_1.png

and we see that the box orbit fraction has increased from 9.5% earlier to 10.3% now.

5. Viewing the “combined” orbit-distribution in \((r, \lambda_z)\) space

We also have the option to see the “combined” orbit-distribution, where all orbits are shown in \((r, \lambda_z)\) space regardless of their classification, by setting the force_lambda_z option to True:

[15]:
fig = plotter.orbit_distribution(mod, nr=nr, nl=nl, minr=minr, force_lambda_z=True)
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification:
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% box
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% x-tubes
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% y-tubes
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary -     - 100.0% z-tubes
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% other types
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary - Amongst tubes, % with only one nonzero component of L:
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% of x-tubes
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% of y-tubes
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary -     - 42.8% of z-tubes
[INFO] 11:02:12 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification DONE.
[INFO] 11:02:12 - dynamite.weight_solvers.NNLS - Using WeightSolver: NNLS/scipy
[INFO] 11:02:15 - dynamite.weight_solvers.NNLS - NNLS solution read from existing output
[INFO] 11:02:15 - dynamite.plotter.Plotter - Plotting orbit distribution for orbit classes all: 4 subplot(s).
[INFO] 11:02:15 - dynamite.plotter.Plotter - fig_size=15.0.
[INFO] 11:02:15 - dynamite.plotter.Plotter - Plot NGC6278_output/plots/orbit_distribution.png saved in NGC6278_output/plots/
../_images/tutorial_notebooks_7_orbital_distributions_30_1.png

Now all orbits are treated as short-axis tube orbits and shown in the third panel, with \(\lambda_z\) on the x-axis. If we wanted to show only this third panel, in the more familiar orientation where circularity is on the y-axis, we can do so as follows:

[16]:
fig = plotter.orbit_distribution(
    mod, nr=nr, nl=nl, minr=minr,
    force_lambda_z=True, subset='short', orientation='vertical'
    )
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification:
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% box
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% x-tubes
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% y-tubes
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary -     - 100.0% z-tubes
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% other types
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary - Amongst tubes, % with only one nonzero component of L:
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% of x-tubes
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% of y-tubes
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary -     - 42.8% of z-tubes
[INFO] 11:02:16 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification DONE.
[INFO] 11:02:16 - dynamite.weight_solvers.NNLS - Using WeightSolver: NNLS/scipy
[INFO] 11:02:19 - dynamite.weight_solvers.NNLS - NNLS solution read from existing output
[INFO] 11:02:19 - dynamite.plotter.Plotter - Plotting orbit distribution for orbit classes short: 1 subplot(s).
[INFO] 11:02:19 - dynamite.plotter.Plotter - fig_size=3.75.
[INFO] 11:02:19 - dynamite.plotter.Plotter - Plot NGC6278_output/plots/orbit_distribution.png saved in NGC6278_output/plots/
../_images/tutorial_notebooks_7_orbital_distributions_32_1.png

Warning: when using force_lambda_z=True, then the titles of the orbit-distribution plots are incorrect. All orbits are shown in this distribution - not only short-axis tubes!

As before, if we wanted to reconstruct this orbit distribution for use in other analysis, then we run get_projection_tensor except now setting the force_lambda_z setting to True. This forces the classification to (incorrectly) identify all orbits as short-axis tubes in the projection_tensor, e.g. if we re-create the orbit-type fraction plot from earlier,

[17]:
orblib.get_projection_tensor(nr=nr, nl=nl, minr=minr, maxr=maxr, force_lambda_z=True)
projection_tensor = orblib.projection_tensor.todense()

orbit_fractions = np.sum(projection_tensor, (1,2))

fig, ax = plt.subplots(1, 4, figsize=(9,3), sharey=True)
titles = ['long-axis tube', 'int-axis tube', 'short-axis tube', 'box']
for i, (ax0, tit0) in enumerate(zip(ax, titles)):
    ax0.plot(orbit_fractions[i], '.')
    ax0.set_title(tit0)
    ax0.set_xlabel('Orbit Bundle Index')
ax[0].set_ylabel('Fraction')
fig.tight_layout()
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification:
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% box
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% x-tubes
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% y-tubes
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary -     - 100.0% z-tubes
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% other types
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary - Amongst tubes, % with only one nonzero component of L:
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% of x-tubes
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary -     - 0.0% of y-tubes
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary -     - 42.8% of z-tubes
[INFO] 11:02:20 - dynamite.orblib.LegacyOrbitLibrary - Orbit library classification DONE.
../_images/tutorial_notebooks_7_orbital_distributions_34_1.png

We see that (almost) all orbits are classified as short-axis tubes. Note that there are some orbits which have orbit fraction = 0 for all four orbit types. This has happened because of our choice of radial range - these orbits do not enter this range. We could include all orbits by decreasing minr and increasing maxr.