Note

This tutorial was generated from an IPython notebook that can be downloaded here. Try a live version: binderbadge, or view in nbviewer.

Level 2 Binning

Standard imports

First, setup some standard modules and matplotlib.

[1]:
%matplotlib inline
%config InlineBackend.figure_format = 'png'

import numpy as np
import xarray as xr

import matplotlib.pyplot as plt

Load the main sciapy module.

[2]:
import sciapy
from sciapy.level2.binning import bin_lat_timeavg
[3]:
# Increase figure sizes and fix mathtext
plt.rcParams["figure.dpi"] = 120
plt.rcParams["mathtext.default"] = "regular"
[4]:
# Reduce chattiness of our code
from logging import getLogger
getLogger().setLevel("WARN")

Raw data

We define helper functions to simplify accessing local or remote data.

[55]:
import requests
import netCDF4

def load_data_store(store, variables=None, **kwargs):
    with xr.open_dataset(store, **kwargs) as data_ds:
        if variables is not None:
            data_ds = data_ds[variables]
        data_ds.load()
        return data_ds

def load_data_url(url, variables=None, **kwargs):
    with requests.get(url, stream=True) as response:
        nc4_ds = netCDF4.Dataset("data", memory=response.content)
        store = xr.backends.NetCDF4DataStore(nc4_ds)
        return load_data_store(store, variables, **kwargs)
[6]:
data_ds = load_data_store(
    "SCIAMACHY_NO_NOM_orbits_20120101-20120104_v6.2.1.nc",
    decode_times=False,
    chunks={"latitude": 24, "altitude": 26},
)

We load some data, saved on google drive. Those are small versions of the full SCIAMACHY NO data set.

[56]:
#url = "https://drive.google.com/uc?id=1oVs1Ue8OVZpwSFFYFy5JBI3PR5E6dONI"  # 2012-01-01 - 2012-01-03
url = "https://drive.google.com/uc?id=1GZM-4orzEXnRlGMA-n9wo-o5Zv56VB49"  # 2012-01-01 - 2012-01-04

data_ds = load_data_url(
    url,
    decode_times=False,
    chunks={"latitude": 24, "altitude": 26},
)

Binning and averaging is easier on the raw (float) values. In the case that the data set contains other time variables except a time dimension and coordinate, you can skip the conversion of time variables using decode_times=False.

But then, you have to fix the time coordinate manually:

[57]:
data_ds["time"] = xr.conventions.decode_cf_variable("time", data_ds.time)

The data set contains the post-processed NO data. Bascially any data will do as long as it has time, latitude, and longitude dimensions. You can use a third variable to bin the data on, in this example, we will use geomagnetic latitudes. Let’s have a look at the content:

[58]:
data_ds
[58]:
<xarray.Dataset>
Dimensions:        (altitude: 51, latitude: 72, time: 57)
Coordinates:
  * time           (time) datetime64[ns] 2012-01-01T01:00:34.732819392 ... 2012-01-04T22:33:35.837857984
  * altitude       (altitude) float32 60.0 62.0 64.0 66.0 ... 156.0 158.0 160.0
  * latitude       (latitude) float32 88.75 86.25 83.75 ... -83.75 -86.25 -88.75
