In [1]:
import datetime
print(datetime.datetime.now().isoformat())


2016-09-06T17:39:51.146021

Is there a cutoff in Dst that allows slot filling?

Method

Using a statistical model of the relationship between the slot filling at 464keV vs Dst.

We model the number of slot filling events as a random sample from a binomial distribution meaning that there is a probability of the event occuring and there may be a parameter that changes the probability. This is not meant as a correlation but as a success failure creiteria.

From Wikipedia: In probability theory and statistics, the binomial distribution with parameters n and p is the discrete probability distribution of the number of successes in a sequence of n independent yes/no experiments, each of which yields success with probability p.

$ change \sim Bin(n,p) \\ logit(p) = \alpha + \beta x \\ a \sim N(0,5) \\ \beta \sim N(0,10) $

where we set vague priors for $\alpha$ and $\beta$, the parameters for the logistic model.

This is the same technique used in the estimation of deaths due to a concentration of a chemical.


In [5]:
# http://onlinelibrary.wiley.com/doi/10.1002/2016JA022652/epdf


import pymc3
import tqdm
from pprint import pprint
import numpy as np
import matplotlib.pyplot as plt
import spacepy.plot as spp
import seaborn as sns
sns.set(font_scale=1.5)

Data delivered by Geoff Reeves 9/6/2016


In [6]:
# min_Dst, min_L
data = np.asarray([
65.000, 3.8000,  
50.000, 3.7000,
67.000, 3.5000,
61.000, 3.4000, 
77.000, 3.2000,
99.000, 2.8900,  
87.000, 2.8000,  
98.000, 2.8000, 
96.000, 2.8000,
93.000, 2.3000,
92.000, 2.3000, 
225.00, 2.3000, 
206.00, 2.3000,
125.00, 2.3000]).reshape((-1,2))

dst = data[:,0]
minL = data[:,1]
print(dst, minL, data.dtype)


[ 65.  50.  67.  61.  77.  99.  87.  98.  96.  93.  92. 225. 206. 125.] [3.8  3.7  3.5  3.4  3.2  2.89 2.8  2.8  2.8  2.3  2.3  2.3  2.3  2.3 ] float64

In [39]:
# make bins in Dst
dst_bins = np.arange(25, 300, 10)
print(dst_bins)
dst_bins_centers = np.asarray([dst_bins[:-1] + np.diff(dst_bins)/2]).T[:,0]
print(dst_bins_centers, dst_bins_centers.shape)
n_events_dig = np.digitize(dst, dst_bins)
print(n_events_dig)
n_events = np.zeros(len(dst_bins)-1)
success = np.zeros_like(n_events)
for i, v in enumerate(np.unique(n_events_dig)):
    n_events[v-1] = np.sum(n_events_dig==v)
    success[v-1] = np.sum(minL[n_events_dig==v] <= 2.4)
print(n_events)
print(success)


[ 25  35  45  55  65  75  85  95 105 115 125 135 145 155 165 175 185 195
 205 215 225 235 245 255 265 275 285 295]
[ 30.  40.  50.  60.  70.  80.  90. 100. 110. 120. 130. 140. 150. 160.
 170. 180. 190. 200. 210. 220. 230. 240. 250. 260. 270. 280. 290.] (27,)
[ 5  3  5  4  6  8  7  8  8  7  7 21 19 11]
[0. 0. 1. 1. 2. 1. 3. 3. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0.
 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 2. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0.
 0. 0. 0.]

In [40]:
plt.plot(dst, minL, 'o')
plt.xlim((25, 250))
plt.ylim((2.2, 4.0))
plt.xlabel('Min Dst')
plt.ylabel('Min L Shell')


Out[40]:
Text(0,0.5,'Min L Shell')

In [41]:
plt.plot(dst, minL, 'o')
plt.xlim((25, 250))
plt.ylim((2.2, 4.0))
plt.xlabel('Min Dst')
plt.ylabel('Min L Shell')
for v in dst_bins:
    plt.axvline(v, lw=0.25)
plt.axhline(2.4, c='r', lw=1)


Out[41]:
<matplotlib.lines.Line2D at 0x1227fff28>

