# KVLCC2 Ikeda estimators

# Purpose
The are a lot of different ways to implement Ikeda's method. This notebook is creating a lot of different estimators and saving this to pkl files.

# Methodology
Build the estimators and save them

# Setup

```python
# %load imports.py
"""
These is the standard setup for the notebooks.
"""

%matplotlib inline
%load_ext autoreload
%autoreload 2

import sys
sys.path.append("../../")

import pandas as pd
pd.options.display.max_rows = 999
pd.options.display.max_columns = 999
pd.set_option("display.max_columns", None)
import numpy as np
import os
import matplotlib.pyplot as plt
from collections import OrderedDict
import copy
from sklearn.pipeline import Pipeline
from rolldecayestimators.transformers import CutTransformer, LowpassFilterDerivatorTransformer, ScaleFactorTransformer, OffsetTransformer
from rolldecayestimators.direct_estimator_cubic import EstimatorQuadraticB, EstimatorCubic
from rolldecayestimators.ikeda_estimator import IkedaQuadraticEstimator
import src.equations as equations
import rolldecayestimators.lambdas as lambdas
from rolldecayestimators.substitute_dynamic_symbols import lambdify
import rolldecayestimators.symbols as symbols
import sympy as sp

from sympy.physics.vector.printing import vpprint, vlatex
from IPython.display import display, Math, Latex

from sklearn.metrics import r2_score
import shipflowmotionshelpers.shipflowmotionshelpers as helpers
import src.visualization.visualize as visualize
import scipy
from copy import deepcopy
import joblib
```

    Duplicate key in file WindowsPath('C:/Users/maa/.matplotlib/stylelib/paper.mplstyle'), line 462 ('figure.figsize   : 5, 3   ## figure size in inches')
    Duplicate key in file WindowsPath('C:/Users/maa/.matplotlib/stylelib/paper.mplstyle'), line 463 ('figure.dpi       : 100        ## figure dots per inch')

```python
import joblib
from src.helpers import get_ikeda, calculate_ikeda, get_estimator_variation, get_data_variation , get_variation, hatify
from rolldecayestimators import fit_on_amplitudes
from copy import deepcopy
import rolldecayestimators.ikeda as ikeda_classes
import rolldecayestimators.ikeda_speed
import scipy
import rolldecayestimators.ikeda_speed
import src.helpers
from pyscores2.runScores2 import Calculation
from pyscores2.indata import Indata
from pyscores2.output import OutputFile
import src.visualization.visualize as visualize
from reports import mdl_results
from notebook_helpers import load_time_series_fnpf

import reports.examples.FNPF
```

## Load data from FNPF:

```python
df_parameters = pd.read_csv('../../data/processed/roll decay KVLCC2/fnpf_parameters.csv', index_col=0)
df_parameters.head()
```

      B
      IXY
      IXZ
      IYY
      IYZ
      IZZ
      KXX
      KXY
      KYY
      KZZ
      LPP
      S
      V
      XCG
      YCG
      ZCG
      accx
      acto
      b1c
      b1cr
      b1l
      b1q
      b2c
      b2cr
      b2l
      b2q
      b3c
      b3cr
      b3l
      b3q
      b4c
      b4cr
      b4l
      b4q
      b5c
      b5cr
      b5l
      b5q
      b6c
      b6cr
      b6l
      b6q
      bdens
      body
      clev
      clevel
      curv
      dens
      densi
      dofa
      dofactor
      dopa
      dopadding
      dopo
      dopower
      down
      downs
      downst
      dt
      file
      file_path_ts
      fn
      form
      free
      gravi
      heave
      heel
      hull
      inter
      k1nd
      k2nd
      k3nd
      k4nd
      k5nd
      k6nd
      kxx
      kyy
      leve
      level
      lpp
      m
      maxti
      maxtime
      mesh
      name
      npxp
      npyp
      nstep
      nthr
      pitch
      powe
      power
      refle
      reflen
      rn
      roll
      rud1
      rud2
      rud3
      rud4
      rud5
      rud6
      rudt
      side
      slim
      stre
      strength
      surge
      sway
      ta
      tf
      tfnhi
      tfnhigh
      tfnlo
      tfnlow
      titl
      title
      trim
      upst
      upstr
      vm_s
      wlin
      wlme
      yaw
      ymax
      ymin
      zcg
      conv
      encounters
      id

      kvlcc2_rolldecay_0kn
      0.853
      0.0
      0.0
      26.055
      0.0
      26.055
      0.341
      7.556
      1.177
      1.177
      4.706
      5.981
      0.993
      2.519
      0.0
      0.274
      0.050
      1.0
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.00000
      0.00000
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.0
      0.0
      0.6
      0.3
      6.0
      6.0
      0.00002
      1000.0
      1000.0
      50.0
      50.0
      2.0
      2.0
      2.0
      2.0
      1.00
      -5.0
      1.00
      0.02
      ..
      C:\Dev\Prediction-of-roll-damping-using-fully-...
      1.472020e-07
      0.23
      0.3
      9.80665
      0.0
      0.0
      0.002
      0.000000e+00
      0.1
      0.1
      0.0
      0.0
      0.0
      0.1
      0.341185
      1.1765
      6.0
      6.0
      4.706
      993.42
      180.0
      180.0
      0.000000e+00
      TRAN
      40.0
      40.0
      30.0
      32.0
      0.0
      2.0
      2.0
      4.706
      4.706
      3.957280e+00
      10.0
      0.0
      0.0
      0.0
      0.0
      0.0
      0.0
      0.0
      1.00
      30.0
      0.50
      0.50
      0.0
      0.0
      0.3059
      0.3059
      4.0
      4.0
      0.5
      0.5
      KVLCC2
      KVLCC2
      0.0
      1.00
      5.0
      0.000001
      0.000001
      0.000001
      0.0
      5.0
      -5.0
      0.2735
      NaN
      NaN
      21338.0

      kvlcc2_rolldecay_15-5kn_const_large2
      0.853
      0.0
      0.0
      26.055
      0.0
      26.055
      0.341
      7.556
      1.177
      1.177
      4.706
      5.981
      0.993
      2.519
      0.0
      0.274
      0.025
      1.0
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.00000
      0.00000
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.0
      0.0
      0.6
      0.3
      6.0
      6.0
      0.00002
      1000.0
      1000.0
      1.0
      1.0
      2.0
      2.0
      1.0
      1.0
      0.70
      -5.0
      0.70
      0.02
      ..
      C:\Dev\Prediction-of-roll-damping-using-fully-...
      1.423410e-01
      0.23
      0.3
      9.80665
      0.0
      0.0
      0.002
      0.000000e+00
      0.1
      0.1
      0.0
      0.0
      0.0
      0.1
      0.341185
      1.1765
      6.0
      6.0
      4.706
      993.42
      200.0
      200.0
      0.000000e+00
      TRAN
      40.0
      40.0
      30.0
      32.0
      0.0
      2.0
      2.0
      4.706
      4.706
      3.826600e+06
      10.0
      0.0
      0.0
      0.0
      0.0
      0.0
      0.0
      0.0
      0.70
      30.0
      0.05
      0.05
      0.0
      0.0
      0.3059
      0.3059
      4.0
      4.0
      0.5
      0.5
      KVLCC2
      KVLCC2
      0.0
      0.70
      5.0
      0.966976
      0.000001
      0.000001
      0.0
      5.0
      -5.0
      0.2735
      NaN
      NaN
      21340.0

      kvlcc2_rolldecay_15-5kn_ikeda_dev
      0.853
      0.0
      0.0
      26.055
      0.0
      26.055
      0.341
      7.556
      1.177
      1.177
      4.706
      5.981
      0.993
      2.519
      0.0
      0.274
      0.050
      1.0
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      6.07217
      2.74371
      0.0
      1.0
      0.0
      0.0
      0.0
      1.0
      0.0
      0.0
      0.6
      0.3
      6.0
      6.0
      0.00004
      1000.0
      1000.0
      0.0
      0.0
      2.0
      2.0
      1.0
      1.0
      0.25
      -2.0
      0.25
      NaN
      ..
      C:\Dev\Prediction-of-roll-damping-using-fully-...
      1.423410e-01
      0.20
      0.3
      9.80665
      0.0
      0.0
      0.002
      1.000000e-07
      0.1
      0.1
      0.0
      0.0
      0.0
      0.1
      0.341185
      1.1765
      6.0
      6.0
      4.706
      993.42
      600.0
      600.0
      1.000000e-07
      TRAN
      24.0
      24.0
      30.0
      6.0
      0.0
      2.0
      2.0
      4.706
      4.706
      3.826600e+06
      10.0
      0.0
      0.0
      0.0
      0.0
      0.0
      0.0
      0.0
      0.25
      30.0
      1.00
      1.00
      0.0
      0.0
      0.3059
      0.3059
      4.0
      4.0
      0.5
      0.5
      KVLCC2
      KVLCC2
      0.0
      0.25
      2.0
      0.966976
      0.000001
      0.000001
      0.0
      2.0
      -2.0
      0.2735
      0.0001
      0.0
      21340.0

## Load MDL results

```python
df_rolldecays = mdl_results.df_rolldecays
```

## Bilge radius

