blob: 3115545eb13cbf2c687ebc1ab95e4d65519cc395 [file] [log] [blame]
package org.eclipse.stem.diseasemodels.standard.impl;
/*******************************************************************************
* Copyright (c) 2006 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.Arrays;
import java.util.Collections;
import java.util.Iterator;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.stem.core.graph.DynamicLabel;
import org.eclipse.stem.core.graph.Edge;
import org.eclipse.stem.core.graph.EdgeLabel;
import org.eclipse.stem.core.graph.Exchange;
import org.eclipse.stem.core.graph.ExchangeType;
import org.eclipse.stem.core.graph.GraphFactory;
import org.eclipse.stem.core.graph.IntegrationLabel;
import org.eclipse.stem.core.graph.IntegrationLabelValue;
import org.eclipse.stem.core.graph.Node;
import org.eclipse.stem.core.graph.NodeLabel;
import org.eclipse.stem.core.model.STEMTime;
import org.eclipse.stem.definitions.labels.AreaLabel;
import org.eclipse.stem.definitions.labels.CommonBorderRelationshipLabelValue;
import org.eclipse.stem.definitions.labels.PopulationLabel;
import org.eclipse.stem.definitions.labels.RoadTransportRelationshipLabelValue;
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.standard.DiseaseModelLabelValue;
import org.eclipse.stem.diseasemodels.standard.StandardDiseaseModel;
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.populationmodels.standard.StandardPopulationModelLabel;
/**
* <!-- begin-user-doc --> An implementation of the model object '
* <em><b>Disease Model</b></em>'. <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link org.eclipse.stem.diseasemodels.standard.impl.StandardDiseaseModelImpl#getReferencePopulationDensity <em>Reference Population Density</em>}</li>
* <li>{@link org.eclipse.stem.diseasemodels.standard.impl.StandardDiseaseModelImpl#getRoadNetworkInfectiousProportion <em>Road Network Infectious Proportion</em>}</li>
* <li>{@link org.eclipse.stem.diseasemodels.standard.impl.StandardDiseaseModelImpl#getCharacteristicMixingDistance <em>Characteristic Mixing Distance</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public abstract class StandardDiseaseModelImpl extends DiseaseModelImpl
implements StandardDiseaseModel {
/**
* The default value of the '{@link #getReferencePopulationDensity() <em>Reference Population Density</em>}' attribute.
* <!-- begin-user-doc
* --> <!-- end-user-doc -->
* @see #getReferencePopulationDensity()
* @generated
* @ordered
*/
protected static final double REFERENCE_POPULATION_DENSITY_EDEFAULT = 100.0;
/**
* The cached value of the '{@link #getReferencePopulationDensity() <em>Reference Population Density</em>}' attribute.
* <!-- begin-user-doc
* --> <!-- end-user-doc -->
* @see #getReferencePopulationDensity()
* @generated
* @ordered
*/
protected double referencePopulationDensity = REFERENCE_POPULATION_DENSITY_EDEFAULT;
/**
* The default value of the '{@link #getRoadNetworkInfectiousProportion()
* <em>Road Network Infectious Proportion</em>}' attribute. <!--
* begin-user-doc --> <!-- end-user-doc -->
*
* @see #getRoadNetworkInfectiousProportion()
* @generated
* @ordered
*/
protected static final double ROAD_NETWORK_INFECTIOUS_PROPORTION_EDEFAULT = 0.01;
/**
* The cached value of the '{@link #getRoadNetworkInfectiousProportion()
* <em>Road Network Infectious Proportion</em>}' attribute. <!--
* begin-user-doc --> <!-- end-user-doc -->
*
* @see #getRoadNetworkInfectiousProportion()
* @generated
* @ordered
*/
protected double roadNetworkInfectiousProportion = ROAD_NETWORK_INFECTIOUS_PROPORTION_EDEFAULT;
/**
* The default value of the '{@link #getCharacteristicMixingDistance() <em>Characteristic Mixing Distance</em>}' attribute.
* <!-- begin-user-doc
* --> <!-- end-user-doc -->
* @see #getCharacteristicMixingDistance()
* @generated
* @ordered
*/
protected static final double CHARACTERISTIC_MIXING_DISTANCE_EDEFAULT = 2.25;
/**
* The cached value of the '{@link #getCharacteristicMixingDistance() <em>Characteristic Mixing Distance</em>}' attribute.
* <!-- begin-user-doc
* --> <!-- end-user-doc -->
* @see #getCharacteristicMixingDistance()
* @generated
* @ordered
*/
protected double characteristicMixingDistance = CHARACTERISTIC_MIXING_DISTANCE_EDEFAULT;
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
protected StandardDiseaseModelImpl() {
super();
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return StandardPackage.Literals.STANDARD_DISEASE_MODEL;
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
public double getReferencePopulationDensity() {
return referencePopulationDensity;
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
public void setReferencePopulationDensity(
double newReferencePopulationDensity) {
double oldReferencePopulationDensity = referencePopulationDensity;
referencePopulationDensity = newReferencePopulationDensity;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY, oldReferencePopulationDensity, referencePopulationDensity));
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
public double getRoadNetworkInfectiousProportion() {
return roadNetworkInfectiousProportion;
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
public void setRoadNetworkInfectiousProportion(
double newRoadNetworkInfectiousProportion) {
double oldRoadNetworkInfectiousProportion = roadNetworkInfectiousProportion;
roadNetworkInfectiousProportion = newRoadNetworkInfectiousProportion;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION, oldRoadNetworkInfectiousProportion, roadNetworkInfectiousProportion));
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
public double getCharacteristicMixingDistance() {
return characteristicMixingDistance;
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
public void setCharacteristicMixingDistance(
double newCharacteristicMixingDistance) {
double oldCharacteristicMixingDistance = characteristicMixingDistance;
characteristicMixingDistance = newCharacteristicMixingDistance;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE, oldCharacteristicMixingDistance, characteristicMixingDistance));
}
/**
* calculateDelta will use the current label values updated by the disease
* model and upon return the delta label values are set with an estimate of
* the derivatives to advance to the next step
*
* @param time
* current time
* @param timeDelta
* delta time step
* @param labels
* The labels to update
*/
@Override
public void calculateDelta(STEMTime time, long timeDelta,
EList<DynamicLabel> labels) {
// Iterate through each of the labels we need to update.
// Place holders to keep delta values.
for (final Iterator<DynamicLabel> currentStateLabelIter = labels
.iterator(); currentStateLabelIter.hasNext();) {
final StandardDiseaseModelLabel diseaseLabel = (StandardDiseaseModelLabel) currentStateLabelIter
.next();
DiseaseModelLabelValue birthDeathsDelta = this
.createDiseaseModelLabelValue(diseaseLabel.getIdentifier());
DiseaseModelLabelValue diseaseDelta = this
.createDiseaseModelLabelValue(diseaseLabel.getIdentifier());
assert diseaseLabel.getPopulationLabel().getPopulationIdentifier()
.equals(getPopulationIdentifier());
// This current state of the disease for this label probed for the
// next delta
final StandardDiseaseModelLabelValue currentProbeState = (StandardDiseaseModelLabelValue) diseaseLabel
.getProbeValue();
// Compute delta changes
final StandardDiseaseModelLabelValue diseaseDeltas = computeDiseaseDeltas(
time, currentProbeState, diseaseLabel, timeDelta,
diseaseDelta);
/*
* 5) Record the new state variable values.
*
* These will become the current state variable values at the end of
* the current simulation cycle and before the next.
*/
// This is the delta disease label
final StandardDiseaseModelLabelValue deltaState = (StandardDiseaseModelLabelValue) diseaseLabel
.getDeltaValue();
// Reset the state
deltaState.reset();
// 1) Update the delta
deltaState.add((IntegrationLabelValue) diseaseDeltas);
// 2) Set the departures
deltaState.getArrivals().clear();
deltaState.getDepartures().clear();
if (((StandardDiseaseModelLabelValue) diseaseDeltas)
.getDiseaseDeaths() > 0.0) {
Exchange deathExchange = GraphFactory.eINSTANCE
.createExchange();
deathExchange.setType(ExchangeType.BIRTHS_AND_DEATHS);
deathExchange
.setCount(((StandardDiseaseModelLabelValue) diseaseDeltas)
.getDiseaseDeaths());
deltaState.getDepartures().add(deathExchange);
}
// and pass on the incidence
// int n=0;
// for(EStructuralFeature es:incidenceFeatures)
// deltaState.eSet(es, incidences.get(n++));
birthDeathsDelta.reset();
diseaseDelta.reset();
} // for
}
@Override
public void applyExternalDeltas(STEMTime time, long timeDelta,
EList<DynamicLabel> labels) {
for (final Iterator<DynamicLabel> currentStateLabelIter = labels
.iterator(); currentStateLabelIter.hasNext();) {
final StandardDiseaseModelLabel diseaseLabel = (StandardDiseaseModelLabel) currentStateLabelIter
.next();
StandardDiseaseModelLabelValue myDelta = (StandardDiseaseModelLabelValue) diseaseLabel
.getDeltaValue();
Node n = diseaseLabel.getNode();
// Find other labels on the node that wants to exchange data
EList<NodeLabel> labs = n.getLabels();
for (NodeLabel l : labs) {
if (l instanceof IntegrationLabel
&& !l.equals(diseaseLabel)
&& ((IntegrationLabel) l).getIdentifier().equals(
diseaseLabel.getIdentifier())) {
IntegrationLabelValue sdeLabelValue = (IntegrationLabelValue) ((IntegrationLabel) l)
.getDeltaValue();
EList<Exchange> arrivals = sdeLabelValue.getArrivals();
EList<Exchange> departures = sdeLabelValue.getDepartures();
if (arrivals == null || departures == null) {
Activator.logError(
"Error, null arrivals or departures for label "
+ l, new Exception());
continue;
}
// Arrivals
for (Exchange entry : arrivals) {
// for(Node n2:arrivals.keySet()) {
if (entry.getType() == ExchangeType.BIRTHS_AND_DEATHS) {
// Births go into the S state.
myDelta.setS(myDelta.getS() + entry.getCount());
} else if (entry.getType() == ExchangeType.MIGRATION) {
double inflow = entry.getCount();
// Find the corresponding disease label on the other
// node
Node otherNode = (Node) entry.getOtherLabel()
.getIdentifiable();
for (NodeLabel nl : otherNode.getLabels())
if (nl instanceof StandardDiseaseModelLabel
&& ((StandardDiseaseModelLabel) nl)
.getDecorator().equals(this)
&& ((StandardDiseaseModelLabel) nl)
.getPopulationModelLabel()
.getPopulationIdentifier()
.equals(diseaseLabel
.getIdentifier())) {
StandardDiseaseModelLabelValue value = (StandardDiseaseModelLabelValue) EcoreUtil
.copy(((StandardDiseaseModelLabel) nl)
.getTempValue());
if (value.getPopulationCount() > 0.0) {
value.scale(inflow
/ value.getPopulationCount());
}
// Remember disease deaths since it'll be
// overwritten in the add
double diseaseDeaths = myDelta
.getDiseaseDeaths();
myDelta.add((IntegrationLabelValue) value);
myDelta.setDiseaseDeaths(diseaseDeaths);
}
} else if (entry.getType() == ExchangeType.AGING) {
// Find the disease label of the other age group
String otherAgeGroup = ((StandardPopulationModelLabel) entry
.getOtherLabel()).getPopulationIdentifier();
for (NodeLabel nl : labs) {
if (nl instanceof StandardDiseaseModelLabel) {
StandardDiseaseModelLabel otherDiseaseLabel = (StandardDiseaseModelLabel) nl;
if (otherDiseaseLabel.getDecorator()
.equals(this)
&& otherDiseaseLabel
.getIdentifier().equals(
otherAgeGroup)) {
StandardDiseaseModelLabelValue value = (StandardDiseaseModelLabelValue) EcoreUtil
.copy(otherDiseaseLabel
.getTempValue());
if (value.getPopulationCount() > 0.0) {
value.scale(entry.getCount()
/ value.getPopulationCount());
}
double diseaseDeaths = myDelta
.getDiseaseDeaths();
myDelta.add((IntegrationLabelValue) value);
myDelta.setDiseaseDeaths(diseaseDeaths);
}
}
}
}
}
// Departures
for (Exchange entry : departures) {
// Departures are either deaths or population moving to
// other nodes, hence we substract from the local node.
StandardDiseaseModelLabelValue currentState = null;
if (entry.getType() == ExchangeType.BIRTHS_AND_DEATHS
|| entry.getType() == ExchangeType.AGING)
currentState = (StandardDiseaseModelLabelValue) EcoreUtil
.copy((StandardDiseaseModelLabelValue) diseaseLabel
.getProbeValue()); // Should be safe
// to use probe
// value for
// deaths
else if (entry.getType() == ExchangeType.MIGRATION)
currentState = (StandardDiseaseModelLabelValue) EcoreUtil
.copy((StandardDiseaseModelLabelValue) diseaseLabel
.getTempValue()); // Need to use
// temp value
// for migration
// or an
// inbalance
// will occyr
double populationCount = currentState
.getPopulationCount();
double outflow = entry.getCount();
double factor = outflow / populationCount;
if (Double.isNaN(factor) || Double.isInfinite(factor))
factor = 0.0; // safe
currentState.scale(factor);
// Remember disease deaths since they will be
// overwritten by sub
double diseaseDeaths = myDelta.getDiseaseDeaths();
myDelta.sub((IntegrationLabelValue) currentState);
myDelta.setDiseaseDeaths(diseaseDeaths);
}
}
}
}
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY:
return getReferencePopulationDensity();
case StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION:
return getRoadNetworkInfectiousProportion();
case StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE:
return getCharacteristicMixingDistance();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY:
setReferencePopulationDensity((Double)newValue);
return;
case StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION:
setRoadNetworkInfectiousProportion((Double)newValue);
return;
case StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE:
setCharacteristicMixingDistance((Double)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY:
setReferencePopulationDensity(REFERENCE_POPULATION_DENSITY_EDEFAULT);
return;
case StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION:
setRoadNetworkInfectiousProportion(ROAD_NETWORK_INFECTIOUS_PROPORTION_EDEFAULT);
return;
case StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE:
setCharacteristicMixingDistance(CHARACTERISTIC_MIXING_DISTANCE_EDEFAULT);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY:
return referencePopulationDensity != REFERENCE_POPULATION_DENSITY_EDEFAULT;
case StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION:
return roadNetworkInfectiousProportion != ROAD_NETWORK_INFECTIOUS_PROPORTION_EDEFAULT;
case StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE:
return characteristicMixingDistance != CHARACTERISTIC_MIXING_DISTANCE_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(" (referencePopulationDensity: "); //$NON-NLS-1$
result.append(referencePopulationDensity);
result.append(", roadNetworkInfectiousProportion: "); //$NON-NLS-1$
result.append(roadNetworkInfectiousProportion);
result.append(", characteristicMixingDistance: "); //$NON-NLS-1$
result.append(characteristicMixingDistance);
result.append(')');
return result.toString();
}
/**
* This method replaces the onsiteInfectious value with an
* effectiveInfectious population 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 node
* the node we are currently looking at to compute the next
* disease state
* @param diseaseLabel
* the label for the current disease computation
* @param onsiteInfectious
* the number of infectious people on site (at the node above)
* @param infectiousAttribute
* Attribute representing the infectious compartment
* @generated NOT
*/
public double getNormalizedEffectiveInfectious(final Node node,
final StandardDiseaseModelLabel diseaseLabel,
final double onsiteInfectious, EAttribute infectiousAttribute) {
double infectiousChangeFromMixing = 0.0;
double populationChangeFromMixing = 0.0;
for (Edge borderEdge : CommonBorderRelationshipLabelImpl
.getCommonBorderEdgesFromNode(node)) {
// If it exists, we're looking for the label this disease model
// updates on the node at the other end of the border edge.
// sum up the changes from each connected node.
// NOTE: some of these changes could be negative
final Node otherNode = borderEdge.getOtherNode(node);
double borderLength = ((CommonBorderRelationshipLabelValue) borderEdge
.getLabel().getCurrentValue()).getBorderLength();
if (otherNode instanceof Region) {
double otherArea = 0.0;
double otherPopulation = 0.0;
double otherInfective = 0.0;
for (NodeLabel otherLabel : otherNode.getLabels()) {
if (otherLabel instanceof AreaLabel) {
otherArea = ((AreaLabel) otherLabel)
.getCurrentAreaValue().getArea();
} else if (otherLabel instanceof StandardDiseaseModelLabel) {
StandardDiseaseModelLabel otherDiseaseLabel = (StandardDiseaseModelLabel) otherLabel;
if (otherDiseaseLabel.getDecorator() == this
&& otherDiseaseLabel.getIdentifier().equals(
diseaseLabel.getIdentifier())) {
otherPopulation = ((StandardDiseaseModelLabelValue) otherDiseaseLabel
.getTempValue()).getPopulationCount();
if (frequencyDependent) {
otherInfective = (Double) otherDiseaseLabel
.getTempValue().eGet(
infectiousAttribute);
} else {
// TODO
}
}
}
}
double mixingFactor = Math.min(characteristicMixingDistance
* borderLength / otherArea, 1.0);
infectiousChangeFromMixing += mixingFactor * otherInfective;
populationChangeFromMixing += mixingFactor * otherPopulation;
}
} // for each border edge
for (Edge roadEdge : RoadTransportRelationshipLabelImpl
.getRoadEdgesFromNode(node)) {
// find the number of edges from the road edge - could be more than
// one
// also, roads have differenct capacities
EdgeLabel edgeLabel = roadEdge.getLabel();
double numCrossings = ((RoadTransportRelationshipLabelValue) edgeLabel
.getCurrentValue()).getNumberCrossings();
double infectiousProportion = Math.min(
roadNetworkInfectiousProportion * numCrossings, 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.
Node otherNode = roadEdge.getOtherNode(node);
double otherPopulation = 0.0;
double otherInfective = 0.0;
for (NodeLabel otherLabel : otherNode.getLabels()) {
if (otherLabel instanceof StandardDiseaseModelLabel) {
StandardDiseaseModelLabel otherDiseaseLabel = (StandardDiseaseModelLabel) otherLabel;
if (otherDiseaseLabel.getDecorator() == this
&& otherDiseaseLabel.getIdentifier().equals(
diseaseLabel.getIdentifier())) {
otherPopulation = ((StandardDiseaseModelLabelValue) otherDiseaseLabel
.getTempValue()).getPopulationCount();
if (frequencyDependent) {
otherInfective = (Double) otherDiseaseLabel
.getTempValue().eGet(infectiousAttribute);
} else {
// TODO
}
}
}
}
infectiousChangeFromMixing += infectiousProportion * otherInfective;
populationChangeFromMixing += infectiousProportion
* otherPopulation;
} // for each road edge
// return the sum normalized to the total population
double totalPopulation = ((StandardDiseaseModelLabelValue) diseaseLabel
.getTempValue()).getPopulationCount()
+ populationChangeFromMixing;
double retVal = 0.0;
if (totalPopulation > 0.0) {
retVal = (onsiteInfectious + infectiousChangeFromMixing)
/ totalPopulation;
}
return retVal;
} // getNormalizedEffectiveInfectious
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated NOT
*/
public EList<Double> getNormalizedEffectiveInfectious(
StandardDiseaseModelLabel diseaseLabel,
EList<EAttribute> infectiousAttributes) {
Node node = diseaseLabel.getNode();
StandardDiseaseModelLabelValue value = (StandardDiseaseModelLabelValue) diseaseLabel
.getTempValue();
int count = infectiousAttributes.size();
double[] totalInfectious = new double[count];
double totalPopulation = value.getPopulationCount();
for (int i = 0; i < count; i++) {
totalInfectious[i] = (Double) value.eGet(infectiousAttributes
.get(i));
}
for (Edge borderEdge : CommonBorderRelationshipLabelImpl
.getCommonBorderEdgesFromNode(node)) {
// If it exists, we're looking for the label this disease model
// updates on the node at the other end of the border edge.
// sum up the changes from each connected node.
// NOTE: some of these changes could be negative
final Node otherNode = borderEdge.getOtherNode(node);
double borderLength = ((CommonBorderRelationshipLabelValue) borderEdge
.getLabel().getCurrentValue()).getBorderLength();
double otherArea = 0.0;
for (NodeLabel otherLabel : otherNode.getLabels()) {
if (otherLabel instanceof AreaLabel) {
otherArea = ((AreaLabel) otherLabel).getCurrentAreaValue()
.getArea();
break;
}
}
double mixingFactor = Math.min(characteristicMixingDistance
* borderLength / otherArea, 1.0);
for (NodeLabel otherLabel : otherNode.getLabels()) {
if (otherLabel instanceof StandardDiseaseModelLabel) {
StandardDiseaseModelLabel otherDiseaseLabel = (StandardDiseaseModelLabel) otherLabel;
if (otherDiseaseLabel.getDecorator() == this
&& otherDiseaseLabel.getIdentifier().equals(
diseaseLabel.getIdentifier())) {
StandardDiseaseModelLabelValue otherValue = (StandardDiseaseModelLabelValue) otherDiseaseLabel
.getTempValue();
if (frequencyDependent) {
for (int i = 0; i < count; i++) {
double infectious = (Double) otherValue
.eGet(infectiousAttributes.get(i));
totalInfectious[i] += mixingFactor * infectious;
}
} else {
// TODO
}
totalPopulation += mixingFactor
* otherValue.getPopulationCount();
break;
}
}
}
} // for each border edge
for (Edge roadEdge : RoadTransportRelationshipLabelImpl
.getRoadEdgesFromNode(node)) {
// find the number of edges from the road edge - could be more than
// one
// also, roads have differenct capacities
EdgeLabel edgeLabel = roadEdge.getLabel();
double numCrossings = ((RoadTransportRelationshipLabelValue) edgeLabel
.getCurrentValue()).getNumberCrossings();
double infectiousProportion = Math.min(
roadNetworkInfectiousProportion * numCrossings, 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.
Node otherNode = roadEdge.getOtherNode(node);
for (NodeLabel otherLabel : otherNode.getLabels()) {
if (otherLabel instanceof StandardDiseaseModelLabel) {
StandardDiseaseModelLabel otherDiseaseLabel = (StandardDiseaseModelLabel) otherLabel;
if (otherDiseaseLabel.getDecorator() == this
&& otherDiseaseLabel.getIdentifier().equals(
diseaseLabel.getIdentifier())) {
StandardDiseaseModelLabelValue otherValue = (StandardDiseaseModelLabelValue) otherDiseaseLabel
.getTempValue();
if (frequencyDependent) {
for (int i = 0; i < count; i++) {
double infectious = (Double) otherValue
.eGet(infectiousAttributes.get(i));
totalInfectious[i] += infectiousProportion
* infectious;
}
} else {
// TODO
}
totalPopulation += infectiousProportion
* otherValue.getPopulationCount();
break;
}
}
}
} // for each road edge
// return the sum normalized to the total population
EList<Double> retVal = new BasicEList<Double>(count);
if (totalPopulation > 0.0) {
for (double infectious : totalInfectious) {
retVal.add(infectious / totalPopulation);
}
} else {
retVal.addAll(Collections.nCopies(count, 0.0));
}
return retVal;
}
/**
* @param populationLabel
* the population label that labels the node
* @return the area of the node associated with the label
*/
public double getArea(final PopulationLabel populationLabel) {
double retValue = 0.0;
// The population label could have an area specified for the population
// that we should use instead of the area of the region labeled by the
// population label. This value would be specified if the population was
// densely packed into a small area of the larger region, for instance
// like a city in an otherwise large desert.
retValue = populationLabel.getPopulatedArea();
// Is there an area specified for the population?
if (retValue == 0.0) {
// No
// Ok, go find the area label and return the area of the region
for (final Iterator<NodeLabel> labelIter = populationLabel
.getNode().getLabels().iterator(); labelIter.hasNext();) {
final NodeLabel nodeLabel = labelIter.next();
// Is this an area label?
if (nodeLabel instanceof AreaLabel) {
// Yes
final AreaLabel areaLabel = (AreaLabel) nodeLabel;
retValue = areaLabel.getCurrentAreaValue().getArea();
break;
}
} // for
} // If no population area specified
return retValue;
} // getArea
/**
* computeDiseaseDeltas. This method calculates the delta changes for each
* disease state depending on disease parameters and mixing factors
*
* @param time
* STEM time
* @param currentState
* the current state of the population
* @param diseaseLabel
* the disease label for which the state transitions are being
* computed.
* @param timeDelta
* the time period (milliseconds) over which the population
* members transition to new states
* @param cycle
* the simulation cycle we're in
* @return a disease state label value that contains the delta changes in
* population members for each state.
*/
public abstract StandardDiseaseModelLabelValue computeDiseaseDeltas(
final STEMTime time,
final StandardDiseaseModelLabelValue currentState,
final StandardDiseaseModelLabel diseaseLabel, final long timeDelta,
DiseaseModelLabelValue returnValue);
} // StandardDiseaseModelImpl