| 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 |