```python
scale_factor = df_rolldecays.iloc[0].scale_factor
lpp = df_rolldecays.iloc[0].lpp/scale_factor

Rs_data = [
          [lpp*scale_factor,40],
          [290,15.21],
          [225,2.4],
          [129,2.4],
          [45,8.48],
          [0,40],
            ]  # Measured on full scale geometry

df_Rs = pd.DataFrame(data=Rs_data, columns=['x','R_b'])
df_Rs['R_b']/=scale_factor
df_Rs['x']/=scale_factor
df_Rs['station'] = df_Rs['x']/lpp*20
df_Rs.sort_values(by='station', inplace=True)

stations = np.arange(0,21,1)
df_Rs_interp = pd.DataFrame(index=stations)

df_Rs_interp['R_b'] = np.interp(stations,df_Rs['station'].values,df_Rs['R_b'].values)
```

```python
df_areas = pd.read_csv('../../data/interim/kvlcc_areas.csv', sep=';', index_col=0)
df_areas.head()
```

      area
      x
      t
      b
      r_b

      no

      0
      13.826612
      -5.495000
      2.00
      11.638577
      6.636080

      1
      123.851306
      10.159932
      18.25
      27.893522
      42.367175

      2
      428.211409
      28.051284
      20.80
      41.824284
      45.369454

      3
      683.709165
      43.706216
      20.80
      50.282514
      41.080696

      4
      917.895066
      61.597568
      20.80
      56.159232
      34.146143

```python
df_areas_model = df_areas.copy()
df_areas_model['area']/=(scale_factor**2)
df_areas_model['x']/=(scale_factor)
df_areas_model['t']/=(scale_factor)
df_areas_model['b']/=(scale_factor)
df_areas_model['r_b']/=(scale_factor)

```

```python
fig,ax=plt.subplots()
df_Rs_interp.plot(y='R_b', label='manually',ax=ax)
df_areas_model.plot(y='r_b', label='points',ax=ax)
ax.legend()
```

```python
c_r_tree = joblib.load('../../models/C_r_tree.pkl')

def predict_C_r(sigma, a_1, a_3):

    X = np.array([sigma,a_1,a_3]).T

    return c_r_tree.predict(X)

```

```python
run_paths={
    21338 : {
        'scores_indata_path':'../../models/KVLCC2_speed.IN',
        'scores_outdata_path':'../../data/interim/KVLCC2_speed.out',
        'roll_decay_model':'../../models/KVLCC2_21338.pkl',
        'motions_file_paths': ['kvlcc2_rolldecay_0kn'],
        'combined_motions_ikeda': ['kvlcc2_rolldecay_0kn'],  ## hybrid model with motions and Ikeda

            },
    21340 : {
        'scores_indata_path':'../../models/KVLCC2_speed.IN',
        'scores_outdata_path':'../../data/interim/KVLCC2_speed.out',
        'roll_decay_model':'../../models/KVLCC2_21340.pkl',
        #'motions_file_paths': ['kvlcc2_rolldecay_15-5kn'],
        #'combined_motions_ikeda': ['kvlcc2_rolldecay_15-5kn'],  ## hybrid model with motions and Ikeda
        'motions_file_paths': ['kvlcc2_rolldecay_15-5kn_const_large2'],
        'combined_motions_ikeda': ['kvlcc2_rolldecay_15-5kn_const_large2'],  ## hybrid model with motions and Ikeda

    }
}
```

## Build Ikeda estimators:

```python
runs = OrderedDict()

for run_id, run in run_paths.items():

    mdl_meta_data = df_rolldecays.loc[run_id]
    runs[run_id] = new_run = {
        'ikedas':OrderedDict(),
    }
    ikedas = new_run['ikedas']

    ## Common data:
    scale_factor = mdl_meta_data.scale_factor
    indata_file_path=run['scores_indata_path']
    output_file_path=run['scores_outdata_path']
    motions_file_path=run['motions_file_paths'][0]  # Assuming same parameters
    parameters = df_parameters.loc[motions_file_path]

    ## Load ScoresII results
    indata = Indata()
    indata.open(indataPath=indata_file_path)
    output_file = OutputFile(filePath=output_file_path)

    V = mdl_meta_data.ship_speed*1.852/3.6/np.sqrt(scale_factor)

    if not mdl_meta_data.BKL:
        BKL=0
    else:
        BKL=mdl_meta_data.BKL/scale_factor

    if not mdl_meta_data.BKB:
        BKB = 0
    else:
        BKB=mdl_meta_data.BKB/scale_factor

    kg=mdl_meta_data.kg/scale_factor

    ## Various Ikeda models:

    # Regular ikeda (ikeda bilge radius approx.)
    name = 'ikeda'
    ikedas[name] = {}
    ikedas[name]['estimator'] = ikeda_classes.Ikeda.load_scoresII(V=V, w=None, fi_a=None, indata=indata, output_file=output_file,
                                scale_factor=scale_factor, BKL=BKL, BKB=BKB, kg=kg)

    # ikeda (bilge radius from CAD)
    name = 'ikeda_r'
    ikedas[name] = {}
    R_b = df_Rs_interp['R_b'].values
    ikedas[name]['estimator'] = ikeda_classes.IkedaR.load_scoresII(V=V, w=None, fi_a=None, indata=indata, output_file=output_file,
                                scale_factor=scale_factor, BKL=BKL, BKB=BKB, kg=kg, R_b=R_b)

    # ikeda (bilge radius from CAD)
    name = 'ikeda_s'
    ikedas[name] = {}
    #R_b = df_Rs_interp['R_b'].values
    R_b = df_areas_model['r_b'].values

    ikedas[name]['estimator'] = ikeda_classes.IkedaR.load_scoresII(V=V, w=None, fi_a=None, indata=indata, output_file=output_file,
                                scale_factor=scale_factor, BKL=BKL, BKB=BKB, kg=kg, R_b=R_b)

    # Same as Ikeda class but with mandatory wetted surface.
    name = 'ikeda_s'
    ikedas[name] = {}
    S_f = parameters.S

    ikedas[name]['estimator'] = ikeda_classes.IkedaS.load_scoresII(V=V, w=None, fi_a=None, indata=indata, output_file=output_file,
                                scale_factor=scale_factor, BKL=BKL, BKB=BKB, kg=kg, S_f=S_f)

    # Same as Ikeda class but with mandatory wetted surface and bilge radius from CAD.
    name = 'ikeda_r_s'
    ikedas[name] = {}
    S_f = parameters.S

    ikedas[name]['estimator'] = ikeda_classes.IkedaR.load_scoresII(V=V, w=None, fi_a=None,
                                indata=indata, output_file=output_file,
                                scale_factor=scale_factor, BKL=BKL, BKB=BKB, kg=kg, S_f=S_f, R_b=R_b)

    # Same as Ikeda eddy damping for barge.
    #name = 'ikeda_barge'
    #ikedas[name] = {}
    #
    #ikedas[name]['estimator'] = ikeda_classes.IkedaBarge.load_scoresII(V=V, w=None, fi_a=None, indata=indata, output_file=output_file,
    #                            scale_factor=scale_factor, BKL=BKL, BKB=BKB, kg=kg)

    # Same as Ikeda manual C_r.
    name = 'ikeda_C_r'
    ikedas[name] = {}

    #ikedas[name]['estimator'] = estimator = ikeda_classes.IkedaCr.load_scoresII(V=V, w=None, fi_a=None,
    #                            indata=indata, output_file=output_file,
    #                            scale_factor=scale_factor, BKL=BKL, BKB=BKB, kg=kg, S_f=S_f, R_b=R_b)
    # Note no S_f!
    ikedas[name]['estimator'] = estimator = ikeda_classes.IkedaCr.load_scoresII(V=V, w=None, fi_a=None,
                                indata=indata, output_file=output_file,
                                scale_factor=scale_factor, BKL=BKL, BKB=BKB, kg=kg, R_b=R_b)

    a, a_1, a_3, sigma_s, H = estimator.calculate_sectional_lewis_coefficients()
    estimator.C_r = predict_C_r(sigma=sigma_s, a_1=a_1, a_3=a_3)

```

    c:\python36-64\lib\re.py:212: FutureWarning: split() requires a non-empty pattern match.
      return _compile(pattern, flags).split(string, maxsplit)
    c:\python36-64\lib\re.py:212: FutureWarning: split() requires a non-empty pattern match.
      return _compile(pattern, flags).split(string, maxsplit)

## Saving Ikeda estimators:

```python
for id,run in runs.items():
    for ikeda_name, ikeda in run['ikedas'].items():

        file_name = '%s_%s.pkl' % (id,ikeda_name)
        joblib.dump(ikeda['estimator'], '../../models/%s' % file_name)

```

## Load time series from FNPF

```python
time_series = load_time_series_fnpf(names=df_parameters.index)
```

## Load FNPF models

```python
motion_models, df_results_motions = reports.examples.FNPF.get_models_and_results()
```

    c:\dev\prediction-of-roll-damping-using-fully-nonlinear-potential-flow-and-ikedas-method\venv\lib\site-packages\sklearn\base.py:334: UserWarning: Trying to unpickle estimator Pipeline from version 0.24.1 when using version 0.23.2. This might lead to breaking code or invalid results. Use at your own risk.
      UserWarning)