Oberved Data:

  • n_pts : the number of points in each of the 10nT wide Dst bins
  • successes : the number of events in each bin where the slot was filled (Min L = 2.3)
  • dst_bins_centers : the centers of the Dst bins

Setup the Bayesian model accorind to the description above. Run the Markov chain monte carlo (MCMC) to sample the posterior distributions for $\alpha$ and $\beta$


In [42]:
ind = n_events > 0

for i, j in zip(success[ind], n_events[ind]):
    print(i,j)


0.0 1.0
0.0 1.0
0.0 2.0
0.0 1.0
2.0 3.0
0.0 3.0
1.0 1.0
1.0 1.0
1.0 1.0

In [69]:
# define priors
# these are wide uninformative priors
# alpha = pymc.Normal('alpha', mu=0, tau=1.0/5**2)
# beta = pymc.Normal('beta', mu=0, tau=1.0/10**2)
with pymc3.Model() as model:
    alpha = pymc3.Uniform('alpha', -100, 100)
    beta = pymc3.Uniform('beta', -100, 100)

    # cannot feed in zero events
    ind = n_events > 0

    # define likelihood
    p = pymc3.math.invlogit(alpha + beta*dst_bins_centers[ind])
    y = pymc3.Binomial('y_obs', n=n_events[ind], p=p, observed=success[ind])
    step = pymc3.Metropolis([alpha, beta])
    trace = pymc3.sample(10000, njobs=5, tune=5000, step=step)


Multiprocess sampling (5 chains in 5 jobs)
CompoundStep
>Metropolis: [beta]
>Metropolis: [alpha]
Sampling 5 chains: 100%|██████████| 75000/75000 [00:14<00:00, 5221.76draws/s]
The estimated number of effective samples is smaller than 200 for some parameters.

Make diagnostic plots of the posteriour distributions as created using MCMC.


In [70]:
pymc3.traceplot(trace, combined=True)


Out[70]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x124888c18>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x123f5ad68>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x124231630>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x123f53390>]],
      dtype=object)

In [71]:
pymc3.summary(trace)


Out[71]:
mean sd mc_error hpd_2.5 hpd_97.5 n_eff Rhat
alpha -12.720232 6.765325 0.534437 -26.486792 -2.241554 91.192343 1.020307
beta 0.123690 0.070100 0.005546 0.015498 0.264355 90.552415 1.020122

In [72]:
xp = np.linspace(dst_bins_centers[ind].min(), dst_bins_centers[ind].max(), 100)
a = trace['alpha'].mean()
b = trace['beta'].mean()
y_val = pymc3.math.invlogit(a + b*xp).eval()
plt.plot(xp, y_val)
plt.scatter(dst_bins_centers[ind], success[ind]/n_events[ind], s=50);
plt.xlabel('Minimum Dst')
plt.ylabel('Probability slot is filled')
plt.gca().ticklabel_format(useOffset=False)


Predictions based on this model


In [73]:
# get the minimum Dst where 99% should be successes
for percentage in [50,75,90,95,99]:
    ind99 = y_val >= percentage/100
    minDst99 = xp[ind99][0]
    print('At a minimum Dst of {0:0.0f}nT it is predicted to have a {1}% percent of a slot filling at this energy'.format(minDst99, percentage))


At a minimum Dst of 105nT it is predicted to have a 50% percent of a slot filling at this energy
At a minimum Dst of 112nT it is predicted to have a 75% percent of a slot filling at this energy
At a minimum Dst of 121nT it is predicted to have a 90% percent of a slot filling at this energy
At a minimum Dst of 128nT it is predicted to have a 95% percent of a slot filling at this energy
At a minimum Dst of 141nT it is predicted to have a 99% percent of a slot filling at this energy

In [ ]:

Plot up many lines for a feel at uncertantity


In [78]:
pymc3.math.invlogit(trace['alpha'][4] + trace['beta'][4]*xp).eval()