Data variables:
    orbit          (time) int32 51453 51454 51455 51456 ... 51507 51508 51509
    longitude      (time, latitude) float32 680.671 316.555 ... -10.1435 -374.26
    NO_DENS        (time, latitude, altitude) float64 9.377e+06 ... 3.359e+06
    NO_ERR         (time, latitude, altitude) float64 1.723e+06 ... 2.664e+05
    NO_ETOT        (time, latitude, altitude) float64 1.236e+08 ... 6.79e+07
    NO_RSTD        (time, latitude, altitude) float64 18.38 16.42 ... 7.931
    NO_AKDIAG      (time, latitude, altitude) float64 0.0 0.0 0.0 ... 0.0 0.0
    NO_APRIORI     (time, latitude, altitude) float64 0.0 0.0 ... 2.209e+07
    NO_NOEM        (time, latitude, altitude) float64 9.368e+07 ... 2.667e+07
    NO_VMR         (time, latitude, altitude) float64 2.727 3.865 ... 1.202e+05
    app_LST        (time, latitude) float32 21.883951 21.626432 ... 21.977247
    mean_LST       (time, latitude) float32 21.936981 21.67946 ... 22.05358
    mean_SZA       (time, latitude) float32 114.12422 116.093376 ... 68.33748
    UTC            (time, latitude) float64 0.5589 0.5758 0.5927 ... 22.99 23.0
    utc_days       (time, latitude) float64 4.383e+03 4.383e+03 ... 4.387e+03
    gm_lats        (time, latitude) float32 84.331696 85.02615 ... -75.37667
    gm_lons        (time, latitude) float32 145.26302 118.34928 ... 13.52788
    aacgm_gm_lats  (time, latitude) float32 83.91623 85.11143 ... -73.33597
    aacgm_gm_lons  (time, latitude) float32 162.09071 139.56108 ... 21.179602
    MSIS_Temp      (time, latitude, altitude) float64 252.7 246.0 ... 818.3
    MSIS_Dens      (time, latitude, altitude) float64 3.439e+15 ... 2.795e+10
Attributes:
    version:          2.2
    L2_data_version:  v6.2_fit_noem_apriori
    creation_time:    Mon Oct 09 2017 11:43:37 +00:00 (UTC)
    author:           Stefan Bender

The easiest way to bin the data into geomagnetic locations is to use the provided pre-calculated geomagnetic latitudes. Those variables are derived from the latitude/longitude combinations, so they have the same dimension as longitude:

[59]:
data_ds.gm_lats
[59]:
<xarray.DataArray 'gm_lats' (time: 57, latitude: 72)>
array([[ 84.331696,  85.02615 ,  87.76751 , ..., -74.830956, -72.70978 ,
        -75.02266 ],
       [ 84.78126 ,  86.64528 ,  85.1038  , ..., -72.68119 , -72.63666 ,
        -75.029884],
       [ 85.00402 ,  87.574165,  82.686935, ..., -71.149734, -73.09879 ,
        -75.2403  ],
       ...,
       [ 82.65202 ,  80.4589  ,  83.06682 , ..., -82.20558 , -76.527885,
        -76.3305  ],
       [ 83.02436 ,  81.3985  ,  85.5422  , ..., -80.9352  , -75.00373 ,
        -75.81156 ],
       [ 83.523766,  82.68859 ,  88.19489 , ..., -78.5798  , -73.75882 ,
        -75.37667 ]], dtype=float32)
Coordinates:
  * time      (time) datetime64[ns] 2012-01-01T01:00:34.732819392 ... 2012-01-04T22:33:35.837857984
  * latitude  (latitude) float32 88.75 86.25 83.75 ... -83.75 -86.25 -88.75
Attributes:
    long_name:  geomagnetic_latitude
    model:      IGRF
    units:      degrees_north

To calculate daily means, we use xarray’s resample interface and apply the binning function via .apply():

[60]:
data_binned = data_ds.resample(time="1d").apply(
    bin_lat_timeavg,
    binvar="gm_lats",
    bins=np.r_[-90:91:30],
    area_weighted=False,
)
/home/ben/Work/miniconda3/envs/stats/lib/python3.6/site-packages/xarray/core/nanops.py:162: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis=axis, dtype=dtype)

This run produces a data set resampled to daily values and 30° geomagnetic latitude bins. In addition to the mean values, bin_lat_timeavg calculates the standard deviation and number of averaged data points. Both values are supplied as <var>_std and <var>_cnt, where <var> stands for the data variable in question.

[61]:
data_binned
[61]:
<xarray.Dataset>
Dimensions:            (altitude: 51, gm_lats_bins: 6, time: 4)
Coordinates:
  * time               (time) datetime64[ns] 2012-01-01 ... 2012-01-04
  * gm_lats_bins       (gm_lats_bins) float64 -75.0 -45.0 -15.0 15.0 45.0 75.0
  * altitude           (altitude) float32 60.0 62.0 64.0 ... 156.0 158.0 160.0