```python
for run_id, run in run_paths.items():

    mdl_meta_data = df_rolldecays.loc[run_id]

    new_run = runs[run_id]

    ## MDL:
    model_mdl = joblib.load(run['roll_decay_model'])
    estimator_mdl = model_mdl['estimator']
    estimator_mdl.calculate_amplitudes_and_damping()
    new_run['model_mdl']=model_mdl
    new_run['estimator_mdl']=estimator_mdl

    scale_factor = mdl_meta_data.scale_factor
    new_run['meta_data'] = meta_data={
            'Volume':mdl_meta_data.Volume/(scale_factor**3),
            'GM':mdl_meta_data.gm/scale_factor,
            'rho':mdl_meta_data.rho,
            'g':mdl_meta_data.g,
            'beam':mdl_meta_data.beam/scale_factor,
        }

    new_run['results'] = estimator_mdl.result_for_database(meta_data=meta_data)
    results = new_run['results']

    # Prediction
    new_run['df_model'] = get_estimator_variation(estimator = estimator_mdl, results=results, meta_data=meta_data)

    # Model tests
    new_run['df'] = get_data_variation(estimator = estimator_mdl, results=results, meta_data=meta_data)
    phi_a = new_run['df']['phi_a']

    ## Motions
    new_run['motions'] = OrderedDict()
    for motions_file_path in run.get('motions_file_paths',[]):
        motion_file = new_run['motions'][motions_file_path] = {}

        motion_file['parameters'] = parameters = df_parameters.loc[motions_file_path]

        motion_file['X'] = X = time_series[motions_file_path]

        motion_file['model'] = model = motion_models[motions_file_path]
        #assert model.score() > 0.90

        motion_file['meta_data'] = meta_data ={
            'Volume':parameters.V,
            'GM':mdl_meta_data.gm/mdl_meta_data.scale_factor,
            'rho':parameters.dens,
            'g':parameters.gravi,
            'beam':parameters.B,
        }

        results = model.result_for_database(meta_data=meta_data)
        if not 'B_3' in results:
            results['B_3'] = 0

        motion_file['results'] = results
        model.calculate_amplitudes_and_damping()

        # Prediction
        motion_file['df_model'] = get_estimator_variation(estimator = model, results = results, meta_data=meta_data)

        # Simulation
        motion_file['df'] = get_data_variation(estimator = model, results = results, meta_data=meta_data)

    ## Ikeda
    for ikeda_name, ikeda in new_run['ikedas'].items():

        omega0=new_run['results']['omega0']
        #phi_a=new_run['results']['phi_a']
        ikeda_estimator = ikeda['estimator']
        ikeda['df'] = results = ikeda_estimator.calculate(w=omega0, fi_a=phi_a)

        results['phi_a'] = phi_a
        results.set_index('phi_a', inplace=True)

        ## Convert to dimensional damping [Nm/s]
        ikeda['meta_data'] = meta_data = new_run['meta_data']
        result_ = src.helpers.unhat(df=results, Disp=meta_data['Volume'], beam=meta_data['beam'], g=meta_data['g'], rho=meta_data['rho'])
        ikeda['df'] = results = pd.concat((results,result_), axis=1)

        ## Feed the results into a quadratic model:
        output = fit_on_amplitudes.fit_quadratic(y=results['B_44'], phi_a=results.index, omega0=omega0,
                                    B_1_0=new_run['results']['B_1'],
                                    B_2_0=new_run['results']['B_2'],
                                    )

        parameters = {
            'B_1A': output['B_1'] / new_run['results']['A_44'],
            'B_2A': output['B_2'] / new_run['results']['A_44'],
            'B_3A': 0,
            'C_1A': estimator_mdl.parameters['C_1A'],
            'C_3A': estimator_mdl.parameters['C_3A'],
            'C_5A': estimator_mdl.parameters['C_5A'],
        }
        ikeda['model'] = EstimatorCubic.load(**parameters, X=estimator_mdl.X)

        ikeda['results'] = ikeda['model'].result_for_database(meta_data=meta_data)
        ikeda['df_model'] = get_estimator_variation(estimator = ikeda['model'], results = ikeda['results'], meta_data=new_run['meta_data'])

    ## Combined model:
    new_run['combined_models'] = combined_models =  {}
    combined_motions_ikedas = run.get('combined_motions_ikeda',[])
    for combined_motions_ikeda in combined_motions_ikedas:

        combined_models[combined_motions_ikeda] = combined_model = {}

        combined_model['motions'] = model_motions = new_run['motions'][combined_motions_ikeda]
        combined_model['ikedas'] = OrderedDict()

        for ikeda_name, ikeda in new_run['ikedas'].items():

            combined_model['ikedas'][ikeda_name] = combined_model_ikeda = {}

            df = ikeda['df']
            df_motions = pd.DataFrame()
            df_motions['phi_a'] = df.index.copy()
            df_motions = get_variation(X_amplitudes=df_motions, results = model_motions['results'], meta_data=model_motions['meta_data'])
            df_motions.set_index('phi_a', inplace=True)

            columns_visc = ['B_L','B_F','B_E','B_BK']
            df_combined = df[columns_visc].copy()
            df_combined['B_W'] = df_motions['B_e']
            df_combined['B'] = df_combined.sum(axis=1)
            combined_model_ikeda['df'] = df_combined

             ## Feed the results into a cubic model:
            output = fit_on_amplitudes.fit_quadratic(y=df_combined['B'], phi_a=df_combined.index, omega0=omega0,
                                    B_1_0=new_run['results']['B_1'],
                                    B_2_0=new_run['results']['B_2'],
                                    )

            parameters = {
                'B_1A': output['B_1'] / new_run['results']['A_44'],
                'B_2A': output['B_2'] / new_run['results']['A_44'],
                'B_3A': 0,
                'C_1A': estimator_mdl.parameters['C_1A'],
                'C_3A': estimator_mdl.parameters['C_3A'],
                'C_5A': estimator_mdl.parameters['C_5A'],
            }
            combined_model_ikeda['model'] = EstimatorCubic.load(**parameters, X=estimator_mdl.X)
            combined_model_ikeda['results'] = combined_model_ikeda['model'].result_for_database(meta_data=meta_data)
            combined_model_ikeda['df_model'] = get_estimator_variation(estimator = combined_model_ikeda['model'], results = combined_model_ikeda['results'], meta_data=new_run['meta_data'])

```

    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))
    c:\dev\rolldecay-estimators\rolldecayestimators\ikeda_speed.py:595: RuntimeWarning: invalid value encountered in sqrt
      gamma=sqrt(pi)*f3*(rmax+2*M/H*sqrt(B0**2*A0**2))/((2*Ts*(1-OG/Ts)*sqrt(H0_prim*sigma_prim)))

## Save Hybrid models

```python
for id, run in runs.items():

    for key, combined_model in run['combined_models'].items():
        for ikeda_name, ikeda in combined_model['ikedas'].items():
            pipeline = Pipeline([('estimator',ikeda['model'])])
            file_name = '%i_%s_%s.pkl' % (id,key,ikeda_name)
            joblib.dump(pipeline, '../../models/%s' % file_name)
```


# This Jupyter notebook illustrates how to read data in from an external file
## [notebook provides a simple illustration, users can easily use these examples to modify and customize  for their data storage scheme and/or preferred workflows]

###Motion Blur Filtering: A Statistical Approach for Extracting  Confinement Forces & Diffusivity from a Single Blurred Trajectory

#####Author: Chris Calderon

Copyright 2015 Ursa Analytics, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

### Cell below loads the required modules and packages

```python
%matplotlib inline
#command above avoids using the "dreaded" pylab flag when launching ipython (always put magic command above as first arg to ipynb file)
import matplotlib.font_manager as font_manager
import matplotlib.pyplot as plt
import numpy as np
import scipy.optimize as spo
import findBerglundVersionOfMA1 #this module builds off of Berglund's 2010 PRE parameterization (atypical MA1 formulation)
import MotionBlurFilter
import Ursa_IPyNBpltWrapper

```

##Now that required modules packages are loaded, set parameters for simulating "Blurred" OU trajectories.  Specific mixed continuous/discrete model:

\begin{align}
dr_t = & ({v}-{\kappa} r_t)dt + \sqrt{2 D}dB_t \\
\psi_{t_i} = & \frac{1}{t_E}\int_{t_{i}-t_E}^{t_i} r_s ds + \epsilon^{\mathrm{loc}}_{t_i}
\end{align}

###In above equations, parameter vector specifying model is: $\theta = (\kappa,D,\sigma_{\mathrm{loc}},v)$

###Statistically exact discretization of above for uniform time spacing  $\delta$  (non-uniform $\delta$ requires time dependent vectors and matrices below):

\begin{align}
r_{t_{i+1}} = & A + F r_{t_{i}} + \eta_{t_i} \\
\psi_{t_i} = & H_A + H_Fr_{t_{i-1}} + \epsilon^{\mathrm{loc}}_{t_i} + \epsilon^{\mathrm{mblur}}_{t_i} \\
\epsilon^{\mathrm{loc}}_{t_i} + & \epsilon^{\mathrm{mblur}}_{t_i} \sim  \mathcal{N}(0,R_i) \\
\eta_i \sim & \mathcal{N}(0,Q) \\
t_{i-1} = & t_{i}-t_E \\
 C = & cov(\epsilon^{\mathrm{mblur}}_{t_i},\eta_{t_{i-1}}) \ne 0
\end{align}

####Note:  Kalman Filter (KF) and Motion Blur Filter (MBF) codes estimate $\sqrt(2D)$ directly as "thermal noise" parameter

### For situations where users would like to read data in from external source, many options exist.