Out[78]:
array([1.25716402e-05, 1.93489333e-05, 2.97797142e-05, 4.58333478e-05,
       7.05405559e-05, 1.08565138e-04, 1.67083283e-04, 2.57135424e-04,
       3.95703361e-04, 6.08898818e-04, 9.36851207e-04, 1.44118376e-03,
       2.21640996e-03, 3.40721472e-03, 5.23444368e-03, 8.03368400e-03,
       1.23113565e-02, 1.88235270e-02, 2.86803263e-02, 4.34698934e-02,
       6.53726998e-02, 9.71901546e-02, 1.42138349e-01, 2.03195401e-01,
       2.81862675e-01, 3.76591664e-01, 4.81798125e-01, 5.88643592e-01,
       6.87737158e-01, 7.72197623e-01, 8.39156123e-01, 8.89255924e-01,
       9.25142656e-01, 9.50053425e-01, 9.66970435e-01, 9.78288561e-01,
       9.85785357e-01, 9.90718126e-01, 9.93949630e-01, 9.96060553e-01,
       9.97436892e-01, 9.98333179e-01, 9.98916386e-01, 9.99295678e-01,
       9.99542269e-01, 9.99702551e-01, 9.99806719e-01, 9.99874411e-01,
       9.99918398e-01, 9.99946979e-01, 9.99965550e-01, 9.99977617e-01,
       9.99985457e-01, 9.99990551e-01, 9.99993861e-01, 9.99996011e-01,
       9.99997408e-01, 9.99998316e-01, 9.99998906e-01, 9.99999289e-01,
       9.99999538e-01, 9.99999700e-01, 9.99999805e-01, 9.99999873e-01,
       9.99999918e-01, 9.99999947e-01, 9.99999965e-01, 9.99999977e-01,
       9.99999985e-01, 9.99999990e-01, 9.99999994e-01, 9.99999996e-01,
       9.99999997e-01, 9.99999998e-01, 9.99999999e-01, 9.99999999e-01,
       1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
       1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
       1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
       1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
       1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
       1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00])

In [89]:



Out[89]:
array([-23.14207014, -23.14207014, -23.14207014, ...,  -7.15932027,
        -7.15932027,  -7.15932027])

In [90]:
# one should be able to get estimates of the line uncertainity
ilu = np.empty((1000, len(xp)), dtype=float)
ilu = []
for ii, v in tqdm.tqdm(enumerate(np.random.randint(0, len(trace['alpha']), 100)), total=100):
    if trace['alpha'][v] == 0:
        continue
    if trace['beta'][v] == 0:
        continue
        
    ilu.append(pymc3.math.invlogit(trace['alpha'][v] + trace['beta'][v]*xp).eval())
