[1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import display

from epimodels.continuous.models import SISLogistic
from epimodels.fitting import (
    Dataset,
    DataSeries,
    ParameterSpec,
    ModelFitter,
    FittingResult,
    fit_model,
    SumOfSquaredErrors,
    WeightedSSE,
    PoissonLikelihood,
    NegativeBinomialLikelihood,
    NormalLikelihood,
    HuberLoss,
    ScipyOptimizer,
    MultiStartOptimizer,
)

np.random.seed(42)
plt.style.use('seaborn-v0_8-whitegrid')
%matplotlib inline
[2]:
df = pd.read_csv("dengue_data_logistic.csv")

df = df.sort_values("data_iniSE")

times = np.arange(len(df))

observed_I = df["casos_est"].values

TOTAL_POPULATION = df["pop"].iloc[0]
INITIAL_INFECTED = observed_I[0]
INITIAL_SUSCEPTIBLE = TOTAL_POPULATION - INITIAL_INFECTED
[3]:
model = SISLogistic()
dataset = Dataset(model)

dataset.register(
    name='infected',
    values=observed_I,
    times=times,
    state_variable='I',
)

validation_result = dataset.validate(total_population=TOTAL_POPULATION)

print(f"Dataset valid: {validation_result.is_valid}")
print(f"Time range: {dataset.time_range}")
print(dataset)
Dataset valid: True
Time range: (0.0, 103.0)
Dataset(n_series=1, variables=['I'], time_range=(0.0, 103.0))
[4]:
param_specs = [
    ParameterSpec(
        name='R0',
        bounds=(1.01, 5.0),
        initial=2.0,
    ),
    ParameterSpec(
        name='gamma',
        bounds=(0.01, 0.5),
        initial=0.3,
    ),
    ParameterSpec(
        name='r',
        bounds=(0.01, 0.5),
        initial=0.4,
    ),
    ParameterSpec(
        name='k',
        bounds=(1000, 20000),
        initial=5000,
    ),
]

print("Parameters to fit:")
for spec in param_specs:
    print(f"  {spec.name}: bounds={spec.bounds}, initial={spec.initial}")
Parameters to fit:
  R0: bounds=(1.01, 5.0), initial=2.0
  gamma: bounds=(0.01, 0.5), initial=0.3
  r: bounds=(0.01, 0.5), initial=0.4
  k: bounds=(1000, 20000), initial=5000
[5]:
fitter = ModelFitter(
    model=model,
    dataset=dataset,
    parameters_to_fit=param_specs,
    total_population=INITIAL_SUSCEPTIBLE + INITIAL_INFECTED,
    optimizer=ScipyOptimizer(method='L-BFGS-B', max_iterations=200),
)

result = fitter.fit()

print("\n" + "="*50)
print("FITTING RESULTS")
print("="*50)
print(f"Convergence: {result.convergence}")
print(f"Number of evaluations: {result.n_evaluations}")
print(f"Final loss: {result.best_loss:.2f}")

print("\nFitted parameters:")

for param, value in result.best_params.items():

    print(f"  {param}: {value:.4f}")

==================================================
FITTING RESULTS
==================================================
Convergence: True
Number of evaluations: 50
Final loss: 248362.48

Fitted parameters:
  R0: 1.0100
  gamma: 0.5000
  r: 0.5000
  k: 1000.0000
[6]:
fitted_model = result.fitted_model

fig, ax = plt.subplots(figsize=(12, 6))

ax.plot(times, observed_I, 'ro', label='Observed I', markersize=4, alpha=0.7)

if fitted_model is not None and fitted_model.traces:
    ax.plot(fitted_model.traces['time'], fitted_model.traces['I'],
            'g--', label='Fitted', linewidth=2)

ax.set_xlabel('Time (days)', fontsize=12)
ax.set_ylabel('Number of Infected', fontsize=12)
ax.set_title('Model Fitting Results', fontsize=14)
ax.legend(fontsize=11)
plt.tight_layout()
plt.show()
../_images/Examples_SISLogistic_fitting_real_data_5_0.png