####In cell below, we show how to read in a text file and process the data assuming the text file contains two columns:  One column with the 1D measurements and one with localization standard deviation vs. time estimates.  Code chunk below sets up some default variables (tunable values indicated by comments below).   Note that for multivariate signals, chunks below can readily be modified to process x/y or x/y/z measurements separately.  Future work will address estimating 2D/3D models with the MBF (computational [not theoretical] issues exists in this case);  however, the code currently provides diagnostic information to determine if unmodeled multivariate interaction effects are important (see main paper and Calderon, Weiss, Moerner, PRE 2014)

### Plot examles from other notebooks can be used to explore output within this notbook or another.   Next, a simple example of "Batch" processing is illustrated.

```python
filenameBase='./ExampleData/MyTraj_' #assume all trajectory files have this prefix (adjust file location accordingly)

N=20 #set the number of trajectories to read.
delta = 25./1000. #user must specify the time (in seconds) between observations.  code provided assumes uniform continuous illumination and
#NOTE: in this simple example, all trajectories assumed to be collected with exposure time delta input above

#now loop over trajectories and store MLE results
resBatch=[] #variable for storing MLE output

#loop below just copies info from cell below (only difference is file to read is modified on each iteration of the loop)
for i in range(N):

    filei = filenameBase + str(i+1) + '.txt'
    print ''
    print '^'*100
    print 'Reading in file: ', filei
    #first load the sample data stored in text file.  here we assume two columns of numerica data (col 1 are measurements)
    data = np.loadtxt(filei)
    (T,ncol)=data.shape
    #above we just used a simple default text file reader;  however, any means of extracting the data and
    #casting it to a Tx2 array (or Tx1 if no localization accuracy info available) will work.

    ymeas = data[:,0]
    locStdGuess = data[:,1]  #if no localization info avaible, just set this to zero or a reasonable estimate of localization error [in nm]

    Dguess = 0.1 #input a guess of the local diffusion coefficient of the trajecotry to seed the MLE searches (need not be accurate)
    velguess = np.mean(np.diff(ymeas))/delta #input a guess of the velocity of the trajecotry to seed the MLE searches (need not be accurate)

    MA=findBerglundVersionOfMA1.CostFuncMA1Diff(ymeas,delta) #construct an instance of the Berglund estimator
    res = spo.minimize(MA.evalCostFuncVel, (np.sqrt(Dguess),np.median(locStdGuess),velguess), method='nelder-mead')

    #output Berglund estimation result.
    print 'Berglund MLE',res.x[0]*np.sqrt(2),res.x[1],res.x[-1]
    print '-'*100

    #obtain crude estimate of mean reversion parameter.  see Calderon, PRE (2013)
    kappa1 = np.log(np.sum(ymeas[1:]*ymeas[0:-1])/(np.sum(ymeas[0:-1]**2)-T*res.x[1]**2))/-delta

    #construct an instance of the MBF estimator
    BlurF = MotionBlurFilter.ModifiedKalmanFilter1DwithCrossCorr(ymeas,delta,StaticErrorEstSeq=locStdGuess)
    #use call below if no localization info avaible
    # BlurF = MotionBlurFilter.ModifiedKalmanFilter1DwithCrossCorr(ymeas,delta)

    parsIG=np.array([np.abs(kappa1),res.x[0]*np.sqrt(2),res.x[1],res.x[-1]]) #kick off MLE search with "warm start" based on simpler model
    #kick off nonlinear cost function optimization given data and initial guess
    resBlur = spo.minimize(BlurF.evalCostFunc,parsIG, method='nelder-mead')

    print 'parsIG for Motion Blur filter',parsIG
    print 'Motion Blur MLE result:',resBlur

    #finally evaluate diagnostic statistics at MLE just obtained
    loglike,xfilt,pit,Shist =BlurF.KFfilterOU1d(resBlur.x)

    print np.mean(pit),np.std(pit)
    print 'crude assessment of model:  check above mean is near 0.5 and std is approximately',np.sqrt(1/12.)
    print 'statements above based on generalized residual U[0,1] shape'
    print 'other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.'

    #finally just store the MLE of the MBF in a list
    resBatch.append(resBlur.x)

```

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_1.txt
    Berglund MLE 0.424450138266 0.0410840106778 -0.000253509776551
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [  6.01896509e-01   4.24450138e-01   4.10840107e-02  -2.53509777e-04]
    Motion Blur MLE result:   status: 0
        nfev: 196
     success: True
         fun: -1.1526156274680164
           x: array([  9.88732097e-01,   4.30329177e-01,   1.69786977e-02,
            -1.88788339e-04])
     message: 'Optimization terminated successfully.'
         nit: 110
    0.512506169502 0.289227348189
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_2.txt
    Berglund MLE 0.403080320506 0.0421133323903 0.0315952570332
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.79926789  0.40308032  0.04211333  0.03159526]
    Motion Blur MLE result:   status: 0
        nfev: 299
     success: True
         fun: -1.1760118286776404
           x: array([ 1.44062784,  0.41103507,  0.01766368, -0.04607467])
     message: 'Optimization terminated successfully.'
         nit: 172
    0.496990426074 0.29206459027
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_3.txt
    Berglund MLE 0.425243165442 0.0383252438668 0.0339861519423
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.27321687  0.42524317  0.03832524  0.03398615]
    Motion Blur MLE result:   status: 0
        nfev: 312
     success: True
         fun: -1.1942812161329239
           x: array([ 1.37933008,  0.44563642,  0.01178971,  0.52399413])
     message: 'Optimization terminated successfully.'
         nit: 186
    0.50078852219 0.291016376117
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_4.txt
    Berglund MLE 0.387088460983 0.0390914442611 0.00401072737933
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.29576551  0.38708846  0.03909144  0.00401073]
    Motion Blur MLE result:   status: 0
        nfev: 429
     success: True
         fun: -1.2220005538177285
           x: array([ 1.20270778,  0.40031886,  0.01525121,  0.37603661])
     message: 'Optimization terminated successfully.'
         nit: 258
    0.501678044756 0.287044032779
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_5.txt
    Berglund MLE 0.373653923964 0.0414090910471 -0.0271831915793
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.60942087  0.37365392  0.04140909 -0.02718319]
    Motion Blur MLE result:   status: 0
        nfev: 315
     success: True
         fun: -1.1972364793651142
           x: array([ 1.42686492,  0.4006258 ,  0.0179909 , -0.15973117])
     message: 'Optimization terminated successfully.'
         nit: 187
    0.505548331825 0.28907161488
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_6.txt
    Berglund MLE 0.405658929477 0.0410255848183 -0.0527407580382
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.88813023  0.40565893  0.04102558 -0.05274076]
    Motion Blur MLE result:   status: 0
        nfev: 278
     success: True
         fun: -1.1785934866396908
           x: array([ 2.206071  ,  0.43743055,  0.01557288, -0.2198948 ])
     message: 'Optimization terminated successfully.'
         nit: 161
    0.49752884216 0.290010436927
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_7.txt
    Berglund MLE 0.440296244194 0.037794781385 0.0555249133931
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.51073785  0.44029624  0.03779478  0.05552491]
    Motion Blur MLE result:   status: 0
        nfev: 296
     success: True
         fun: -1.1646850756274711
           x: array([ 1.00900231,  0.45080595,  0.01384808,  0.0596462 ])
     message: 'Optimization terminated successfully.'
         nit: 171
    0.500138244772 0.285738276794
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_8.txt
    Berglund MLE 0.388193789739 0.0433344124496 -0.0232538599371
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 1.23208956  0.38819379  0.04333441 -0.02325386]
    Motion Blur MLE result:   status: 0
        nfev: 318
     success: True
         fun: -1.1901666108672013
           x: array([ 2.23788936,  0.40683237,  0.01763311, -0.06170199])
     message: 'Optimization terminated successfully.'
         nit: 185
    0.500831978254 0.28767904269
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_9.txt
    Berglund MLE 0.428119184149 0.0368338621282 0.0631101005882
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.42504155  0.42811918  0.03683386  0.0631101 ]
    Motion Blur MLE result:   status: 0
        nfev: 313
     success: True
         fun: -1.1921480409010281
           x: array([ 1.0874416 ,  0.43535992,  0.0134389 ,  0.19952   ])
     message: 'Optimization terminated successfully.'
         nit: 177
    0.499882963813 0.286378046611
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_10.txt
    Berglund MLE 0.403241526019 0.0448782500646 0.0326597583831
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.36721914  0.40324153  0.04487825  0.03265976]
    Motion Blur MLE result:   status: 0
        nfev: 295
     success: True
         fun: -1.1280944693617625
           x: array([ 0.88575554,  0.40813484,  0.02201115,  0.19055693])
     message: 'Optimization terminated successfully.'
         nit: 173
    0.499027710082 0.290215367984
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_11.txt
    Berglund MLE 0.446022076218 0.0386925793552 0.0317446002903
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.75851698  0.44602208  0.03869258  0.0317446 ]
    Motion Blur MLE result:   status: 0
        nfev: 364
     success: True
         fun: -1.1477995850212523
           x: array([ 1.34146215,  0.45217896,  0.01547886,  0.11062506])
     message: 'Optimization terminated successfully.'
         nit: 217
    0.498350123323 0.28489583658
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_12.txt
    Berglund MLE 0.433878819812 0.0405257997338 0.0194618189645
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.57081066  0.43387882  0.0405258   0.01946182]
    Motion Blur MLE result:   status: 0
        nfev: 320
     success: True
         fun: -1.1258718069898108
           x: array([ 1.0535438 ,  0.44151737,  0.01909119,  0.0921696 ])
     message: 'Optimization terminated successfully.'
         nit: 189
    0.4993722138 0.286382226048
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_13.txt
    Berglund MLE 0.442289936266 0.0413708496844 0.0900189405225
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.53984449  0.44228994  0.04137085  0.09001894]
    Motion Blur MLE result:   status: 0
        nfev: 281
     success: True
         fun: -1.1194332404998935
           x: array([ 1.44682073,  0.44948337,  0.01867071,  0.17022423])
     message: 'Optimization terminated successfully.'
         nit: 167
    0.498968531464 0.286556318588
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_14.txt
    Berglund MLE 0.434387236759 0.0392930335766 0.0256938157463
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.57814585  0.43438724  0.03929303  0.02569382]
    Motion Blur MLE result:   status: 0
        nfev: 287
     success: True
         fun: -1.1622391321135688
           x: array([ 0.99021595,  0.44116143,  0.01484123, -0.01121947])
     message: 'Optimization terminated successfully.'
         nit: 167
    0.503103615691 0.292303358037
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_15.txt
    Berglund MLE 0.411721173737 0.0381990349157 0.0153091535058
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.60076698  0.41172117  0.03819903  0.01530915]
    Motion Blur MLE result:   status: 0
        nfev: 310
     success: True
         fun: -1.1694922158999403
           x: array([ 1.11385547,  0.42298358,  0.01809222,  0.09968667])
     message: 'Optimization terminated successfully.'
         nit: 191
    0.493928160614 0.283653076911
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_16.txt
    Berglund MLE 0.449853292681 0.0346580553668 -0.014228133955
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.88913235  0.44985329  0.03465806 -0.01422813]
    Motion Blur MLE result:   status: 0
        nfev: 189
     success: True
         fun: -1.1617781756413692
           x: array([ 1.49678266,  0.46607595,  0.01368101, -0.01265549])
     message: 'Optimization terminated successfully.'
         nit: 104
    0.502248368185 0.285265534615
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_17.txt
    Berglund MLE 0.405791875716 0.0429526801662 0.0281841646573
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.79922712  0.40579188  0.04295268  0.02818416]
    Motion Blur MLE result:   status: 0
        nfev: 311
     success: True
         fun: -1.1566192303985554
           x: array([ 1.80755174,  0.41859545,  0.01897457, -0.21484235])
     message: 'Optimization terminated successfully.'
         nit: 182
    0.498866022839 0.288461118604
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_18.txt
    Berglund MLE 0.480290453713 0.033150036359 -0.0363831128213
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.44079153  0.48029045  0.03315004 -0.03638311]
    Motion Blur MLE result:   status: 0
        nfev: 286
     success: True
         fun: -1.1667980253486265
           x: array([ 0.90486109,  0.4872516 ,  0.00819091,  0.11628986])
     message: 'Optimization terminated successfully.'
         nit: 170
    0.498456742145 0.288303457635
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_19.txt
    Berglund MLE 0.401125045744 0.0394428992004 -0.00560612519608
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [ 0.75923837  0.40112505  0.0394429  -0.00560613]
    Motion Blur MLE result:   status: 0
        nfev: 358
     success: True
         fun: -1.182656245292518
           x: array([ 1.41280844,  0.41718142,  0.01732866, -0.11048628])
     message: 'Optimization terminated successfully.'
         nit: 218
    0.499503636338 0.288565336397
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Reading in file:  ./ExampleData/MyTraj_20.txt
    Berglund MLE 0.4678828153 0.0341188814665 0.000390470606951
    ----------------------------------------------------------------------------------------------------
    parsIG for Motion Blur filter [  4.71922369e-01   4.67882815e-01   3.41188815e-02   3.90470607e-04]
    Motion Blur MLE result:   status: 0
        nfev: 419
     success: True
         fun: -1.1464820600970622
           x: array([ 1.01456235,  0.46829891,  0.01419429,  0.20915194])
     message: 'Optimization terminated successfully.'
         nit: 245
    0.502468629673 0.293260000307
    crude assessment of model:  check above mean is near 0.5 and std is approximately 0.288675134595
    statements above based on generalized residual U[0,1] shape
    other hypothesis tests outlined which can use PIT sequence above outlined/referenced in paper.