ilu=np.asarray(ilu)
ilu.shape


  0%|          | 0/100 [00:00<?, ?it/s]INFO (theano.gof.compilelock): Refreshing lock /Users/balarsen/.theano/compiledir_Darwin-15.6.0-x86_64-i386-64bit-i386-3.6.5-64/lock_dir/lock

  1%|          | 1/100 [00:00<00:26,  3.69it/s]
  2%|▏         | 2/100 [00:00<00:26,  3.75it/s]
  3%|▎         | 3/100 [00:00<00:25,  3.75it/s]
  4%|▍         | 4/100 [00:01<00:25,  3.72it/s]
  5%|▌         | 5/100 [00:01<00:25,  3.72it/s]
  6%|▌         | 6/100 [00:01<00:29,  3.15it/s]
  7%|▋         | 7/100 [00:02<00:28,  3.22it/s]
  8%|▊         | 8/100 [00:02<00:28,  3.28it/s]
  9%|▉         | 9/100 [00:02<00:27,  3.31it/s]
 10%|█         | 10/100 [00:02<00:26,  3.35it/s]
 11%|█         | 11/100 [00:03<00:26,  3.38it/s]
 12%|█▏        | 12/100 [00:03<00:25,  3.41it/s]
 13%|█▎        | 13/100 [00:03<00:25,  3.43it/s]
 14%|█▍        | 14/100 [00:04<00:24,  3.45it/s]
 15%|█▌        | 15/100 [00:04<00:26,  3.24it/s]
 16%|█▌        | 16/100 [00:04<00:25,  3.26it/s]
 17%|█▋        | 17/100 [00:05<00:25,  3.28it/s]
 18%|█▊        | 18/100 [00:05<00:24,  3.30it/s]
 19%|█▉        | 19/100 [00:05<00:24,  3.31it/s]
 20%|██        | 20/100 [00:06<00:24,  3.33it/s]
 21%|██        | 21/100 [00:06<00:23,  3.34it/s]
 22%|██▏       | 22/100 [00:06<00:23,  3.35it/s]
 23%|██▎       | 23/100 [00:07<00:23,  3.23it/s]
 24%|██▍       | 24/100 [00:07<00:23,  3.24it/s]
 25%|██▌       | 25/100 [00:07<00:23,  3.25it/s]
 26%|██▌       | 26/100 [00:07<00:22,  3.27it/s]
 27%|██▋       | 27/100 [00:08<00:22,  3.28it/s]
 28%|██▊       | 28/100 [00:08<00:21,  3.29it/s]
 29%|██▉       | 29/100 [00:08<00:21,  3.30it/s]
 30%|███       | 30/100 [00:09<00:21,  3.31it/s]
 31%|███       | 31/100 [00:09<00:21,  3.21it/s]
 32%|███▏      | 32/100 [00:09<00:21,  3.23it/s]
 33%|███▎      | 33/100 [00:10<00:20,  3.24it/s]
 34%|███▍      | 34/100 [00:10<00:20,  3.25it/s]
 35%|███▌      | 35/100 [00:10<00:19,  3.25it/s]
 36%|███▌      | 36/100 [00:11<00:19,  3.26it/s]
 37%|███▋      | 37/100 [00:11<00:19,  3.27it/s]
 38%|███▊      | 38/100 [00:11<00:19,  3.20it/s]
 40%|████      | 40/100 [00:12<00:18,  3.28it/s]
 41%|████      | 41/100 [00:12<00:17,  3.28it/s]
 42%|████▏     | 42/100 [00:12<00:17,  3.29it/s]
 43%|████▎     | 43/100 [00:13<00:17,  3.30it/s]
 44%|████▍     | 44/100 [00:13<00:16,  3.30it/s]
 45%|████▌     | 45/100 [00:13<00:16,  3.30it/s]
 46%|████▌     | 46/100 [00:14<00:16,  3.24it/s]
 47%|████▋     | 47/100 [00:14<00:16,  3.24it/s]
 48%|████▊     | 48/100 [00:14<00:16,  3.25it/s]
 49%|████▉     | 49/100 [00:15<00:15,  3.25it/s]
 50%|█████     | 50/100 [00:15<00:15,  3.26it/s]
 51%|█████     | 51/100 [00:15<00:15,  3.26it/s]
 52%|█████▏    | 52/100 [00:15<00:14,  3.26it/s]
 53%|█████▎    | 53/100 [00:16<00:14,  3.26it/s]
 54%|█████▍    | 54/100 [00:16<00:14,  3.21it/s]
 55%|█████▌    | 55/100 [00:17<00:13,  3.22it/s]
 56%|█████▌    | 56/100 [00:17<00:13,  3.22it/s]
 57%|█████▋    | 57/100 [00:17<00:13,  3.22it/s]
 58%|█████▊    | 58/100 [00:17<00:13,  3.23it/s]
 59%|█████▉    | 59/100 [00:18<00:12,  3.23it/s]
 60%|██████    | 60/100 [00:18<00:12,  3.23it/s]
 61%|██████    | 61/100 [00:19<00:12,  3.18it/s]
 62%|██████▏   | 62/100 [00:19<00:11,  3.18it/s]
 63%|██████▎   | 63/100 [00:19<00:11,  3.19it/s]
 64%|██████▍   | 64/100 [00:20<00:11,  3.19it/s]
 65%|██████▌   | 65/100 [00:20<00:10,  3.19it/s]
 66%|██████▌   | 66/100 [00:20<00:10,  3.19it/s]
 67%|██████▋   | 67/100 [00:20<00:10,  3.20it/s]
 68%|██████▊   | 68/100 [00:21<00:10,  3.16it/s]
 69%|██████▉   | 69/100 [00:21<00:09,  3.16it/s]
 70%|███████   | 70/100 [00:22<00:09,  3.16it/s]
 71%|███████   | 71/100 [00:22<00:09,  3.16it/s]
 72%|███████▏  | 72/100 [00:22<00:08,  3.17it/s]
 73%|███████▎  | 73/100 [00:23<00:08,  3.17it/s]
 74%|███████▍  | 74/100 [00:23<00:08,  3.17it/s]
 76%|███████▌  | 76/100 [00:23<00:07,  3.17it/s]
 77%|███████▋  | 77/100 [00:24<00:07,  3.17it/s]
 78%|███████▊  | 78/100 [00:24<00:06,  3.18it/s]
 79%|███████▉  | 79/100 [00:24<00:06,  3.18it/s]
 80%|████████  | 80/100 [00:25<00:06,  3.18it/s]
 81%|████████  | 81/100 [00:25<00:05,  3.18it/s]
 82%|████████▏ | 82/100 [00:25<00:05,  3.18it/s]
 83%|████████▎ | 83/100 [00:26<00:05,  3.15it/s]
 84%|████████▍ | 84/100 [00:26<00:05,  3.15it/s]
 85%|████████▌ | 85/100 [00:26<00:04,  3.15it/s]
 86%|████████▌ | 86/100 [00:27<00:04,  3.16it/s]
 87%|████████▋ | 87/100 [00:27<00:04,  3.16it/s]
 88%|████████▊ | 88/100 [00:27<00:03,  3.16it/s]
 89%|████████▉ | 89/100 [00:28<00:03,  3.16it/s]
 90%|█████████ | 90/100 [00:28<00:03,  3.13it/s]
 91%|█████████ | 91/100 [00:29<00:02,  3.13it/s]
 92%|█████████▏| 92/100 [00:29<00:02,  3.13it/s]
 93%|█████████▎| 93/100 [00:29<00:02,  3.13it/s]
 94%|█████████▍| 94/100 [00:30<00:01,  3.13it/s]
 95%|█████████▌| 95/100 [00:30<00:01,  3.13it/s]
 96%|█████████▌| 96/100 [00:30<00:01,  3.14it/s]
 97%|█████████▋| 97/100 [00:31<00:00,  3.11it/s]
 98%|█████████▊| 98/100 [00:31<00:00,  3.11it/s]
 99%|█████████▉| 99/100 [00:31<00:00,  3.11it/s]
