{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Example Notebook to fit a microlensing event\n",
    "\n",
    "The procedure is:\n",
    "1. Estimate the point lens parameters (`t_0`, `u_0`, `t_E`) from the light curve.\n",
    "2. Fit a point lens model (excluding the planetary perturbation).\n",
    "3. Estimate the planet parameters (`s`, `alpha`) from the light curve.\n",
    "4. Search for the best planetary model using a grid of `s`, `q` (fixed parameters); fits for `rho` and `alpha` but holds the PSPL parameters (`t_0`, `u_0`, `t_E`) fixed.\n",
    "\n",
    "This notebook is setup to run on a simulated data file: `WFIRST_1827.dat`. To run it on a different data file requires some limited user interaction indicated by `***`:\n",
    "1. Set `filename` and `path`\n",
    "2. Set the plot limits: `t_min`, `t_max`\n",
    "3. Define the time window of the planetary perturbation: `t_planet_start`, `t_planet_stop`\n",
    "\n",
    "The goal of the notebook is to demonstrate the procedure and run quickly, so it is not robust. The fitting procedure is very simplistic and relies on assuming this is a Gould & Loeb (1996) type planet, which means\n",
    "- It is a planetary caustic perturbation\n",
    "- It is well described as a _perturbation_, which means\n",
    "  - The perturbation data can be isolated from the underlying PSPL event \n",
    "  - The location of the planet can be estimated from the location of the images at the time of the perturbation\n",
    "  \n",
    "This notebook will **not** perform well for:\n",
    "- central caustic planets (u_0 << 1 and/or u_0 < rho)\n",
    "- resonant caustic planets (s ~ 1)\n",
    "- binaries (i.e. the assumption that q << 1 is false)\n",
    "\n",
    "Simple modifications that could improve performance indicated by `*`:\n",
    "- Change the `magnification_methods`, i.e. the method used and the time range it is used for.\n",
    "- Change the minimization routine in `fit_model()` (This notebook is set up to use a 'Nelder-Mead' simplex algorithm. Simplex algorithms are known to perform poorly on microlensing events.)\n",
    "- Change the size of the grid or the grid steps: `delta_log_s`, `delta_log_q`, `grid_log_s`, `grid_log_q`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Import packages\n",
    "from datetime import datetime\n",
    "start_time = datetime.now() # initialize timer\n",
    "import MulensModel as mm\n",
    "import matplotlib.pyplot as pl\n",
    "import numpy as np\n",
    "import scipy.optimize as op\n",
    "import os\n",
    "import astropy.units as u"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Define fitting functions\n",
    "\n",
    "def chi2_fun(theta, event, parameters_to_fit):\n",
    "    \"\"\"                                                                         \n",
    "    Chi2 function. Changes values of the parameters and recalculates chi2.\n",
    "    \n",
    "    event = a MulensModel.Event\n",
    "    parameters_to_fit = list of names of parameters to be changed\n",
    "    theta = values of the corresponding parameters\n",
    "    \"\"\"\n",
    "    # key = the name of the MulensModel parameter\n",
    "    for (index, key) in enumerate(parameters_to_fit):\n",
    "        if (key == 't_E' or key =='rho') and theta[index] < 0.:\n",
    "            return np.inf\n",
    "        setattr(event.model.parameters, key, theta[index])\n",
    "    return event.get_chi2()\n",
    "\n",
    "def fit_model(event, parameters_to_fit):\n",
    "    \"\"\"\n",
    "    Fit an \"event\" with \"parameters_to_fit\" as free parameters.\n",
    "    \n",
    "    event = a MulensModel event\n",
    "    parameters_to_fit = list of parameters to fit\n",
    "    \"\"\"\n",
    "    # Take the initial starting point from the event.\n",
    "    x0 = []\n",
    "    for key in parameters_to_fit:\n",
    "        value = getattr(event.model.parameters, key)\n",
    "        if isinstance(value, u.Quantity):\n",
    "            x0.append(value.value)\n",
    "        else:\n",
    "            x0.append(value)\n",
    "\n",
    "    # *Execute fit using a 'Nelder-Mead' algorithm*\n",
    "    result = op.minimize(\n",
    "        chi2_fun, x0=x0, args=(event, parameters_to_fit),\n",
    "        method='Nelder-Mead')\n",
    "\n",
    "    return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# ***Read in data file***\n",
    "path = os.path.join(mm.MODULE_PATH, \"data\")\n",
    "filename = 'WFIRST_1827.dat' # Planet file\n",
    "file = os.path.join(path, filename)\n",
    "data = mm.MulensData(file_name=file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plot the data\n",
    "pl.errorbar(data.time, data.mag, yerr=data.err_mag, fmt='o')\n",
    "pl.gca().invert_yaxis()\n",
    "pl.show()\n",
    "\n",
    "# ***Define plot limits for a zoom (of the planetary perturbation)***\n",
    "(t_min, t_max) = (2460980, 2460990)\n",
    "\n",
    "# Plot a zoom of the data\n",
    "pl.errorbar(data.time - 2460000., data.mag, yerr=data.err_mag, fmt='o')\n",
    "pl.xlim(t_min - 2460000., t_max - 2460000.)\n",
    "pl.xlabel('t - 2460000')\n",
    "pl.gca().invert_yaxis()\n",
    "pl.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# ***Set time range of planetary perturbation (including 2460000).***\n",
    "(t_planet_start, t_planet_stop) = (2460982., 2460985.)\n",
    "\n",
    "# *Set the magnification methods for the planet model*\n",
    "# VBBL method will be used between t_planet_start and t_planet_stop, \n",
    "# and point_source_point_lens will be used everywhere else.\n",
    "magnification_methods = [\n",
    "    0., 'point_source_point_lens', \n",
    "    t_planet_start, 'VBBL', t_planet_stop, \n",
    "    'point_source_point_lens', 2470000.]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Flag data related to the planet\n",
    "flag_planet = (data.time > t_planet_start) & (data.time < t_planet_stop) | np.isnan(data.err_mag)\n",
    "\n",
    "# Exclude those data from the fitting (for now)\n",
    "data.bad = flag_planet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Estimate point lens parameters assuming zero blending\n",
    "# \n",
    "# Equation for point lens magnification:\n",
    "#\n",
    "# A(u) = (u^2 + 2) / (u * sqrt(u^2 + 4))\n",
    "#\n",
    "# where\n",
    "# \n",
    "# u = sqrt(u_0^2 + tau^2) and tau = (t - t_0) / t_E\n",
    "#\n",
    "# Thus, the light curve is defined by 3 variables: t_0, u_0, t_E\n",
    "#\n",
    "\n",
    "# Estimate t_0 (time of peak magnification)\n",
    "index_t_0 = np.argmin(data.mag[np.invert(flag_planet)])\n",
    "t_0 = data.time[index_t_0]\n",
    "\n",
    "# Estimate u_0\n",
    "baseline_mag = np.min([data.mag[0], data.mag[-1]]) # A crude estimate\n",
    "A_max = 10.**((data.mag[index_t_0] - baseline_mag) / -2.5)\n",
    "u_0 = 1. / A_max # True in the high-magnification limit\n",
    "\n",
    "# Estimate t_E by determining when the light curve is A(t) = 1.3 (i.e. delta_mag = 0.3)\n",
    "t_1 = np.interp(\n",
    "    baseline_mag - 0.3, data.mag[index_t_0:0:-1], data.time[index_t_0:0:-1])\n",
    "t_E = np.abs((t_0 - t_1) / np.sqrt(1. - u_0**2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define the Point Lens Model\n",
    "point_lens_model = mm.Model({'t_0': t_0, 'u_0': u_0, 't_E': t_E})\n",
    "point_lens_event = mm.Event(datasets=data, model=point_lens_model)\n",
    "print('Initial Guess')\n",
    "print(point_lens_model)\n",
    "\n",
    "# Plot (excluded data shown as 'X')\n",
    "point_lens_event.plot_model(color='black')\n",
    "point_lens_event.plot_data(show_bad=True)\n",
    "pl.show()\n",
    "print(point_lens_event.get_ref_fluxes())\n",
    "print(point_lens_event.model.magnification(t_0))\n",
    "\n",
    "point_lens_event.plot_model(subtract_2460000=True, color='black', zorder=10)\n",
    "point_lens_event.plot_data(show_bad=True, subtract_2460000=True)\n",
    "pl.xlim(t_min - 2460000., t_max - 2460000.)\n",
    "pl.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Fit the Point Lens Model\n",
    "result = fit_model(point_lens_event, parameters_to_fit=['t_0', 'u_0', 't_E'])\n",
    "print('Best-fit Point Lens')\n",
    "print(point_lens_event.model)\n",
    "\n",
    "# Plot \n",
    "point_lens_event.plot_model(\n",
    "    t_range=[point_lens_event.model.parameters.t_0 - 5. * point_lens_event.model.parameters.t_E,\n",
    "             point_lens_event.model.parameters.t_0 + 5. * point_lens_event.model.parameters.t_E],\n",
    "    color='black', zorder=10)\n",
    "point_lens_event.plot_data(show_bad=True)\n",
    "pl.show()\n",
    "\n",
    "point_lens_event.plot_model(color='black', zorder=10)\n",
    "point_lens_event.plot_data(show_bad=True)\n",
    "pl.xlim(t_min, t_max)\n",
    "pl.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Un-flag planet data (include it in future fits)\n",
    "data.bad = np.isnan(data.err_mag)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Estimate s (projected separation) of the planet, alpha (angle of source trajectory)\n",
    "\n",
    "# Approximate time of the planetary perturbation\n",
    "t_planet = (t_planet_stop + t_planet_start) / 2.\n",
    "\n",
    "# Position of the source at the time of the planetary perturbation\n",
    "tau_planet = ((t_planet - point_lens_event.model.parameters.t_0) /\n",
    "              point_lens_event.model.parameters.t_E)\n",
    "u_planet = np.sqrt(\n",
    "    point_lens_event.model.parameters.u_0**2 + tau_planet**2)\n",
    "\n",
    "# Position of the lens images at the time of the planetary perturbation\n",
    "# --> Estimate of the planet location\n",
    "s_minus = 0.5 * (np.sqrt(u_planet**2 + 4.) - u_planet)\n",
    "s_plus = 0.5 * (np.sqrt(u_planet**2 + 4.) + u_planet)\n",
    "\n",
    "# Angle between the source trajectory and the binary axis\n",
    "alpha_planet = np.rad2deg(-np.arctan2(\n",
    "    point_lens_event.model.parameters.u_0, tau_planet))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Check the estimated model\n",
    "# Note that there are two possibilities for s: s_plus and s_minus. \n",
    "# Only s_plus is tested here, but both are considered in the grid search below.\n",
    "\n",
    "# Define the model\n",
    "test_model = mm.Model({\n",
    "    't_0': point_lens_event.model.parameters.t_0, \n",
    "    'u_0': point_lens_event.model.parameters.u_0,\n",
    "    't_E': point_lens_event.model.parameters.t_E,\n",
    "    'rho': 0.001,\n",
    "    's': s_plus,\n",
    "    'q': 10.**(-4),\n",
    "    'alpha': alpha_planet})\n",
    "test_model.set_magnification_methods(magnification_methods)\n",
    "test_event = mm.Event(datasets=data, model=test_model)\n",
    "print(test_event.model)\n",
    "\n",
    "# Plot the model light curve\n",
    "test_event.plot_data()\n",
    "test_event.plot_model(t_range=[t_min, t_max], color='black', zorder=10)\n",
    "pl.xlim(t_min, t_max)\n",
    "pl.show()\n",
    "\n",
    "# Plot the trajectory of the source relative to the caustics\n",
    "test_event.model.plot_trajectory(color='black', caustics=True)\n",
    "pl.xlim(-1,1)\n",
    "pl.ylim(-1,1)\n",
    "pl.show()\n",
    "# It doesn't have to be perfect, but there should be a planetary perturbation\n",
    "# at around the time of the perturbation in the data. If there is no perturbation\n",
    "# and/or the source trajectory doesn't pass very near/through the caustics, there is some \n",
    "# problem with the model and the fit will likely fail."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Using the Point Lens fit as input, search for a planetary solution\n",
    "#\n",
    "# Grid parameters: s (log), q (log)\n",
    "# Fit parameters: rho, alpha\n",
    "# PSPL parameters: t_0, u_0, t_E\n",
    "#\n",
    "\n",
    "# *Define the grid*\n",
    "delta_log_s = 0.01\n",
    "delta_log_q = 0.25\n",
    "grid_log_s = np.hstack(\n",
    "    (np.arange(\n",
    "        np.log10(s_minus) - 0.02, np.log10(s_minus) + 0.02, delta_log_s),\n",
    "    np.arange(\n",
    "        np.log10(s_plus) - 0.02, np.log10(s_plus) + 0.02, delta_log_s)))\n",
    "grid_log_q = np.arange(-5, -2, delta_log_q)\n",
    "\n",
    "# For each grid point, fit for rho, alpha\n",
    "grid = np.empty((5, len(grid_log_s) * len(grid_log_q)))\n",
    "i = 0\n",
    "print('{0:>12} {1:>6} {2:>7} {3:>7} {4:>7}'.format('chi2', 's', 'q', 'alpha', 'rho'))\n",
    "for log_s in grid_log_s:\n",
    "    for log_q in grid_log_q:\n",
    "        # The major and minor images are on opposite sides of the lens:\n",
    "        if log_s < 0.:\n",
    "            alpha = alpha_planet + 180.\n",
    "        else:\n",
    "            alpha = alpha_planet\n",
    "            \n",
    "        # Define the Model and Event\n",
    "        planet_model = mm.Model({\n",
    "            't_0': point_lens_event.model.parameters.t_0, \n",
    "            'u_0': point_lens_event.model.parameters.u_0,\n",
    "            't_E': point_lens_event.model.parameters.t_E,\n",
    "            'rho': 0.001,\n",
    "            's': 10.**log_s,\n",
    "            'q': 10.**log_q,\n",
    "            'alpha': alpha})\n",
    "        planet_model.set_magnification_methods(magnification_methods)\n",
    "        planet_event = mm.Event(datasets=[data], model=planet_model)\n",
    "            \n",
    "        # Fit the Event\n",
    "        result = fit_model(planet_event, parameters_to_fit=['rho', 'alpha'])\n",
    "        if result.success:\n",
    "            chi2 = planet_event.get_chi2()\n",
    "        else:\n",
    "            chi2 = np.inf\n",
    "                \n",
    "        # Print and store result of fit\n",
    "        print('{0:12.2f} {1:6.4f} {2:7.5f} {3:7.2f} {4:7.5f}'.format(\n",
    "            chi2, 10.**log_s, 10.**log_q, \n",
    "            planet_event.model.parameters.alpha, planet_event.model.parameters.rho))\n",
    "        grid[0, i] = log_s\n",
    "        grid[1, i] = log_q\n",
    "        grid[2, i] = chi2\n",
    "        grid[3, i] = planet_event.model.parameters.alpha.value\n",
    "        grid[4, i] = planet_event.model.parameters.rho\n",
    "            \n",
    "        i += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plot the grid\n",
    "\n",
    "# Identify the best model(s)\n",
    "index_best = np.argmin(np.array(grid[2,:]))\n",
    "index_sorted = np.argsort(np.array(grid[2,:]))\n",
    "n_best = 5 \n",
    "colors = ['magenta', 'green', 'cyan','yellow']\n",
    "if len(colors) < n_best - 1:\n",
    "    raise ValueError('colors must have at least n_best -1 entries.')\n",
    "\n",
    "# Plot the grid\n",
    "fig, axes = pl.subplots(nrows=1, ncols=2)\n",
    "n_plot = 0\n",
    "for i in np.arange(2):\n",
    "    if i == 0:\n",
    "        index_logs = np.where(grid_log_s < 0.)[0]\n",
    "        index_grid = np.where(grid[0, :] < 0.)[0]\n",
    "    else:\n",
    "        index_logs = np.where(grid_log_s >= 0.)[0]\n",
    "        index_grid = np.where(grid[0, :] >= 0.)[0]\n",
    "    \n",
    "    # Plot chi2 map\n",
    "    chi2 = np.transpose(\n",
    "            grid[2, index_grid].reshape(len(index_logs), len(grid_log_q)))\n",
    "\n",
    "    im = axes[i].imshow(\n",
    "        chi2, aspect='auto', origin='lower',\n",
    "        extent=[\n",
    "            np.min(grid_log_s[index_logs]) - delta_log_s / 2., \n",
    "            np.max(grid_log_s[index_logs]) + delta_log_s / 2.,\n",
    "            np.min(grid_log_q) - delta_log_q / 2., \n",
    "            np.max(grid_log_q) + delta_log_q / 2.],\n",
    "        cmap='viridis', \n",
    "        vmin=np.min(grid[2,:]), vmax=np.nanmax(grid[2,np.isfinite(grid[2,:])]))  \n",
    "    \n",
    "    # Mark best values: best=\"X\", other good=\"o\"\n",
    "    if index_best in index_grid:\n",
    "        axes[i].scatter(grid[0, index_best], grid[1, index_best], marker='x', color='white')\n",
    "    for j, index in enumerate(index_sorted[1:n_best]):\n",
    "        if index in index_grid:\n",
    "            axes[i].scatter(grid[0, index], grid[1, index], marker='o', color=colors[j - 1])\n",
    "            \n",
    "fig.subplots_adjust(right=0.9)\n",
    "cbar_ax = fig.add_axes([0.95, 0.15, 0.05, 0.7])\n",
    "fig.colorbar(im, cax=cbar_ax)\n",
    "\n",
    "fig.text(0.5, 0.92, r'$\\chi^2$ Map', ha='center')\n",
    "fig.text(0.5, 0.04, 'log s', ha='center')\n",
    "fig.text(0.04, 0.5, 'log q', va='center', rotation='vertical')\n",
    "fig.text(1.1, 0.5, r'$\\chi^2$', va='center', rotation='vertical')\n",
    "\n",
    "pl.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def make_grid_model(index):\n",
    "    \"\"\"\n",
    "    Define a Model using the gridpoint information + the PSPL parameters.\n",
    "    \n",
    "    index = index of the grid point for which to generate the model\n",
    "    \"\"\"\n",
    "    model = mm.Model({\n",
    "        't_0': point_lens_event.model.parameters.t_0, \n",
    "        'u_0': point_lens_event.model.parameters.u_0,\n",
    "        't_E': point_lens_event.model.parameters.t_E,\n",
    "        'rho': grid[4, index],\n",
    "        's': 10.**grid[0, index],\n",
    "        'q': 10.**grid[1, index],\n",
    "        'alpha': grid[3, index]})\n",
    "    model.set_magnification_methods(magnification_methods)\n",
    "    return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plot the best-fit model\n",
    "best_fit_model = make_grid_model(index_best)\n",
    "print('Best Models')\n",
    "print(best_fit_model)\n",
    "                   \n",
    "best_fit_event = mm.Event(datasets=data, model=best_fit_model)\n",
    "(f_source, f_blend) = best_fit_event.get_ref_fluxes()\n",
    "\n",
    "# Whole model\n",
    "t_range_whole = [best_fit_model.parameters.t_0 - 5. * best_fit_model.parameters.t_E,\n",
    "                 best_fit_model.parameters.t_0 + 5. * best_fit_model.parameters.t_E]\n",
    "best_fit_event.plot_model(t_range=t_range_whole, subtract_2460000=True, color='black', lw=4)\n",
    "best_fit_event.plot_data(subtract_2460000=True)\n",
    "pl.show()\n",
    "\n",
    "\n",
    "# Zoom of planet\n",
    "t_range_planet = [t_min, t_max]\n",
    "# Best model = black\n",
    "best_fit_event.plot_data(subtract_2460000=True, s=10, zorder=0)\n",
    "best_fit_event.plot_model(\n",
    "    t_range=t_range_planet, subtract_2460000=True, color='black', lw=3, label='best',\n",
    "    zorder=10)\n",
    "# Other models (color-coding matches grid)\n",
    "for j, index in enumerate(index_sorted[1:n_best]):\n",
    "    model = make_grid_model(index)\n",
    "    model.plot_lc(\n",
    "        t_range=t_range_planet, source_flux=f_source, blend_flux=f_blend,\n",
    "        subtract_2460000=True, color=colors[j - 1], lw=2)\n",
    "    print(model)\n",
    "    \n",
    "pl.title('{0} best models'.format(n_best))\n",
    "pl.xlim(np.array(t_range_planet) - 2460000.)\n",
    "pl.legend(loc='best')\n",
    "\n",
    "pl.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Refine the n_best minima to get the best-fit solution\n",
    "parameters_to_fit = ['t_0', 'u_0', 't_E', 'rho', 'alpha', 's', 'q']\n",
    "\n",
    "fits = []\n",
    "for index in index_sorted[:n_best]:\n",
    "    model = make_grid_model(index)\n",
    "    event = mm.Event(datasets=data, model=model)\n",
    "    print(event.model)\n",
    "    result = fit_model( \n",
    "        event, parameters_to_fit=parameters_to_fit)\n",
    "    fits.append([result.fun, result.x])\n",
    "    print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plot the best-fit model and output the parameters\n",
    "\n",
    "# Extract best fit\n",
    "chi2 = [x[0] for x in fits]\n",
    "fit_parameters = [x[1] for x in fits]\n",
    "index_best = np.argmin(chi2)\n",
    "\n",
    "# Setup the model and event\n",
    "parameters = {}\n",
    "for i, parameter in enumerate(parameters_to_fit):\n",
    "    parameters[parameter] = fit_parameters[index_best][i]\n",
    "    \n",
    "final_model = mm.Model(parameters)\n",
    "final_model.set_magnification_methods(magnification_methods)\n",
    "final_event = mm.Event(datasets=data, model=final_model)\n",
    "print(final_event.model)\n",
    "print('chi2: {0}'.format(final_event.get_chi2()))\n",
    "\n",
    "# Plot the whole light curve\n",
    "final_event.plot_data(subtract_2460000=True)\n",
    "final_event.plot_model(t_range=t_range_whole, \n",
    "                       subtract_2460000=True, color='black', zorder=10)\n",
    "pl.show()\n",
    "\n",
    "# Plot zoom of the planet\n",
    "final_event.plot_data(subtract_2460000=True)\n",
    "final_event.plot_model(t_range=t_range_planet, subtract_2460000=True, color='black', zorder=10)\n",
    "pl.xlim(t_min - 2460000., t_max - 2460000.)\n",
    "pl.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "end_time = datetime.now()\n",
    "print('Total Runtime: {0}'.format(end_time - start_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "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.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}