```python
#Summarize the results of the above N simulations
#

resSUM=np.array(resBatch)
print 'Blur medians',np.median(resSUM[:,0]),np.median(resSUM[:,1]),np.median(resSUM[:,2]),np.median(resSUM[:,3])
print 'means',np.mean(resSUM[:,0]),np.mean(resSUM[:,1]),np.mean(resSUM[:,2]),np.mean(resSUM[:,3])
print 'std',np.std(resSUM[:,0]),np.std(resSUM[:,1]),np.std(resSUM[:,2]),np.std(resSUM[:,3])

print '^'*100 ,'\n\n'
```

    Blur medians 1.27208496571 0.436395237852 0.0162757902936 0.0759079000468
    means 1.32234434672 0.434561850166 0.0160360992158 0.0655553122287
    std 0.380912845778 0.0234327797792 0.00299196795637 0.182354637945
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


```python
%%capture
## compile PyRoss for this notebook
import os
owd = os.getcwd()
os.chdir('../../')
%run setup.py install
os.chdir(owd)
```

```python
%matplotlib inline
import numpy as np
from matplotlib import pyplot as plt
import pyross
import time
import seaborn as sns
import pandas as pd
from matplotlib.pyplot import cm
```

In this notebook we consider a control protocol consisting of an initial lockdown, which is then partly released. For our numerical study we generate synthetic data using the stochastic SIIR model.

While we use the UK age structure and contact matrix, we used here simulated data.

**Summary:**

1. We load the age structure and contact matrix for Denmark. The contact matrix is generally given as
\begin{equation}
    C = C_{H} + C_{W} + C_{S} + C_{O},
\end{equation}
where the four terms denote the number of contacts at home, work, school, and all other remaining contacts.
2. We define the other model parameters of the SIIR model **(these are not fitted to any real data)**.
3. We define a "lockdown-protocol":
    Withing a certain time range, a lockdown is imposed (shcool closure). The contact matrix is reduced to
    \begin{equation}
        C = C_{H}
     \end{equation}

We want to see an impact if the school reopen, when do we see a change in the number of people infected ? Which age group is the most infected ?

## Get the contact Matrices for UK

```python
M=16  # number of age groups

# load age structure data
my_data = np.genfromtxt('../../data/age_structures/UK.csv', delimiter=',', skip_header=1)
aM, aF = my_data[:, 1], my_data[:, 2]

# set age groups
Ni=aM+aF;   Ni=Ni[0:M];  N=np.sum(Ni)
```

```python
df1= pd.DataFrame({'Female':aF,  'Age':['0-4','5-9','10-14','15-19','20-24','25-29','30-34','35-39','40-44','45-49','50-54','55-59','60-64','65-69','70-74','75-79','80-84','85-89','90-94','95-99','100+'], 'Sex':['F']*21})
df2 = pd.DataFrame({'Male':aM,  'Age':['0-4','5-9','10-14','15-19','20-24','25-29','30-34','35-39','40-44','45-49','50-54','55-59','60-64','65-69','70-74','75-79','80-84','85-89','90-94','95-99','100+'], 'Sex':['M']*21})
df3 = pd.concat([df1, df2], join='inner')
df3['number'] = np.concatenate((aF,aM))
```

C is the sum of contributions from contacts at home, workplace, schools and all other public spheres. Using superscripts $H$, $W$, $S$ and $O$ for each of these, we write the contact matrix as
$$
C_{ij} = C^H_{ij} + C^W_{ij} + C^S_{ij} + C^O_{ij}
$$

We read in these contact matrices from the data sets provided in the paper *Projecting social contact matrices in 152 countries using contact surveys and demographic data* by Prem et al, sum them to obtain the total contact matrix. We also read in the age distribution of UK obtained from the *Population pyramid* website.

```python
# Get individual contact matrices
CH, CW, CS, CO = pyross.contactMatrix.UK()

# By default, home, work, school, and others contribute to the contact matrix
C = CH + CW + CS + CO

# Illustrate the individual contact matrices:
fig,aCF =  plt.subplots(2,2);
aCF[0][0].pcolor(CH, cmap=plt.cm.get_cmap('GnBu', 10));
aCF[0][1].pcolor(CW, cmap=plt.cm.get_cmap('GnBu', 10));
aCF[1][0].pcolor(CS, cmap=plt.cm.get_cmap('GnBu', 10));
aCF[1][1].pcolor(CO, cmap=plt.cm.get_cmap('GnBu', 10));
```

## Covid19 data

```python
# Get the latest data from Johns Hopkins University
!git clone https://github.com/CSSEGISandData/COVID-19
```

    fatal: destination path 'COVID-19' already exists and is not an empty directory.