100%|██████████| 100/100 [00:32<00:00,  3.11it/s]
Out[90]:
(100, 100)

In [95]:
plt.figure(figsize=(8,5))
xp = np.linspace(dst_bins_centers[ind].min(), dst_bins_centers[ind].max(), 100)
for v in ilu:
    plt.plot(xp, v, alpha=.3, c='r')

plt.plot(xp, np.percentile(ilu, [25, 50, 75],axis=0).T, c='k', lw=3)
    
# a = trace['alpha'].mean()
# b = trace['beta'].mean()
# plt.plot(xp, invlogit(a + b*xp).value)

# a = trace['alpha'].stats()['quantiles'][50]
# b = trace['beta'].stats()['quantiles'][50]
# plt.plot(xp, invlogit(a + b*xp).value, c='y')


plt.scatter(dst_bins_centers[ind], success[ind]/n_events[ind], s=50);
plt.xlabel('Minimum Dst')
plt.ylabel('Probability slot is filled')


Out[95]:
Text(0,0.5,'Probability slot is filled')

Same as previous figure with the red lines overlayed as 100 joint draws from the model posterior in order to show spread.


In [98]:
xp.shape, np.percentile(ilu, [25, 50, 75],axis=0).T.shape


Out[98]:
((100,), (100, 3))

In [109]:
ii50 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.5)[0]
ii75 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.75)[0]
ii90 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.90)[0]
ii95 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.95)[0]
ii99 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.99)[0]

