{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"http://www.datascience-paris-saclay.fr\">\n",
    "<img src=\"img/logoUPSayPlusCDS_990.png\" width=\"600px\">\n",
    "</a>\n",
    "\n",
    "# PLAsTiCC - RAMP: classification of astronomical transients\n",
    "\n",
    "##### Alexandre Boucaud (Paris-Saclay Center for Data Science) \n",
    "##### Emille E. O. Ishida (Universite Clermont-Auvergne)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction\n",
    "\n",
    "\n",
    "Most of the sources we observe in the night sky evolve during a very long period of time (millions or even billions of years) - rendering them practically static in comparison to the time scale of  a human life. However, this is only a partial description of possible events taking place in the Universe. \n",
    "\n",
    "For a long time, astronomers have [recorded the observation](https://en.wikipedia.org/wiki/SN_185) events whose life spam lasts for days or months.  More  recently, the advent of modern telescopes expanded our ability to detect astronomical events which happen from a few seconds to years. These are called **[transients](https://www.lsst.org/science/transient-optical-sky)** and they are the may concern of researchers working in **time domain astronomy**.\n",
    "\n",
    "\n",
    "\n",
    "Transients can are the observational consequence of a large variety of astronomical phenomena. For example,  a cataclismic event (e.g. a stellar explosion in the case of [supernovae](https://www.nasa.gov/audience/forstudents/5-8/features/nasa-knows/what-is-a-supernova.html)); the physical process governing high density regions of the Universe (e.g. [active galactic nuclei (AGN)](https://ned.ipac.caltech.edu/level5/Cambridge/frames.html)) or our position in relation to a set of observed objects (e.g. [eclipsing binaries](http://www.physics.sfasu.edu/astro/ebstar/ebstar.html)). \n",
    "\n",
    "\n",
    "These relatively rapid changing objects can provide important clues about themselves and their environement - as well as the evolution of the universe as a whole (e.g. [type Ia supernovae](http://hubblesite.org/hubble_discoveries/dark_energy/de-type_ia_supernovae.php) provided the first evidence of the current accelerated expansion of the Universe caused by [dark energy](http://astronomy.swin.edu.au/cosmos/D/Dark+Energy)). Therefore, the proper classification of transients is a crucial task in observational astronomy - specially in the light of large data volumes expected for the next generation of astronomical surveys.\n",
    "\n",
    "\n",
    "In what follows, we will use the example of supernovae to illustrate the more general problem of transient classification. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The Data Problem\n",
    "\n",
    "\n",
    "Once a supernova is detected, we need to scrutinize its  light through two different channels before we can use it in subsequent astrophysical analysis. These two methods are called *spectroscopy* and *photometry*. \n",
    "\n",
    "**[Spectroscopy](http://loke.as.arizona.edu/~ckulesa/camp/spectroscopy_intro.html)**  is the modern equivalent of using a prism to separate a beam of white light in the rainbown colours. It is a high resolution measurement which allows us to identify emission/absorption features indicative of specific chemical elements - and are also the main source of information enabling classification. \n",
    "\n",
    "Despite being paramount for the classification task, spectroscopy is an extremely time consuming process - with integration times hanging from 20 minutes to a few hours depending on the telescope and brightness of the source. \n",
    "\n",
    "\n",
    "Traditionally, transient classification is completely based on spectroscopic measurements - however, given the volume of data expected from the upcoming large scale sky surveys, this strategy is not sustainable. An alternative approach, based on cheaper/lower resolution measurements must be found."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<figure>\n",
    "    <img src=\"img/SNspectra.jpg\" width=\"400px\">\n",
    "    <figcaption>**Figure 1**: Example of spectra of SNe Ia, Ic, Ib and II (from top to bottom) highlighting their main spectral features. \n",
    "        *Figure by Daniel Kasen*\n",
    "    </figcaption>\n",
    "</figure>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Photometry**  gives the overall information of how bright the source is (how much energy the object is emitting) at a particular moment. It can be described as the low resolution counterpart of spectroscopy - or the integral of all the information stored in the spectra. \n",
    "\n",
    "\n",
    "A sequence of photometric observations made at different moments in time is called a *light curve*. It holds the information of how the energy of the source evolves with time and can also be used to characterize different types of supernovae (although the distinction between classes is much more discrete than we would hope it to be). \n",
    "\n",
    "\n",
    "Photometry has the advantadge of being a relatevely straight forward and cheap process. Moreover, it is also capable of accessing a much larger volume of the universe - reaching dimmer and, consequently, further objects."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<figure>\n",
    "    <img src=\"img/lightcurves.jpg\" width=\"500px\">\n",
    "    <figcaption>**Figure 2**: Example of the light-curves (brightness as a function of time) for different supernova types. *Image: J. Craig Wheeler, 2012*\n",
    "    </figcaption>\n",
    "</figure>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "New instruments, like the [Large Synoptic Survey Telescope (LSST)](https://www.lsst.org/) - scheduled to begin observations in 2022 - will produce an unprecedented number of light curves. Once these transients are detected, we rely on agreements with other telescopes in order to acquire a small number of spectroscopic observations. \n",
    "\n",
    "\n",
    "In summary: we must develop ways to classify transients using only their light curves. \n",
    "\n",
    "\n",
    "In the context of machine learning, this means using the small, biased spectroscopic sample in order to train a classifier which will subsequently be applied to the larger, photometric-only sample."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Filters\n",
    "\n",
    "\n",
    "In a real data scenario, the concetual description of a light curve given above has a further degree of complexity. \n",
    "\n",
    "The electromagnetic spectrum is divided in broad wavelength ranges and the signal from the source is integrate only within this range - and convolved with the filter transmission.\n",
    "\n",
    "The figure bellow shown an example of a set of broad-band filters superimposed to a type Ia supernova spectra."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<figure>\n",
    "    <img src=\"img/filters_snIa_max_z1.png\" width=\"700px\">\n",
    "    <figcaption>**Figure 3**: Example of DES broad-band filters transmission superimposed to a type Ia supernova spectrum at peak brightness. *Figure by Emille Ishida*\n",
    "    </figcaption>\n",
    "</figure>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As a consequence, for each supernova we will have a set of 4 light curves. These express the evolution of the brightness of the object as a function of time *for each one of the wavelength intervals covered by the broad-band filters*."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The prediction task"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For this specific challenge we wil focus on the binary classification of supernovae, between SNIa and non-SNIa."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Road so Far\n",
    "\n",
    "\n",
    "The photometric classification of supernovae has been studied in the astronomical literature for a long time. This culminated in the *Supernova Photometric Classification Challenge (SNPCC)* ([Kessler *et al.*, 2010](https://arxiv.org/pdf/1008.1024.pdf)), where the participants were invited to classify a simulated dataset designed to mimic the specifications of the *[Dark Energy Survey](https://www.darkenergysurvey.org/)*. \n",
    "\n",
    "\n",
    "The challenge provided a state of the art description of the classification methods available in the literature, bringing together different groups who had been investigating the problem for a while. Although none of the algorithms performed obviously better than all others, its main legacy was the updated data set and corresponding labels which were made public to the community. \n",
    "\n",
    "\n",
    "This is the data set that we will use in this RAMP.  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### References\n",
    "\n",
    "A recent review of how different machine learning methods perform on this dataset can be found at [Lochner *et al.*, 2016](https://arxiv.org/abs/1603.00882) and references therein."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Data\n",
    "\n",
    "\n",
    "\n",
    "The lightcurve data is made of **non-homogeneously sampled**, **non-periodic** time series with correlated errors obtained in several wavelength filters.\n",
    "\n",
    "The DES dataset provided with this RAMP has light curves in 4 filters *g*, *r*, *i* and *z*."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Downloading data\n",
    "\n",
    "To obtain the DES dataset, make sure to run the provided script `download_data.py`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!python download_data.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading the data\n",
    "\n",
    "Here we provide methods to read the `pickle` files and convert the data to a `pandas` dataframe for convenience.\n",
    "\n",
    "The SN label is removed from the main dataframe and provided as a separate one."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import gzip\n",
    "import pickle\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "def read_data(filename):\n",
    "    \"\"\"Read data from pickled file to a pandas dataframe\"\"\"\n",
    "    with gzip.open(filename, 'rb') as f:\n",
    "        data = pickle.load(f)\n",
    "\n",
    "    X = to_dataframe(data)\n",
    "    y = pd.get_dummies(X.type == 0, prefix='SNIa', drop_first=True)\n",
    "    X = X.drop(columns=['comment', 'type'])\n",
    "\n",
    "    return X, y\n",
    "\n",
    "\n",
    "def to_dataframe(data):\n",
    "    \"\"\"Converts from a python dictionary to a pandas dataframe\"\"\"\n",
    "    for idx in data:\n",
    "        sn = data[idx]\n",
    "        for filt in 'griz':\n",
    "            sn['mjd_%s' % filt] = np.array(sn[filt]['mjd'])\n",
    "            sn['fluxcal_%s' % filt] = np.array(sn[filt]['fluxcal'])\n",
    "            sn['fluxcalerr_%s' % filt] = np.array(sn[filt]['fluxcalerr'])\n",
    "            del sn[filt]\n",
    "        sn.update(sn['header'])\n",
    "        del sn['header']\n",
    "\n",
    "    return pd.DataFrame.from_dict(data, orient='index')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is a peak at the data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "X, y = read_data('data/des_train.pkl')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>mjd_g</th>\n",
       "      <th>fluxcal_g</th>\n",
       "      <th>fluxcalerr_g</th>\n",
       "      <th>mjd_r</th>\n",
       "      <th>fluxcal_r</th>\n",
       "      <th>fluxcalerr_r</th>\n",
       "      <th>mjd_i</th>\n",
       "      <th>fluxcal_i</th>\n",
       "      <th>fluxcalerr_i</th>\n",
       "      <th>mjd_z</th>\n",
       "      <th>fluxcal_z</th>\n",
       "      <th>fluxcalerr_z</th>\n",
       "      <th>snid</th>\n",
       "      <th>z</th>\n",
       "      <th>pkmjd</th>\n",
       "      <th>pkmag_g</th>\n",
       "      <th>pkmag_r</th>\n",
       "      <th>pkmag_i</th>\n",
       "      <th>pkmag_z</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1186</th>\n",
       "      <td>[56283.203, 56288.199, 56292.098, 56304.051, 5...</td>\n",
       "      <td>[3.182, -13.07, -7.177, -0.4645, 0.2906, 16.63...</td>\n",
       "      <td>[6.285, 11.79, 11.65, 2.479, 7.569, 6.195, 3.6...</td>\n",
       "      <td>[56283.211, 56288.215, 56292.102, 56304.055, 5...</td>\n",
       "      <td>[-4.973, -6.427, 9.861, -1.663, 6.724, 23.82, ...</td>\n",
       "      <td>[3.326, 6.181, 4.83, 1.657, 2.966, 2.553, 3.07...</td>\n",
       "      <td>[56283.215, 56289.109, 56292.191, 56304.07, 56...</td>\n",
       "      <td>[-0.615, -9.294, 0.8371, 0.6895, -1.593, 24.51...</td>\n",
       "      <td>[5.816, 7.082, 5.599, 2.506, 5.021, 3.699, 4.5...</td>\n",
       "      <td>[56283.223, 56289.125, 56292.199, 56304.086, 5...</td>\n",
       "      <td>[11.06, 9.393, 3.887, -0.519, 7.005, 33.13, 94...</td>\n",
       "      <td>[5.047, 5.425, 5.158, 3.934, 5.43, 4.443, 7.02...</td>\n",
       "      <td>1186</td>\n",
       "      <td>0.3698</td>\n",
       "      <td>56335.335938</td>\n",
       "      <td>23.07</td>\n",
       "      <td>22.27</td>\n",
       "      <td>22.21</td>\n",
       "      <td>22.43</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1292</th>\n",
       "      <td>[56177.172, 56179.172, 56187.156, 56189.148, 5...</td>\n",
       "      <td>[27.18, 34.83, 24.15, 34.06, 20.13, 5.124, 2.7...</td>\n",
       "      <td>[4.837, 2.372, 1.805, 9.802, 3.809, 2.291, 1.5...</td>\n",
       "      <td>[56177.188, 56179.312, 56187.172, 56189.16, 56...</td>\n",
       "      <td>[33.02, 34.65, 26.92, 33.84, 18.57, 17.39, 17....</td>\n",
       "      <td>[5.375, 3.109, 1.365, 3.938, 2.385, 1.643, 1.1...</td>\n",
       "      <td>[56177.203, 56179.328, 56187.188, 56189.176, 5...</td>\n",
       "      <td>[49.55, 42.79, 30.72, 34.43, 23.86, 14.07, 12....</td>\n",
       "      <td>[5.519, 4.282, 1.993, 8.104, 8.079, 2.161, 1.4...</td>\n",
       "      <td>[56177.234, 56179.359, 56187.211, 56189.203, 5...</td>\n",
       "      <td>[49.68, 48.62, 42.8, 43.68, 33.21, 27.07, 21.5...</td>\n",
       "      <td>[4.784, 3.636, 2.322, 4.765, 5.671, 2.26, 1.86...</td>\n",
       "      <td>1292</td>\n",
       "      <td>0.3501</td>\n",
       "      <td>56164.195312</td>\n",
       "      <td>23.44</td>\n",
       "      <td>23.36</td>\n",
       "      <td>23.35</td>\n",
       "      <td>23.12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2542</th>\n",
       "      <td>[56176.191, 56179.188, 56180.266, 56188.16, 56...</td>\n",
       "      <td>[6.955, 21.06, 24.68, 31.91, 27.69, 22.4, 13.2...</td>\n",
       "      <td>[4.773, 2.635, 2.617, 5.746, 2.38, 2.698, 4.80...</td>\n",
       "      <td>[56176.199, 56179.195, 56180.281, 56188.176, 5...</td>\n",
       "      <td>[38.23, 49.79, 54.4, 86.6, 80.42, 73.66, 56.32...</td>\n",
       "      <td>[2.257, 1.963, 1.675, 5.829, 3.629, 2.059, 2.5...</td>\n",
       "      <td>[56176.215, 56179.234, 56180.297, 56188.211, 5...</td>\n",
       "      <td>[36.53, 48.08, 55.75, 70.12, 78.81, 71.36, 68....</td>\n",
       "      <td>[3.225, 2.191, 3.837, 4.723, 9.182, 2.675, 4.3...</td>\n",
       "      <td>[56176.238, 56179.266, 56180.328, 56188.238, 5...</td>\n",
       "      <td>[29.16, 46.65, 45.53, 64.54, 77.19, 75.92, 62....</td>\n",
       "      <td>[2.545, 3.832, 4.569, 3.611, 3.302, 2.779, 2.9...</td>\n",
       "      <td>2542</td>\n",
       "      <td>0.5415</td>\n",
       "      <td>56192.007812</td>\n",
       "      <td>24.17</td>\n",
       "      <td>22.79</td>\n",
       "      <td>22.81</td>\n",
       "      <td>22.85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2598</th>\n",
       "      <td>[56248.324, 56258.215, 56261.098, 56273.16, 56...</td>\n",
       "      <td>[1.006, -4.694, -2.976, -1.77, 19.69, 61.47, 6...</td>\n",
       "      <td>[1.701, 4.948, 8.828, 1.752, 2.131, 5.026, 6.6...</td>\n",
       "      <td>[56248.34, 56258.227, 56261.102, 56273.176, 56...</td>\n",
       "      <td>[-3.556, -3.604, -5.289, 1.965, 22.99, 84.78, ...</td>\n",
       "      <td>[1.337, 2.382, 3.395, 1.214, 1.358, 2.664, 3.3...</td>\n",
       "      <td>[56258.035, 56261.125, 56273.188, 56281.203, 5...</td>\n",
       "      <td>[22.24, 3.958, -0.1393, 23.06, 90.29, 93.4, 12...</td>\n",
       "      <td>[9.893, 3.854, 2.023, 1.858, 3.509, 5.387, 3.5...</td>\n",
       "      <td>[56258.066, 56261.156, 56273.219, 56281.227, 5...</td>\n",
       "      <td>[4.218, 1.312, 0.01804, 25.39, 87.45, 116.4, 1...</td>\n",
       "      <td>[3.968, 3.086, 2.251, 2.342, 3.062, 3.001, 3.2...</td>\n",
       "      <td>2598</td>\n",
       "      <td>0.3513</td>\n",
       "      <td>56301.996094</td>\n",
       "      <td>22.46</td>\n",
       "      <td>22.02</td>\n",
       "      <td>21.94</td>\n",
       "      <td>22.21</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3644</th>\n",
       "      <td>[56177.172, 56179.172, 56187.156, 56189.148, 5...</td>\n",
       "      <td>[10.03, 3.29, 25.31, 52.93, 137.8, 113.8, 66.4...</td>\n",
       "      <td>[4.792, 2.242, 1.817, 9.857, 4.69, 3.219, 2.12...</td>\n",
       "      <td>[56177.188, 56179.312, 56187.172, 56189.16, 56...</td>\n",
       "      <td>[3.537, 10.17, 45.56, 59.92, 111.3, 139.9, 124...</td>\n",
       "      <td>[5.336, 3.038, 1.537, 4.06, 3.17, 3.089, 2.598...</td>\n",
       "      <td>[56177.203, 56179.328, 56187.188, 56189.176, 5...</td>\n",
       "      <td>[-2.231, 3.372, 28.65, 42.03, 151.9, 155.9, 14...</td>\n",
       "      <td>[5.436, 4.201, 1.98, 8.119, 8.558, 3.634, 3.05...</td>\n",
       "      <td>[56177.234, 56179.359, 56187.211, 56189.203, 5...</td>\n",
       "      <td>[-0.1238, -3.598, 15.7, 14.39, 136.5, 142.2, 1...</td>\n",
       "      <td>[4.691, 3.518, 2.197, 4.702, 6.187, 3.451, 2.9...</td>\n",
       "      <td>3644</td>\n",
       "      <td>0.2705</td>\n",
       "      <td>56204.546875</td>\n",
       "      <td>22.18</td>\n",
       "      <td>22.13</td>\n",
       "      <td>22.00</td>\n",
       "      <td>22.15</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                  mjd_g  \\\n",
       "1186  [56283.203, 56288.199, 56292.098, 56304.051, 5...   \n",
       "1292  [56177.172, 56179.172, 56187.156, 56189.148, 5...   \n",
       "2542  [56176.191, 56179.188, 56180.266, 56188.16, 56...   \n",
       "2598  [56248.324, 56258.215, 56261.098, 56273.16, 56...   \n",
       "3644  [56177.172, 56179.172, 56187.156, 56189.148, 5...   \n",
       "\n",
       "                                              fluxcal_g  \\\n",
       "1186  [3.182, -13.07, -7.177, -0.4645, 0.2906, 16.63...   \n",
       "1292  [27.18, 34.83, 24.15, 34.06, 20.13, 5.124, 2.7...   \n",
       "2542  [6.955, 21.06, 24.68, 31.91, 27.69, 22.4, 13.2...   \n",
       "2598  [1.006, -4.694, -2.976, -1.77, 19.69, 61.47, 6...   \n",
       "3644  [10.03, 3.29, 25.31, 52.93, 137.8, 113.8, 66.4...   \n",
       "\n",
       "                                           fluxcalerr_g  \\\n",
       "1186  [6.285, 11.79, 11.65, 2.479, 7.569, 6.195, 3.6...   \n",
       "1292  [4.837, 2.372, 1.805, 9.802, 3.809, 2.291, 1.5...   \n",
       "2542  [4.773, 2.635, 2.617, 5.746, 2.38, 2.698, 4.80...   \n",
       "2598  [1.701, 4.948, 8.828, 1.752, 2.131, 5.026, 6.6...   \n",
       "3644  [4.792, 2.242, 1.817, 9.857, 4.69, 3.219, 2.12...   \n",
       "\n",
       "                                                  mjd_r  \\\n",
       "1186  [56283.211, 56288.215, 56292.102, 56304.055, 5...   \n",
       "1292  [56177.188, 56179.312, 56187.172, 56189.16, 56...   \n",
       "2542  [56176.199, 56179.195, 56180.281, 56188.176, 5...   \n",
       "2598  [56248.34, 56258.227, 56261.102, 56273.176, 56...   \n",
       "3644  [56177.188, 56179.312, 56187.172, 56189.16, 56...   \n",
       "\n",
       "                                              fluxcal_r  \\\n",
       "1186  [-4.973, -6.427, 9.861, -1.663, 6.724, 23.82, ...   \n",
       "1292  [33.02, 34.65, 26.92, 33.84, 18.57, 17.39, 17....   \n",
       "2542  [38.23, 49.79, 54.4, 86.6, 80.42, 73.66, 56.32...   \n",
       "2598  [-3.556, -3.604, -5.289, 1.965, 22.99, 84.78, ...   \n",
       "3644  [3.537, 10.17, 45.56, 59.92, 111.3, 139.9, 124...   \n",
       "\n",
       "                                           fluxcalerr_r  \\\n",
       "1186  [3.326, 6.181, 4.83, 1.657, 2.966, 2.553, 3.07...   \n",
       "1292  [5.375, 3.109, 1.365, 3.938, 2.385, 1.643, 1.1...   \n",
       "2542  [2.257, 1.963, 1.675, 5.829, 3.629, 2.059, 2.5...   \n",
       "2598  [1.337, 2.382, 3.395, 1.214, 1.358, 2.664, 3.3...   \n",
       "3644  [5.336, 3.038, 1.537, 4.06, 3.17, 3.089, 2.598...   \n",
       "\n",
       "                                                  mjd_i  \\\n",
       "1186  [56283.215, 56289.109, 56292.191, 56304.07, 56...   \n",
       "1292  [56177.203, 56179.328, 56187.188, 56189.176, 5...   \n",
       "2542  [56176.215, 56179.234, 56180.297, 56188.211, 5...   \n",
       "2598  [56258.035, 56261.125, 56273.188, 56281.203, 5...   \n",
       "3644  [56177.203, 56179.328, 56187.188, 56189.176, 5...   \n",
       "\n",
       "                                              fluxcal_i  \\\n",
       "1186  [-0.615, -9.294, 0.8371, 0.6895, -1.593, 24.51...   \n",
       "1292  [49.55, 42.79, 30.72, 34.43, 23.86, 14.07, 12....   \n",
       "2542  [36.53, 48.08, 55.75, 70.12, 78.81, 71.36, 68....   \n",
       "2598  [22.24, 3.958, -0.1393, 23.06, 90.29, 93.4, 12...   \n",
       "3644  [-2.231, 3.372, 28.65, 42.03, 151.9, 155.9, 14...   \n",
       "\n",
       "                                           fluxcalerr_i  \\\n",
       "1186  [5.816, 7.082, 5.599, 2.506, 5.021, 3.699, 4.5...   \n",
       "1292  [5.519, 4.282, 1.993, 8.104, 8.079, 2.161, 1.4...   \n",
       "2542  [3.225, 2.191, 3.837, 4.723, 9.182, 2.675, 4.3...   \n",
       "2598  [9.893, 3.854, 2.023, 1.858, 3.509, 5.387, 3.5...   \n",
       "3644  [5.436, 4.201, 1.98, 8.119, 8.558, 3.634, 3.05...   \n",
       "\n",
       "                                                  mjd_z  \\\n",
       "1186  [56283.223, 56289.125, 56292.199, 56304.086, 5...   \n",
       "1292  [56177.234, 56179.359, 56187.211, 56189.203, 5...   \n",
       "2542  [56176.238, 56179.266, 56180.328, 56188.238, 5...   \n",
       "2598  [56258.066, 56261.156, 56273.219, 56281.227, 5...   \n",
       "3644  [56177.234, 56179.359, 56187.211, 56189.203, 5...   \n",
       "\n",
       "                                              fluxcal_z  \\\n",
       "1186  [11.06, 9.393, 3.887, -0.519, 7.005, 33.13, 94...   \n",
       "1292  [49.68, 48.62, 42.8, 43.68, 33.21, 27.07, 21.5...   \n",
       "2542  [29.16, 46.65, 45.53, 64.54, 77.19, 75.92, 62....   \n",
       "2598  [4.218, 1.312, 0.01804, 25.39, 87.45, 116.4, 1...   \n",
       "3644  [-0.1238, -3.598, 15.7, 14.39, 136.5, 142.2, 1...   \n",
       "\n",
       "                                           fluxcalerr_z  snid       z  \\\n",
       "1186  [5.047, 5.425, 5.158, 3.934, 5.43, 4.443, 7.02...  1186  0.3698   \n",
       "1292  [4.784, 3.636, 2.322, 4.765, 5.671, 2.26, 1.86...  1292  0.3501   \n",
       "2542  [2.545, 3.832, 4.569, 3.611, 3.302, 2.779, 2.9...  2542  0.5415   \n",
       "2598  [3.968, 3.086, 2.251, 2.342, 3.062, 3.001, 3.2...  2598  0.3513   \n",
       "3644  [4.691, 3.518, 2.197, 4.702, 6.187, 3.451, 2.9...  3644  0.2705   \n",
       "\n",
       "             pkmjd  pkmag_g  pkmag_r  pkmag_i  pkmag_z  \n",
       "1186  56335.335938    23.07    22.27    22.21    22.43  \n",
       "1292  56164.195312    23.44    23.36    23.35    23.12  \n",
       "2542  56192.007812    24.17    22.79    22.81    22.85  \n",
       "2598  56301.996094    22.46    22.02    21.94    22.21  \n",
       "3644  56204.546875    22.18    22.13    22.00    22.15  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 5 first rows of the dataframe\n",
    "X.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And the labels, converted to a {0, 1} array."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>SNIa_True</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1186</th>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1292</th>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2542</th>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2598</th>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3644</th>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      SNIa_True\n",
       "1186          1\n",
       "1292          0\n",
       "2542          1\n",
       "2598          1\n",
       "3644          0"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the DataFrame, each supernova is indexed by its ID"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Int64Index([1186, 1292, 2542, 2598, 3644], dtype='int64')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.head().index"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "and can be accessed via the `loc` accessor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "mjd_g           [56283.203, 56288.199, 56292.098, 56304.051, 5...\n",
       "fluxcal_g       [3.182, -13.07, -7.177, -0.4645, 0.2906, 16.63...\n",
       "fluxcalerr_g    [6.285, 11.79, 11.65, 2.479, 7.569, 6.195, 3.6...\n",
       "mjd_r           [56283.211, 56288.215, 56292.102, 56304.055, 5...\n",
       "fluxcal_r       [-4.973, -6.427, 9.861, -1.663, 6.724, 23.82, ...\n",
       "fluxcalerr_r    [3.326, 6.181, 4.83, 1.657, 2.966, 2.553, 3.07...\n",
       "mjd_i           [56283.215, 56289.109, 56292.191, 56304.07, 56...\n",
       "fluxcal_i       [-0.615, -9.294, 0.8371, 0.6895, -1.593, 24.51...\n",
       "fluxcalerr_i    [5.816, 7.082, 5.599, 2.506, 5.021, 3.699, 4.5...\n",
       "mjd_z           [56283.223, 56289.125, 56292.199, 56304.086, 5...\n",
       "fluxcal_z       [11.06, 9.393, 3.887, -0.519, 7.005, 33.13, 94...\n",
       "fluxcalerr_z    [5.047, 5.425, 5.158, 3.934, 5.43, 4.443, 7.02...\n",
       "snid                                                         1186\n",
       "z                                                          0.3698\n",
       "pkmjd                                                     56335.3\n",
       "pkmag_g                                                     23.07\n",
       "pkmag_r                                                     22.27\n",
       "pkmag_i                                                     22.21\n",
       "pkmag_z                                                     22.43\n",
       "Name: 1186, dtype: object"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# SN 1186\n",
    "X.loc[1186]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "or via positional indexing with the `iloc` accessor."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Also SN 1186\n",
    "sn0 = X.iloc[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is a method to visualize the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "plt.style.use('seaborn')\n",
    "%matplotlib inline\n",
    "\n",
    "DES_FILTERS = 'griz'\n",
    "\n",
    "def plot_lightcurves(idx):\n",
    "    fig, axes = plt.subplots(2, 2, sharex=True, sharey=True, figsize=(12, 8))\n",
    "    for id_f, f in enumerate(DES_FILTERS):\n",
    "        ax = axes[id_f // 2, id_f % 2]\n",
    "        ax.errorbar(X.iloc[idx]['mjd_%s' % f], \n",
    "                    X.iloc[idx]['fluxcal_%s' % f], \n",
    "                    X.iloc[idx]['fluxcalerr_%s' % f], \n",
    "                    fmt='o')\n",
    "        ax.set_xlabel('MJD')\n",
    "        ax.set_ylabel('Calibrated flux')\n",
    "        ax.set_title('%s-band' % f)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Use this method to look at the raw light curves"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAtIAAAHtCAYAAAA0rplPAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzs3X+0XHV97//nIYGkSU7SGE5TcmMTrfZ9CbcIgsSgQmwVxNh4r9deq7XWgpYWvm2tNVqVxpZi/RGL1dYohXjR2tpbUdalcCncFkFq8FgUbeHA28oVNAsaDzGBkJBoTub7x8yBQzg/Z/ae2TPn+VgrK7M/M9n7dQ5rfT5vPvPZn91Xq9WQJEmSNDNHdTqAJEmS1I0spCVJkqQmWEhLkiRJTbCQliRJkppgIS1JkiQ1wUJakiRJaoKFtGadiLgyIt5W4vnvjIj1ZZ1fkmaLiFgfEXeWeP63RcSVZZ1fvc9CWpIkSWrC3E4HkIoUEb8PnAfsBb4E/NfMXD3OR18YEa8GFgM3Am/LzEMRcS5wPnAM8DTg/Zn58Yh4I/DfgMPAs4EfAm/IzDsjYg3wSWABcA+wsMQfUZJ6SuMbvI8A+6j3n6dl5sExH1kUEVcBzwL2AL+emd+KiJ8BPgYsAlYA3wBek5kHIuIA8H7gpY33PpKZfxYRRwMfbbR/H9gJPNyGH1M9yhlp9YyIOBt4I/A84BSgf5KPrwR+HjgJeA7w5ohYBLwZeHlmngy8BvjgmH9zJvBbmflfgC8Dmxrtfw1cnpknUh8MVhX1M0nSLPFfgNdm5nOOKKIBng5cmpknAX8D/FWj/c3ApzJzHfUi+xnAhsZ784CHMvMFwKuB90fEfOAC4GeANdSL6Z8q8WfSLGAhrV7ycuBzmbknM2vUZyom8leZuS8zfwh8BnhpZj4KvALYEBF/DLyb+kzHqK9l5o7G668DT4uIZcCJwKcBMvPLQGnr+SSpR30vM++f4L1/zcztjddXAqdGxBLgHcBwRLwd+Dj1meexffb/bvz9deqF9ULgJcDfZOYPM3Mf9YkQqWku7VAvOQT0jTkeAYiIb4xpe9PY9xr6gB9FxErgNuAvgX8GrqJeWI96bMzrWuPf1cacY2wOSdL0PQoQERcDGxtt1wA38eT+Gur97o+Az1KvY/4OuI767PLYvvgxgMysRQQ80WfbX6swzkirl1wH/PfGTAXU10rXMvOkMX9ub7z3SxExr/FV3xuB64FTgWHgksy8gUYRHRFzJrpgZv4A+BqNAj0ingv8bPE/miT1vszcPKa/3txofk5EnNR4fT7wz5m5HzgbuDgz/xf1AnktMGF/3fAPwBsiYn6j/39NCT+GZhFnpNUzMvOmiLgcuC0i9gN3Afsn+Ph3qM86LwKuBj4F/BhwLpARsQ/4KvXC+llTXPq1wP+MiN8Evg3c3erPIkl63N3AeyLimdRvEPzVRvu7gKsj4gfU+/pbmLq/vqzxmTuBXcC/l5JYs0ZfrVab+lNSF4iIU4HTM/OjjeO3Amsz0xkHSZJUOGek1Uu+BbwjIn6d+td83wV+vbORJElSr3JGWpIkSWqCNxtKkiRJTbCQliRJkppgIS1JkiQ1oStvNhwe3ltbunQBu3dPtLNZNZixdVXPB2YsymzKODDQ3zf1p3qHfXZxzNi6qucDMxalHX12185Iz5071Z7rnWfG1lU9H5ixKGbsbd3wuzNjMaqeser5wIxFaUfGri2kJUmSpE4qvZCOiLURcfMRba+LiNvGHL85Im6PiK9ExCvKziRJkiS1qtRCOiLeDlwBzB/TdjJwHtDXOP5J4LeBFwBnA++LiHll5pIkSZJaVfaM9L3Aq0YPImIZ8CfAW8Z85jTgy5l5MDMfBr4NnFhyLkmSJKklpe7akZmfj4jVABExB9gGvBV4bMzHFgMPjzneCyyZ7LxLly4AYGCgv8C05TBj66qeD8xYFDP2JvvsYpmxdVXPB2YsStkZ27n93SnAs4GPU1/qsSYi/gy4CRj7U/YDeyY70e7d+xkY6Gd4eG9ZWQthxtZVPR+YsSizKWM3DD5Fss8ujhlbV/V8YMaitKPPblshnZlfBU4AaMxS/21mvqWxRvq9ETEfmAccD9zZrlySJElSMzq+/V1m/gfwUeBW6rPT787MA51NJUmSJE2u9BnpzLwPeP5kbZl5OXB52VkkSZKkonR8RlqSJEnqRhbSkiRJUhMspCVJkqQmWEhLkiRJTbCQliRJkppgIS1JkiQ1wUJakiRJaoKFtCRJktQEC2lJkiSpCRbSkiRJUhMspCVJkqQmWEhLkiRJTbCQliRJkppgIS1JkiQ1YW7ZF4iItcAHMnN9RJwE/DkwAhwE3pCZOyPizcD5wCHgksy8tuxckiRJUitKnZGOiLcDVwDzG00fAX4rM9cDXwDeERE/Cfw28ALgbOB9ETGvzFySJEmz1aat29m0dXunY/SEspd23Au8aszxL2XmNxqv5wIHgNOAL2fmwcx8GPg2cGLJuSRJkmadwaGd7Hn0ILseOcDmbYMMDu3sdKSu1ler1Uq9QESsBv42M58/pu10YBtwBvVZ6J/NzHc03vs08OnM/MeJznno0Eht7tw5peaWpBL1dTpAO9lnS9XwpTt2sOUzX3tK+6bXn8IZJ6/sQKKuMWGfXfoa6SNFxGuAdwMbMnM4Ih4B+sd8pB/YM9k5du/ez8BAP8PDe0tM2joztq7q+cCMRZlNGQcG+qf+UA+xzy6OGVtX9XxQXsbP3nDPBO3J8SuXzOhcs+n3OFmf3dZCOiJeT/2mwvWZ+YNG81eB90bEfGAecDxwZztzSZIk9boHHto/bvuDu/a1OUnvaFshHRFzgI8C3wW+EBEAt2TmeyLio8Ct1NdsvzszD7QrlyRJ0myw4tgF7Bh+atF83LKFHUjTG0ovpDPzPmB0ffTTJvjM5cDlZWeRJEmarTasW81l19w1TvuqDqTpDW1fIy1JkqT2W7tmOQBXXDvEyOEaKwcWsWHdqsfbNXMW0pIkSbPE2jXLLZwL5CPCJUmSpCZYSEuSJElNsJCWJEmSmmAhLUmSJDXBQlqSJElqgoW0JEmS1AQLaUmSJKkJFtKSJElSEyykJUmSpCZYSEuSJElNsJCWJEmSmmAhLUmSJDVhbtkXiIi1wAcyc31EPAu4EqgBdwIXZubhiHgPsAE4BLwlM79adi5JkiSpFaXOSEfE24ErgPmNpkuBizLzRUAf8MqIeC5wJrAW+CXgY2VmkiRJkopQ9tKOe4FXjTk+Bbil8fp64CXAC4EbM7OWmd8F5kbEQMm5JEmSpJaUWkhn5ueBH41p6svMWuP1XmAJsBh4eMxnRtslSZKkyip9jfQRDo953Q/sAR5pvD6yfUJLly4AYGCgf7KPVYIZW1f1fGDGopixN9lnF8uMrat6PjBjUcrO2O5C+o6IWJ+ZNwPnAF8Evg18MCI+BKwEjsrMhyY7ye7d+xkY6Gd4eG/pgVthxtZVPR+YsSizKWM3DD5Fss8ujhlbV/V8YMaitKPPbnch/XvA5RFxDHA3cFVmjkTErcBt1JeaXNjmTJIkSaUbHNrJFdcOMXK4xsqBhWxYt5q1a5Z3OpZaUHohnZn3Ac9vvP4W9R06jvzMHwJ/WHYWSZKkThgc2sll19z1+PGO4X2PH1tMdy8fyCJJklSy6267b4L2+9uaQ8WykJYkSSrZAw/tH7f9wV372pykmjZt3c6mrds7HWPGLKQlSZJKtuLYBeO2H7dsYZuTVM/g0E72PHqQXY8cYPO2QQaHdnY60rRZSEuSJJVsw7rVE7Svam+QihldOz5yuP6YkdG1491STFtIS5IklWztmuWcv/EE5hzVB8DKgUWcv/GEWX+jYbevHW/39neSJEmz0to1y2d94Xykbl877oy0JEmSOqLb145bSEuSJKkjun3tuEs7JEmS1BGjS12eeOLjIjasW9U1S2CmnJGOiHPGaXtbOXEkSVXmmCCpaGvXLOfHF81j2eL5XHzeaV1TRMP0ZqTfHxG/APwesBK4EtgFfKjEXJKkanJMkFS4LRec3ukITZnOGulTgR8AdwL/CPxpZm4sNZUkqaocEySpYTqF9DOBFwAJPAKcERHj32IpSep1jgmS1DCdQvpLwJWZ+XLqMxE/oj4TIUmafRwTJKlhOmukT8nMHQCZeRDYFBGfb+ZiEXE08ClgNTACvBk4RH2NXY16Z3xhZh5u5vySpNIVNiZIUrebTiF9cUSM1/6VJq73cmBuZp4eES8F3gscDVyUmTdHxCeAVwJXN3FuSVL5ihwTJKmrTaeQvmXM66OBjcA9TV7vW8DciDgKWEz9K8Hnj7nG9cBZWEhLUlUVOSZIUlebspDOzE+NPY6IbcCXm7zeo9SXddwDHAu8AjgjM2uN9/cCS5o8tySpZAWPCZLU1Zp5suHxwHFNXu93gRsy850R8XTgJuCYMe/3A3umOsnSpfUbxAcG+puM0T5mbF3V84EZi2LGrjTlmGCfXSwztq7q+cCMRSk745SFdEQcpn4jYF+jaRh4Z5PX2019OQfU9yE9GrgjItZn5s3AOcAXpzzJ7v0MDPQzPLy3yRjtYcbWVT0fmLEosyljNww+E2lmTLDPLo4ZW1f1fGDGorSjz57O0o7pbJE3XR8GPhkRt1KfiX4XcDtweUQcA9wNXFXg9SRJBSp4TJCkrjZhIR0Rmyf7h5l58UwvlpmPAv9jnLfOnOm5JEntU8aYIEndbrKZhcXUv7qb6I8kafZwTJCkI0y2tOPMzHxeRGzNzAvalkiSVEWOCZJ0hMkK6UUR8RngZREx/8g3M/Pc8mJJkirGMUGSjjBZIX0W8GLgRTx5A35J0uzjmCBJR5iwkM7M7wGfjohvZuY325hJklQxjgmS9FRTbmNkhylJGuWYIElPcD9QSZIkqQkW0pIkSVITJnsgy3eoPwZ2XJn5zFISSZIqxzFBkp5qsl071lPfZH8z8P+AK4FDwC8Dzyg7mCSpUtbjmCBJTzLZrh33A0TEiUfsD/qnEfG10pNJkirDMUGSnmo6a6T7IuLFowcRcQ71WQhJ0uzjmCCp8jZt3c55l9xY+nUmW9ox6k3ApyJiReP4fuBXyoskSaowxwRJlTY4tJM9jx5k5HCNzdsG2bBuNWvXLC/lWlMW0pl5B3BiRCwDapn5g1KSSJIqzzFBUpUNDu3ksmvuevx4x/C+x4/LKKanXNoREasi4v8CXwGOiYibImJ14UkkSZXnmCCpyq677b4J2u8v5XrTWdpxGbAF+ACwE/gs8GngjGYuGBHvBDYCxwBbgVuo3/1dA+4ELszMw82cW5JUukLHBEkq0gMP7R+3/cFd+0q53nRuNjw2M28EyMxaZl4OLG7mYhGxHjgdeAFwJvB04FLgosx8EfWtlV7ZzLkldc6mrdvZtHV7p2OoPQobEySpaCuOXTBu+3HLFpZyvekU0o9FxEoaG/FHxAuBg01e72zg34Crgb8HrgVOoT4rDXA98JImzy1JKl+RY4IkFWrDutUTtK8q5XrTWdrxVuoF709HxDeApwG/2OT1jgVWAa+gvoH/NcBRmTn6tKy9wJKpTrJ0af3/NgYG+puM0T5mbF3V88HszvilO3awZ99BRkZqXPyp2/nFn382Z5y8sqlzzebfYxeZ8Zhgn10sM7au6vnAjM16xZn9LF48nw9/9uscGqmx+rjFLY1LU5lOIf1t4HnAzwBzgHuA45q83i7gnsz8IZARcYD68o5R/cCeqU6ye/d+Bgb6GR7e22SM9jBj66qeD2Z3xiPvjr7vwUfY8pmv8cgjB2Z8d/Rs+j1WcfCZgRmPCfbZxTFj66qeD8zYquNXLmHJwnnMmdPH5l89FaClrJP12RMu7YiIp0fETwG3Aj9JfbZ4D7ASuKHJLP8MvCwi+hp7kC4E/qmxdhrgnMb1JHWBdt8drc4paUyQpFJsueB0tl10VunXmWxG+o+AFwMrgC+NaT9E/Wu9GcvMayPiDOCr1Iv4C4HvAJdHxDHA3cBVzZxbUvu1++5odVThY4IkdbsJC+nMPBcgIt6RmR8o6oKZ+fZxms8s6vzSbDO6W8aWC05v+7VXHLuAHcNPLZrLujtanVPWmCBJ3Ww6a6SvjIjfBRZR355uDvCMzHxDqckkTamdj0Edz4Z1q5+0RvqJ9nLujlYlOCZIUsN0tr/7PHAS8Hrqa5o3Aj4wReqw0Rv9Rg7XN70ZfQzq4NDOtmVYu2Y55288gTlH9QGwcmAR5288oa3FvNrOMUGSGqYzI31sZr4wIj4EfAH4E+Afy40laSqT3ejXzkJ27ZrlFs6zi2OCJDVMZ0Z6d+PvBJ6TmQ8DR5cXSdJ0eKOfOsQxQZIapjMjfVNEfA54G3BjRDwXOFBuLElT8UY/dYhjgiQ1TGdG+sPA72fm/cBrqc9CvKrUVJKm1O7HoEoNjgmS1DCdGelbM/N4gMz8OvD1ciNJmo7RdclXXDvEyOEaKwcWsWHdKtcrq2yOCZLUMJ1C+psR8SvUH6Ly2GhjZn63tFSSpsUb/dQBjgmS1DCdQnpt489YNeCZxceRJFWcY4IkNUxZSGfmM9oRRJJUfY4JkvSEKQvpiFgCbAbWAz8C/i/wvswcf+8tSVLPckyQpCdMZ9eObcAh4I3ArwP9wF+WmEmSVF2OCZLUMJ010s/KzFePOX5LRPxrWYEkSZXmmCBJDdOZkc6IWDd6EBHPAf69vEiSpApzTJCkhglnpCPiO9TvxP4x4NURcQ8wAhxPi51mRPwE8DXgpdS/Iryyca07gQsz83Ar55ckFavMMUGSutVkSzvWl3HBiDgauIwn9h+9FLgoM2+OiE8ArwSuLuPakqSmre90AEmqmsmWdvxs4xGwZ07wp1kfAj4BPNA4PgW4pfH6euAlLZxbkti0dTubtm7vdIxeU9aYIElda7IZ6ecB1wIvHue9GvDpmV4sIt4IDGfmDRHxzkZzX2bWGq/3AkumOs/SpQsAGBjon2mEtjNj66qeD8xYlKIyzpnTV+j5xuqG32NJmh4T7LOLZcbWVT0fmLEoZWecsJDOzPc0/v61Aq93LlCLiJcAJ1HveH9izPv9wJ6pTrJ7934GBvoZHt5bYLTimbF1Vc8HZixKkRlHRur/b170z1xUxm4YfI7Uyphgn10cM7au6vnAjEVpR589nZsNx5WZM34cbGaeMeb8NwO/AWyJiPWZeTNwDvDFmZ5XklSuMsYESep2bb/ZcBy/B1weEccAdwNXtem6kqTpW9/pAJJUNZMt7bgfICLmAS8HFgF9wBzgGdQfEdu0zFw/5tAbVSQVYnBoJ3sePcjI4Rqbtw2yYd1q1q5Z3ulYXa/sMUGSutF0nmz4BWAB8CzgVuAM4LYyQ0lSMwaHdnLZNXc9frxjeN/jxxbThXFMkKSG6TzZMICfo7638weB04D/VGYoSWrGdbfdN0H7/W3N0eMcEySpYTqF9M7G9nT3ACdm5gPAvHJjSdLMPfDQ/nHbH9y1r81JeppjgiQ1TGdpx10R8efAx4G/jogVwNHlxpKkmVtx7AJ2DD+1aD5u2cIOpOlZjgmS1DCdGenfBP4uM4eo30xyHPC6UlNJUhM2rFs9Qfuq9gbpbY4JktQw6Yx0RCwF5mTmrY2mR4BLMnO49GSSNEOjNxRece0QI4drrBxYxIZ1q7zRsCCOCZL0ZBPOSEfEycAQcOqY5rOAb0TEiWUHk6RmrF2znB9fNI9li+dz8XmnWUQXxDFBkp5qsqUdHwJem5n/MNqQme+m/pjvS8sOJkmqFMcESTrCZIX00sZju58kM28Aji0tkSSpihwTJOkIkxXSR0fEU95vtB1TXiRJUgU5JkjSESa72fAW4D2NP2NdBNxeWiJJatGWC07vdIRe5Jigrjc4tJMrrvsiIyM1Vg4sZMO61d5HoZZMVki/E/g/EfHLwL8AfcBzge8DG9uQTZJUHY4J6mqDQzu57Jq7Hj/eMbzv8WOLaTVrwkI6M/dGxBnAi4GTgcPAx8ZseyRJmiUcE9Ttrrvtvgna77eQVtMm3Ue68RjYmxp/JEmzmGOCutkDD+0ft/3BXU99Gqo0XdN5RHhhIuJo4JPAamAecAn1fUmvBGrAncCFmXm4nbmkZm3aup05c/p4//nrOh1FkjSJFccuYMfwU4vm45Yt7EAa9YrpPCK8SK8HdmXmi4CXAX9Bff/RixptfcAr25xJkiT1uA3rVk/Qvqq9QdRT2jojDXwOuKrxug84BJxC/W5wgOupPynr6jbnkiRJPWx0HfQN//I9vrdzL8ctW8iGdatcH62W9NVqtbZfNCL6gWuAy4EPZeaKRvvPAedm5usn+/eHDo3U5s6dU35QaQrnXXIjANsuOqvDSVS2gv9b9xVxkm5hny2py03YZ7d7RpqIeDr1Geetmfk3EfHBMW/3A3umOsfu3fsZGOhneHhvWTELYcbWVTnf4NBOdj18gJHDNX7z/f9Y6f1Iq/x7HFX1jCMjNebM6Ssk48BAfwGJuod9dnHM2Lqq5wMzFqWojJP12W1dIx0Ry4EbgXdk5icbzXdExPrG63MAt1JS5Y3uRzpyuP6Nzuh+pINDOzucTJIktUu7Z6TfBSwF/iAi/qDR9jvARyPiGOBunlhDLVWW+5FKkqS2FtKZ+TvUC+cjndnOHFKr3I9UkiS1e/s7qSesOHbBuO3uR9qbBod2sufRg3x/92Ns3jboEh5JEmAhLTXF/UhnD9fDa9SmrdvZtHV7p2NIqhALaakJa9cs5/yNJzDnqPqOOCsHFnH+xhNcH92DJlsPL0ma3SykpSatXbOcH180j59Y+mNcfN5pFtE9yvXwgieW9+x65IDLeyQ9zkJakibheni5vEfSRCykJWkSroeXy3skTaTtTzaUesmWC07viqc7qXmjS3auuHaIkcM1Vg4sYsO6VS7lmUVc3lOc0Zs1t1xweoeTSMWYNTPS3m0tqVmuh5/dXN5TDNeZqxfNmkJavcn/QZJUNpf3tM515upVFtKSJE3C7S5b5zpz9SrXSEvSNLgefnZbu2Y5V918LwAXn3dah9N0H9eZq1fNihlp12VJktQ5rjNXr+r5GenRdVmjRtdlAR39Ws47lyWpu9hfN2/DutVPGoufaHedubpbzxfSk63Lcn2bJEnlGx1vr7vtfh7ctY/jli10G0n1hEoU0hFxFLAVeA5wEHhTZn67iHO7Lqt3jS7ZGTlcY/O2QTasW22nLEkVtXbNcvto9ZxKFNLAfwXmZ+a6iHg+8KfAK4s48YpjF7Bj+KlFs+uyWjM4tHPMAyoWtr2IreqSHUmSNHtU5WbDFwL/AJCZXwFOLerE7v9ZvCrsB+pWSpI0fYNDO9m8bZA3feCL3nQvFagqM9KLgYfHHI9ExNzMPDTeh5curd/9OzDQP+WJX3FmP4sXz+fDn/06h0ZqrD5uMb/488/mjJNXFpF7ShNlnDOnb9L322mmGW74l9snaP8erzjzWUVEepLx8j2wa+IlO534nVbhv+NUzFiMbshYNTPps8t03iU3ArDtorMm/EynM07HTDN+6Y4d436Dt3jx/NLGwqr/HqueD8xYlLIzVqWQfgQY+5MeNVERDbB79/4Z7ed6/MolLFk4D4DNv1qf7G7HXrCTZRwZqbUtx2Sa2Rf3u/8x/ue/t3Nv4T/PRPlWLJt4yU67f6fdsLewGYtRVMZuGHyKNNM+uyxT9btVyDiVZjJ+9oZ7JmhPjl+5pIhYT1L132PV84EZi9KOPrsqSzu+DLwcoLFG+t86G2dqs/nR1FXYD9QlO1Jvm819bNG86V4qT1UK6auBAxGxHfgw8LsdzqNJVKGI9ZG9Uu/yIVrFqsLkh9SrKrG0IzMPA79R5jXcSL84VdkP1Ef2Sr2nrB15ZvN2mT4MRSpPJQrp2aYXOnT3A5VUhjIeojXbt8usyuSH1IsspNtstnfokjSZMtbz+oRbJz+kslRljfSs4f7HkjSxMtbzerOdpLJYSLeZHXqxtlxwuuvfpR5Sxs3M3mwnqSwW0m1mhy5JExvdkWflwCLmHNVXyI48VdhpSFJvco10m3n3tCRNruj1vKPnuuLaIUYO11g5sMib7SQVwkK6zezQJan93C5TUhlc2tGEVh8WsHbNcn580TyWLZ7PxeedZhEtSZLUhZyRniG3r5MkSRJYSM+Y+5FKUndyhx9JRXNpxwy5fZ0kSZLAQnrG3L5OkiRJYCE9Y+5HKkmSJHCN9Iy5fZ0kSZKgzYV0RCwBPgMsBo4B3pqZt0XE84GPAIeAGzPzj9qZa6bcj1SSJEntXtrxVuCfMvNM4I3AxxrtnwBeB7wQWBsRJ7c5lyRJkjQj7V7a8WHg4JhrH4iIxcC8zLwXICJuAF4C3NHmbG3lNkySJEndrbRCOiLOA373iOZfy8x/iYifpL7E4y3Ul3k8MuYze4FnTnbupUvrO2cMDPQXlnem5szpm1aGTmacrqpnrHo+MGNRzNibqtBnT5cZi1H1jFXPB2YsStkZSyukM3MbsO3I9oj4WeBvgbdl5i2NGemxP2U/sGeyc+/evZ+BgX6Gh/cWGXlGRkZqAJNm6HTG6ah6xqrnAzMWZTZl7IbBp0hV6LOnw4zFqHrGqucDMxalHX12W9dIR8Qa4HPA6zLzeoDMfAT4YUT8dET0AWcDt7YzlyRJkjRT7V4j/T5gPvCRiAB4ODNfCfwG8NfAHOq7dgy2OZckSZI0I20tpBtF83jtXwGe384skiRJUit8sqEkSZLUBJ9s2CS3r5MkSZrdnJGWJEmSmmAhLUmSJDXBQlqSJElqgoW0JEmS1AQLaUmSJKkJFtKSJElSEyykJUmSpCZYSEuSJElN6KvVap3OIEmSJHUdZ6QlSZKkJlhIS5IkSU2wkJYkSZKaMLfTAaR2iYjVwHeAv8zM88e0nwTcAfxaZl455rM3Z+bqiHgjcCnwXaAPmA9cA/x+Zo608UeQpFnDPlvdwBlpzTa7gJdFxJwxba8Bhqf4d9dk5kmZ+RzgFOBk4A/LiShJarDPVqVZSGu2eZT6TMYZY9rOAv5xuifIzEeBdwG/GRF9xcaTJI1hn61Ks5DWbPR3wKsBIuJ5wL8CP5zhOe4ElgEDxUaTJB3BPluVZSGt2ejvgXMi4ijqXxH+rybOMboB+2OFpZIkjcc+W5VUWKVLAAAgAElEQVRlIa1ZJzP3At8EXgj8HE98RXhMRJzceN0HHJrkNCcCOxrnkiSVxD5bVWYhrdnq74D3A7dn5mjnexzwzsbrE4H/N94/jIglwB8DHys7pCQJsM9WRbn9nWarvwe2AX8wpm0ncHJE3En9a8A3jnlvY0R8o9E+F7gK+GB7okrSrGefrUrqq9VqU39KkiRJ0pO4tEOSJElqgoW0JEmS1AQLaUmSJKkJFtKSJElSEyykJUmSpCZYSEuSJElNsJCWJEmSmmAhLUmSJDXBQlqSJElqgoW0JEmS1AQLaUmSJKkJFtKSJElSEyyk1ZMi4tSIuGqc9isj4m0lXvfOiFhf1vklabaJiPURcWeJ539bRFxZ1vnV2+Z2OoBUhsy8HXh1p3NIkqTeZSGtntSYFf6LzPwv47z9woh4NbAYuBF4W2YeiohzgfOBY4CnAe/PzI9HxBuB/wYcBp4N/BB4Q2beGRFrgE8CC4B7gIXl/mSS1Dsi4kLgzWOa1gAfyMw/OOKjixrfMj4L2AP8emZ+KyJ+BvgYsAhYAXwDeE1mHoiIA8D7gZc23vtIZv5ZRBwNfLTR/n1gJ/BwaT+keppLOzQbrQR+HjgJeA7w5ohYRL0zf3lmngy8BvjgmH9zJvBbjcL8y8CmRvtfA5dn5onAR4BV7fkRJKn7ZebHMvOkzDwJuAz4JvXi90hPBy5tfO5vgL9qtL8Z+FRmrqNeZD8D2NB4bx7wUGa+gPo3lO+PiPnABcDPUC/aXwr8VCk/nGYFC2nNRn+Vmfsy84fAZ4CXZuajwCuADRHxx8C7qc9wjPpaZu5ovP468LSIWAacCHwaIDO/DJS2jk+SelVE/DfgbcAvZOa+cT7yr5m5vfH6SuDUiFgCvAMYjoi3Ax+nPvM8tu/+342/v069sF4IvAT4m8z8YeNaf130z6PZw6Ud6mkR8Y0xh29q/D0ypq0P+FFErARuA/4S+GfgKuqF9ajHxryuNf5dbcw5Rh0qILYkzRoR8QLqyzNekpn/EREXAxsbb18D3MST+22o978/Aj5LvZb5O+A66rPLY/vkxwAysxYR8ETfbb+tQjgjrZ42+pVh48/tjeZfioh5ja/43ghcD5wKDAOXZOYNNIroiJgzybl/AHyNRoEeEc8Ffra0H0aSekzjPpPPAa/LzCGAzNw8pt/e3PjocyLipMbr84F/zsz9wNnAxZn5v6gXyGuBCfvthn8A3hAR8xvjwGsK/rE0izgjrdnoO9RnnRcBVwOfAn4MOBfIiNgHfJV6Yf2sKc71WuB/RsRvAt8G7i4rtCT1oA9Tv8H7QxExWpPcnplvOuJzdwPviYhnUr9B8Fcb7e8Cro6IHwD7gVuYut++rPGZO4FdwL+3/FNo1uqr1WpTf0qSJEnSk7i0Q5IkSWqChbQkSZLUBAtpSZIkqQkW0pIkSVITLKQlSZKkJnTl9nfDw3trS5cuYPfu/Z2OMikztq7q+cCMRZlNGQcG+vum/lTvsM8ujhlbV/V8YMaitKPP7toZ6blzp9pvvfPM2Lqq5wMzFsWMva0bfndmLEbVM1Y9H5ixKO3I2LWFtCRJktRJpRfSEbE2Im4+ou11EXHbmOM3R8TtEfGViHhF2ZkkSZKkVpVaSEfE24ErgPlj2k4GzgP6Gsc/Cfw28ALgbOB9ETGvzFySJElSq8qekb4XeNXoQUQsA/4EeMuYz5wGfDkzD2bmw8C3gRNLziVJkiS1pNRCOjM/D/wIICLmANuAtwJ7x3xsMfDwmOO9wJIyc0mSJEmt6qvVaqVeICJWA39LffnG/wSGqS/1WAN8ErgJeFlmXtD4/NXAezPz9onOeejQSK0b7haVpAnMqu3v7LMldbkJ++y27SOdmV8FToAniuvMfEtjjfR7I2I+MA84HrhzsnPt3r2fgYF+hof3TvaxjjNj66qeD8xYlNmUcWCgv4A03cM+uzhmbF3V84EZi9KOPrvj299l5n8AHwVupT47/e7MPNDZVJJasWnrdjZt3d7pGJIklar0GenMvA94/mRtmXk5cHnZWSSVb3BoJ3sePcjI4Rqbtw2yYd1q1q5Z3ulYkiQVrisfES6pmgaHdnLZNXc9frxjeN/jxxbTkqRe0/GlHZJ6x3W33TdB+/1tzSFJUjtYSEsqzAMP7R+3/cFd+9qcRJKk8llISyrMimMXjNt+3LKFbU4iSVL5LKQlFWbDutUTtK9qbxBJktrAmw0lFWb0hsIrrh1i5HCNlQOL2LBulTcaSpJ6koW0pEKtXbOcq26+F4CLzzutw2kkSSqPhbSkwm254PROR5AkqXSukZYkSZKaYCEtSZIkNcFCWpIkSWqChbQkSZLUBAtpSZIkqQkW0pIkSVITSt/+LiLWAh/IzPURcRLw58AIcBB4Q2bujIg3A+cDh4BLMvPasnNJkiRJrSh1Rjoi3g5cAcxvNH0E+K3MXA98AXhHRPwk8NvAC4CzgfdFxLwyc0mSJEmtKntpx73Aq8Yc/1JmfqPxei5wADgN+HJmHszMh4FvAyeWnEuSJElqSamFdGZ+HvjRmOMHASLidOD/Az4MLAYeHvPP9gJLyswlSZIktartjwiPiNcA7wY2ZOZwRDwC9I/5SD+wZ7JzLF26AICBgf7JPlYJZmxd1fOBGYtixt5kn10sM7au6vnAjEUpO2NbC+mIeD31mwrXZ+YPGs1fBd4bEfOBecDxwJ2TnWf37v0MDPQzPLy31LytMmPrqp4PzFiU2ZSxGwafItlnF8eMrat6PjBjUdrRZ7etkI6IOcBHge8CX4gIgFsy8z0R8VHgVupLTd6dmQfalUuSJElqRumFdGbeBzy/cfi0CT5zOXB52VkkSZKkovhAFkk9b9PW7Wzaur3TMSRJPcZCWpIkaRZzsqF5FtKSJElSEyykJUmSZqnBoZ3sefQgux45wOZtgwwO7ex0pK5iIS2ppzlISNL4Bod2ctk1dzFyuAbAjuF9XHbNXfaTM2AhLalnOUhI0sSuu+2+Cdrvb2uObmYhLalnOUhI0sQeeGj/uO0P7trX5iTdy0JaUs9ykJCkia04dsG47cctW9jmJN3LQlpSz3KQkKSJbVi3eoL2Ve0N0sUspCX1LAcJSZrY2jXLOX/jCcw5qg+AlQOLOH/jCaxds7zDybpH6Y8Il1Su0U30t1xweoeTVM/oYHDFtUOMHK6xcmARG9atcpCQpIa1a5Zz1c33AnDxead1OE33sZCW1NMcJCRpck7ENM+lHVIXc49kSZI6xxlpqUuN7pE8anSPZMClC5IktYGFtNSlJtsj2UL6yfzaUpJUhtIL6YhYC3wgM9dHxLOAK4EacCdwYWYejoj3ABuAQ8BbMvOrZeeSup17JEuS1FmlrpGOiLcDVwDzG02XAhdl5ouAPuCVEfFc4ExgLfBLwMfKzCT1CvdIlqTus2nr9sd3W1L3K/tmw3uBV405PgW4pfH6euAlwAuBGzOzlpnfBeZGxEDJuaSu5x7JkiR1VqlLOzLz8xGxekxTX2bWGq/3AkuAxcCuMZ8ZbR+e6LxLl9Zn4gYG+ouMWwoztq7q+aAzGV9xZj+LF8/nw5/9OodGaqw+bjG/+PPP5oyTV477eX+PrTnvkhsB2HbRWR1O0n3ss4tlxtZ1Mt+cOX3TylD13yGYEdp/s+HhMa/7gT3AI43XR7ZPaPfu/QwM9DM8vLf4hAUyY+uqng86m/H4lUtYsnAeAJt/9VSAcbP4e2zdyEiNOXP6CsnYDYNPkeyzi2PG1nU638hIfT5xsgydzjgdsynjZH12u/eRviMi1jdenwPcCnwZODsijoqInwKOysyH2pxL6lpbLjjdXSkkqQu493/vafeM9O8Bl0fEMcDdwFWZORIRtwK3US/sL2xzJkmSpFK5939vKr2Qzsz7gOc3Xn+L+g4dR37mD4E/LDuLJElSJ7j3f2/yEeGSNIXRr2O/v/sxv46V1BT3/u9NFtKSNInRr2NHDtdvEBr9OtZiWtJMuPd/b7KQlqRJTPZ1rCRNl3v/96Z232woSV3Fr2MlFWF0HfQV1w4xcrjGyoFFbFi3yvXRXc4ZaUmahF/HSirK2jXL+fFF81i2eD4Xn3eaRXQPsJCWpEn4dawkaSIu7ZCkSfh1rCRpIhbSkjSFtWuWc9XN9zJnTh8Xn3dap+NIkirCQlqSJKlNtlxweqcjqEBTrpGOiHPGaXtbOXEkSVXmmCBJT5jOjPT7I+IXgN8DVgJXAruAD5WYS5IqZcsFpzMw0M/w8N5OR+k0xwRJapjOrh2nAj8A7gT+EfjTzNxYaipJUlU5JkhSw3QK6WcCLwASeAQ4IyLG31hVktTrHBMkqWE6hfSXgCsz8+XUZyJ+RH0mQpI0+zgmSFLDdNZIn5KZOwAy8yCwKSI+38zFIuJo4FPAamAEeDNwiPoauxr1zvjCzDzczPklSaUrbEyQpGZt2rod6PwuKNMppC+OiPHav9LE9V4OzM3M0yPipcB7gaOBizLz5oj4BPBK4Oomzi1JKl+RY4IkdbXpFNK3jHl9NLARuKfJ630LmBsRRwGLqX8l+Pwx17geOAsLaUmqqiLHBEnqan21Wm1G/yAi+oAvZ+aM59Ij4unA/wYWAccCrwCuyswVjfd/Djg3M18/2XkOHRqpzZ07Z6aXl6Sq6Ot0gKJMZ0ywz5ZUpC/dsYNLP/t1RkZqrD5uMb/488/mjJNXlnnJCfvsZp5seDxwXJNBfhe4ITPf2SiqbwKOGfN+P7BnqpPs3r2/K/ZzNWPrqp4PzFiU2ZRxYKC/gDSVMeWYYJ9dHDO2rur5wIyTGRzayWXX3PX48X0PPsKWz3yNRx45wNo1y5/02Xb02VMW0hFxmPqNgKPV+DDwziaz7Ka+nAPq+5AeDdwREesz82bgHOCLTZ5bklSygscESZqR6267b4L2+59SSLfDlIV0Zk5ni7zp+jDwyYi4lfpM9LuA24HLI+IY4G7gqgKvJ0kqUMFjgiTNyAMP7R+3/cFd+9qcpG7CQjoiNk/2DzPz4pleLDMfBf7HOG+dOdNzSZLap4wxQZJmasWxC9gx/NSi+bhlCzuQZvIHsiym/tXdRH8kSbOHY4KkjtuwbvUE7avaG6RhsqUdZ2bm8yJia2Ze0LZEkqQqckyQ1HGj66CvuHaIkcM1Vg4sYsO6VR1ZHw2TF9KLIuIzwMsiYv6Rb2bmueXFkiRVjGOCpEpYu2Y5V918LwAXn3daR7NMVkifBbwYeBFP3oBfkjT7OCZI0hEmLKQz83vApyPim5n5zTZmkiRVjGOCpCrZcsGMnwtYiim3MbLDlCSNckyQpCe4H6gkSZLUBAtpSZIkqQmTPZDlO9QfAzuuzHxmKYkkSZXjmCCpm23auh0ofm31ZLt2rKe+yf5m4P8BVwKHgF8GnlFoCklS1a3HMUGSnmSyXTvuB4iIE4/YH/RPI+JrpSeTJFWGY4IkPdV01kj3RcSLRw8i4hzqsxCSpNnHMUGSGiZb2jHqTcCnImJF4/h+4FfKiyRJqjDHBEldZXBoJ3sePcjI4Rqbtw2yYd3qwh4pPmUhnZl3ACdGxDKglpk/KOTKkqSu45ggqZsMDu3ksmvuevx4x/C+x4+LKKanLKQjYhVwBbAaeFFE3AScm5n3NXPBiHgnsBE4BthK/VGzV1K/G/xO4MLMPNzMuSVJ5Sp6TJCkMl13230TtN9fSCE9nTXSlwFbgEeBncBngU83c7GIWA+cDrwAOBN4OnApcFFmvoj6HeGvbObckqS2KGxMkKSyPfDQ/nHbH9y1r5DzT6eQPjYzbwTIzFpmXg4sbvJ6ZwP/BlwN/D1wLXAK9VlpgOuBlzR5bklS+YocEySpVCuOXTBu+3HLFhZy/uncbPhYRKyksRF/RLwQONjk9Y4FVgGvoL7v6DXAUZk5usn/XmDJVCdZurT+SxkY6G8yRvuYsXVVzwdmLIoZu8KMxwT77GKZsXVVzwdmLMprz/7PbPnMU3fofO3ZUUj+6RTSb6U+c/zTEfEN4GnALzZ5vV3APZn5QyAj4gD15R2j+oE9U51k9+79DAz0Mzy8t8kY7WHG1lU9H5ixKLMpYzcMPpOY8Zhgn10cM7au6vnAjEUZGOjn+JVLOH/jCVxx7RAjh2usHFjEhnWrOH7lkmnnn6zPnk4h/W3gecDPAHOAe4DjpnXlp/pn4Hci4tLGORYC/xQR6zPzZuAc4ItNnluSVL4ixwRJKt3aNcu56uZ7Abj4vNMKPfeEhXREPJ36zX//h3qBO1q2r2y0/eeZXiwzr42IM4CvUl+ffSHwHeDyiDgGuBu4aqbnlSSVq4wxQZK63WQz0n8EvBhYAXxpTPsh6l/rNSUz3z5O85nNnk+S1BaljAmS1M0mLKQz81yAiHhHZn6gfZEkSVXjmCCpm2254PRSzjudNdJXRsTvAouof603B3hGZr6hlESSpCpzTJCkhunsI/154CTg9dRvDtwI+ORBSZqdHBMkqWG6D2T5VeoPUPkCsB44ocxQkqTKckyQpIbpFNK7G38n8JzMfBg4urxIkqQKc0yQpIbprJG+KSI+B7wNuDEingscKDeWJKmiHBMkqWE6M9IfBn4/M+8HXkt9FuJVpaaSJFWVY4IkNUxnRvrWzDweIDO/Dny93EiSpApzTJCkhukU0t+MiF+h/jTCx0YbM/O7paWSJFWVY4IkNUynkF7b+DNWDXhm8XEkSRXnmCBJDVMW0pn5jHYEkSRVn2OCJD1hykI6IpYAm6nvFfoj4P8C78vM/eVGkyRVjWOCJD1hOrt2bAMOAW8Efh3oB/6yxEySpOpyTJCkhumskX5WZr56zPFbIuJfywokSao0xwRJaphOIZ0RsS4zbwOIiOcA/97KRSPiJ4CvAS+lPrNxJfWbVe4ELszMw62cX5JUmsLHBEnqVhMW0hHxHerF7Y8Br46Ie4AR4Hha6DQj4mjgMp7YNulS4KLMvDkiPgG8Eri62fNLkopX1pggSd1sshnp9SVd80PAJ4B3No5PAW5pvL4eOAsLaUmqmvWdDiBJVTNZIf2zmXltRLxhgvc/PdOLRcQbgeHMvCEiRgvpvsysNV7vBZZMdZ6lSxcAMDDQP9MIbWfG1lU9H5ixKGastKbHBPvsYpmxdVXPB2YsStkZJyuknwdcC7x4nPdqNFFIA+cCtYh4CXBS4xw/Meb9fmDPVCfZvXs/AwP9DA/vbSJC+5ixdVXPB2YsymzK2A2DzziaHhPss4tjxtZVPR+YsSjt6LMnLKQz8z2Nv3+t5QRPnPOM0dcRcTPwG8CWiFifmTcD5wBfLOp6kqRilDEmSFK3m87NhuPKzKIeB/t7wOURcQxwN3BVQeeVJBWkjWOCVKrzLrmRkZEaWy44vdNR1AM6cbMhAJk59vxnlnktSVLL1nc6gCRVzWRLO+4HiIh5wMuBRUAfMAd4BvVHxEqSZgHHBPWCwaGd7HrkACMjNTZvG2TDutWsXbO807HUxabzQJYvAAuAZwG3AmcAt5UZSpJUWY4J6kqDQzu57Jq7Hj/eMbzv8WOLaTXrqGl8JoCfo7638weB04D/VGYoSVJlOSaoK113230TtN/f1hzqLdMppHc29nm+BzgxMx8A5pUbS5JUUY4J6koPPLR/3PYHd+1rcxL1kuks7bgrIv4c+Djw1xGxAji63FiSpIpyTFBXWnHsAnYMP7VoPm7Zwg6kUa+Yzoz0bwJ/l5lD1G8mOQ54XampJElV5ZigrrRh3eoJ2le1N4h6yqQz0hGxFJiTmbc2mh4BLsnM4dKTSZIqxTFB3Wz0hsJt1w1xaKTGyoFFbFi3yhsN1ZIJZ6Qj4mRgCDh1TPNZwDci4sSyg0mSqsMxQb1g7ZrlPG3xfJYtns/F551mEa2WTba040PAazPzH0YbMvPdwLnApWUHk7rBpq3bOe+SGzsdQ2oHxwT1hG0XneVTDVWYyQrppZl585GNmXkDcGxpiaQuMTi0kz2PHuT7ux9j87ZBBod2djqSVCbHBEk6wmSF9NER8ZT3G23HlBdJqr7Rjf1HDteAJzb2t5hWD3NMkKQjTFZI3wK8Z5z2i4Dby4kjdQc39tcs5JggSUeYbNeOdwL/JyJ+GfgXoA94LvB9YGMbskmV5cb+moUcEyTpCBMW0pm5NyLOAF4MnAwcBj42ZtsjadZyY3/NNo4JkvRUk+4j3XgM7E2NPy2LiKOBTwKrqT9S9hLq2yldCdSAO4ELM/NwEdeTyrJh3Wouu+aucdrd2F+9q+gxQZK63XSebFik1wO7MvNFwMuAv6C+bdJFjbY+4JVtziTN2No1yzl/4wnMOaoPgJUDizh/4wnuSSpJ0iwy6Yx0CT4HXNV43QccAk6hfhMLwPXUN/i/us25pBlbu2Y5a9csZ2Cgn+HhvZ2OI0mS2qyvVqu1/aIR0Q9cA1wOfCgzVzTafw44NzNfP9m/P3RopDZ37pzyg0pSOfo6HaCd7LMldbkJ++x2z0gTEU+nPuO8NTP/JiI+OObtfmDPVOfYvXt/V8wCmrF1Vc8HZizKbMo4MNBfQJruYZ9dHDO2rur5wIxFaUef3dY10hGxHLgReEdmfrLRfEdErG+8PgfwDnBJkiRVXrtnpN8FLAX+ICL+oNH2O8BHI+IY4G6eWEMtSZIkVVZbC+nM/B3qhfORzmxnDkmSJKlV7d7+TpKkKW3aup1NW7d3OoYkTcpCWpI061ioSyqChbQkqVIGh3ay59GD7HrkAJu3DTI4tLPTkSRpXG3f/k6SpIkMDu3ksmvuevx4x/C+x499cqikqnFGWpJUGdfddt8E7fcXdg1nvDvHJTXqNRbSkqTKeOCh/eO2P7hrXyHnH53xHjlcf6rv6Iy3xbSkZlhIS5IqY8WxC8ZtP27ZwkLO344Zb0mzh4W0JKkyNqxbPUH7qkLO38qMt8sSWuOSGvUibzaUJFXG6A2FV1w7xMjhGisHFrFh3arCbjRccewCdgw/tWguasZb4/MmUvUqZ6QlSZWyds1yfnzRPJYtns/F551WaKFV9oy3xueSGvUqC+kO8mtCSWqvtWuWc/7GE5hzVB8AKwcWcf7GE6Ys1l2W0JqybyKVOsWlHZKkytlywemlnXvtmuVcdfO9AFx83mlTft5lCa1zSY161ayZkXb2V5LUDJcltM4lNepVzkh3yOjXhCOHa2zeNsiGdaud2ZCkNpnJjLfLElpX9k2kUqdUopCOiKOArcBzgIPAmzLz251NVZ5e+JpwcGjnmA5xYcf+R2D0W4YyvwaWNLv1yrKETveXM11SI3WDqizt+K/A/MxcB/w+8KdFnrxqN4l0+9eEPhlM0mzSC8sSqjYOSr2iKoX0C4F/AMjMrwCnFnXiKhZ93f41YVX+R8CBQVI7NLvTR1VUaRzccsHpfoOonlKJpR3AYuDhMccjETE3Mw+N9+Gl/397dx9sR13fcfx9kxii9SYDeiUyhGLR+SqOYAYRGIH4QI0o4jg6o8PYEfABrFpF2zHaijqW2qm2SGssIw2CoqiI+IBDQUUUER/QYA3FL/WhVUSYCBECmECS0z9+m+EQ7iW5e3bP2Zvzfv11796zez939+73fHf3d3b3LI+QnZqa3OmCL//hdTNM/w3HrXjirIPO1nQZ91s6yf/+7q6HTF+29+Qu/U1Nm+3vvOX2mQ8E2sg/3TK/vfbmaYfHLF68iKOX79t4hp0ZxXabLTM2Yy5k7JrZ1OxRmynjcSsmueTqXwLw76ueN8xIDzHb9TiK98Gub+uu5wMzNqXtjF1ppO8C+v/SeTM10QAbNtzL1NQk69dv3OmCf33r9K/5zW0bd2n+QcyUceWhyx7UBPZPbzvTjnZ1Pfbb5zEzjxdsOv9M+S68/GfTvv7Cy5On7Luk0Qw7U2cdDpsZm9FUxrnw5tOk2dTsUdpZxq1byxndUf4dddbjsN8Hu76tu54PzNiUYdTsrgztuAZ4IUBEHA78tKkF7/PYR007fZQfEpnrlwm7MF5wrg+PkTT3zNVhCV18H5R2F11ppC8BNkXEd4EzgdOaWvCwmr7Z3qe6zUfgtm37gcC+U49m/ryJkRwI+MYgSbumCyc/pN1VJ4Z2ZOY24NQ2lu29K9tx2IF7j3QdvuiI/acdHuMbgyQ9mO+DUns60Ui3zXtX7n58Y5CkXTfqkx/S7mosGumumotj7brEAyRJkjRKY9NI27RKkiSpSWPTSLdp+4NBtm7rcfqa74/scdnjyAMkSZI0Kl25a8ec1aUnRkmSJGl4bKQH1JXHZUuSJGm4bKQH5INBJEmSxpON9IB8MIgkSdJ4spEekE+MkiRJGk/etWNAPhhEkiRpPNlIN8AHg0iSJI0fh3ZIkiRJNdhIS5IkSTU4tKMhPmFPkiRpvAy1kY6IJcAFwGJgIfC2zLw2Ig4HzgK2AFdk5vuGmUuSJEmarWEP7Xgb8I3MXAGcCKyupp8NnAAcCRwWEcuHnEuSJEmalWEP7TgT2Nz3uzdFxGJgj8z8BUBEXA4cA6wdcjZJkiRpl030er1WFhwRrwFO22HySZn5w4hYClwGvBX4BXBxZh5WzXcy8GeZ+XczLXvLlq29BQvmt5JbkoZgYtQBhsmaLWmOm7Fmt3ZGOjPXAGt2nB4RTwM+A/x1Zn6rOiM92feSSeAPD7fsDRvuZWpqkvXrNzYZuXFmHFzX84EZmzJOGaemJnf+ot2INbs5Zhxc1/OBGZsyjJo91DHSEXEgcBFwQmZeBpCZdwH3RcQBETEBrASuHmYuSZIkabaGPUb6A8Ai4KyIALgzM18CnAp8CphPuWvH94ecS5IkSZqVoTbSVdM83fTvAYcPM4skSZI0CJ9sKEmSJNVgIy1JkiTVYCMtSZIk1WAjLUmSJNVgIy1JkiTVYCMtSZIk1WAjLUmSJNVgIy1JkiTVYCMtSZIk1WAjLUmSJNUw0ev1Rp1BkiRJmnM8Iy1JkiTVYCMtSZIk1WAjLUmSJNVgIy1JkiTVYCMtSZIk1WAjLUmSJNWwYNQBACLix8Bd1XEABlIAAAcXSURBVLe/As4AzgYWApuBV2bm7RHxQeBISu6PZeY5EbEf8ElgArgDOCEz742IFwOnA1uAczPznBFmfAJwfpXx/4DXVxlfB5xSZfz7zLx0SBnPAI4BesCqzLwqIh4LfBp4JHALcFLXMvYt463A0sxcVX0/qm093XrcDziXsv0nKNs6m8w4YL7HAxdUr70DeFVmbuzSOuxbxgrggsxcVn3fmYwRsRdwE7Cumv+SzDyr6f2ly6zbg29ja3Yn9uXWa3YDGVuv29bs+vvLyO8jHRGLgGszc3nftCuBd2Xm9yLiZZQisQj4q8x8aUTsAdwAHErZSP+TmR+tVt6tlBV7Y/Xze4BrgOMy87YRZTwH+EJmfjoiXgssBf4D+BrwjGq+7wDPyMzNLWfcBHyI8k/2p8CXMvPgiPhX4MeZeV5ErKL8U17YsYyPpKy3ZwIXZ+aqiHgEo9nWM2U8n7KDfjEiVlJ20Fc0lbGBfB+mbOdPRMR7gTuBjzSVr4mM1euXVbkOy8ylHdzOxwAvycw3982/lAb3ly6zbg++ja3ZndmXW63ZDWVstW5bswfbX7owtONg4FERcUVEXBkRRwCPA14cEVcBRwA/AK4FTq7m6QHzgfuB64E9q+mLq2lPAX6emRsy8z7Kyjl6hBkPBC6rpl9DOfPxTOCazNycmXcCPwcOajtjZq4FVmZmj/JP9odq/iOB/6y+vozyT9i1jIsoZ4jO6FvmSLb1w2R8O/DV6usFlJ26yYyD5jsNuCAi5gHLqumdWodVwTwb+Mu+ZXYqI3AIcEhEfCsiLqrOGDW9v3SZdXvwbWzN7sa+3HbNbiJj23Xbmj3A/tKFRvpeytHDSuBUyqWqpwJfB55DKbavzsxNmbmhOso5n3L57W7gZuBNEXEDcCxwEaUw39n3OzYCS0aY8Xrg+GpZxwN/MqqMAJm5pToLdCnw8Wr+/jzbs3QqY7VDXrHDMruW8feZeX9ERLWc9zWccdB82xuFddXrr2w438AZKWc1PpSZv+1bZtcy/gw4PTNXAF8E/q2FjF1m3R48ozW7GxnbrtlNZGy7bluzB8jYhUb6JsqYml5m3gT8HiAzv1n981xKOe1OROxJOQL/78z8QDX/B4ETM/OpwFuAT1DG0Ez2/Y5JHjgqGUXGtwPHV0dNvWr+kWWspv8tsA/wNxFxwA55tmfpWsbpdC5jRDyHsqP+RWZmwxkHzpeZ92fmgcDrGfH+Mk3GZwFHAe+p9pe9IuIzHct4AOWN7JvVjy8BlreQscus24NntGZ3JGPLNbuRjC3XbWv2ABm70EifDPwzQETsQ/lDfhQRR1U/Pxq4IcpYq29QBqy/v2/+DTxwRHEL5ajkRuBJEbFXRCyslnHtCDP+OWUcz7OBrZQxOT8AjoqIRRGxhHIZZB317WrG50bE6mraJsolzG2US5cvrKYfC1zdwYzTGdW2njZjVZDPAl6Qmde1kHHQfB+tMkI5+t7WcL5BM96SmZGZz672lzsy85Udy7iNMu7zZdX05wE/ovn9pcus24NvY2t2B/blIdTsJjK2Xbet2QPsL134sOFC4DxgP8pR/zsoA9NXU8Yr/Ypyuv6NwHsol9u2O4nyieWPUC57TABvycy18cCnRedRCuRqamog4+Oq126mfJDljdWlpNdRji7nAf+QmRcPIeNWyvo6iLLO1mT5hPrelMuak5QjvRMy854uZexbzonAk/OhnwAf5raeaT3+BNiD8uEpgMzMU5rK2EC+J1PGsvUoxeVNmXljl9bhDsu6NTOXVl93JmOUOzqcS6k59wCvzczfNbm/dJl1e/BtbM3uzL7cas1uKGOrdduaPdj+MvJGWpIkSZqLujC0Q5IkSZpzbKQlSZKkGmykJUmSpBpspCVJkqQabKQlSZKkGhaMOoA0LBGxP+UWOR/LzFP6pj8dWAuclJnn9b32qszcv7p1078Av6bcOmcR8GVgVWZuHeKfIEljw5qtucAz0ho3twMviIj5fdNeAazfyXxfzsynZ+bBwCGUpyK9t52IkqSKNVudZiOtcXM35UzG0X3Tng98fVcXkJl3A+8C3hARE83GkyT1sWar02ykNY4+B7wcICIOBf4LuG+Wy1gHPAaYajaaJGkH1mx1lo20xtFXgGMjYh7lEuFnayxj+yNB/9hYKknSdKzZ6iwbaY2dzNwI/AQ4EnguD1wiXBgRy6uvJ4AtD7OYg4Cbq2VJklpizVaX2UhrXH0O+EfguszcXnwfD7yz+vog4JfTzRgRS4D3A6vbDilJAqzZ6ihvf6dx9RVgDfDuvmm3AcsjYh3lMuCJfT87PiKur6YvAD4P/NNwokrS2LNmq5Mmer3ezl8lSZIk6UEc2iFJkiTVYCMtSZIk1WAjLUmSJNVgIy1JkiTVYCMtSZIk1WAjLUmSJNVgIy1JkiTVYCMtSZIk1fD/ogi8SImzniMAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1069eb668>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_lightcurves(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Starting kit pipeline elements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For this classification challenge, participants are required to submit two files:\n",
    "* `feature_extractor.py` \n",
    "* `classifier.py`     \n",
    "\n",
    "In the following, we will go through the process of designing a baseline submission, that is writing the script for both the pre-processing step and the classification step."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pre-processing - a.k.a. feature extraction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As the SN data is highly non-homogeneous a little pre-processing need to be done. In the example below we fit the data using a parametric function proposed by [Bazin et al., 2009](https://arxiv.org/pdf/0904.1066.pdf):"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$ f(t) = A \\frac{\\exp\\left(-\\frac{t - t_0}{\\tau_{fall}}\\right)}{1 + \\exp\\left(\\frac{t - t_0}{\\tau_{rise}}\\right)}  + B$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def bazin(time, A, B, t0, tfall, trise):\n",
    "    X = np.exp(-(time - t0) / tfall) / (1 + np.exp((time - t0) / trise))\n",
    "    return A * X + B"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Although this parametric form does not have a physical motivation, it reproduces quiet well the behavior of most light curves.  \n",
    "\n",
    "<div class=\"alert alert-warning\">\n",
    "<b>NOTE</b>  \n",
    "This function is very sensitive to the magnitude of the time of observation. The use of [Modified Julian Date](https://bowie.gsfc.nasa.gov/time/) creates large time values, which are not relevant for such analysis so we use a scaled time instead in order to ensure the convergence of the fit.\n",
    "</div>\n",
    "\n",
    "\n",
    "We provide an example fitting function, so you can fit a light curve and plot reslts as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.optimize import least_squares\n",
    "\n",
    "def lightcurve_fit(time, flux):\n",
    "    scaled_time = time - time.min()\n",
    "    t0 = scaled_time[flux.argmax()]\n",
    "    guess = (0, 0, t0, 40, -5)\n",
    "\n",
    "    errfunc = lambda params: abs(flux - bazin(scaled_time, *params))\n",
    "\n",
    "    result = least_squares(errfunc, guess, method='lm')\n",
    "\n",
    "    return result.x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The parametric fit on the light curves yields 5 parameters for each filter $A, B, t_0, \\tau_{fall}, \\tau_{rise}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([132.37309428,  -5.38585536,  47.36812147,  10.92992313,  -3.95247409])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lightcurve_fit(sn0.mjd_g, sn0.fluxcal_g)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_lightcurves_with_fit(idx):\n",
    "    fig, axes = plt.subplots(2, 2, sharex=True, sharey=True, figsize=(12, 8))\n",
    "    for id_f, f in enumerate(DES_FILTERS):\n",
    "        ax = axes[id_f // 2, id_f % 2]\n",
    "        \n",
    "        time = X.iloc[idx]['mjd_%s' % f]\n",
    "        flux = X.iloc[idx]['fluxcal_%s' % f]\n",
    "        \n",
    "        fit = lightcurve_fit(time, flux)\n",
    "        stime = np.arange(time.min(), time.max())\n",
    "        \n",
    "        ax.plot(time, flux, 'o')\n",
    "        ax.plot(stime, bazin(stime - stime.min(), *fit))\n",
    "        ax.set_xlabel('MJD')\n",
    "        ax.set_ylabel('Calibrated flux')\n",
    "        ax.set_title('%s-band' % f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10ab29828>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_lightcurves_with_fit(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Constructing the data matrix for classification\n",
    "\n",
    "Now that you can fit each individual light curve, you are ready to build your low dimension representation of the data.  \n",
    "\n",
    "\n",
    "In this example, each entry in the data matrix will correspond to one object and each column to a best-fit parameters. As we have 4 filters, we will concatenate the 20 best-fit results for different filters in the same row of the data matrix.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def preprocessing(data):\n",
    "    # Create palceholder for output matrix\n",
    "    full_params = np.zeros((len(data), 5 * len(DES_FILTERS)))\n",
    "    # Iterate over supernovae\n",
    "    for idx, snid in enumerate(data.index):\n",
    "        params = np.zeros((len(DES_FILTERS), 5))\n",
    "        # Iterate over filters\n",
    "        for id_f, f in enumerate(DES_FILTERS):\n",
    "            time = data.loc[snid, 'mjd_%s' % f]\n",
    "            flux = data.loc[snid, 'fluxcal_%s' % f]\n",
    "            try:\n",
    "                params[id_f] = lightcurve_fit(time, flux)\n",
    "            except ValueError:\n",
    "                # If fit does not converge leave zeros\n",
    "                continue\n",
    "        full_params[idx] = params.ravel()\n",
    "                           \n",
    "    return full_params"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `feature_extractor.py`\n",
    "\n",
    "The submitted `feature_extractor.py` is expected to define part of the `FeatureExtractor` class, namely the `transform` method that will process the raw data `X`.\n",
    "\n",
    "Given the methods defined in the section above, the class would boil down to"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# feature_extractor.py\n",
    "\n",
    "class FeatureExtractor():\n",
    "    def __init__(self):\n",
    "        pass\n",
    "\n",
    "    def fit(self, X_df, y):\n",
    "        pass\n",
    "\n",
    "    def transform(self, X_df):\n",
    "        return preprocessing(X_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "However it will need to have all the methods above implemented with the right imports **within the file**.\n",
    "\n",
    "Checkout the baseline submission for a working example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load submissions/starting_kit/feature_extractor.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Classification"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now use the feature matrix to train a classifier of our choosing. This is the second expected contribution to the challenge."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `classifier.py`\n",
    "\n",
    "As for the `feature_extractor.py`, the `classifier.py` needs a `Classifier` class with `__init__()`, `fit()` and `predict_proba()` methods to be implemented.\n",
    "\n",
    "Since this is not the main focus of the challenge, we chose a very simple implementation for the baseline, that is a random forest classifier. The starting_kit example looks like"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# classifier.py\n",
    "\n",
    "from sklearn.base import BaseEstimator\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "\n",
    "\n",
    "class Classifier(BaseEstimator):\n",
    "    def __init__(self):\n",
    "        self.clf = RandomForestClassifier()\n",
    "\n",
    "    def fit(self, X, y):\n",
    "        self.clf.fit(X, y)\n",
    "\n",
    "    def predict_proba(self, X):\n",
    "        return self.clf.predict_proba(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This classifier will take the output of the `FeatureExtractor.transform()` and train using the `y` labels from the beginning.\n",
    "\n",
    "Once trained, the RAMP pipeline will automatically then test the `Classifier` predictions against the expected labels, following scores/metrics defined in the `problem.py`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Local testing\n",
    "\n",
    "To test locally that the pipeline works, the RAMP workflow provides a command line tool: `ramp_test_submission`.\n",
    "\n",
    "For relatively big datasets (e.g. the DES target set has 20 000 + entries), a smaller portion of the data is also delivered:\n",
    "* `des_train_mini.pkl`\n",
    "* `des_test_mini.pkl`\n",
    "so that the local testing is only a few minutes long.\n",
    "\n",
    "To train/test on this minimalist dataset, use the `--quick-test` keyword."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[38;5;178m\u001b[1mTesting PLAsTiCC transient classification RAMP\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1mReading train and test files from ./data ...\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1mReading cv ...\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1mTraining ./submissions/starting_kit ...\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1mCV fold 0\u001b[0m\n",
      "\t\u001b[38;5;178m\u001b[1mscore   auc   acc   nll\u001b[0m\n",
      "\t\u001b[38;5;10m\u001b[1mtrain\u001b[0m  \u001b[38;5;10m\u001b[1m\u001b[38;5;150m1.00\u001b[0m\u001b[0m  \u001b[38;5;10m\u001b[1m\u001b[38;5;150m1.00\u001b[0m\u001b[0m  \u001b[38;5;150m0.10\u001b[0m\n",
      "\t\u001b[38;5;12m\u001b[1mvalid\u001b[0m  \u001b[38;5;12m\u001b[1m0.83\u001b[0m  \u001b[38;5;105m0.73\u001b[0m  \u001b[38;5;105m1.01\u001b[0m\n",
      "\t\u001b[38;5;1m\u001b[1mtest\u001b[0m   \u001b[38;5;1m\u001b[1m0.83\u001b[0m  \u001b[38;5;218m0.69\u001b[0m  \u001b[38;5;218m0.82\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1mCV fold 1\u001b[0m\n",
      "\t\u001b[38;5;178m\u001b[1mscore   auc   acc   nll\u001b[0m\n",
      "\t\u001b[38;5;10m\u001b[1mtrain\u001b[0m  \u001b[38;5;10m\u001b[1m1.00\u001b[0m  \u001b[38;5;150m0.99\u001b[0m  \u001b[38;5;150m0.12\u001b[0m\n",
      "\t\u001b[38;5;12m\u001b[1mvalid\u001b[0m  \u001b[38;5;12m\u001b[1m0.89\u001b[0m  \u001b[38;5;105m0.77\u001b[0m  \u001b[38;5;105m0.40\u001b[0m\n",
      "\t\u001b[38;5;1m\u001b[1mtest\u001b[0m   \u001b[38;5;1m\u001b[1m0.77\u001b[0m  \u001b[38;5;218m0.65\u001b[0m  \u001b[38;5;218m0.66\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1mCV fold 2\u001b[0m\n",
      "\t\u001b[38;5;178m\u001b[1mscore   auc   acc   nll\u001b[0m\n",
      "\t\u001b[38;5;10m\u001b[1mtrain\u001b[0m  \u001b[38;5;10m\u001b[1m1.00\u001b[0m  \u001b[38;5;150m0.98\u001b[0m  \u001b[38;5;150m0.12\u001b[0m\n",
      "\t\u001b[38;5;12m\u001b[1mvalid\u001b[0m  \u001b[38;5;12m\u001b[1m0.82\u001b[0m  \u001b[38;5;105m0.73\u001b[0m  \u001b[38;5;105m1.06\u001b[0m\n",
      "\t\u001b[38;5;1m\u001b[1mtest\u001b[0m   \u001b[38;5;1m\u001b[1m0.72\u001b[0m  \u001b[38;5;218m0.61\u001b[0m  \u001b[38;5;218m1.97\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1m----------------------------\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1mMean CV scores\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1m----------------------------\u001b[0m\n",
      "\t\u001b[38;5;178m\u001b[1mscore           auc           acc           nll\u001b[0m\n",
      "\t\u001b[38;5;10m\u001b[1mtrain\u001b[0m     \u001b[38;5;10m\u001b[1m1.0\u001b[0m \u001b[38;5;150m\u001b[38;5;150m\u001b[38;5;150m±\u001b[0m\u001b[0m\u001b[0m \u001b[38;5;150m0.0\u001b[0m  \u001b[38;5;150m0.99\u001b[0m \u001b[38;5;150m\u001b[38;5;150m\u001b[38;5;150m±\u001b[0m\u001b[0m\u001b[0m \u001b[38;5;150m0.0\u001b[0m05   \u001b[38;5;150m0.11\u001b[0m \u001b[38;5;150m\u001b[38;5;150m\u001b[38;5;150m±\u001b[0m\u001b[0m\u001b[0m \u001b[38;5;150m0.0\u001b[0m1\n",
      "\t\u001b[38;5;12m\u001b[1mvalid\u001b[0m  \u001b[38;5;12m\u001b[1m0.85\u001b[0m \u001b[38;5;105m\u001b[38;5;105m\u001b[38;5;105m±\u001b[0m\u001b[0m\u001b[0m \u001b[38;5;105m0.033\u001b[0m  \u001b[38;5;105m0.74\u001b[0m \u001b[38;5;105m\u001b[38;5;105m\u001b[38;5;105m±\u001b[0m\u001b[0m\u001b[0m \u001b[38;5;105m0.016\u001b[0m  \u001b[38;5;105m0.82\u001b[0m \u001b[38;5;105m\u001b[38;5;105m\u001b[38;5;105m±\u001b[0m\u001b[0m\u001b[0m \u001b[38;5;105m0.299\u001b[0m\n",
      "\t\u001b[38;5;1m\u001b[1mtest\u001b[0m   \u001b[38;5;1m\u001b[1m0.77\u001b[0m \u001b[38;5;218m\u001b[38;5;218m\u001b[38;5;218m±\u001b[0m\u001b[0m\u001b[0m \u001b[38;5;218m0.045\u001b[0m  \u001b[38;5;218m0.65\u001b[0m \u001b[38;5;218m\u001b[38;5;218m\u001b[38;5;218m±\u001b[0m\u001b[0m\u001b[0m \u001b[38;5;218m0.033\u001b[0m  \u001b[38;5;218m1.15\u001b[0m \u001b[38;5;218m\u001b[38;5;218m\u001b[38;5;218m±\u001b[0m\u001b[0m\u001b[0m \u001b[38;5;218m0.583\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1m----------------------------\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1mBagged scores\u001b[0m\n",
      "\u001b[38;5;178m\u001b[1m----------------------------\u001b[0m\n",
      "\t\u001b[38;5;178m\u001b[1mscore   auc\u001b[0m\n",
      "\t\u001b[38;5;12m\u001b[1mvalid\u001b[0m  \u001b[38;5;12m\u001b[1m0.85\u001b[0m\n",
      "\t\u001b[38;5;1m\u001b[1mtest\u001b[0m   \u001b[38;5;1m\u001b[1m0.81\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "!ramp_test_submission --quick-test"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Writing your own submissions locally\n",
    "\n",
    "To start working on a new submission, the easiest way is to copy the starting_kit into a new directory and then modify the files from the notebook using the `%%file` magic command."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!cp -r submissions/starting_kit submissions/first_submission"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%file submissions/first_submission/feature_extractor.py\n",
    "\n",
    "class FeatureExtractor():\n",
    "    def __init__(self):\n",
    "        pass\n",
    "\n",
    "    def fit(self, X_df, y):\n",
    "        pass\n",
    "\n",
    "    def transform(self, X_df):\n",
    "        return preprocessing(X_df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%file submissions/first_submission/classifier.py\n",
    "\n",
    "from sklearn.base import BaseEstimator\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "\n",
    "\n",
    "class Classifier(BaseEstimator):\n",
    "    def __init__(self):\n",
    "        self.clf = RandomForestClassifier()\n",
    "\n",
    "    def fit(self, X, y):\n",
    "        self.clf.fit(X, y)\n",
    "\n",
    "    def predict_proba(self, X):\n",
    "        return self.clf.predict_proba(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, test your new submission by providing the name of the submission"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!ramp_test_submission --submission=first_submission --quick-test"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<footer style=\"float:right; color:#999;background:#fff;\">\n",
    "HAPPY CODING...\n",
    "</footer>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "/*Mostly inspired from Lorena Barba's configuration\n",
       "https://github.com/barbagroup/AeroPython/blob/master/styles/custom.css*/\n",
       "\n",
       "<link href='http://fonts.googleapis.com/css?family=Fenix' rel='stylesheet' type='text/css'>\n",
       "<link href='http://fonts.googleapis.com/css?family=Alegreya+Sans:100,300,400,500,700,800,900,100italic,300italic,400italic,500italic,700italic,800italic,900italic' rel='stylesheet' type='text/css'>\n",
       "<link href='http://fonts.googleapis.com/css?family=Source+Code+Pro:300,400' rel='stylesheet' type='text/css'>\n",
       "<style>\n",
       "\n",
       "@font-face {\n",
       "    font-family: \"Computer Modern\";\n",
       "    src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');\n",
       "}\n",
       "\n",
       "\n",
       "#notebook_panel { /* main background */\n",
       "    background: rgb(245,245,245);\n",
       "}\n",
       "\n",
       "div.cell { /* set cell width */\n",
       "    width: 750px;\n",
       "}\n",
       "\n",
       "div #notebook { /* centre the content */\n",
       "    background: #fff; /* white background for content */\n",
       "    width: 1100px;\n",
       "    margin: auto;\n",
       "    padding-left: 0em;\n",
       "}\n",
       "\n",
       "#notebook li { /* More space between bullet points */\n",
       "margin-top:0.8em;\n",
       "}\n",
       "\n",
       "/* draw border around running cells */\n",
       "div.cell.border-box-sizing.code_cell.running {\n",
       "    border: 1px solid #111;\n",
       "}\n",
       "\n",
       "/* Put a solid color box around each cell and its output, visually linking them*/\n",
       "div.cell.code_cell {\n",
       "    background-color: rgb(256,256,256);\n",
       "    border-radius: 0px;\n",
       "    padding: 0.5em;\n",
       "    margin-left:1em;\n",
       "    margin-top: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "div.text_cell_render{\n",
       "    font-family: 'Alegreya Sans' sans-serif;\n",
       "    line-height: 140%;\n",
       "    font-size: 125%;\n",
       "    font-weight: 400;\n",
       "    width:600px;\n",
       "    margin-left:auto;\n",
       "    margin-right:auto;\n",
       "}\n",
       "\n",
       "/* Formatting for header cells */\n",
       ".text_cell_render h1 {\n",
       "    font-family: 'Alegreya Sans', sans-serif;\n",
       "    font-style:regular;\n",
       "    font-weight: 200;\n",
       "    font-size: 50pt;\n",
       "    line-height: 100%;\n",
       "    /*color:#CD2305;*/\n",
       "    color:#62003C;\n",
       "    margin-bottom: 0.5em;\n",
       "    margin-top: 0.5em;\n",
       "    display: block;\n",
       "}\n",
       ".text_cell_render h2 {\n",
       "    font-family: 'Fenix', serif;\n",
       "    font-size: 22pt;\n",
       "    line-height: 100%;\n",
       "    margin-bottom: 0.1em;\n",
       "    margin-top: 0.3em;\n",
       "    display: block;\n",
       "}\n",
       "\n",
       ".text_cell_render h3 {\n",
       "    font-family: 'Fenix', serif;\n",
       "    margin-top:12px;\n",
       "    font-size: 16pt;\n",
       "    margin-bottom: 3px;\n",
       "    font-style: regular;\n",
       "}\n",
       "\n",
       ".text_cell_render h4 {    /*Use this for captions*/\n",
       "    font-family: 'Fenix', serif;\n",
       "    font-size: 2pt;\n",
       "    text-align: center;\n",
       "    margin-top: 0em;\n",
       "    margin-bottom: 2em;\n",
       "    font-style: regular;\n",
       "}\n",
       "\n",
       ".text_cell_render h5 {  /*Use this for small titles*/\n",
       "    font-family: 'Alegreya Sans', sans-serif;\n",
       "    font-weight: 300;\n",
       "    font-size: 16pt;\n",
       "    color: #62003C;\n",
       "    font-style: italic;\n",
       "    margin-bottom: .5em;\n",
       "    margin-top: 0.5em;\n",
       "    display: block;\n",
       "}\n",
       "\n",
       ".text_cell_render h6 { /*use this for copyright note*/\n",
       "    font-family: 'Source Code Pro', sans-serif;\n",
       "    font-weight: 300;\n",
       "    font-size: 9pt;\n",
       "    line-height: 100%;\n",
       "    color: grey;\n",
       "    margin-bottom: 1px;\n",
       "    margin-top: 1px;\n",
       "}\n",
       "\n",
       "figcaption {\n",
       "    /*display: block;*/\n",
       "    padding: 1.5em;\n",
       "}\n",
       "\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "HTML(open(\"style/custom.css\").read())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  },
  "widgets": {
   "state": {},
   "version": "1.1.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