```python
cases = pd.read_csv('COVID-19/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv')
cases.head()
```

      Province/State
      Country/Region
      Lat
      Long
      1/22/20
      1/23/20
      1/24/20
      1/25/20
      1/26/20
      1/27/20
      ...
      5/24/20
      5/25/20
      5/26/20
      5/27/20
      5/28/20
      5/29/20
      5/30/20
      5/31/20
      6/1/20
      6/2/20

      0
      NaN
      Afghanistan
      33.0000
      65.0000
      0
      0
      0
      0
      0
      0
      ...
      10582
      11173
      11831
      12456
      13036
      13659
      14525
      15205
      15750
      16509

      1
      NaN
      Albania
      41.1533
      20.1683
      0
      0
      0
      0
      0
      0
      ...
      998
      1004
      1029
      1050
      1076
      1099
      1122
      1137
      1143
      1164

      2
      NaN
      Algeria
      28.0339
      1.6596
      0
      0
      0
      0
      0
      0
      ...
      8306
      8503
      8697
      8857
      8997
      9134
      9267
      9394
      9513
      9626

      3
      NaN
      Andorra
      42.5063
      1.5218
      0
      0
      0
      0
      0
      0
      ...
      762
      763
      763
      763
      763
      764
      764
      764
      765
      844

      4
      NaN
      Angola
      -11.2027
      17.8739
      0
      0
      0
      0
      0
      0
      ...
      69
      70
      70
      71
      74
      81
      84
      86
      86
      86

5 rows × 137 columns

```python
deaths = pd.read_csv('COVID-19/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv')
deaths.shape
```

    (266, 137)

```python
cases[cases['Country/Region']=='United Kingdom']
```

      Province/State
      Country/Region
      Lat
      Long
      1/22/20
      1/23/20
      1/24/20
      1/25/20
      1/26/20
      1/27/20
      ...
      5/24/20
      5/25/20
      5/26/20
      5/27/20
      5/28/20
      5/29/20
      5/30/20
      5/31/20
      6/1/20
      6/2/20

      217
      Bermuda
      United Kingdom
      32.3078
      -64.7505
      0
      0
      0
      0
      0
      0
      ...
      133
      133
      139
      139
      140
      140
      140
      140
      141
      141

      218
      Cayman Islands
      United Kingdom
      19.3133
      -81.2546
      0
      0
      0
      0
      0
      0
      ...
      129
      134
      137
      140
      140
      141
      141
      141
      150
      151

      219
      Channel Islands
      United Kingdom
      49.3723
      -2.3644
      0
      0
      0
      0
      0
      0
      ...
      558
      559
      559
      560
      560
      560
      560
      560
      560
      560

      220
      Gibraltar
      United Kingdom
      36.1408
      -5.3536
      0
      0
      0
      0
      0
      0
      ...
      154
      154
      154
      157
      158
      161
      169
      170
      170
      172

      221
      Isle of Man
      United Kingdom
      54.2361
      -4.5481
      0
      0
      0
      0
      0
      0
      ...
      336
      336
      336
      336
      336
      336
      336
      336
      336
      336

      222
      Montserrat
      United Kingdom
      16.7425
      -62.1874
      0
      0
      0
      0
      0
      0
      ...
      11
      11
      11
      11
      11
      11
      11
      11
      11
      11

      223
      NaN
      United Kingdom
      55.3781
      -3.4360
      0
      0
      0
      0
      0
      0
      ...
      259559
      261184
      265227
      267240
      269127
      271222
      272826
      274762
      276332
      277985

      248
      Anguilla
      United Kingdom
      18.2206
      -63.0686
      0
      0
      0
      0
      0
      0
      ...
      3
      3
      3
      3
      3
      3
      3
      3
      3
      3

      249
      British Virgin Islands
      United Kingdom
      18.4207
      -64.6400
      0
      0
      0
      0
      0
      0
      ...
      8
      8
      8
      8
      8
      8
      8
      8
      8
      8

      250
      Turks and Caicos Islands
      United Kingdom
      21.6940
      -71.7979
      0
      0
      0
      0
      0
      0
      ...
      12
      12
      12
      12
      12
      12
      12
      12
      12
      12

      257
      Falkland Islands (Malvinas)
      United Kingdom
      -51.7963
      -59.5236
      0
      0
      0
      0
      0
      0
      ...
      13
      13
      13
      13
      13
      13
      13
      13
      13
      13

11 rows × 137 columns

```python
cols = cases.columns.tolist()
case = cases.loc[223,][4:]
death = deaths.loc[223,][4:]
```

```python
plt.figure(figsize=(20,10))
sns.set(font_scale=3)  # crazy big
plt.legend(fontsize='x-large', title_fontsize='1000')
sns.set_style(style='white')
plt.legend(fontsize='x-large', title_fontsize='10000')
sns.scatterplot(np.arange(len(death)),death, label='death');
sns.scatterplot(x=np.arange(len(case)), y=case, label='case');
plt.ylabel('')
plt.title('')
plt.xticks(np.arange(0, 115,15), ('1/22', '2/6', '2/21', '3/16', '3/31', '4/15','4/30', '04/05'));
plt.savefig('UKcovid19.png', format='png', dpi=200)
```

## Deterministic SIR model for UK

Using this code : https://github.com/rajeshrinet/pyross/blob/master/examples/deterministic/ex03-age-structured-SIR-for-India.ipynb

Assume that the population has been partitioned into  $i=1,\ldots, M$ age groups and that we have available the $M\times M$ contact matrix $C_{ij}$.  We assume all initial cases are symptomatic, and remain so.

See SIR model : pyross/deterministic.pyx

```python
# Generate class with contact matrix for SIR model with UK contact structure
generator = pyross.contactMatrix.SIR(CH, CW, CS, CO)
```

The infection parameter $\beta$ is unknown, so we fit it to the case data till 25th March.

```python
## Parameters of the model (random)

beta  = 0.01546692 # infection rate assumed intrinsic to the pathogen
gIa   = 1./7             # recovery rate of asymptomatic infectives (7 days)
gIs   = 1./7             # recovery rate of symptomatic infectives
alpha = 0.               # fraction of asymptomatic infectives
fsa   = 1             # the self-isolation parameter

# initial conditions
Is_0 = np.zeros((M));  Is_0[0:15]=200
Ia_0 = np.zeros((M)) # no asymptomatic infectives
R_0  = np.zeros((M))
S_0  = Ni - (Ia_0 + Is_0 + R_0)
```

```python
# matrix for linearised dynamics
L0 = np.zeros((M, M))
L  = np.zeros((2*M, 2*M))

for i in range(M):
    for j in range(M):
        L0[i,j]=C[i,j]*Ni[i]/Ni[j]

L[0:M, 0:M]     =    alpha*beta/gIs*L0
L[0:M, M:2*M]   = fsa*alpha*beta/gIs*L0
L[M:2*M, 0:M]   =    ((1-alpha)*beta/gIs)*L0
L[M:2*M, M:2*M] = fsa*((1-alpha)*beta/gIs)*L0

r0 = np.max(np.linalg.eigvals(L))
print("The basic reproductive ratio for these parameters is", r0)
```

    The basic reproductive ratio for these parameters is (1.264513426078052+0j)

```python
# instantiate model
parameters = {'alpha':alpha,'beta':beta, 'gIa':gIa,'gIs':gIs,'fsa':fsa}
model = pyross.deterministic.SIR(parameters, M, Ni)
```

```python
# the contact structure is independent of time
def contactMatrix(t):
    return C
```

```python
# time_points to solve the ode (using odeint) Ti = 0 by default
Tf=350;  Nf=3500;  #Tf is the final day np.linspace(Ti, Tf, Nf)
```

```python
# run model
data=model.simulate(S_0, Ia_0, Is_0, contactMatrix, Tf, Nf)
```

```python
data['X'].shape # 48 because 16 groups * 4 equations
```

    (3500, 48)

```python
t = data['t']; IC  = np.zeros((Nf))
for i in range(M):
        IC += data['X'][:,2*M+i]
```

```python
index_max = np.argmax(IC)
```

```python
fig = plt.figure(num=None, figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 12})
plt.plot(t, IC, '-', lw=4, color='#A60628', label='forecast', alpha=0.8)
plt.axvline(x=index_max/10, ymin=0, ymax=175000, color='#A60628')
day, cases = np.array(np.arange(1,Tf)), np.array(case[0:Tf])
plt.plot(cases, 'o-', lw=4, color='#348ABD', ms=5, label='data', alpha=0.5)
plt.legend(fontsize=15, loc='upper left'); plt.grid()
plt.autoscale(enable=True, axis='x', tight=True)
plt.ylabel('Infected individuals');
plt.title('No measure');
plt.savefig('FullmatrixC.png', format='png', dpi=200)
```

```python
SC  = np.zeros((Nf))
for i in range(M):
        SC += data.get('X')[:,0*M+i]
        IC += data.get('X')[:,2*M+i]

fig = plt.figure(num=None, figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 22})

plt.plot(t, SC*10**(-6), '-', lw=4, color='#348ABD', label='susceptible', alpha=0.8,)
plt.fill_between(t, 0, SC*10**(-6), color="#348ABD", alpha=0.3)

plt.plot(t, IC*10**(-6), '-', lw=4, color='#A60628', label='infected', alpha=0.8)
plt.fill_between(t, 0, IC*10**(-6), color="#A60628", alpha=0.3)

plt.plot(cases*10**(-6), 'ro-', lw=4, color='dimgrey', ms=16, label='data', alpha=0.5)

plt.legend(fontsize=26); plt.grid()
plt.autoscale(enable=True, axis='x', tight=True)
plt.ylabel('Individuals (millions)')
plt.xticks(np.arange(0, Tf, 90), ('22/01', '30/04'  ));
plt.savefig('C-SIRNomesure.png', format='png', dpi=200)
```