In [110]:
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 50% percent of a slot filling at this energy'.format(xp[ii50[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 75% percent of a slot filling at this energy'.format(xp[ii75[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 90% percent of a slot filling at this energy'.format(xp[ii90[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 95% percent of a slot filling at this energy'.format(xp[ii95[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 99% percent of a slot filling at this energy'.format(xp[ii99[0]]))


At a minimum Dst of 110nT it is predicted to have a 50% percent of a slot filling at this energy
At a minimum Dst of 121nT it is predicted to have a 75% percent of a slot filling at this energy
At a minimum Dst of 134nT it is predicted to have a 90% percent of a slot filling at this energy
At a minimum Dst of 143nT it is predicted to have a 95% percent of a slot filling at this energy
At a minimum Dst of 166nT it is predicted to have a 99% percent of a slot filling at this energy

In [111]:
ii50 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.5)[0]
ii75 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.75)[0]
ii90 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.90)[0]
ii95 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.95)[0]
ii99 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.99)[0]
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 50% percent of a slot filling at this energy'.format(xp[ii50[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 75% percent of a slot filling at this energy'.format(xp[ii75[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 90% percent of a slot filling at this energy'.format(xp[ii90[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 95% percent of a slot filling at this energy'.format(xp[ii95[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 99% percent of a slot filling at this energy'.format(xp[ii99[0]]))


At a minimum Dst of 105nT it is predicted to have a 50% percent of a slot filling at this energy
At a minimum Dst of 114nT it is predicted to have a 75% percent of a slot filling at this energy
At a minimum Dst of 125nT it is predicted to have a 90% percent of a slot filling at this energy
At a minimum Dst of 132nT it is predicted to have a 95% percent of a slot filling at this energy
At a minimum Dst of 148nT it is predicted to have a 99% percent of a slot filling at this energy

In [112]:
ii50 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.5)[0]
ii75 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.75)[0]
ii90 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.90)[0]
ii95 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.95)[0]
ii99 = np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.99)[0]
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 50% percent of a slot filling at this energy'.format(xp[ii50[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 75% percent of a slot filling at this energy'.format(xp[ii75[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 90% percent of a slot filling at this energy'.format(xp[ii90[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 95% percent of a slot filling at this energy'.format(xp[ii95[0]]))
print('At a minimum Dst of {0:0.0f}nT it is predicted to have a 99% percent of a slot filling at this energy'.format(xp[ii99[0]]))


At a minimum Dst of 97nT it is predicted to have a 50% percent of a slot filling at this energy
At a minimum Dst of 106nT it is predicted to have a 75% percent of a slot filling at this energy
At a minimum Dst of 115nT it is predicted to have a 90% percent of a slot filling at this energy
At a minimum Dst of 119nT it is predicted to have a 95% percent of a slot filling at this energy
At a minimum Dst of 130nT it is predicted to have a 99% percent of a slot filling at this energy

In [116]:
v50 = [xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.5)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.5)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.5)[0][0]]]
v75 = [xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.75)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.75)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.75)[0][0]]]
       
v90 = [xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.90)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.90)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.90)[0][0]]]
v95 = [xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.95)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.95)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.95)[0][0]]]
       
v99 = [xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,2] > 0.99)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,1] > 0.99)[0][0]], 
       xp[np.where(np.percentile(ilu, [25, 50, 75],axis=0).T[:,0] > 0.99)[0][0]]]

In [117]:
v50, v75, v90, v95, v99


Out[117]:
([97.27272727272728, 104.54545454545455, 110.0],
 [106.36363636363636, 113.63636363636363, 120.9090909090909],
 [115.45454545454545, 124.54545454545455, 133.63636363636363],
 [119.0909090909091, 131.8181818181818, 142.72727272727272],
 [130.0, 148.1818181818182, 166.36363636363637])

In [129]:
print("a 50% probability of slot filling for {0:.0f}<dst<{1:.0f}".format(v50[0], v50[2]))
print("a 75% probability of slot filling for {0:.0f}<dst<{1:.0f}".format(v75[0], v75[2]))
print("a 90% probability of slot filling for {0:.0f}<dst<{1:.0f}".format(v90[0], v90[2]))
print("a 95% probability of slot filling for {0:.0f}<dst<{1:.0f}".format(v95[0], v95[2]))
print("a 99% probability of slot filling for {0:.0f}<dst<{1:.0f}".format(v99[0], v99[2]))


a 50% probability of slot filling for 97<dst<110
a 75% probability of slot filling for 106<dst<121
a 90% probability of slot filling for 115<dst<134
a 95% probability of slot filling for 119<dst<143
a 99% probability of slot filling for 130<dst<166

In [124]:



Out[124]:
array([[ 7.27272727,  5.45454545],
       [ 7.27272727,  7.27272727],
       [ 9.09090909,  9.09090909],
       [12.72727273, 10.90909091],
       [18.18181818, 18.18181818]])

In [ ]: