blob: 4683ef54970241109a8ee6b7af2b51f9a3f95ce6 [file] [log] [blame]
/**
* <copyright>
* </copyright>
*
* $Id$
*/
package org.eclipse.stem.diseasemodels.evolving.impl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.stem.core.graph.DynamicLabel;
import org.eclipse.stem.core.graph.Exchange;
import org.eclipse.stem.core.graph.ExchangePool;
import org.eclipse.stem.core.graph.ExchangeType;
import org.eclipse.stem.core.graph.IntegrationLabel;
import org.eclipse.stem.core.graph.Node;
import org.eclipse.stem.core.graph.NodeLabel;
import org.eclipse.stem.core.model.Decorator;
import org.eclipse.stem.core.model.STEMTime;
import org.eclipse.stem.diseasemodels.evolving.EvolvingFactory;
import org.eclipse.stem.diseasemodels.evolving.EvolvingPackage;
import org.eclipse.stem.diseasemodels.evolving.EvolvingSEIRDiseaseModel;
import org.eclipse.stem.diseasemodels.evolving.EvolvingSEIRDiseaseModelLabel;
import org.eclipse.stem.diseasemodels.evolving.EvolvingSEIRDiseaseModelLabelValue;
import org.eclipse.stem.diseasemodels.standard.DiseaseModelLabel;
import org.eclipse.stem.diseasemodels.standard.DiseaseModelLabelValue;
import org.eclipse.stem.diseasemodels.standard.SEIRLabelValue;
import org.eclipse.stem.diseasemodels.standard.StandardDiseaseModelLabel;
import org.eclipse.stem.diseasemodels.standard.StandardDiseaseModelLabelValue;
import org.eclipse.stem.diseasemodels.standard.StandardPackage;
import org.eclipse.stem.diseasemodels.standard.impl.SEIRLabelValueImpl;
import org.eclipse.stem.interventions.StandardInterventionLabel;
import org.eclipse.stem.interventions.StandardInterventionLabelValue;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>SEIR Disease Model</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link org.eclipse.stem.diseasemodels.evolving.impl.EvolvingSEIRDiseaseModelImpl#getIncubationRate <em>Incubation Rate</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class EvolvingSEIRDiseaseModelImpl extends EvolvingSIRDiseaseModelImpl implements EvolvingSEIRDiseaseModel {
/**
* The default value of the '{@link #getIncubationRate() <em>Incubation Rate</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getIncubationRate()
* @generated
* @ordered
*/
protected static final double INCUBATION_RATE_EDEFAULT = 0.0;
/**
* The cached value of the '{@link #getIncubationRate() <em>Incubation Rate</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getIncubationRate()
* @generated
* @ordered
*/
protected double incubationRate = INCUBATION_RATE_EDEFAULT;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EvolvingSEIRDiseaseModelImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return EvolvingPackage.Literals.EVOLVING_SEIR_DISEASE_MODEL;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public double getIncubationRate() {
return incubationRate;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setIncubationRate(double newIncubationRate) {
incubationRate = newIncubationRate;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case EvolvingPackage.EVOLVING_SEIR_DISEASE_MODEL__INCUBATION_RATE:
return getIncubationRate();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case EvolvingPackage.EVOLVING_SEIR_DISEASE_MODEL__INCUBATION_RATE:
setIncubationRate((Double)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case EvolvingPackage.EVOLVING_SEIR_DISEASE_MODEL__INCUBATION_RATE:
setIncubationRate(INCUBATION_RATE_EDEFAULT);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case EvolvingPackage.EVOLVING_SEIR_DISEASE_MODEL__INCUBATION_RATE:
return incubationRate != INCUBATION_RATE_EDEFAULT;
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public String toString() {
if (eIsProxy()) return super.toString();
StringBuffer result = new StringBuffer(super.toString());
result.append(" (incubationRate: ");
result.append(incubationRate);
result.append(')');
return result.toString();
}
/**
* @see org.eclipse.stem.diseasemodels.standard.impl.SIImpl#computeDiseaseDeltas(StandardDiseaseModelLabelValue,
* StandardDiseaseModelLabel, long)
* @generated NOT
*/
@Override
public void calculateDeltas(STEMTime time, double t, long timeDelta, EList<DynamicLabel> labels) {
final double adjustedInfectiousMortalityRate = getAdjustedInfectiousMortalityRate(timeDelta);
double transmissionRate = getAdjustedTransmissionRate(timeDelta);
final double adjustedRecoveryRate = getAdjustedRecoveryRate(timeDelta);
final double adjustedImmunityLossRate = getAdjustedImmunityLossRate(timeDelta);
final double adjustedIncubationRate = getAdjustedIncubationRate(timeDelta);
for(int _i=0;_i<labels.size();++_i) {
final DynamicLabel label = labels.get(_i);
IntegrationLabel ilabel = (IntegrationLabel)label;
StandardDiseaseModelLabel diseaseLabel = (StandardDiseaseModelLabel)ilabel;
StandardDiseaseModelLabelValue currentState = (StandardDiseaseModelLabelValue)ilabel.getProbeValue();
StandardDiseaseModelLabelValue deltaValue = (StandardDiseaseModelLabelValue)ilabel.getDeltaValue();
deltaValue.reset();
final SEIRLabelValue currentSEIR = (SEIRLabelValue) currentState;
// Compute deaths
final double diseaseDeaths = adjustedInfectiousMortalityRate
* currentSEIR.getI();
if(!this.isFrequencyDependent()) transmissionRate = transmissionRate * getTransmissionRateScaleFactor(diseaseLabel);
// The effective Infectious population is a dimensionles number normalize by total
// population used in teh computation of bets*S*i where i = Ieffective/Pop.
// This includes a correction to the current
// infectious population (Ieffective) based on the conserved exchange of people (circulation)
// between regions. Note that this is no the "arrivals" and "departures" which are
// a different process.
final double effectiveInfectious = getNormalizedEffectiveInfectious(diseaseLabel.getNode(), diseaseLabel, currentSEIR.getI(), StandardPackage.Literals.SI_LABEL_VALUE__I, StandardPackage.Literals.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE, StandardPackage.Literals.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION);
/*
* Compute state transitions
*
* Regarding computing the number of transitions from Susceptible to Exposed:
* In a linear model the "effective" number of infectious people is just
* the number of infectious people In a nonlinear model we have a
* nonLinearity exponent that is > 1 this models the effect of immune
* system saturation when Susceptible people are exposed to large
* numbers of infectious people. then the "effective" number of
* infectious people is I^nonLinearity exponent to allow for either
* linear or nonlinear models we always calculate I^nonLinearity
* exponent and allow nonLinearity exponent >= 1.0
*/
double numberOfInfectedToRecovered = adjustedRecoveryRate
* currentSEIR.getI();
double numberOfRecoveredToSusceptible = adjustedImmunityLossRate
* currentSEIR.getR();
// Need to checked what do do here. If non linear coefficient is not 1 and
// the effective infectious is negative (which is possible), what do do?
// Let's fall back on the linear method for now.
////////////////////////////////////////////////////
// ******* EVOLVING DISEASE MODEL *************** //
//
// Si* = Si ∏_(j≠i) 〖[1-χji (Rj/N〗)]
//
double effectiveSusceptible = currentSEIR.getS();
double popCount = currentSEIR.getS()+currentSEIR.getE()+currentSEIR.getI()+currentSEIR.getR();
double crossProduct = 1.0;
if((crossImmunityRate>0.0)&&(effectiveSusceptible>1)) {
// NEED TO CORRECT SUSCEPTIBLES BASED ON CROSS STRAIN IMMUNITY //
Node thisNode = diseaseLabel.getNode();
EList<NodeLabel> allLabels = thisNode.getLabels();
for(NodeLabel nl:allLabels) {
if(nl instanceof EvolvingSEIRDiseaseModelLabel) {
EvolvingSEIRDiseaseModelLabel seirLabel = (EvolvingSEIRDiseaseModelLabel) nl;
Decorator otherDisease = seirLabel.getDecorator();
if(otherDisease instanceof EvolvingSEIRDiseaseModel) {
// should always be true
EvolvingSEIRDiseaseModel otherSEIRDiease = (EvolvingSEIRDiseaseModel)otherDisease;
if(!otherSEIRDiease.getDiseaseName().equals(this.getDiseaseName())) {
// ie NOT this DISEASE
EvolvingSEIRDiseaseModelLabelValue otherValue = (EvolvingSEIRDiseaseModelLabelValue)seirLabel.getCurrentValue();
double immuneTerm = otherValue.getR()/popCount;
// the genetic distance is based on comparing the 2 genomes. Each letter gives a difference of 1
// the crossImmunityRate is the crossImmunity with 1 nt different
double geneticDistance = getGeneticDistance(otherSEIRDiease);
// for a center of mass distance model uncomment the following....
// double geneticDistance *= getCMdistance(otherSEIR);
if(geneticDistance >= 1 ) {
immuneTerm *= (crossImmunityRate/ geneticDistance);
}
crossProduct *= (1.0-immuneTerm);
// prevent round off error
if(crossProduct < 0) {
crossProduct = 0.0; // round off error
}
}
}
}
}
}
effectiveSusceptible *= crossProduct;
//System.out.println("S = "+currentSEIR.getS()+" crossProduct = "+crossProduct+" Seffective = "+effectiveSusceptible);
double numberOfSusceptibleToExposed = 0.0;
if(getNonLinearityCoefficient() != 1.0 && effectiveInfectious >=0.0)
numberOfSusceptibleToExposed = transmissionRate
* effectiveSusceptible* Math.pow(effectiveInfectious, getNonLinearityCoefficient());
else
numberOfSusceptibleToExposed = transmissionRate
* effectiveSusceptible* effectiveInfectious;
// ******* EVOLVING DISEASE MODEL *************** //
////////////////////////////////////////////////////
double numberOfExposedToInfectious =adjustedIncubationRate
* currentSEIR.getE();
// Determine delta S
double deltaS = numberOfRecoveredToSusceptible - numberOfSusceptibleToExposed;
// Determine delta E
double deltaE = numberOfSusceptibleToExposed - numberOfExposedToInfectious;
// Determine delta I
double deltaI = numberOfExposedToInfectious - numberOfInfectedToRecovered - diseaseDeaths;
// Determine delta R
double deltaR = numberOfInfectedToRecovered - numberOfRecoveredToSusceptible;
StandardInterventionLabel scl = findInterventionLabel((Node)diseaseLabel.getIdentifiable());
if(scl != null) {
double vaccinations = ((StandardInterventionLabelValue)scl.getCurrentValue()).getVaccinations();
double isolations = ((StandardInterventionLabelValue)scl.getCurrentValue()).getIsolations();
vaccinations *= ((double) timeDelta / (double) getTimePeriod());
isolations *= ((double) timeDelta / (double) getTimePeriod());
if(currentSEIR.getS() < vaccinations) vaccinations = currentSEIR.getS();
if(currentSEIR.getI() < isolations) isolations = currentSEIR.getI();
deltaS -= vaccinations;
deltaR += vaccinations;
deltaI -= isolations;
deltaR += isolations;
}
/////////////////////////////////////////////////////////////////////////////
// added to express the transitions. Necessary to support stochastic modeling
// S->E
Exchange seExchange = (Exchange)ExchangePool.POOL.get();
seExchange.setSource(StandardPackage.eINSTANCE.getStandardDiseaseModelLabelValue_S());
seExchange.setTarget(StandardPackage.eINSTANCE.getSEIRLabelValue_E());
seExchange.setCount(numberOfSusceptibleToExposed);
seExchange.getForIncidence().add(StandardPackage.eINSTANCE.getStandardDiseaseModelLabelValue_Incidence());
seExchange.setType(ExchangeType.COMPARTMENT_TRANSITION);
deltaValue.getDepartures().add(seExchange);
// E->I
Exchange eiExchange = (Exchange)ExchangePool.POOL.get();
eiExchange.setSource(StandardPackage.eINSTANCE.getSEIRLabelValue_E());
eiExchange.setTarget(StandardPackage.eINSTANCE.getSILabelValue_I());
eiExchange.setCount(numberOfExposedToInfectious);
eiExchange.setType(ExchangeType.COMPARTMENT_TRANSITION);
deltaValue.getDepartures().add(eiExchange);
// I->R
Exchange irExchange = (Exchange)ExchangePool.POOL.get();
irExchange.setSource(StandardPackage.eINSTANCE.getSILabelValue_I());
irExchange.setTarget(StandardPackage.eINSTANCE.getSIRLabelValue_R());
irExchange.setCount(numberOfInfectedToRecovered);
irExchange.setType(ExchangeType.COMPARTMENT_TRANSITION);
deltaValue.getDepartures().add(irExchange);
// R->S
Exchange rsExchange = (Exchange)ExchangePool.POOL.get();
rsExchange.setSource(StandardPackage.eINSTANCE.getSIRLabelValue_R());
rsExchange.setTarget(StandardPackage.eINSTANCE.getStandardDiseaseModelLabelValue_S());
rsExchange.setCount(numberOfRecoveredToSusceptible);
rsExchange.setType(ExchangeType.COMPARTMENT_TRANSITION);
deltaValue.getDepartures().add(rsExchange);
// added to express the transitions. Necessary to support stochastic modeling
/////////////////////////////////////////////////////////////////////////////
SEIRLabelValueImpl ret = (SEIRLabelValueImpl)deltaValue;
ret.setS(deltaS);
ret.setE(deltaE);
ret.setI(deltaI);
ret.setIncidence(numberOfSusceptibleToExposed);
ret.setR(deltaR);
ret.setDiseaseDeaths(diseaseDeaths);
computeAdditionalDeltasAndExchanges(ilabel, time, t, timeDelta);
}
} // computeDiseaseDeltas
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public void calculateEvolvedInitialState() {
EvolvingSEIRDiseaseModel parentDiseaseModel = (EvolvingSEIRDiseaseModel)getParentDisease();
DiseaseModelLabel parentEvolutionSource = getEvolvedAt();
if (parentDiseaseModel == null && parentEvolutionSource == null) {
// The evolution wasn't initialized correctly.
// This should be unreachable but who knows.
System.err.println("Trying to calculate label state from an improperly initialized evolved model. Do something.");
return;
}
Node currentNode = parentEvolutionSource.getNode();
URI evolutionLocation = currentNode.getURI();
// // Matt, we have not decorated the graph at this point right??
for (DynamicLabel dl : this.getLabelsToUpdate()) {
if (dl instanceof EvolvingSEIRDiseaseModelLabel) {
double s = 0.0;
double e = 0.0;
double i = 0.0;
double r = 0.0;
double diseaseDeaths = 0.0;
// this is the new label we need to set
EvolvingSEIRDiseaseModelLabel childLabel = (EvolvingSEIRDiseaseModelLabel)dl;
EvolvingSEIRDiseaseModelLabelValue childLabelValues = (EvolvingSEIRDiseaseModelLabelValue)childLabel.getCurrentValue();
// this is the new label we need to set
EvolvingSEIRDiseaseModelLabel parentSEIRlabel = (EvolvingSEIRDiseaseModelLabel) parentEvolutionSource;
// same parent population
childLabel.setPopulationLabel(parentSEIRlabel.getPopulationLabel());
childLabel.setPopulationModelLabel(parentSEIRlabel.getPopulationModelLabel());
// get the parent label value - we need this to know the current population
EvolvingSEIRDiseaseModelLabelValue lv = (EvolvingSEIRDiseaseModelLabelValue)parentSEIRlabel.getCurrentValue();
double popCount = lv.getPopulationCount();
s = popCount;
// Do something interesting here to initialize disease state
// TODO performance question
// TODO we are looking through the entire graphs to find THIS label.
if (childLabel.getNode().getURI().equals(evolutionLocation)) {
// This is where the evolution happened, so you probably need to set your
// infectious state differently
//System.out.println("initializing child disease at evolution location "+evolutionLocation.lastSegment());
if(parentEvolutionSource instanceof EvolvingSEIRDiseaseModelLabel) {
// should be true
if(popCount > 1.0) {
// init the child diseases values
e = 1.0;
s = s - 1.0;
//System.err.println("!!! Evolving SEIR Mutation !!! at "+evolutionLocation.lastSegment());
} else {
System.err.println("Likely ERROR: Zero population detected on node "+currentNode.getURI().lastSegment()+" ... Do something.");
}
}
} else {
// This is everywhere else
// for now we are already set
} // if else
childLabelValues.setS(s);
childLabelValues.setE(e);
childLabelValues.setI(i);
childLabelValues.setR(r);
childLabelValues.setDiseaseDeaths(diseaseDeaths);
}
}
}
/**
* This method is called when a disease model mutates back into itself
* @generated NOT
*/
protected void updateDuplicateEvolvedInitialState(Node currentNode) {
URI evolutionLocation = currentNode.getURI();
// // Matt, we have not decorated the graph at this point right??
for (DynamicLabel dl : this.getLabelsToUpdate()) {
if (dl instanceof EvolvingSEIRDiseaseModelLabel) {
// this is the new label we need to set
EvolvingSEIRDiseaseModelLabel diseaseLabel = (EvolvingSEIRDiseaseModelLabel)dl;
EvolvingSEIRDiseaseModelLabelValue childLabelValues = (EvolvingSEIRDiseaseModelLabelValue)diseaseLabel.getCurrentValue();
double s = childLabelValues.getS();
double e = childLabelValues.getE();
double i = childLabelValues.getI();
double r = childLabelValues.getR();
double diseaseDeaths = childLabelValues.getDiseaseDeaths();
// Do something interesting here to initialize disease state
// TODO performance question
// TODO we are looking through the entire graphs to find THIS label.
if (diseaseLabel.getNode().getURI().equals(evolutionLocation)) {
// This is where the evolution happened, so you probably need to set your
// infectious state differently
//System.out.println("initializing child disease a
if(s > 2.0) {
// init the child diseases values
e = 1.0;
s = s - 1.0;
//System.err.println("!!! Evolving SEIR Mutation !!! at "+evolutionLocation.lastSegment());
} else {
//System.err.println("Likely ERROR: Zero population detected on node "+currentNode.getURI().lastSegment()+" ... Do something.");
}
} else {
// This is everywhere else
// for now we are already set
} // if else
childLabelValues.setS(s);
childLabelValues.setE(e);
childLabelValues.setI(i);
childLabelValues.setR(r);
childLabelValues.setDiseaseDeaths(diseaseDeaths);
}
}
}
protected double getAdjustedIncubationRate(long timeDelta) {
return getIncubationRate()
* ((double) timeDelta / (double) getTimePeriod());
} // getAdjustedIncubationRate
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public DiseaseModelLabel createDiseaseModelLabel(String populationIdentifier) {
DiseaseModelLabel label = EvolvingFactory.eINSTANCE.createEvolvingSEIRDiseaseModelLabel();
label.setTypeURI(DiseaseModelLabel.URI_TYPE_DYNAMIC_DISEASE_LABEL);
return label;
} // createDiseaseModelLabel
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public DiseaseModelLabelValue createDiseaseModelLabelValue(String populationIdentifier) {
return EvolvingFactory.eINSTANCE.createEvolvingSEIRDiseaseModelLabelValue();
}
} //EvolvingSEIRDiseaseModelImpl