```python
# matrix for linearised dynamics
L0 = np.zeros((M, M))
L  = np.zeros((2*M, 2*M))
xind=[np.argsort(IC)[-1]]

rr = np.zeros((Tf))

for tt in range(Tf):
    Si = np.array((data['X'][tt*10,0:M])).flatten()
    for i in range(M):
        for j in range(M):
            L0[i,j]=C[i,j]*Si[i]/Ni[j]
    L[0:M, 0:M]     =    alpha*beta/gIs*L0
    L[0:M, M:2*M]   = fsa*alpha*beta/gIs*L0
    L[M:2*M, 0:M]   =    ((1-alpha)*beta/gIs)*L0
    L[M:2*M, M:2*M] = fsa*((1-alpha)*beta/gIs)*L0

    rr[tt] = np.real(np.max(np.linalg.eigvals(L)))

fig = plt.figure(num=None, figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 22})

plt.plot(t[::10], rr, 'o', lw=4, color='#A60628', label='suscetible', alpha=0.8,)
plt.fill_between(t, 0, t*0+1, color="dimgrey", alpha=0.2); plt.ylabel('Basic reproductive ratio')
plt.ylim(np.min(rr)-.1, np.max(rr)+.1)
plt.xticks(np.arange(0, Tf, 90), ('22/01', '30/04'  ));
plt.savefig('C-R0Nomesure.png', format='png', dpi=200)
```

```python
fig = plt.figure(num=None, figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 22})

plt.bar(np.arange(16),data.get('X')[0,0:M]*10**(-6),   label='susceptible (initial)', alpha=0.8)
plt.bar(np.arange(16),data.get('X')[-1,0:M]*10**(-6),   label='susceptible (final)', alpha=0.8)

plt.xticks(np.arange(-0.4, 16.45, 3.95), ('0', '20', '40', '60', '80'));
plt.xlim(-0.45, 15.45); plt.ylabel('Individuals (millions)'); plt.xlabel('Age')
plt.legend(fontsize=22); plt.axis('tight')
plt.autoscale(enable=True, axis='x', tight=True)

plt.savefig('C-indsusNomesure.png', format='png', dpi=200)
```

### Mortality

We extract the number of susceptibles remaining in each age group, and the difference with the initial number of susceptibles is the total number that are infected. We multiply this with mortality data from China to obtain mortality estimates.

```python
MM = np.array((0,0,.0,1,1,1,1,1,1,3.5,3.5,3.5,3.5,6,6,14.2))
```

```python
fig = plt.figure(num=None, figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 22})

m1 = .01*MM*(data.get('X')[0,0:M]-data['X'][-1,0:M])
plt.bar(np.arange(16),m1*10**(-6),   label='susceptible (final)', alpha=0.8)

plt.axis('tight'); plt.xticks(np.arange(-0.4, 16.45, 3.95), ('0', '20', '40', '60', '80'));
plt.xlim(-0.45, 15.45); plt.ylabel('Mortality (millions)'); plt.xlabel('Age')

plt.autoscale(enable=True, axis='x', tight=True)

plt.savefig('C-mortalityNomesure.png', format='png', dpi=200)

```

## Non Pharmaceutical intervention

# School closure

Friday, March 20 in UK

###  Change the day to open again schools

```python
dayclosure = 58
dayopen1 = dayclosure+60
dayopen2 = dayclosure+80
dayopen3 = dayclosure+200

```

```python
model = pyross.deterministic.SIR(parameters, M, Ni)
```

```python
# the contact matrix is time-dependent
def contactMatrix1(t):
    if t<dayclosure:
        xx = C
    elif dayclosure<=t<dayopen1:
        xx = CH
    else:
        xx = C
    return xx

def contactMatrix2(t):
    if t<dayclosure:
        xx = C
    elif dayclosure<=t<dayopen2:
        xx = CH
    else:
        xx = C
    return xx

def contactMatrix3(t):
    if t<dayclosure:
        xx = C
    elif dayclosure<=t<dayopen3:
        xx = CH
    else:
        xx = C
    return xx

```

```python
# start simulation
Tf=1000;  Nf=3500
data=model.simulate(S_0, Ia_0, Is_0, contactMatrix1, Tf, Nf)
data2=model.simulate(S_0, Ia_0, Is_0, contactMatrix2, Tf, Nf)
data3=model.simulate(S_0, Ia_0, Is_0, contactMatrix3, Tf, Nf)
```

```python
t1 = data['t']; IC1  = np.zeros((Nf))
for i in range(M):
        IC1 += data['X'][:,2*M+i]

t2 = data2['t']; IC2 = np.zeros((Nf))
for i in range(M):
        IC2 += data2['X'][:,2*M+i]

t3 = data3['t']; IC3= np.zeros((Nf))
for i in range(M):
        IC3 += data3['X'][:,2*M+i]
```
index_max = np.argmax(IC1)

```python
fig = plt.figure(num=None, figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 6})
plt.plot(t1, IC1, '-', lw=3, color='#A60628', label='+10 days', alpha=0.8)
plt.fill_between(np.arange(dayclosure,dayopen1), 0, 1750000, color="#A60628", alpha=0.2)

plt.plot(t2, IC2, '-', lw=3, color='#063ba6', label='+30 days', alpha=0.8)
plt.fill_between(np.arange(dayopen1,dayopen2), 0, 1750000, color="#063ba6", alpha=0.2)

plt.plot(t3, IC3, '-', lw=3, color='#61a606', label='+150 days', alpha=0.8)
plt.fill_between(np.arange(dayopen2,dayopen3), 0, 1750000, color="#61a606", alpha=0.2)

plt.legend(fontsize=22); plt.axis('tight'); plt.grid()
plt.ylabel('Infected individuals');
plt.xlabel('Days')
plt.title('UK forecast with different school closure period ');
plt.savefig('UK-forecast-with-different-school-closure-period.png', format='png', dpi=200)
```

```python
fig = plt.figure(num=None, figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 6})
plt.plot(t1[1:1000], IC1[1:1000], '-', lw=3, color='#A60628', label='+10 days', alpha=0.8)
plt.fill_between(np.arange(dayclosure,dayopen1), 0, 1750000, color="#A60628", alpha=0.2)

plt.legend(fontsize=12); plt.axis('tight'); plt.grid()
plt.ylabel('Infected individuals');
plt.xlabel('Days')
plt.title('UK forecast with different school closure period ');
plt.savefig('UK-forecast-with-different-school-closure-period.png', format='png', dpi=200)
```

### Look at the numbers per age range

```python
S1= np.zeros((Nf, M))
S2 = np.zeros((Nf, M))
S3 = np.zeros((Nf, M))
I1 = np.zeros((Nf, M))
I2 = np.zeros((Nf, M))
I3 = np.zeros((Nf, M))

for i in range(M):
        S1[:,i] = data.get('X')[:,0*M+i]
        I1[:,i] = data.get('X')[:,2*M+i]
        S2[:,i] = data2.get('X')[:,0*M+i]
        I2[:,i] = data2.get('X')[:,2*M+i]
        S3[:,i] = data3.get('X')[:,0*M+i]
        I3[:,i] = data3.get('X')[:,2*M+i]
```

```python
fig = plt.figure(num=None, figsize=(7, 5), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 5})

color=['blue','red','green']
color1=['darkblue','darkred','green']
age = df3.Age.to_list()
plt.subplot(2,2,1)
for j,m in enumerate([1, 2 , 13]):
    plt.plot(t1, I1[:,m]*10**(-6), '-', lw=3, color=color[j], label='+10 days '+age[m]+' years old', alpha=0.8)
plt.legend(fontsize=10);
plt.tick_params(axis='both', which='major', labelsize=10)

plt.ylabel('Infected (millions)', fontsize=12)
plt.subplot(2,2,2)
for j,m in enumerate([1, 2 , 13]):
    plt.plot(t2, I2[:,m]*10**(-6), '-', lw=3, color=color1[j], label='+30 days '+age[m]+' years old', alpha=0.8)

plt.legend(fontsize=10);
plt.axis('tight')
plt.tick_params(axis='both', which='major', labelsize=10)
plt.savefig('UK-forecastI1.png', format='png', dpi=200);
```

```python
color=['blue','red']
color1=['darkblue','darkred']
age = df3.Age.to_list()
fig = plt.figure(num=None, figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 22})

for j,m in enumerate([1, 2]):
    plt.plot(t1, I1[:,m]*10**(-6), '-', lw=4, color=color[j], label='+10 days '+age[m]+' years old', alpha=0.8)
    plt.plot(t2,I2[:,m]*10**(-6), '-', lw=4, color=color1[j], label='+30 days '+age[m]+' years old', alpha=0.8)

plt.ylabel('Infected(millions)')
plt.legend();
```

```python
S1d = pd.DataFrame(S1, columns=df3.Age.to_list()[0:16])
I1d = pd.DataFrame(I1, columns=df3.Age.to_list()[0:16])
S2d = pd.DataFrame(S2, columns=df3.Age.to_list()[0:16])
I2d = pd.DataFrame(I2, columns=df3.Age.to_list()[0:16])
S3d = pd.DataFrame(S3, columns=df3.Age.to_list()[0:16])
I3d = pd.DataFrame(I3, columns=df3.Age.to_list()[0:16])
```

After the closure day, the total number of infected per category is the same for all closure periods.

```python
list_eld = ['60-64','65-69','70-74','75-79']
list_young =  ['0-4','5-9','10-14', '15-19']
day = dayopen1
```