Data variables:
    orbit              (time, gm_lats_bins) float64 5.146e+04 ... 5.15e+04
    longitude          (time, gm_lats_bins) float32 60.51928 ... 295.44537
    NO_DENS            (time, gm_lats_bins, altitude) float64 -2.082e+07 ... 7.386e+06
    NO_ERR             (time, gm_lats_bins, altitude) float64 1.334e+07 ... 1.509e+06
    NO_ETOT            (time, gm_lats_bins, altitude) float64 9.214e+07 ... 8.038e+07
    NO_RSTD            (time, gm_lats_bins, altitude) float64 163.0 ... 32.98
    NO_AKDIAG          (time, gm_lats_bins, altitude) float64 0.006177 ... 0.0007348
    NO_APRIORI         (time, gm_lats_bins, altitude) float64 0.0 ... 1.424e+07
    NO_NOEM            (time, gm_lats_bins, altitude) float64 6.843e+07 ... 2.062e+07
    NO_VMR             (time, gm_lats_bins, altitude) float64 -2.243 ... 2.751e+05
    app_LST            (time, gm_lats_bins) float32 9.768799 ... 14.348375
    mean_LST           (time, gm_lats_bins) float32 9.821828 ... 14.424706
    mean_SZA           (time, gm_lats_bins) float32 61.30505 ... 99.51569
    UTC                (time, gm_lats_bins) float64 11.67 11.72 ... 11.55 12.17
    utc_days           (time, gm_lats_bins) float64 4.383e+03 ... 4.387e+03
    gm_lats            (time, gm_lats_bins) float32 -72.28236 ... 74.27136
    gm_lons            (time, gm_lats_bins) float32 4.6845183 ... 22.456472
    aacgm_gm_lats      (time, gm_lats_bins) float32 -63.07603 ... 77.34904
    aacgm_gm_lons      (time, gm_lats_bins) float32 2.5101104 ... -1.7533023
    MSIS_Temp          (time, gm_lats_bins, altitude) float64 265.4 ... 714.1
    MSIS_Dens          (time, gm_lats_bins, altitude) float64 9.252e+15 ... 2.688e+10
    wsqsum             (time, gm_lats_bins) float32 0.0062893075 ... 0.0062111802
    orbit_std          (time, gm_lats_bins) float64 4.58 3.879 ... 3.884 4.012
    longitude_std      (time, gm_lats_bins) float64 165.2 107.9 ... 106.8 170.6
    NO_DENS_std        (time, gm_lats_bins, altitude) float64 2.116e+07 ... 3.359e+06
    NO_ERR_std         (time, gm_lats_bins, altitude) float64 4.678e+06 ... 1.509e+06
    NO_ETOT_std        (time, gm_lats_bins, altitude) float64 5.485e+06 ... 4.914e+06
    NO_RSTD_std        (time, gm_lats_bins, altitude) float64 548.9 ... 116.6
    NO_AKDIAG_std      (time, gm_lats_bins, altitude) float64 0.006565 ... 0.001811
    NO_APRIORI_std     (time, gm_lats_bins, altitude) float64 0.0 ... 1.96e+06
    NO_NOEM_std        (time, gm_lats_bins, altitude) float64 4.991e+06 ... 8.959e+05
    NO_VMR_std         (time, gm_lats_bins, altitude) float64 2.312 ... 1.25e+05
    app_LST_std        (time, gm_lats_bins) float64 5.965 0.4112 ... 3.748
    mean_LST_std       (time, gm_lats_bins) float64 5.965 0.4112 ... 3.748
    mean_SZA_std       (time, gm_lats_bins) float64 8.639 7.489 ... 8.383 10.39
    UTC_std            (time, gm_lats_bins) float64 7.659 6.496 ... 6.507 6.713
    utc_days_std       (time, gm_lats_bins) float64 0.3191 0.2706 ... 0.2797
    gm_lats_std        (time, gm_lats_bins) float64 6.725 8.79 ... 8.746 7.847
    gm_lons_std        (time, gm_lats_bins) float64 76.51 90.55 ... 103.7 116.3
    aacgm_gm_lats_std  (time, gm_lats_bins) float64 10.08 12.31 ... 11.75 7.525
    aacgm_gm_lons_std  (time, gm_lats_bins) float64 25.09 42.02 ... 59.91 97.16
    MSIS_Temp_std      (time, gm_lats_bins, altitude) float64 3.77 ... 13.79
    MSIS_Dens_std      (time, gm_lats_bins, altitude) float64 4.178e+14 ... 7.472e+08
    orbit_cnt          (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    longitude_cnt      (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    NO_DENS_cnt        (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
    NO_ERR_cnt         (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
    NO_ETOT_cnt        (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
    NO_RSTD_cnt        (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
    NO_AKDIAG_cnt      (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
    NO_APRIORI_cnt     (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
    NO_NOEM_cnt        (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
    NO_VMR_cnt         (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
    app_LST_cnt        (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    mean_LST_cnt       (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    mean_SZA_cnt       (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    UTC_cnt            (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    utc_days_cnt       (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    gm_lats_cnt        (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    gm_lons_cnt        (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    aacgm_gm_lats_cnt  (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    aacgm_gm_lons_cnt  (time, gm_lats_bins) int64 159 179 172 ... 169 168 161
    MSIS_Temp_cnt      (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
    MSIS_Dens_cnt      (time, gm_lats_bins, altitude) int64 159 159 ... 161 161
Attributes:
    version:          2.2
    L2_data_version:  v6.2_fit_noem_apriori
    creation_time:    Mon Oct 09 2017 11:43:37 +00:00 (UTC)
    author:           Stefan Bender

The data are now binned into daily 30° latitude bins, but we probably want the latitudes still be named “latitude”.

[62]:
data_binned = data_binned.rename({"gm_lats_bins": "latitude"})

External binning

There are various packages around for converting geographic locations to geomagnetic locations (or whatever geo-coordinate system you like).

Two of the main packages usually used are aacgmv2 and apexpy

aacgmv2

[63]:
import aacgmv2

For using the sciapy.level2.binning method, you need to put the coordinates you want to bin tghe data on into data variables first. You can set this variable for example by defining helper function like this (the idx parameter can be used for switching to longitudes by setting it to 1):

[64]:
def conv_gm_lat(da, idx=0, alt=110.):
    return [aacgmv2.convert(
                da.latitude.data,
                d,
                alt,
                date=d.time.data.astype("M8[s]").astype("O"),
            )[idx]
            for d in da
           ]

Then apply the helper function to the longitudes through via .pipe(). If you supply a new data variable directly as a tuple has the advantage that xarray can work its magic and assigns the dimensions and coordinates automatically:

[65]:
data_ds["AACGMv2_lats"] = (
    ["time", "latitude"],
    data_ds.longitude.pipe(conv_gm_lat, idx=0, alt=data_ds.altitude.mean()))
/home/ben/Work/miniconda3/envs/stats/lib/python3.6/site-packages/numpy/lib/function_base.py:2048: RuntimeWarning: AACGM_v2_Convert returned error code -1
  outputs = ufunc(*inputs)

Alternatively, you can supply the latitude list directly via an appropriate list comprehension:

[66]:
data_ds["AACGMv2_lats2"] = (
    ["time", "latitude"],
    [aacgmv2.convert(
         data_ds.latitude.data,
         long.data,
         data_ds.altitude.mean().data,
         date=date.data.astype("M8[s]").astype("O"),
     )[0]
     for date, long in zip(data_ds.time, data_ds.longitude)])

Whatever way you chose to prepare the data variable to bin the data on, you can now use it in the same way as gm_lats before:

[67]:
data_binned2 = data_ds.resample(time="1d").apply(
    bin_lat_timeavg,
    binvar="AACGMv2_lats",
    bins=np.r_[-90:91:30],
    area_weighted=False,
)
[68]:
data_binned2
[68]:
<xarray.Dataset>
Dimensions:            (AACGMv2_lats_bins: 6, altitude: 51, time: 4)
Coordinates:
  * time               (time) datetime64[ns] 2012-01-01 ... 2012-01-04
  * AACGMv2_lats_bins  (AACGMv2_lats_bins) float64 -75.0 -45.0 ... 45.0 75.0
  * altitude           (altitude) float32 60.0 62.0 64.0 ... 156.0 158.0 160.0
Data variables:
    orbit              (time, AACGMv2_lats_bins) float64 5.146e+04 ... 5.15e+04
    longitude          (time, AACGMv2_lats_bins) float32 56.82753 ... 290.32748
    NO_DENS            (time, AACGMv2_lats_bins, altitude) float64 -2.081e+07 ... 7.647e+06
    NO_ERR             (time, AACGMv2_lats_bins, altitude) float64 1.334e+07 ... 1.611e+06
    NO_ETOT            (time, AACGMv2_lats_bins, altitude) float64 9.214e+07 ... 8.028e+07
    NO_RSTD            (time, AACGMv2_lats_bins, altitude) float64 146.0 ... 35.93
    NO_AKDIAG          (time, AACGMv2_lats_bins, altitude) float64 0.006205 ... 0.0009047
    NO_APRIORI         (time, AACGMv2_lats_bins, altitude) float64 0.0 ... 1.412e+07
    NO_NOEM            (time, AACGMv2_lats_bins, altitude) float64 6.839e+07 ... 2.047e+07
    NO_VMR             (time, AACGMv2_lats_bins, altitude) float64 -2.243 ... 2.847e+05
    app_LST            (time, AACGMv2_lats_bins) float32 9.781969 ... 14.2096615
    mean_LST           (time, AACGMv2_lats_bins) float32 9.834998 ... 14.285992
    mean_SZA           (time, AACGMv2_lats_bins) float32 61.200176 ... 98.79113
    UTC                (time, AACGMv2_lats_bins) float64 11.63 11.72 ... 12.07
    utc_days           (time, AACGMv2_lats_bins) float64 4.383e+03 ... 4.387e+03
    gm_lats            (time, AACGMv2_lats_bins) float32 -72.263626 ... 73.571884
    gm_lons            (time, AACGMv2_lats_bins) float32 7.3087535 ... 25.604252
    aacgm_gm_lats      (time, AACGMv2_lats_bins) float32 -63.15835 ... 77.0171
    aacgm_gm_lons      (time, AACGMv2_lats_bins) float32 1.4909898 ... -2.2973938
    MSIS_Temp          (time, AACGMv2_lats_bins, altitude) float64 265.4 ... 714.7
    MSIS_Dens          (time, AACGMv2_lats_bins, altitude) float64 9.246e+15 ... 2.69e+10
    AACGMv2_lats       (time, AACGMv2_lats_bins) float64 -71.49 -45.57 ... 74.19
    AACGMv2_lats2      (time, AACGMv2_lats_bins) float64 -71.49 -45.57 ... 74.19
    wsqsum             (time, AACGMv2_lats_bins) float64 0.006289 ... 0.005952
    orbit_std          (time, AACGMv2_lats_bins) float64 4.575 3.731 ... 3.912
    longitude_std      (time, AACGMv2_lats_bins) float64 163.1 112.6 ... 170.8
    NO_DENS_std        (time, AACGMv2_lats_bins, altitude) float64 2.115e+07 ... 4.031e+06
    NO_ERR_std         (time, AACGMv2_lats_bins, altitude) float64 4.676e+06 ... 1.562e+06
    NO_ETOT_std        (time, AACGMv2_lats_bins, altitude) float64 5.486e+06 ... 4.833e+06
    NO_RSTD_std        (time, AACGMv2_lats_bins, altitude) float64 488.9 ... 117.8
    NO_AKDIAG_std      (time, AACGMv2_lats_bins, altitude) float64 0.006534 ... 0.001954
    NO_APRIORI_std     (time, AACGMv2_lats_bins, altitude) float64 0.0 ... 2.017e+06
    NO_NOEM_std        (time, AACGMv2_lats_bins, altitude) float64 5.099e+06 ... 1.153e+06
    NO_VMR_std         (time, AACGMv2_lats_bins, altitude) float64 2.311 ... 1.502e+05
    app_LST_std        (time, AACGMv2_lats_bins) float64 5.961 0.4403 ... 3.729
    mean_LST_std       (time, AACGMv2_lats_bins) float64 5.961 0.4403 ... 3.729
    mean_SZA_std       (time, AACGMv2_lats_bins) float64 8.668 7.76 ... 10.82
    UTC_std            (time, AACGMv2_lats_bins) float64 7.651 6.249 ... 6.544
    utc_days_std       (time, AACGMv2_lats_bins) float64 0.3188 ... 0.2727
    gm_lats_std        (time, AACGMv2_lats_bins) float64 6.758 10.19 ... 8.378
    gm_lons_std        (time, AACGMv2_lats_bins) float64 76.25 87.65 ... 115.1
    aacgm_gm_lats_std  (time, AACGMv2_lats_bins) float64 9.982 11.89 ... 7.591
    aacgm_gm_lons_std  (time, AACGMv2_lats_bins) float64 25.95 44.65 ... 94.99
    MSIS_Temp_std      (time, AACGMv2_lats_bins, altitude) float64 3.731 ... 13.92
    MSIS_Dens_std      (time, AACGMv2_lats_bins, altitude) float64 4.162e+14 ... 7.485e+08
    AACGMv2_lats_std   (time, AACGMv2_lats_bins) float64 6.609 8.546 ... 7.944
    AACGMv2_lats2_std  (time, AACGMv2_lats_bins) float64 6.609 8.546 ... 7.944
    orbit_cnt          (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    longitude_cnt      (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    NO_DENS_cnt        (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    NO_ERR_cnt         (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    NO_ETOT_cnt        (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    NO_RSTD_cnt        (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    NO_AKDIAG_cnt      (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    NO_APRIORI_cnt     (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    NO_NOEM_cnt        (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    NO_VMR_cnt         (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    app_LST_cnt        (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    mean_LST_cnt       (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    mean_SZA_cnt       (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    UTC_cnt            (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    utc_days_cnt       (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    gm_lats_cnt        (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    gm_lons_cnt        (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    aacgm_gm_lats_cnt  (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    aacgm_gm_lons_cnt  (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    MSIS_Temp_cnt      (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    MSIS_Dens_cnt      (time, AACGMv2_lats_bins, altitude) int64 159 159 ... 168
    AACGMv2_lats_cnt   (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
    AACGMv2_lats2_cnt  (time, AACGMv2_lats_bins) int64 159 193 154 ... 160 168
Attributes:
    version:          2.2
    L2_data_version:  v6.2_fit_noem_apriori
    creation_time:    Mon Oct 09 2017 11:43:37 +00:00 (UTC)
    author:           Stefan Bender
[69]:
data_binned2 = data_binned2.rename({"AACGMv2_lats_bins": "latitude"})
[70]:
data_binned2.sel(latitude=75).NO_DENS.plot(x="time")
[70]:
<matplotlib.collections.QuadMesh at 0x7fd4754d7e48>
../_images/tutorials_level2_binning_37_1.png
[71]:
(data_binned2.sel(latitude=75).NO_DENS - data_binned.sel(latitude=75).NO_DENS).plot(x="time")
[71]:
<matplotlib.collections.QuadMesh at 0x7fd474e3e208>
../_images/tutorials_level2_binning_38_1.png

apexpy

[72]:
import apexpy

For the sake of brewity, we skip the definition of a helper function and construct the bin variables directly. apexpy provides two main variants, “quasi-dipole” and “apex” coordinates, see also [1] and the other references on the apexpy documentation page

[1] Emmert, J. T., A. D. Richmond, and D. P. Drob (2010), A computationally compact representation of Magnetic-Apex and Quasi-Dipole coordinates with smooth base vectors, J. Geophys. Res., 115(A8), A08322, doi:10.1029/2010JA015326.

[73]:
data_ds["qd_lats"] = (
    ["time", "latitude"],
    [apexpy.Apex(date=date.data.astype("M8[s]").astype("O"))
         .convert(
             data_ds.latitude.values,
              long.values,
              "geo",
              "qd",
              height=data_ds.altitude.mean().values,
         )[0]
     for date, long in zip(data_ds.time, data_ds.longitude)])
[74]:
data_ds["apex_lats"] = (
    ["time", "latitude"],
    [apexpy.Apex(date=date.data.astype("M8[s]").astype("O"))
         .convert(
             data_ds.latitude.values,
              long.values,
              "geo",
              "apex",
              height=data_ds.altitude.mean().values,
         )[0]
     for date, long in zip(data_ds.time, data_ds.longitude)])
[75]:
data_binnedqd = data_ds.resample(time="1d").apply(
    bin_lat_timeavg,
    binvar="qd_lats",
    bins=np.r_[-90:91:30],
    area_weighted=False,
)
/home/ben/Work/miniconda3/envs/stats/lib/python3.6/site-packages/xarray/core/nanops.py:162: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis=axis, dtype=dtype)
[76]:
data_binnedqd = data_binnedqd.rename({"qd_lats_bins": "latitude"})
[77]:
data_binnedapex = data_ds.resample(time="1d").apply(
    bin_lat_timeavg,
    binvar="apex_lats",
    bins=np.r_[-90:91:30],
    area_weighted=False,
)
[78]:
data_binnedapex = data_binnedapex.rename({"apex_lats_bins": "latitude"})
[79]:
(data_binnedqd.sel(latitude=75).NO_DENS - data_binned.sel(latitude=75).NO_DENS).plot(x="time")
[79]:
<matplotlib.collections.QuadMesh at 0x7fd47555ed68>
../_images/tutorials_level2_binning_48_1.png
[80]:
(data_binnedapex.sel(latitude=75).NO_DENS - data_binned.sel(latitude=75).NO_DENS).plot(x="time")
[80]:
<matplotlib.collections.QuadMesh at 0x7fd474c736a0>
../_images/tutorials_level2_binning_49_1.png
[81]:
(data_binnedapex.sel(latitude=75) - data_binnedqd.sel(latitude=75)).NO_DENS.plot(x="time")
[81]:
<matplotlib.collections.QuadMesh at 0x7fd474be1b00>
../_images/tutorials_level2_binning_50_1.png
[82]:
data_binned2.sel(latitude=75).NO_DENS_std.plot(x="time", cmap="cividis")
[82]:
<matplotlib.collections.QuadMesh at 0x7fd474b823c8>
../_images/tutorials_level2_binning_51_1.png
[83]:
mean_N = data_binned2.NO_ERR_cnt
mean_var = (mean_N - 1) / mean_N * data_binned2.NO_ERR_std**2 + data_binned2.NO_ERR**2
mean_err = np.sqrt(mean_var)
[84]:
mean_err.sel(latitude=-15).plot(x="time", cmap="cividis")
[84]:
<matplotlib.collections.QuadMesh at 0x7fd474a9e630>
../_images/tutorials_level2_binning_53_1.png
[85]:
full_var = data_binned2.NO_DENS_std**2 + mean_var
full_err = np.sqrt(full_var)
[86]:
(full_err - data_binned2.NO_DENS_std).sel(latitude=-15).plot(x="time", cmap="cividis")
[86]:
<matplotlib.collections.QuadMesh at 0x7fd474a3c5f8>
../_images/tutorials_level2_binning_55_1.png
[87]:
lat, alt = -15, 72
data_bin = data_binned2.sel(latitude=lat, altitude=alt)
plt.errorbar(data_bin.time.data,
             data_bin.NO_DENS.data,
             yerr=full_err.sel(latitude=lat, altitude=alt) / np.sqrt(mean_N.sel(latitude=lat, altitude=alt)),
             fmt='.',
             label="total",
            )
plt.errorbar(data_bin.time.data,
             data_bin.NO_DENS.data,
             yerr=data_bin.NO_DENS_std.data / np.sqrt(mean_N.sel(latitude=lat, altitude=alt)),
             fmt='.',
             label="data sem",
            )
plt.errorbar(data_bin.time.data,
             data_bin.NO_DENS.data,
             yerr=mean_err.sel(latitude=lat, altitude=alt) / np.sqrt(mean_N.sel(latitude=lat, altitude=alt)),
             fmt='.',
             label="err var",
            )
plt.legend();
../_images/tutorials_level2_binning_56_0.png