blob: c345b74411401fa4f63f2d4b014c7955a8651e42 [file] [log] [blame]
package org.eclipse.stem.diseasemodels.multipopulation.impl;
/*******************************************************************************
* Copyright (c) 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.stem.core.STEMURI;
import org.eclipse.stem.core.common.DoubleValue;
import org.eclipse.stem.core.common.DoubleValueList;
import org.eclipse.stem.core.common.DoubleValueMatrix;
import org.eclipse.stem.core.common.StringValue;
import org.eclipse.stem.core.common.StringValueList;
import org.eclipse.stem.core.graph.Edge;
import org.eclipse.stem.core.graph.EdgeLabel;
import org.eclipse.stem.core.graph.Graph;
import org.eclipse.stem.core.graph.IntegrationLabel;
import org.eclipse.stem.core.graph.LabelValue;
import org.eclipse.stem.core.graph.Node;
import org.eclipse.stem.core.graph.NodeLabel;
import org.eclipse.stem.core.model.Model;
import org.eclipse.stem.core.model.STEMTime;
import org.eclipse.stem.definitions.labels.AreaLabel;
import org.eclipse.stem.definitions.labels.impl.CommonBorderRelationshipLabelImpl;
import org.eclipse.stem.definitions.labels.impl.RoadTransportRelationshipLabelImpl;
import org.eclipse.stem.definitions.labels.impl.RoadTransportRelationshipLabelValueImpl;
import org.eclipse.stem.definitions.nodes.Region;
import org.eclipse.stem.diseasemodels.Activator;
import org.eclipse.stem.diseasemodels.multipopulation.MultiPopulationSIDiseaseModel;
import org.eclipse.stem.diseasemodels.multipopulation.MultipopulationPackage;
import org.eclipse.stem.diseasemodels.standard.DiseaseModelLabel;
import org.eclipse.stem.diseasemodels.standard.DiseaseModelLabelValue;
import org.eclipse.stem.diseasemodels.standard.Infector;
import org.eclipse.stem.diseasemodels.standard.SIInfector;
import org.eclipse.stem.diseasemodels.standard.SILabel;
import org.eclipse.stem.diseasemodels.standard.SILabelValue;
import org.eclipse.stem.diseasemodels.standard.StandardDiseaseModelLabel;
import org.eclipse.stem.diseasemodels.standard.StandardDiseaseModelLabelValue;
import org.eclipse.stem.diseasemodels.standard.StandardFactory;
import org.eclipse.stem.diseasemodels.standard.impl.SILabelValueImpl;
import org.eclipse.stem.diseasemodels.standard.impl.StandardDiseaseModelImpl;
import org.eclipse.stem.populationmodels.standard.PopulationModelLabel;
import org.eclipse.stem.populationmodels.standard.StandardPopulationModel;
import org.eclipse.stem.populationmodels.standard.impl.StandardFactoryImpl;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Multi Population SI Disease Model</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link org.eclipse.stem.diseasemodels.multipopulation.impl.MultiPopulationSIDiseaseModelImpl#getPopulationGroups <em>Population Groups</em>}</li>
* <li>{@link org.eclipse.stem.diseasemodels.multipopulation.impl.MultiPopulationSIDiseaseModelImpl#getTransmissionRate <em>Transmission Rate</em>}</li>
* <li>{@link org.eclipse.stem.diseasemodels.multipopulation.impl.MultiPopulationSIDiseaseModelImpl#getRecoveryRate <em>Recovery Rate</em>}</li>
* <li>{@link org.eclipse.stem.diseasemodels.multipopulation.impl.MultiPopulationSIDiseaseModelImpl#getInfectiousMortalityRate <em>Infectious Mortality Rate</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class MultiPopulationSIDiseaseModelImpl extends StandardDiseaseModelImpl implements MultiPopulationSIDiseaseModel {
/**
* The cached value of the '{@link #getPopulationGroups() <em>Population Groups</em>}' containment reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getPopulationGroups()
* @generated
* @ordered
*/
protected StringValueList populationGroups;
/**
* The cached value of the '{@link #getTransmissionRate() <em>Transmission Rate</em>}' containment reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTransmissionRate()
* @generated
* @ordered
*/
protected DoubleValueMatrix transmissionRate;
/**
* The cached value of the '{@link #getRecoveryRate() <em>Recovery Rate</em>}' containment reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getRecoveryRate()
* @generated
* @ordered
*/
protected DoubleValueList recoveryRate;
/**
* The cached value of the '{@link #getInfectiousMortalityRate() <em>Infectious Mortality Rate</em>}' containment reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getInfectiousMortalityRate()
* @generated
* @ordered
*/
protected DoubleValueList infectiousMortalityRate;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public MultiPopulationSIDiseaseModelImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return MultipopulationPackage.Literals.MULTI_POPULATION_SI_DISEASE_MODEL;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public DoubleValueMatrix getTransmissionRate() {
return transmissionRate;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public NotificationChain basicSetTransmissionRate(DoubleValueMatrix newTransmissionRate, NotificationChain msgs) {
DoubleValueMatrix oldTransmissionRate = transmissionRate;
transmissionRate = newTransmissionRate;
if (eNotificationRequired()) {
ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__TRANSMISSION_RATE, oldTransmissionRate, newTransmissionRate);
if (msgs == null) msgs = notification; else msgs.add(notification);
}
return msgs;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setTransmissionRate(DoubleValueMatrix newTransmissionRate) {
if (newTransmissionRate != transmissionRate) {
NotificationChain msgs = null;
if (transmissionRate != null)
msgs = ((InternalEObject)transmissionRate).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__TRANSMISSION_RATE, null, msgs);
if (newTransmissionRate != null)
msgs = ((InternalEObject)newTransmissionRate).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__TRANSMISSION_RATE, null, msgs);
msgs = basicSetTransmissionRate(newTransmissionRate, msgs);
if (msgs != null) msgs.dispatch();
}
else if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__TRANSMISSION_RATE, newTransmissionRate, newTransmissionRate));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public DoubleValueList getRecoveryRate() {
return recoveryRate;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public NotificationChain basicSetRecoveryRate(DoubleValueList newRecoveryRate, NotificationChain msgs) {
DoubleValueList oldRecoveryRate = recoveryRate;
recoveryRate = newRecoveryRate;
if (eNotificationRequired()) {
ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__RECOVERY_RATE, oldRecoveryRate, newRecoveryRate);
if (msgs == null) msgs = notification; else msgs.add(notification);
}
return msgs;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setRecoveryRate(DoubleValueList newRecoveryRate) {
if (newRecoveryRate != recoveryRate) {
NotificationChain msgs = null;
if (recoveryRate != null)
msgs = ((InternalEObject)recoveryRate).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__RECOVERY_RATE, null, msgs);
if (newRecoveryRate != null)
msgs = ((InternalEObject)newRecoveryRate).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__RECOVERY_RATE, null, msgs);
msgs = basicSetRecoveryRate(newRecoveryRate, msgs);
if (msgs != null) msgs.dispatch();
}
else if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__RECOVERY_RATE, newRecoveryRate, newRecoveryRate));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public DoubleValueList getInfectiousMortalityRate() {
return infectiousMortalityRate;
}
/**
* Get the particular infectious mortality rate for a specific population group by name
* @generated NOT
*/
public double getInfectiousMortality(String populationName) {
// next get it's INDEX in the model
// TODO we should encapsulate this code in a helper method
int populationIndex = this.getPopulationIndex(populationName);
if(getInfectiousMortalityRate() != null)
return getInfectiousMortalityRate().getValues().get(populationIndex).getValue();
else return 0.0; //default if not specified
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public NotificationChain basicSetInfectiousMortalityRate(DoubleValueList newInfectiousMortalityRate, NotificationChain msgs) {
DoubleValueList oldInfectiousMortalityRate = infectiousMortalityRate;
infectiousMortalityRate = newInfectiousMortalityRate;
if (eNotificationRequired()) {
ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__INFECTIOUS_MORTALITY_RATE, oldInfectiousMortalityRate, newInfectiousMortalityRate);
if (msgs == null) msgs = notification; else msgs.add(notification);
}
return msgs;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setInfectiousMortalityRate(DoubleValueList newInfectiousMortalityRate) {
if (newInfectiousMortalityRate != infectiousMortalityRate) {
NotificationChain msgs = null;
if (infectiousMortalityRate != null)
msgs = ((InternalEObject)infectiousMortalityRate).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__INFECTIOUS_MORTALITY_RATE, null, msgs);
if (newInfectiousMortalityRate != null)
msgs = ((InternalEObject)newInfectiousMortalityRate).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__INFECTIOUS_MORTALITY_RATE, null, msgs);
msgs = basicSetInfectiousMortalityRate(newInfectiousMortalityRate, msgs);
if (msgs != null) msgs.dispatch();
}
else if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__INFECTIOUS_MORTALITY_RATE, newInfectiousMortalityRate, newInfectiousMortalityRate));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public StringValueList getPopulationGroups() {
return populationGroups;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public NotificationChain basicSetPopulationGroups(StringValueList newPopulationGroups, NotificationChain msgs) {
StringValueList oldPopulationGroups = populationGroups;
populationGroups = newPopulationGroups;
if (eNotificationRequired()) {
ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__POPULATION_GROUPS, oldPopulationGroups, newPopulationGroups);
if (msgs == null) msgs = notification; else msgs.add(notification);
}
return msgs;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setPopulationGroups(StringValueList newPopulationGroups) {
if (newPopulationGroups != populationGroups) {
NotificationChain msgs = null;
if (populationGroups != null)
msgs = ((InternalEObject)populationGroups).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__POPULATION_GROUPS, null, msgs);
if (newPopulationGroups != null)
msgs = ((InternalEObject)newPopulationGroups).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__POPULATION_GROUPS, null, msgs);
msgs = basicSetPopulationGroups(newPopulationGroups, msgs);
if (msgs != null) msgs.dispatch();
}
else if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__POPULATION_GROUPS, newPopulationGroups, newPopulationGroups));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
switch (featureID) {
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__POPULATION_GROUPS:
return basicSetPopulationGroups(null, msgs);
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__TRANSMISSION_RATE:
return basicSetTransmissionRate(null, msgs);
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__RECOVERY_RATE:
return basicSetRecoveryRate(null, msgs);
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__INFECTIOUS_MORTALITY_RATE:
return basicSetInfectiousMortalityRate(null, msgs);
}
return super.eInverseRemove(otherEnd, featureID, msgs);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__POPULATION_GROUPS:
return getPopulationGroups();
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__TRANSMISSION_RATE:
return getTransmissionRate();
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__RECOVERY_RATE:
return getRecoveryRate();
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__INFECTIOUS_MORTALITY_RATE:
return getInfectiousMortalityRate();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__POPULATION_GROUPS:
setPopulationGroups((StringValueList)newValue);
return;
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__TRANSMISSION_RATE:
setTransmissionRate((DoubleValueMatrix)newValue);
return;
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__RECOVERY_RATE:
setRecoveryRate((DoubleValueList)newValue);
return;
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__INFECTIOUS_MORTALITY_RATE:
setInfectiousMortalityRate((DoubleValueList)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__POPULATION_GROUPS:
setPopulationGroups((StringValueList)null);
return;
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__TRANSMISSION_RATE:
setTransmissionRate((DoubleValueMatrix)null);
return;
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__RECOVERY_RATE:
setRecoveryRate((DoubleValueList)null);
return;
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__INFECTIOUS_MORTALITY_RATE:
setInfectiousMortalityRate((DoubleValueList)null);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__POPULATION_GROUPS:
return populationGroups != null;
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__TRANSMISSION_RATE:
return transmissionRate != null;
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__RECOVERY_RATE:
return recoveryRate != null;
case MultipopulationPackage.MULTI_POPULATION_SI_DISEASE_MODEL__INFECTIOUS_MORTALITY_RATE:
return infectiousMortalityRate != null;
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public double getAdjustedInfectiousMortalityRate(long timeDelta, final String populationName) {
// TODO this division can be eliminated if timeDelta==getTimePeriod
return getInfectiousMortality(populationName)
* ((double) timeDelta / (double) getTimePeriod());
} // getAdjustedInfectiousMortalityRate
@Override
public StandardDiseaseModelLabelValue computeDiseaseDeltas(STEMTime time,
StandardDiseaseModelLabelValue currentState,
StandardDiseaseModelLabel diseaseLabel, long timeDelta,
DiseaseModelLabelValue returnValue) {
// THIS method gets called multiple times, once for each population identifier
// in the population model.
// which population is "this"....
final SILabelValue currentSI = (SILabelValue) currentState;
String thisPopulation = diseaseLabel.getPopulationModelLabel().getPopulationIdentifier();
// Compute deaths
final double adjustedInfectiousMortalityRate = getAdjustedInfectiousMortalityRate(timeDelta, thisPopulation);
final double diseaseDeaths = adjustedInfectiousMortalityRate
* currentSI.getI();
// next get it's INDEX in the model
int populationIndex = getPopulationIndex(thisPopulation);
// now we know the index of the current population being integrated.
// Get the correct transmission rate list from the MATRIX
EList<DoubleValue> transmissionVector = getTransmissionRate().getValueLists().get(populationIndex).getValues();
// ALL the other disease parameters are also DoubleValueLists. We now iterate through all populations
// get the specific rate parameters from EACH list based on this population index
double thisRecoveryRate = 0.0;
if(getRecoveryRate() != null) thisRecoveryRate = getRecoveryRate().getValues().get(populationIndex).getValue();
// NOW iterate over every population (including this one) to compute new infections
// this includes infections within a population group
// and all the cross terms
double numberOfSusceptibleToInfected = 0.0;
double numberSusceptible = currentSI.getS();
Node thisNode = diseaseLabel.getNode();
EList<StringValue> groupList = getPopulationGroups().getValues();
for(int i = 0; i< transmissionVector.size(); i ++) {
// We need to get the identifier of the ith population model
String nextPop = groupList.get(i).getValue();
//////////////////
// 1. compute BETA for transmission from the ith population to this population
double specificTransmission = transmissionVector.get(i).getValue();
double adjustedTransmission = getAdjustedTransmissionRate(specificTransmission, timeDelta);
if(!this.isFrequencyDependent()) adjustedTransmission *= getTransmissionRateScaleFactor(diseaseLabel);
// we need to get the disease label for the ith population as well.
// to get the on site number of infectios individuals of type i
EList<NodeLabel> nodeLabels = thisNode.getLabels();
for(int j = 0; j < nodeLabels.size(); j ++) {
NodeLabel label = nodeLabels.get(j);
if(label instanceof SILabel) {
if (this == ((SILabel)label).getDecorator()) {
StandardDiseaseModelLabel otherDiseaseLabel = (StandardDiseaseModelLabel) label;
// now check the popualtion type
String otherPopulation = otherDiseaseLabel.getPopulationModelLabel().getPopulationIdentifier();
if(otherPopulation.equals(nextPop)) {
// Yes?
// then we found the label for the correct next population
// for this population we need to get the EFFECTIVE Infectious including
// ALL neighboring nodes
double onsiteInfectious = ((SILabelValue) otherDiseaseLabel.getTempValue()).getI();
final double effectiveInfectious = getNormalizedEffectiveInfectious(otherPopulation, thisNode, otherDiseaseLabel, onsiteInfectious);
// ADD up the new incidence
numberOfSusceptibleToInfected += adjustedTransmission * numberSusceptible * effectiveInfectious;
}
}
}// if it's an SI label
}//for all labels in THIS node
}// For all population in the model
double numberOfInfectedToSusceptible = getAdjustedRecoveryRate(thisRecoveryRate, timeDelta) * currentSI.getI();
// Determine delta S
final double deltaS = - numberOfSusceptibleToInfected + numberOfInfectedToSusceptible;
// Determine delta I
final double deltaI = numberOfSusceptibleToInfected - numberOfInfectedToSusceptible - diseaseDeaths;
SILabelValueImpl ret = (SILabelValueImpl)returnValue;
ret.setS(deltaS);
ret.setI(deltaI);
ret.setIncidence(numberOfSusceptibleToInfected);
ret.setDiseaseDeaths(diseaseDeaths);
return ret;
}
protected int getPopulationIndex(String thisPopulation) {
// next get it's INDEX in the model
// TODO we should encapsulate this code in a helper method
int populationIndex = -1;
EList<StringValue> groupList = getPopulationGroups().getValues();
for(int i =0; i < groupList.size(); i ++) {
String nextPop = groupList.get(i).getValue();
if(nextPop.equalsIgnoreCase(thisPopulation)) {
populationIndex = i;
break;
}
}
if(populationIndex < 0) {
// should never happen
Activator.logError("MultiPopulationSIDiseaseModel.computeDiseaseDeltas() Error, Population named "+thisPopulation+" not found. check spelling !!", new Exception());
}
return populationIndex;
}
/**
* <!-- begin-user-doc -->
* Returns the time interval deltaT divided by the initial time period
* @param timeDelta
* @param specificTransmission
* @return
*
* <!-- end-user-doc -->
*
* @generated NOT
*/
public double getAdjustedTransmissionRate(double specificTransmission, long timeDelta) {
return (specificTransmission * ((double) timeDelta / (double) getTimePeriod()) );
} // getAdjustedTransmissionRate
/**
* <!-- begin-user-doc -->
*
* @param timeDelta
*
* @return
*
* <!-- end-user-doc -->
*
* @generated NOT
*/
public double getAdjustedRecoveryRate(double specificRecoveryRate, long timeDelta) {
return (specificRecoveryRate * ((double) timeDelta / (double) getTimePeriod()) );
} // getAdjustedRecoveryRate
/**
* This method is used to scale the transmission rate.
* it returns the local density divided by a "reference" density
* @param diseaseLabel the label being processed
* @return the transmission rate scale factor for the label being processed
*/
public double getTransmissionRateScaleFactor(
StandardDiseaseModelLabel diseaseLabel) {
double referenceDensity = getReferencePopulationDensity();
// assert(referenceDensity > 0);
// need editor check so ref density always >1. Default is 100.
assert getArea(diseaseLabel.getPopulationLabel()) > 0.0;
double localDensity = ((StandardDiseaseModelLabelValue)diseaseLabel.getTempValue()).getPopulationCount()/getArea(diseaseLabel.getPopulationLabel());
return localDensity/referenceDensity;
} // getTransmissionRateScaleFactor
/**
* This method replaces the onsiteInfectious value
* for a specific population type (by index)
* with an effectiveInfectious of a particular population group (by name)
* size based on mixing with neighboring sites. In this implementation the edges are bidirectional
* and have a fixed weight based on getPhysicallyAdjacentInfectiousProportion() (called in the helper method
* getInfectiousChangeFromMixing(). But the mixing is also weighted by the areas and populations of a site relative
* to the area and population of it's neighbors. Note that the value returned must be NORMALIZED by the total
* population because the product beta * S * Ieffective must have units of persons. Since S has units of persons
* the Ieffective must be dimensionless (normalized to the population). beta is the infection rate and has units
* of inverse time.
* @see org.eclipse.stem.diseasemodels.standard.SI.getNormalizedEffectiveInfectious
* @param targetPopulationName
* @param node
* @param diseaseLabel
* @param onsiteInfectious
* @generated NOT
* @return
*/
public double getNormalizedEffectiveInfectious(final String targetPopulationName, final Node node, final StandardDiseaseModelLabel diseaseLabel, final double onsiteInfectious) {
// running tally of changes from mixing with other nodes
double infectiousChangeFromMixing = 0.0;
double borderDivisor = 0.0;
double roadDivisor = 0.0;
for (final Iterator<Edge> commonBorderEdgeIter = CommonBorderRelationshipLabelImpl
.getCommonBorderEdgesFromNode(node).iterator(); commonBorderEdgeIter
.hasNext();) {
final Edge borderEdge = commonBorderEdgeIter.next();
// If it exists, we're looking for the label this disease model
// updates on the node at the other end of the border edge.
final Node otherNode = borderEdge.getOtherNode(node);
double characteristicMixingDistance = getCharacteristicMixingDistance();
double mixingFactor = 0.0;
if (otherNode instanceof Region) {
double otherAvgExtent = -1.0;
for (final Iterator<NodeLabel> labelIter = otherNode.getLabels().iterator(); labelIter.hasNext();) {
final NodeLabel nodeLabel = labelIter.next();
// Is this an area label?
if (nodeLabel instanceof AreaLabel) {
// Yes
final AreaLabel areaLabel = (AreaLabel) nodeLabel;
otherAvgExtent = areaLabel.getCurrentAreaValue().getAverageExtent();
break;
}
} // for
// IF we have a valid area
if(otherAvgExtent >= 0.0) {
mixingFactor = (characteristicMixingDistance/otherAvgExtent) ;
if(mixingFactor > 1.0) mixingFactor = 1.0;
}
}
// for EACH connected Node add up the infectious of the particular
// population GROUPD
infectiousChangeFromMixing += getInfectiousChangeFromMixing(this, otherNode, targetPopulationName, diseaseLabel, onsiteInfectious, mixingFactor);
borderDivisor += mixingFactor*this.getLocalPopulation(this, otherNode, targetPopulationName);
} // for each border edge
for (final Iterator<Edge> roadEdgeIter = RoadTransportRelationshipLabelImpl.getRoadEdgesFromNode(node).iterator(); roadEdgeIter.hasNext();) {
final Edge roadEdge = roadEdgeIter.next();
// find the number of edges from the road edge - could be more than one
// also, roads have differenct capacities
final EdgeLabel edgeLabel = roadEdge.getLabel();
// init the number of crossings or total road connections across the border
double numCrossings = 1.0;
if (edgeLabel instanceof RoadTransportRelationshipLabelImpl) {
RoadTransportRelationshipLabelValueImpl roadLabelValue = (RoadTransportRelationshipLabelValueImpl)(edgeLabel.getCurrentValue());
numCrossings = roadLabelValue.getNumberCrossings();
}
double infectiousProportion = getRoadNetworkInfectiousProportion() * numCrossings;
// must never be greater than 1
if(infectiousProportion > 1.0) infectiousProportion = 1.0;
// If it exists, we're looking for the label this disease model
// updates on the node at the other end of the border edge.
final Node otherNode = roadEdge.getOtherNode(node);
// sum up the changes from each connected node by population group (by name).
// NOTE: some of these changes could be negative
infectiousChangeFromMixing += getInfectiousChangeFromMixing(this, otherNode, targetPopulationName, diseaseLabel, onsiteInfectious, infectiousProportion);
roadDivisor += infectiousProportion*this.getLocalPopulation(this, otherNode, targetPopulationName);
} // for each road edge
// return the sum normalized to the total population
double denom = ((StandardDiseaseModelLabelValue)diseaseLabel.getTempValue()).getPopulationCount() + borderDivisor + roadDivisor;
double retVal = 0.0;
if (denom > 0.0) {
retVal = ( onsiteInfectious + infectiousChangeFromMixing ) / denom;
}
return retVal;
} // getNormalizedEffectiveInfectious
/**
* This method correctly computes the mixing of the infectious population (onsite) with the infectious population
* at neighboring nodes
* @param diseaseModel
* @param the node
* @param diseaseLabel
* @param onsiteInfectious
* @param connectedInfectiousProportion (this is the weight given to the edge connection)
* @return the number of population members at a node infected by the disease modeled by diseaseModel
*/
protected double getInfectiousChangeFromMixing(final MultiPopulationSIDiseaseModel diseaseModel,
final Node node, final String populationName, final StandardDiseaseModelLabel diseaseLabel, final double onsiteInfectious, double connectedInfectiousProportion) {
// infectious from other sites mixing here at site 0
double mixing = 0.0;
for (final Iterator<NodeLabel> labelIter = node.getLabels().iterator(); labelIter
.hasNext();) {
final NodeLabel nodeLabel = labelIter.next();
// Is this a disease label?
if (nodeLabel instanceof StandardDiseaseModelLabel) {
final IntegrationLabel otherSILabel = (IntegrationLabel) nodeLabel;
// Yes
// Is it updated by this disease model?
if (diseaseModel == otherSILabel.getDecorator()) {
// CHECK THE POPULATION OF THE NEIGHBOR
StandardDiseaseModelLabel checkLabel = (StandardDiseaseModelLabel)otherSILabel;
String checkPopulation = checkLabel.getPopulationModelLabel().getPopulationIdentifier();
if(checkPopulation.equals(populationName)) {
if(this.isFrequencyDependent()) {
double Iother = (((SILabelValue)otherSILabel.getTempValue())).getI();
//double Iother = otherSILabel.getCurrentSIValue().getI();
double mixingFactor = connectedInfectiousProportion;
mixing = Iother * mixingFactor;
}
// break ? only one per population?
}//if(checkPopulation.equals(populationName))
} // if
}
} // for
return mixing;
} // getInfectiousChangeFromMixing
/**
* Get the onsite total population for a particular population group by name
* @param diseaseModel
* @param node
* @return
*/
private double getLocalPopulation(final MultiPopulationSIDiseaseModel diseaseModel, Node node, final String populationName) {
double totalPopulation = 0.0;
for (final Iterator<NodeLabel> labelIter = node.getLabels().iterator(); labelIter.hasNext();) {
final NodeLabel nodeLabel = labelIter.next();
// Is this a disease label?
if (nodeLabel instanceof StandardDiseaseModelLabel) {
final IntegrationLabel otherSILabel = (IntegrationLabel) nodeLabel;
// Yes
// Is it updated by this disease model?
if (diseaseModel == otherSILabel.getDecorator()) {
// CHECK THE POPULATION OF THE NEIGHBOR
StandardDiseaseModelLabel checkLabel = (StandardDiseaseModelLabel)otherSILabel;
String checkPopulation = checkLabel.getPopulationModelLabel().getPopulationIdentifier();
if(checkPopulation.equals(populationName)) {
totalPopulation = ((StandardDiseaseModelLabelValue)otherSILabel.getTempValue()).getPopulationCount();
return totalPopulation;
}//if(checkPopulation.equals(populationName))
}
}
}
return 0.0;
}
@Override
public DiseaseModelLabel createDiseaseModelLabel(String populationIdentifier) {
return StandardFactory.eINSTANCE.createSILabel();
}
@Override
public DiseaseModelLabelValue createDiseaseModelLabelValue(String populationIdentifier) {
return StandardFactory.eINSTANCE.createSILabelValue();
}
/**
* @see org.eclipse.stem.diseasemodels.standard.impl.DiseaseModelImpl#createInfector()
*/
@Override
public Infector createInfector() {
SIInfector retValue = StandardFactory.eINSTANCE.createSIInfector();
retValue.setDiseaseName(this.getDiseaseName());
retValue.setPopulationIdentifier(getPopulationIdentifier());
return retValue;
} // createInfector
public void doModelSpecificAdjustments(LabelValue label) {
// Nothing to do here...
}
/**
* We need to override this method to return all population model labels for the population groups
*
* @param populationIdentifier
* the population being labeled
* @param graph
* the graph to search
* @return the PopulationLabel instances of the graph that match the
* identifier.
*/
@Override
public EList<PopulationModelLabel> getPopulationModelLabels(
String populationIdentifier, Graph graph) {
final EList<PopulationModelLabel> retValue = new BasicEList<PopulationModelLabel>();
// Iterate through all of the population labels in the graph
EList<NodeLabel> labels = graph.getNodeLabelsByTypeURI(
PopulationModelLabel.URI_TYPE_DYNAMIC_POPULATION_LABEL);
for (NodeLabel pl:labels) {
final PopulationModelLabel populationLabel = (PopulationModelLabel) pl;
// Is this label for the population we're looking for?
boolean keep = false;
// if (populationLabel.getPopulationIdentifier().equals(
// populationIdentifier)) keep = true;
// else
for(StringValue g:this.getPopulationGroups().getValues())
if(g.getValue().equals(populationLabel.getPopulationIdentifier())) {keep=true;break;}
if (keep) {
// Yes
// If there is a problem with the "node uri" of the population
// label then it would not have been associated with a node
// instance in the graph at this point. This is a problem for
// disease models that are trying to label the node (there isn't
// one!). So filter out those mistakes here.
// Does the population label have an associated node?
if (populationLabel.getNode() != null) {
// Yes
retValue.add(populationLabel);
} // if the population label has a node
} // if the population we're looking for
} // for each population label
return retValue;
} // getPopulationLabels
/**
* We need to override to check all population groups
*/
@Override
public void prepare(Model model, STEMTime time) {
for(StringValue sv:this.getPopulationGroups().getValues()) {
boolean found = findPopulationModel(model, sv.getValue());
if(!found) {
// Create a new standard population model
StandardPopulationModel spm = StandardFactoryImpl.eINSTANCE.createStandardPopulationModel();
spm.setPopulationIdentifier(sv.getValue());
String title = "Auto Generated "+sv.getValue()+" population model";
String name = "auto_gen_"+sv.getValue()+"_population_model";
spm.setURI(STEMURI.createURI(name+"/"+STEMURI.generateUniquePart()));
spm.setName(name);
spm.getDublinCore().setTitle(title);
model.getNodeDecorators().add(0, spm);
}
}
}
@Override
public boolean isDeterministic() {
return true;
}
@Override
public EList<String> getAllLabelIdentifiers() {
EList<String> identifiers = new BasicEList<String>();
EList<StringValue> groups = getPopulationGroups().getValues();
for (StringValue g : groups) {
identifiers.add(g.getValue());
}
return identifiers;
}
} //MultiPopulationSIDiseaseModelImpl