```python
fig = plt.figure(num=None, figsize=(23, 20), dpi=80, facecolor='w', edgecolor='k')
plt.rcParams.update({'font.size': 5})
plt.subplot(3,3,1)
plt.bar(list_eld,I1d.loc[:dayclosure, list_eld].mean(axis=0), label='before closure', alpha=0.8);
plt.legend(fontsize=15);
plt.subplot(3,3,2)
plt.bar(list_eld,I1d.loc[dayclosure:day, list_eld].mean(axis=0),label='during closure', alpha=0.8);
plt.legend(fontsize=15);
plt.subplot(3,3,3)
plt.bar(list_eld,I1d.loc[day:, list_eld].mean(axis=0),   label='after opening', alpha=0.8);
plt.legend(fontsize=15);
plt.axis('tight')

plt.title('Mean of infected people per day for different age with 10 more days of closure');

```


```python
# Erasmus+ ICCT project (2018-1-SI01-KA203-047081)

# Toggle cell visibility

from IPython.display import HTML
tag = HTML('''
Toggle cell visibility <a href="javascript:code_toggle()">here</a>.''')
display(tag)

# Hide the code completely

# from IPython.display import HTML
# tag = HTML('''<style>
# div.input {
#     display:none;
# }
# </style>''')
# display(tag)
```

Toggle cell visibility here.

```python
# Examples:
# Factored form: 1/(x**2*(x**2 + 1))
# Expanded form: 1/(x**4+x**2)

import sympy as sym
from IPython.display import Latex, display, Markdown, Javascript, clear_output
from ipywidgets import widgets, Layout # Interactivity module
```

## Decomposizione in fratti semplici

Quando si utilizza la trasformata di Laplace per l'analisi dei sistemi, la trasformata di Laplace del segnale di uscita si ottiene come prodotto della funzione di trasferimento del sistema per la trasformata di Laplace del segnale di ingresso. Il risultato di questa moltiplicazione solitamente è abbastanza complesso da interpretare. Per eseguire la trasformata inversa di Laplace, si esegue prima la decomposizione in fratti semplici. Questo esempio dimostra questa procedura.

---

### Come usare questo notebook?
Alterna tra l'opzione *Input da funzione* o *Input da coefficienti polinomiali*.

1. *Input da funzione*:
 * Esempio: per inserire la funzione $\frac{1}{x^2(x^2 + 1)}$ (formato fattorizzato) digitare 1/(x\*\*2\*(x\*\*2 + 1)); per inserire la stessa funzione nella forma espansa ($\frac{1}{x^4+x^2}$) digitare 1/(x\*\*4+x\*\*2).

2. *Input da coefficienti polinomiali*:
 * Usa i cursori per selezionare l'ordine del numeratore e del denominatore della funzione razionale di interesse.
 * Inserisci i coefficienti sia del numeratore che del denominatore nelle caselle di testo dedicate e fai clic su *Conferma*.

```python
## System selector buttons
style = {'description_width': 'initial'}
typeSelect = widgets.ToggleButtons(
    options=[('Input da funzione', 0), ('Input da coefficienti polinomiali', 1),],
    description='Select: ',style={'button_width':'230px'})

btnReset=widgets.Button(description="Reset")

# function
textbox=widgets.Text(description=('Inserisci la funzione:'),style=style)
btnConfirmFunc=widgets.Button(description="Conferma") # ex btnConfirm

# poly
btnConfirmPoly=widgets.Button(description="Conferma") # ex btn

display(typeSelect)

def on_button_clickedReset(ev):
    display(Javascript("Jupyter.notebook.execute_cells_below()"))

def on_button_clickedFunc(ev):
    eq = sym.sympify(textbox.value)

    if eq==sym.factor(eq):
        display(Markdown('La funzione $%s$ è scritta in forma fattorizzata. ' %sym.latex(eq) + 'La sua forma espansa è $%s$.' %sym.latex(sym.expand(eq))))

    else:
        display(Markdown('La funzione $%s$ è scritta in forma espansa. ' %sym.latex(eq) + 'La sua forma fattorizzata è $%s$.' %sym.latex(sym.factor(eq))))

    display(Markdown('Il risultato della decomposizione in fratti semplici è: $%s$' %sym.latex(sym.apart(eq)) + '.'))
    display(btnReset)

def transfer_function(num,denom):
    num = np.array(num, dtype=np.float64)
    denom = np.array(denom, dtype=np.float64)
    len_dif = len(denom) - len(num)
    if len_dif<0:
        temp = np.zeros(abs(len_dif))
        denom = np.concatenate((temp, denom))
        transferf = np.vstack((num, denom))
    elif len_dif>0:
        temp = np.zeros(len_dif)
        num = np.concatenate((temp, num))
        transferf = np.vstack((num, denom))
    return transferf

def f(orderNum, orderDenom):
    global text1, text2
    text1=[None]*(int(orderNum)+1)
    text2=[None]*(int(orderDenom)+1)
    display(Markdown('2. Inserisci i coefficienti del numeratore.'))
    for i in range(orderNum+1):
        text1[i]=widgets.Text(description=(r'a%i'%(orderNum-i)))
        display(text1[i])
    display(Markdown('3. Inserisci i coefficienti del denominatore.'))
    for j in range(orderDenom+1):
        text2[j]=widgets.Text(description=(r'b%i'%(orderDenom-j)))
        display(text2[j])
    global orderNum1, orderDenom1
    orderNum1=orderNum
    orderDenom1=orderDenom

def on_button_clickedPoly(btn):
    clear_output()
    global num,denom
    enacbaNum=""
    enacbaDenom=""
    num=[None]*(int(orderNum1)+1)
    denom=[None]*(int(orderDenom1)+1)
    for i in range(int(orderNum1)+1):
        if text1[i].value=='' or text1[i].value=='Please insert a coefficient':
            text1[i].value='Please insert a coefficient'
        else:
            try:
                num[i]=int(text1[i].value)
            except ValueError:
                if text1[i].value!='' or text1[i].value!='Please insert a coefficient':
                    num[i]=sym.var(text1[i].value)

    for i in range (len(num)-1,-1,-1):
        if i==0:
            enacbaNum=enacbaNum+str(num[len(num)-i-1])
        elif i==1:
            enacbaNum=enacbaNum+"+"+str(num[len(num)-i-1])+"*x+"
        elif i==int(len(num)-1):
            enacbaNum=enacbaNum+str(num[0])+"*x**"+str(len(num)-1)
        else:
            enacbaNum=enacbaNum+"+"+str(num[len(num)-i-1])+"*x**"+str(i)

    for j in range(int(orderDenom1)+1):
        if text2[j].value=='' or text2[j].value=='Please insert a coefficient':
            text2[j].value='Please insert a coefficient'
        else:
            try:
                denom[j]=int(text2[j].value)
            except ValueError:
                if text2[j].value!='' or text2[j].value!='Please insert a coefficient':
                    denom[j]=sym.var(text2[j].value)

    for i in range (len(denom)-1,-1,-1):
        if i==0:
            enacbaDenom=enacbaDenom+"+"+str(denom[len(denom)-i-1])
        elif i==1:
            enacbaDenom=enacbaDenom+"+"+str(denom[len(denom)-i-1])+"*x"
        elif i==int(len(denom)-1):
            enacbaDenom=enacbaDenom+str(denom[0])+"*x**"+str(len(denom)-1)
        else:
            enacbaDenom=enacbaDenom+"+"+str(denom[len(denom)-i-1])+"*x**"+str(i)

    funcSym=sym.sympify('('+enacbaNum+')/('+enacbaDenom+')')

    DenomSym=sym.sympify(enacbaDenom)
    NumSym=sym.sympify(enacbaNum)
    DenomSymFact=sym.factor(DenomSym);
    funcFactSym=NumSym/DenomSymFact;

    if DenomSym==sym.expand(enacbaDenom):
        if DenomSym==DenomSymFact:
            display(Markdown('La funzione di interesse è: $%s$. Il numeratore non può essere fattorizzato.' %sym.latex(funcSym)))
        else:
            display(Markdown('La funzione di interesse è: $%s$. Il numeratore non può essere fattorizzato. La funzione con il denominatore fattorizzato è: $%s$.' %(sym.latex(funcSym), sym.latex(funcFactSym))))

    if sym.apart(funcSym)==funcSym:
        display(Markdown('La decomposizione in fratti semplici non può essere eseguita.'))
    else:
        display(Markdown('Il risultato della decomposizione in fratti semplici è: $%s$' %sym.latex(sym.apart(funcSym)) + '.'))

    btnReset.on_click(on_button_clickedReset)
    display(btnReset)

def partial_frac(index):

    if index==0:
        x = sym.Symbol('x')
        display(widgets.HBox((textbox, btnConfirmFunc)))
        btnConfirmFunc.on_click(on_button_clickedFunc)
        btnReset.on_click(on_button_clickedReset)

    elif index==1:
        display(Markdown('1. Definisci l\'ordine del numeratore (orderNum) e del denominatore (orderDenom).'))
        widgets.interact(f, orderNum=widgets.IntSlider(min=0,max=10,step=1,value=0),
                 orderDenom=widgets.IntSlider(min=0,max=10,step=1,value=0));
        btnConfirmPoly.on_click(on_button_clickedPoly)
        display(btnConfirmPoly)

input_data=widgets.interactive_output(partial_frac,{'index':typeSelect})
display(input_data)
```

    ToggleButtons(description='Select: ', options=(('Input da funzione', 0), ('Input da coefficienti polinomiali',…

    Output()