From 627311af887124559e2abe8aa5e08f7eb5b9f403 Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Mon, 21 Apr 2025 10:18:02 -0700 Subject: [PATCH 01/14] introduce new config param -- VARIANCE_ONLY --- src/arcade/core/parameter.xml | 1 + src/arcade/core/sim/Series.java | 9 +++++ test_variance_only.xml | 66 +++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 test_variance_only.xml diff --git a/src/arcade/core/parameter.xml b/src/arcade/core/parameter.xml index d1675a1d2..a32eb650f 100644 --- a/src/arcade/core/parameter.xml +++ b/src/arcade/core/parameter.xml @@ -4,6 +4,7 @@ + diff --git a/src/arcade/core/sim/Series.java b/src/arcade/core/sim/Series.java index 39193d707..02908328a 100644 --- a/src/arcade/core/sim/Series.java +++ b/src/arcade/core/sim/Series.java @@ -85,6 +85,9 @@ public abstract class Series { /** Snapshot interval in ticks. */ private final int interval; + /** Variance only. */ + private final int varianceOnly; + /** Length of the simulation. */ public final int length; @@ -147,6 +150,12 @@ public Series( ? series.getInt("interval") : defaults.getInt("INTERVAL")); + // Set variance only. + this.varianceOnly = + (series.contains("varianceOnly") + ? series.getInt("varianceOnly") + : defaults.getInt("VARIANCE_ONLY")); + // Set sizing. this.length = (series.contains("length") ? series.getInt("length") : defaults.getInt("LENGTH")); diff --git a/test_variance_only.xml b/test_variance_only.xml new file mode 100644 index 000000000..b6d1bddeb --- /dev/null +++ b/test_variance_only.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 5ad3d45b089e49c995de9c7759c00a66a18e57ae Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Wed, 23 Apr 2025 16:17:30 -0700 Subject: [PATCH 02/14] add ICs to parseParameter() --- src/arcade/core/parameter.xml | 2 +- src/arcade/core/sim/Series.java | 49 +++++++++++++++---- .../patch/agent/cell/PatchCellFactory.java | 3 +- src/arcade/patch/sim/PatchSeries.java | 6 ++- .../patch/sim/input/PatchInputBuilder.java | 1 + test_variance_only.xml | 6 +-- 6 files changed, 51 insertions(+), 16 deletions(-) diff --git a/src/arcade/core/parameter.xml b/src/arcade/core/parameter.xml index a32eb650f..ca51ca3b4 100644 --- a/src/arcade/core/parameter.xml +++ b/src/arcade/core/parameter.xml @@ -4,12 +4,12 @@ - + diff --git a/src/arcade/core/sim/Series.java b/src/arcade/core/sim/Series.java index 02908328a..fa75f98c5 100644 --- a/src/arcade/core/sim/Series.java +++ b/src/arcade/core/sim/Series.java @@ -85,9 +85,6 @@ public abstract class Series { /** Snapshot interval in ticks. */ private final int interval; - /** Variance only. */ - private final int varianceOnly; - /** Length of the simulation. */ public final int length; @@ -150,12 +147,6 @@ public Series( ? series.getInt("interval") : defaults.getInt("INTERVAL")); - // Set variance only. - this.varianceOnly = - (series.contains("varianceOnly") - ? series.getInt("varianceOnly") - : defaults.getInt("VARIANCE_ONLY")); - // Set sizing. this.length = (series.contains("length") ? series.getInt("length") : defaults.getInt("LENGTH")); @@ -326,8 +317,45 @@ protected static void parseParameter( if (match.find()) { box.put("(DISTRIBUTION)" + TAG_SEPARATOR + parameter, match.group(1).toUpperCase()); + // System.out.println("(DISTRIBUTION)" + TAG_SEPARATOR + parameter); + for (int i = 0; i < (match.groupCount() - 1) / 2; i++) { + int index = 2 * (i + 1); + // System.out.println(parameter + "_" + match.group(index)); + box.put(parameter + "_" + match.group(index), match.group(index + 1)); + } + } else { + box.put(parameter, value); + if (scales.contains(parameter)) { + box.put(parameter, box.getDouble(parameter) * scales.getDouble(parameter)); + } + } + } + + /** + * Parses parameter values based on default value. + * + * @param box the parameter map + * @param parameter the parameter name + * @param defaultParameter the default parameter value + * @param values the map of parameter values + * @param scales the map of parameter scaling + */ + protected static void parseParameter( + MiniBox box, + String parameter, + String defaultParameter, + MiniBox values, + MiniBox scales, + MiniBox ICs) { + String value = values.contains(parameter) ? values.get(parameter) : defaultParameter; + Matcher match = Pattern.compile(DISTRIBUTION_REGEX).matcher(value); + + if (match.find()) { + box.put("(DISTRIBUTION)" + TAG_SEPARATOR + parameter, match.group(1).toUpperCase()); + // System.out.println("(DISTRIBUTION)" + TAG_SEPARATOR + parameter); for (int i = 0; i < (match.groupCount() - 1) / 2; i++) { int index = 2 * (i + 1); + // System.out.println(parameter + "_" + match.group(index)); box.put(parameter + "_" + match.group(index), match.group(index + 1)); } } else { @@ -336,6 +364,9 @@ protected static void parseParameter( box.put(parameter, box.getDouble(parameter) * scales.getDouble(parameter)); } } + if (ICs.contains(parameter)) { + box.put(parameter + "_IC", true); + } } /** diff --git a/src/arcade/patch/agent/cell/PatchCellFactory.java b/src/arcade/patch/agent/cell/PatchCellFactory.java index 0492e0801..47f9ea37e 100644 --- a/src/arcade/patch/agent/cell/PatchCellFactory.java +++ b/src/arcade/patch/agent/cell/PatchCellFactory.java @@ -132,7 +132,8 @@ public void createCells(Series series) { } int pop = population.getInt("CODE"); - + MiniBox popu = popToParameters.get(pop); + System.out.println("population: " + popu.getKeys()); for (int i = 0; i < init; i++) { PatchCellContainer container = createCellForPopulation(id, pop); cells.put(id, container); diff --git a/src/arcade/patch/sim/PatchSeries.java b/src/arcade/patch/sim/PatchSeries.java index 861002b09..275e53697 100644 --- a/src/arcade/patch/sim/PatchSeries.java +++ b/src/arcade/patch/sim/PatchSeries.java @@ -175,7 +175,8 @@ protected void updatePopulations( Box parameters = box.filterBoxByTag("PARAMETER"); MiniBox parameterValues = parameters.getIdValForTagAtt("PARAMETER", "value"); MiniBox parameterScales = parameters.getIdValForTagAtt("PARAMETER", "scale"); - + MiniBox parameterICs = parameters.getIdValForTagAtt("PARAMETER", "ic"); + System.out.println("parameterICs: " + parameterICs.getKeys()); // Apply conversion factors. for (String convert : populationConversions.getKeys()) { double conversion = parseConversion(populationConversions.get(convert), ds, dt); @@ -194,7 +195,8 @@ protected void updatePopulations( parameter, populationDefaults.get(parameter), parameterValues, - parameterScales); + parameterScales, + parameterICs); } // Get list of links, if valid. diff --git a/src/arcade/patch/sim/input/PatchInputBuilder.java b/src/arcade/patch/sim/input/PatchInputBuilder.java index a546ee3e8..f41130b62 100644 --- a/src/arcade/patch/sim/input/PatchInputBuilder.java +++ b/src/arcade/patch/sim/input/PatchInputBuilder.java @@ -112,6 +112,7 @@ public void startElement(String uri, String local, String name, Attributes atts) case "component": Box box = makeBox(atts); setupLists.get(name + "s").add(box); + System.out.println(name + "s: " + atts.getValue("id")); break; default: break; diff --git a/test_variance_only.xml b/test_variance_only.xml index b6d1bddeb..6ab3bf681 100644 --- a/test_variance_only.xml +++ b/test_variance_only.xml @@ -1,5 +1,5 @@ - + @@ -16,8 +16,8 @@ - - + + From c6932e50f657f741e70fe97010a66fdedc3e527d Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Wed, 23 Apr 2025 23:15:13 -0700 Subject: [PATCH 03/14] use degenerate dist for IC param --- src/arcade/core/sim/Series.java | 5 +- src/arcade/core/util/Parameters.java | 6 +- .../distributions/DegenerateDistribution.java | 81 +++++++++++++++++++ src/arcade/patch/sim/PatchSeries.java | 6 ++ test_variance_only.xml | 4 +- 5 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 src/arcade/core/util/distributions/DegenerateDistribution.java diff --git a/src/arcade/core/sim/Series.java b/src/arcade/core/sim/Series.java index fa75f98c5..6dac0b1f5 100644 --- a/src/arcade/core/sim/Series.java +++ b/src/arcade/core/sim/Series.java @@ -352,10 +352,8 @@ protected static void parseParameter( if (match.find()) { box.put("(DISTRIBUTION)" + TAG_SEPARATOR + parameter, match.group(1).toUpperCase()); - // System.out.println("(DISTRIBUTION)" + TAG_SEPARATOR + parameter); for (int i = 0; i < (match.groupCount() - 1) / 2; i++) { int index = 2 * (i + 1); - // System.out.println(parameter + "_" + match.group(index)); box.put(parameter + "_" + match.group(index), match.group(index + 1)); } } else { @@ -365,7 +363,8 @@ protected static void parseParameter( } } if (ICs.contains(parameter)) { - box.put(parameter + "_IC", true); + System.out.println("Hello"); + box.put(parameter + "_IC", ICs.get(parameter)); } } diff --git a/src/arcade/core/util/Parameters.java b/src/arcade/core/util/Parameters.java index 75cd68aac..b30e812bb 100644 --- a/src/arcade/core/util/Parameters.java +++ b/src/arcade/core/util/Parameters.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.HashSet; import ec.util.MersenneTwisterFast; +import arcade.core.util.distributions.DegenerateDistribution; import arcade.core.util.distributions.Distribution; /** @@ -39,9 +40,12 @@ public Parameters( MiniBox distributionsBox = popParameters.filter("(DISTRIBUTION)"); for (String key : distributionsBox.getKeys()) { Distribution distribution; - + System.out.println("Key: " + key); if (cellParameters != null && cellParameters.distributions.containsKey(key)) { distribution = cellParameters.distributions.get(key).rebase(random); + } else if (popParameters.contains(key + "_IC")) { + System.out.println("Key: " + key + "_IC"); + distribution = new DegenerateDistribution(key, popParameters, random); } else { distribution = popParameters.getDistribution(key, random); } diff --git a/src/arcade/core/util/distributions/DegenerateDistribution.java b/src/arcade/core/util/distributions/DegenerateDistribution.java new file mode 100644 index 000000000..2b061cb36 --- /dev/null +++ b/src/arcade/core/util/distributions/DegenerateDistribution.java @@ -0,0 +1,81 @@ +package arcade.core.util.distributions; + +import ec.util.MersenneTwisterFast; +import arcade.core.util.MiniBox; + +/** Container class for degenerate distribution (constant value). */ +public class DegenerateDistribution implements Distribution { + /** The constant value of the distribution. */ + private final double value; + + /** + * Creates a degenerate {@code Distribution} from parameters dictionary. + * + * @param name the distribution parameter name + * @param parameters the distribution parameters dictionary + * @param random the random number generator instance (unused for degenerate distribution) + */ + public DegenerateDistribution(String name, MiniBox parameters, MersenneTwisterFast random) { + this(getValueFromParameters(name, parameters)); + } + + /** Helper method to get the value from parameters based on IC type. */ + private static double getValueFromParameters(String name, MiniBox parameters) { + System.out.println("parameters: " + parameters.get("IC")); + if (parameters.get("IC") == "MU") { + return parameters.getDouble(name + "_MU"); + } else if (parameters.get("IC") == "MIN") { + return parameters.getDouble(name + "_MIN"); + } else if (parameters.get("IC") == "MAX") { + return parameters.getDouble(name + "_MAX"); + } else { + throw new IllegalArgumentException("Invalid IC: " + parameters.get("IC")); + } + } + + /** + * Creates a degenerate {@code Distribution} with a constant value. + * + * @param value the constant value of the distribution + */ + public DegenerateDistribution(double value) { + this.value = value; + } + + @Override + public MiniBox getParameters() { + MiniBox parameters = new MiniBox(); + parameters.put("VALUE", value); + return parameters; + } + + @Override + public double getExpected() { + return value; + } + + @Override + public double getDoubleValue() { + return value; + } + + @Override + public int getIntValue() { + return (int) Math.round(value); + } + + @Override + public double nextDouble() { + return value; + } + + @Override + public int nextInt() { + return (int) Math.round(value); + } + + @Override + public Distribution rebase(MersenneTwisterFast random) { + return new DegenerateDistribution(value); + } +} diff --git a/src/arcade/patch/sim/PatchSeries.java b/src/arcade/patch/sim/PatchSeries.java index 275e53697..de2157684 100644 --- a/src/arcade/patch/sim/PatchSeries.java +++ b/src/arcade/patch/sim/PatchSeries.java @@ -177,6 +177,10 @@ protected void updatePopulations( MiniBox parameterScales = parameters.getIdValForTagAtt("PARAMETER", "scale"); MiniBox parameterICs = parameters.getIdValForTagAtt("PARAMETER", "ic"); System.out.println("parameterICs: " + parameterICs.getKeys()); + System.out.println( + "parameterICs values: " + parameterICs.get("proliferation/SYNTHESIS_DURATION")); + System.out.println( + "parameterICs values: " + parameterICs.get("metabolism/MIGRATION_ENERGY")); // Apply conversion factors. for (String convert : populationConversions.getKeys()) { double conversion = parseConversion(populationConversions.get(convert), ds, dt); @@ -198,6 +202,8 @@ protected void updatePopulations( parameterScales, parameterICs); } + System.out.println("population: " + population.getKeys()); + System.out.println("population: " + population.get("SYNTHESIS_DURATION_IC")); // Get list of links, if valid. MiniBox links = box.filterBoxByTag("LINK").getIdValForTagAtt("LINK", "weight"); diff --git a/test_variance_only.xml b/test_variance_only.xml index 6ab3bf681..0f3c61fc6 100644 --- a/test_variance_only.xml +++ b/test_variance_only.xml @@ -16,8 +16,8 @@ - - + + From 3116f2ad969c480e2ef81e2e93a16b8bbb74ef2d Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Thu, 24 Apr 2025 12:24:49 -0700 Subject: [PATCH 04/14] use degenerate dist for ic params --- src/arcade/core/sim/Series.java | 3 --- src/arcade/core/util/Parameters.java | 3 --- .../distributions/DegenerateDistribution.java | 10 +++++----- .../patch/agent/cell/PatchCellFactory.java | 2 -- src/arcade/patch/sim/PatchSeries.java | 7 ------- .../patch/sim/input/PatchInputBuilder.java | 1 - test_variance_only.xml | 16 +--------------- 7 files changed, 6 insertions(+), 36 deletions(-) diff --git a/src/arcade/core/sim/Series.java b/src/arcade/core/sim/Series.java index 6dac0b1f5..214b97cbe 100644 --- a/src/arcade/core/sim/Series.java +++ b/src/arcade/core/sim/Series.java @@ -317,10 +317,8 @@ protected static void parseParameter( if (match.find()) { box.put("(DISTRIBUTION)" + TAG_SEPARATOR + parameter, match.group(1).toUpperCase()); - // System.out.println("(DISTRIBUTION)" + TAG_SEPARATOR + parameter); for (int i = 0; i < (match.groupCount() - 1) / 2; i++) { int index = 2 * (i + 1); - // System.out.println(parameter + "_" + match.group(index)); box.put(parameter + "_" + match.group(index), match.group(index + 1)); } } else { @@ -363,7 +361,6 @@ protected static void parseParameter( } } if (ICs.contains(parameter)) { - System.out.println("Hello"); box.put(parameter + "_IC", ICs.get(parameter)); } } diff --git a/src/arcade/core/util/Parameters.java b/src/arcade/core/util/Parameters.java index b30e812bb..cb53ade5a 100644 --- a/src/arcade/core/util/Parameters.java +++ b/src/arcade/core/util/Parameters.java @@ -40,16 +40,13 @@ public Parameters( MiniBox distributionsBox = popParameters.filter("(DISTRIBUTION)"); for (String key : distributionsBox.getKeys()) { Distribution distribution; - System.out.println("Key: " + key); if (cellParameters != null && cellParameters.distributions.containsKey(key)) { distribution = cellParameters.distributions.get(key).rebase(random); } else if (popParameters.contains(key + "_IC")) { - System.out.println("Key: " + key + "_IC"); distribution = new DegenerateDistribution(key, popParameters, random); } else { distribution = popParameters.getDistribution(key, random); } - distributions.put(key, distribution); } } diff --git a/src/arcade/core/util/distributions/DegenerateDistribution.java b/src/arcade/core/util/distributions/DegenerateDistribution.java index 2b061cb36..47c7e846d 100644 --- a/src/arcade/core/util/distributions/DegenerateDistribution.java +++ b/src/arcade/core/util/distributions/DegenerateDistribution.java @@ -21,15 +21,15 @@ public DegenerateDistribution(String name, MiniBox parameters, MersenneTwisterFa /** Helper method to get the value from parameters based on IC type. */ private static double getValueFromParameters(String name, MiniBox parameters) { - System.out.println("parameters: " + parameters.get("IC")); - if (parameters.get("IC") == "MU") { + String ic_type = parameters.get(name + "_IC"); + if (ic_type.equals("MU")) { return parameters.getDouble(name + "_MU"); - } else if (parameters.get("IC") == "MIN") { + } else if (ic_type.equals("MIN")) { return parameters.getDouble(name + "_MIN"); - } else if (parameters.get("IC") == "MAX") { + } else if (ic_type.equals("MAX")) { return parameters.getDouble(name + "_MAX"); } else { - throw new IllegalArgumentException("Invalid IC: " + parameters.get("IC")); + throw new IllegalArgumentException("Invalid IC: " + ic_type); } } diff --git a/src/arcade/patch/agent/cell/PatchCellFactory.java b/src/arcade/patch/agent/cell/PatchCellFactory.java index 47f9ea37e..517c0e19b 100644 --- a/src/arcade/patch/agent/cell/PatchCellFactory.java +++ b/src/arcade/patch/agent/cell/PatchCellFactory.java @@ -132,8 +132,6 @@ public void createCells(Series series) { } int pop = population.getInt("CODE"); - MiniBox popu = popToParameters.get(pop); - System.out.println("population: " + popu.getKeys()); for (int i = 0; i < init; i++) { PatchCellContainer container = createCellForPopulation(id, pop); cells.put(id, container); diff --git a/src/arcade/patch/sim/PatchSeries.java b/src/arcade/patch/sim/PatchSeries.java index de2157684..d306e1382 100644 --- a/src/arcade/patch/sim/PatchSeries.java +++ b/src/arcade/patch/sim/PatchSeries.java @@ -176,11 +176,6 @@ protected void updatePopulations( MiniBox parameterValues = parameters.getIdValForTagAtt("PARAMETER", "value"); MiniBox parameterScales = parameters.getIdValForTagAtt("PARAMETER", "scale"); MiniBox parameterICs = parameters.getIdValForTagAtt("PARAMETER", "ic"); - System.out.println("parameterICs: " + parameterICs.getKeys()); - System.out.println( - "parameterICs values: " + parameterICs.get("proliferation/SYNTHESIS_DURATION")); - System.out.println( - "parameterICs values: " + parameterICs.get("metabolism/MIGRATION_ENERGY")); // Apply conversion factors. for (String convert : populationConversions.getKeys()) { double conversion = parseConversion(populationConversions.get(convert), ds, dt); @@ -202,8 +197,6 @@ protected void updatePopulations( parameterScales, parameterICs); } - System.out.println("population: " + population.getKeys()); - System.out.println("population: " + population.get("SYNTHESIS_DURATION_IC")); // Get list of links, if valid. MiniBox links = box.filterBoxByTag("LINK").getIdValForTagAtt("LINK", "weight"); diff --git a/src/arcade/patch/sim/input/PatchInputBuilder.java b/src/arcade/patch/sim/input/PatchInputBuilder.java index f41130b62..a546ee3e8 100644 --- a/src/arcade/patch/sim/input/PatchInputBuilder.java +++ b/src/arcade/patch/sim/input/PatchInputBuilder.java @@ -112,7 +112,6 @@ public void startElement(String uri, String local, String name, Attributes atts) case "component": Box box = makeBox(atts); setupLists.get(name + "s").add(box); - System.out.println(name + "s: " + atts.getValue("id")); break; default: break; diff --git a/test_variance_only.xml b/test_variance_only.xml index 0f3c61fc6..cce055787 100644 --- a/test_variance_only.xml +++ b/test_variance_only.xml @@ -5,28 +5,14 @@ - + - - - - - - - - - - - - - - From 2699dce90b6f46277db8b6640d48dc2fe459195c Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Thu, 24 Apr 2025 15:14:39 -0700 Subject: [PATCH 05/14] test degenerateDist Serires --- src/arcade/core/sim/Series.java | 1 + src/arcade/core/util/MiniBox.java | 5 + src/arcade/patch/sim/PatchSeries.java | 9 +- test/arcade/core/sim/SeriesTest.java | 30 +++++ .../DegenerateDistributionTest.java | 103 ++++++++++++++++++ ...stributionTest - Copy.java:Zone.Identifier | 0 test/arcade/patch/sim/PatchSeriesTest.java | 15 +++ 7 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 test/arcade/core/util/distributions/DegenerateDistributionTest.java create mode 100644 test/arcade/core/util/distributions/NormalDistributionTest - Copy.java:Zone.Identifier diff --git a/src/arcade/core/sim/Series.java b/src/arcade/core/sim/Series.java index 214b97cbe..3654a2850 100644 --- a/src/arcade/core/sim/Series.java +++ b/src/arcade/core/sim/Series.java @@ -337,6 +337,7 @@ protected static void parseParameter( * @param defaultParameter the default parameter value * @param values the map of parameter values * @param scales the map of parameter scaling + * @param ICs the map of initial condition parameters */ protected static void parseParameter( MiniBox box, diff --git a/src/arcade/core/util/MiniBox.java b/src/arcade/core/util/MiniBox.java index eb5037bbd..1de803c2d 100644 --- a/src/arcade/core/util/MiniBox.java +++ b/src/arcade/core/util/MiniBox.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.HashSet; import ec.util.MersenneTwisterFast; +import arcade.core.util.distributions.DegenerateDistribution; import arcade.core.util.distributions.Distribution; import arcade.core.util.distributions.NormalDistribution; import arcade.core.util.distributions.NormalFractionalDistribution; @@ -107,6 +108,10 @@ public double getDouble(String id) { double denominator = (!split[1].matches(NUMBER_REGEX) ? Double.NaN : Double.parseDouble(split[1])); return (denominator == 0 ? Double.NaN : numerator / denominator); + } else if (contents.containsKey(id + "_IC")) { + Distribution distribution = + new DegenerateDistribution(id, this, new MersenneTwisterFast()); + return distribution.getExpected(); } else if (contents.containsKey("(DISTRIBUTION)" + TAG_SEPARATOR + id)) { return getDistribution(id, new MersenneTwisterFast()).getExpected(); } diff --git a/src/arcade/patch/sim/PatchSeries.java b/src/arcade/patch/sim/PatchSeries.java index d306e1382..e5323f8bd 100644 --- a/src/arcade/patch/sim/PatchSeries.java +++ b/src/arcade/patch/sim/PatchSeries.java @@ -197,7 +197,14 @@ protected void updatePopulations( parameterScales, parameterICs); } - + System.out.println(population.getKeys()); + System.out.println(population.get("SYNTHESIS_DURATION")); + System.out.println(population.getDouble("SYNTHESIS_DURATION")); + System.out.println(population.get("SYNTHESIS_DURATION_IC")); + System.out.println(population.getDouble("SYNTHESIS_DURATION_IC")); + System.out.println(population.get("(DISTRIBUTION)/proliferation/SYNTHESIS_DURATION")); + System.out.println( + population.getDouble("(DISTRIBUTION)/proliferation/SYNTHESIS_DURATION")); // Get list of links, if valid. MiniBox links = box.filterBoxByTag("LINK").getIdValForTagAtt("LINK", "weight"); for (String link : links.getKeys()) { diff --git a/test/arcade/core/sim/SeriesTest.java b/test/arcade/core/sim/SeriesTest.java index 5292f2453..83db9462c 100644 --- a/test/arcade/core/sim/SeriesTest.java +++ b/test/arcade/core/sim/SeriesTest.java @@ -693,6 +693,36 @@ public void parseParameter_withTwoParameterDistributionValue_usesValue() { assertEquals(valueB, box.getDouble(parameter + "_B"), EPSILON); } + @Test + public void parseParameter_withIC_putsICInBox() { + MiniBox box = new MiniBox(); + String parameter = randomString(); + double defaultParameter = randomDoubleBetween(0, 100); + + MiniBox values = new MiniBox(); + MiniBox scales = new MiniBox(); + MiniBox ICs = new MiniBox(); + ICs.put(parameter, "MU"); + Series.parseParameter(box, parameter, "" + defaultParameter, values, scales, ICs); + + assertEquals("MU", box.get(parameter + "_IC")); + } + + @Test + public void parseParameter_withoutIC_doesNotPutICInBox() { + MiniBox box = new MiniBox(); + String parameter = randomString(); + double defaultParameter = randomDoubleBetween(0, 100); + + MiniBox values = new MiniBox(); + MiniBox scales = new MiniBox(); + MiniBox ICs = new MiniBox(); + + Series.parseParameter(box, parameter, "" + defaultParameter, values, scales, ICs); + + assertFalse(box.contains(parameter + "_IC")); + } + @Test public void parseConversion_invalidConversion_returnsOne() { assertEquals(1, Series.parseConversion(randomString(), DS, DZ, DT), EPSILON); diff --git a/test/arcade/core/util/distributions/DegenerateDistributionTest.java b/test/arcade/core/util/distributions/DegenerateDistributionTest.java new file mode 100644 index 000000000..03f20eb48 --- /dev/null +++ b/test/arcade/core/util/distributions/DegenerateDistributionTest.java @@ -0,0 +1,103 @@ +package arcade.core.util.distributions; + +import org.junit.jupiter.api.Test; +import ec.util.MersenneTwisterFast; +import arcade.core.util.MiniBox; +import static org.junit.jupiter.api.Assertions.*; +import static arcade.core.ARCADETestUtilities.*; + +public class DegenerateDistributionTest { + private static final double EPSILON = 1E-5; + private static final MersenneTwisterFast RANDOM = new MersenneTwisterFast(); + + @Test + public void constructor_withDirectValue_setsValueCorrectly() { + double expected = 42.0; + DegenerateDistribution dist = new DegenerateDistribution(expected); + + assertEquals(expected, dist.getDoubleValue(), EPSILON); + assertEquals(expected, dist.getExpected(), EPSILON); + assertEquals((int) Math.round(expected), dist.getIntValue()); + } + + @Test + public void constructor_withICMU_setsValueFromMU() { + MiniBox parameters = new MiniBox(); + String name = randomString().toUpperCase(); + double mu = randomDoubleBetween(0, 100); + parameters.put(name + "_IC", "MU"); + parameters.put(name + "_MU", mu); + + DegenerateDistribution dist = new DegenerateDistribution(name, parameters, RANDOM); + + assertEquals(mu, dist.getDoubleValue(), EPSILON); + } + + @Test + public void constructor_withICMIN_setsValueFromMIN() { + MiniBox parameters = new MiniBox(); + String name = randomString().toUpperCase(); + double min = randomDoubleBetween(0, 100); + parameters.put(name + "_IC", "MIN"); + parameters.put(name + "_MIN", min); + + DegenerateDistribution dist = new DegenerateDistribution(name, parameters, RANDOM); + + assertEquals(min, dist.getDoubleValue(), EPSILON); + } + + @Test + public void constructor_withICMAX_setsValueFromMAX() { + MiniBox parameters = new MiniBox(); + String name = randomString().toUpperCase(); + double max = randomDoubleBetween(0, 100); + parameters.put(name + "_IC", "MAX"); + parameters.put(name + "_MAX", max); + + DegenerateDistribution dist = new DegenerateDistribution(name, parameters, RANDOM); + + assertEquals(max, dist.getDoubleValue(), EPSILON); + } + + @Test + public void constructor_withInvalidIC_throwsException() { + MiniBox parameters = new MiniBox(); + String name = randomString().toUpperCase(); + parameters.put(name + "_IC", "INVALID"); + + Exception exception = + assertThrows( + IllegalArgumentException.class, + () -> new DegenerateDistribution(name, parameters, RANDOM)); + + assertTrue(exception.getMessage().contains("Invalid IC")); + } + + @Test + public void getParameters_returnsCorrectMiniBox() { + double expected = randomDoubleBetween(0, 100); + DegenerateDistribution dist = new DegenerateDistribution(expected); + MiniBox parameters = dist.getParameters(); + + assertEquals(expected, parameters.getDouble("VALUE"), EPSILON); + } + + @Test + public void rebase_returnsIdenticalDistribution() { + double value = randomDoubleBetween(0, 100); + DegenerateDistribution dist = new DegenerateDistribution(value); + DegenerateDistribution rebased = (DegenerateDistribution) dist.rebase(RANDOM); + + assertEquals(value, rebased.getDoubleValue(), EPSILON); + assertEquals(value, rebased.getExpected(), EPSILON); + } + + @Test + public void nextDouble_and_nextInt_returnConstantValue() { + double value = randomDoubleBetween(0, 100); + DegenerateDistribution dist = new DegenerateDistribution(value); + + assertEquals(value, dist.nextDouble(), EPSILON); + assertEquals((int) Math.round(value), dist.nextInt()); + } +} diff --git a/test/arcade/core/util/distributions/NormalDistributionTest - Copy.java:Zone.Identifier b/test/arcade/core/util/distributions/NormalDistributionTest - Copy.java:Zone.Identifier new file mode 100644 index 000000000..e69de29bb diff --git a/test/arcade/patch/sim/PatchSeriesTest.java b/test/arcade/patch/sim/PatchSeriesTest.java index 357a0e9d8..42f4f036f 100644 --- a/test/arcade/patch/sim/PatchSeriesTest.java +++ b/test/arcade/patch/sim/PatchSeriesTest.java @@ -189,6 +189,21 @@ public void updatePatch_givenParameters_updatesValues() { } } + @Test + public void updatePatch_givenIC_usesIC() { + for (String patchParameter : PATCH_PARAMETER_NAMES) { + Box patch = new Box(); + double mu = randomDoubleBetween(0, 100); + patch.addAtt(patchParameter, "IC", "MU"); + patch.addAtt(patchParameter, "MU", "" + mu); + PatchSeries series = makeSeriesForPatch(patch); + MiniBox box = series.patch; + // for (String parameter : PATCH_PARAMETER_NAMES) { + // assertEquals(mu, box.getDouble(parameter), EPSILON); + // } + } + } + private PatchSeries makeSeriesForPopulation(Box[] boxes) { HashMap> setupLists = makeLists(); PatchSeries series = mock(PatchSeries.class, CALLS_REAL_METHODS); From f07cae9ec4333602d56dbe46096631dbd0a623ee Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Fri, 25 Apr 2025 15:55:11 -0700 Subject: [PATCH 06/14] test createCells_withIC --- src/arcade/core/util/MiniBox.java | 5 --- .../patch/agent/cell/PatchCellFactory.java | 11 +++++- .../agent/cell/PatchCellFactoryTest.java | 37 +++++++++++++++++++ test/arcade/patch/sim/PatchSeriesTest.java | 15 -------- test_variance_only.xml | 2 +- 5 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/arcade/core/util/MiniBox.java b/src/arcade/core/util/MiniBox.java index 1de803c2d..eb5037bbd 100644 --- a/src/arcade/core/util/MiniBox.java +++ b/src/arcade/core/util/MiniBox.java @@ -4,7 +4,6 @@ import java.util.HashMap; import java.util.HashSet; import ec.util.MersenneTwisterFast; -import arcade.core.util.distributions.DegenerateDistribution; import arcade.core.util.distributions.Distribution; import arcade.core.util.distributions.NormalDistribution; import arcade.core.util.distributions.NormalFractionalDistribution; @@ -108,10 +107,6 @@ public double getDouble(String id) { double denominator = (!split[1].matches(NUMBER_REGEX) ? Double.NaN : Double.parseDouble(split[1])); return (denominator == 0 ? Double.NaN : numerator / denominator); - } else if (contents.containsKey(id + "_IC")) { - Distribution distribution = - new DegenerateDistribution(id, this, new MersenneTwisterFast()); - return distribution.getExpected(); } else if (contents.containsKey("(DISTRIBUTION)" + TAG_SEPARATOR + id)) { return getDistribution(id, new MersenneTwisterFast()).getExpected(); } diff --git a/src/arcade/patch/agent/cell/PatchCellFactory.java b/src/arcade/patch/agent/cell/PatchCellFactory.java index 517c0e19b..9062411df 100644 --- a/src/arcade/patch/agent/cell/PatchCellFactory.java +++ b/src/arcade/patch/agent/cell/PatchCellFactory.java @@ -63,6 +63,9 @@ public void initialize(Series series, MersenneTwisterFast random) { loadCells(series); } else { createCells(series); + // System.out.println("cells id: " + cells.get(1).id); + // System.out.println("cells size: " + cells.size()); + // System.out.println("cells volume: " + cells.get(1).volume); } } @@ -132,6 +135,12 @@ public void createCells(Series series) { } int pop = population.getInt("CODE"); + MiniBox populationParameters = popToParameters.get(pop); + System.out.println(populationParameters.getKeys()); + System.out.println(populationParameters.getDouble("CELL_VOLUME")); + System.out.println(populationParameters.getDouble("CELL_VOLUME_MU")); + System.out.println(populationParameters.getDouble("CELL_VOLUME_SIGMA")); + for (int i = 0; i < init; i++) { PatchCellContainer container = createCellForPopulation(id, pop); cells.put(id, container); @@ -151,7 +160,7 @@ public void createCells(Series series) { public PatchCellContainer createCellForPopulation(int id, int pop) { MiniBox population = popToParameters.get(pop); Parameters parameters = new Parameters(population, null, random); - + System.out.println(parameters.getDouble("CELL_VOLUME")); double compression = parameters.getDouble("COMPRESSION_TOLERANCE"); double volume = parameters.getDouble("CELL_VOLUME"); diff --git a/test/arcade/patch/agent/cell/PatchCellFactoryTest.java b/test/arcade/patch/agent/cell/PatchCellFactoryTest.java index 103b6d3bc..844ca8175 100644 --- a/test/arcade/patch/agent/cell/PatchCellFactoryTest.java +++ b/test/arcade/patch/agent/cell/PatchCellFactoryTest.java @@ -39,6 +39,43 @@ public void createCells_noPopulation_createsEmpty() { assertEquals(0, factory.popToIDs.size()); } + @Test + public void createCells_withICParameters_createsList() { + int count = randomIntBetween(1, 10); + PatchSeries series = createSeries(new int[] {count}, new String[] {"COUNT"}); + + double volumeMu = randomDoubleBetween(1, 10); + double volumeSigma = randomDoubleBetween(1, 10); + double height = randomDoubleBetween(1, 10); + int age = randomIntBetween(1, 100); + double compression = randomDoubleBetween(1, 10); + + MiniBox parameters = new MiniBox(); + parameters.put("(DISTRIBUTION)/CELL_VOLUME", "NORMAL"); + parameters.put("CELL_VOLUME_MU", volumeMu); + parameters.put("CELL_VOLUME_SIGMA", volumeSigma); + parameters.put("CELL_VOLUME_IC", "MU"); + parameters.put("CELL_HEIGHT", height); + parameters.put("CELL_AGE", age); + parameters.put("COMPRESSION_TOLERANCE", compression); + + PatchCellFactory factory = new PatchCellFactory(); + factory.popToIDs.put(1, new HashSet<>()); + factory.popToParameters.put(1, parameters); + factory.createCells(series); + + assertEquals(count, factory.cells.size()); + assertEquals(count, factory.popToIDs.get(1).size()); + + for (int i : factory.popToIDs.get(1)) { + PatchCellContainer patchCellContainer = factory.cells.get(i); + assertEquals(volumeMu, patchCellContainer.criticalVolume, EPSILON); + assertEquals(height + compression, patchCellContainer.criticalHeight, EPSILON); + assertEquals(age, patchCellContainer.age); + assertEquals(0, patchCellContainer.divisions); + } + } + @Test public void createCells_onePopulationInitByCount_createsList() { int count = randomIntBetween(1, 10); diff --git a/test/arcade/patch/sim/PatchSeriesTest.java b/test/arcade/patch/sim/PatchSeriesTest.java index 42f4f036f..357a0e9d8 100644 --- a/test/arcade/patch/sim/PatchSeriesTest.java +++ b/test/arcade/patch/sim/PatchSeriesTest.java @@ -189,21 +189,6 @@ public void updatePatch_givenParameters_updatesValues() { } } - @Test - public void updatePatch_givenIC_usesIC() { - for (String patchParameter : PATCH_PARAMETER_NAMES) { - Box patch = new Box(); - double mu = randomDoubleBetween(0, 100); - patch.addAtt(patchParameter, "IC", "MU"); - patch.addAtt(patchParameter, "MU", "" + mu); - PatchSeries series = makeSeriesForPatch(patch); - MiniBox box = series.patch; - // for (String parameter : PATCH_PARAMETER_NAMES) { - // assertEquals(mu, box.getDouble(parameter), EPSILON); - // } - } - } - private PatchSeries makeSeriesForPopulation(Box[] boxes) { HashMap> setupLists = makeLists(); PatchSeries series = mock(PatchSeries.class, CALLS_REAL_METHODS); diff --git a/test_variance_only.xml b/test_variance_only.xml index cce055787..ae6ade9bf 100644 --- a/test_variance_only.xml +++ b/test_variance_only.xml @@ -6,7 +6,7 @@ - + From 1fb551169716e07b2bc180f7af415177621fbb52 Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Sun, 27 Apr 2025 12:56:10 -0700 Subject: [PATCH 07/14] update variance --- src/arcade/core/util/MiniBox.java | 4 ---- ...alDistributionTest - Copy.java:Zone.Identifier | 0 test/arcade/patch/sim/PatchSeriesTest.java | 15 --------------- 3 files changed, 19 deletions(-) delete mode 100644 test/arcade/core/util/distributions/NormalDistributionTest - Copy.java:Zone.Identifier diff --git a/src/arcade/core/util/MiniBox.java b/src/arcade/core/util/MiniBox.java index 1de803c2d..d53fc4449 100644 --- a/src/arcade/core/util/MiniBox.java +++ b/src/arcade/core/util/MiniBox.java @@ -108,10 +108,6 @@ public double getDouble(String id) { double denominator = (!split[1].matches(NUMBER_REGEX) ? Double.NaN : Double.parseDouble(split[1])); return (denominator == 0 ? Double.NaN : numerator / denominator); - } else if (contents.containsKey(id + "_IC")) { - Distribution distribution = - new DegenerateDistribution(id, this, new MersenneTwisterFast()); - return distribution.getExpected(); } else if (contents.containsKey("(DISTRIBUTION)" + TAG_SEPARATOR + id)) { return getDistribution(id, new MersenneTwisterFast()).getExpected(); } diff --git a/test/arcade/core/util/distributions/NormalDistributionTest - Copy.java:Zone.Identifier b/test/arcade/core/util/distributions/NormalDistributionTest - Copy.java:Zone.Identifier deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/arcade/patch/sim/PatchSeriesTest.java b/test/arcade/patch/sim/PatchSeriesTest.java index 42f4f036f..357a0e9d8 100644 --- a/test/arcade/patch/sim/PatchSeriesTest.java +++ b/test/arcade/patch/sim/PatchSeriesTest.java @@ -189,21 +189,6 @@ public void updatePatch_givenParameters_updatesValues() { } } - @Test - public void updatePatch_givenIC_usesIC() { - for (String patchParameter : PATCH_PARAMETER_NAMES) { - Box patch = new Box(); - double mu = randomDoubleBetween(0, 100); - patch.addAtt(patchParameter, "IC", "MU"); - patch.addAtt(patchParameter, "MU", "" + mu); - PatchSeries series = makeSeriesForPatch(patch); - MiniBox box = series.patch; - // for (String parameter : PATCH_PARAMETER_NAMES) { - // assertEquals(mu, box.getDouble(parameter), EPSILON); - // } - } - } - private PatchSeries makeSeriesForPopulation(Box[] boxes) { HashMap> setupLists = makeLists(); PatchSeries series = mock(PatchSeries.class, CALLS_REAL_METHODS); From d076255f463b3a1753affd352a0327d17975cef9 Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Sun, 27 Apr 2025 16:21:52 -0700 Subject: [PATCH 08/14] create daughter cells with ICs --- src/arcade/patch/agent/cell/PatchCell.java | 2 + .../patch/agent/cell/PatchCellFactory.java | 8 -- .../module/PatchModuleProliferation.java | 13 +-- .../patch/agent/cell/PatchCellTest.java | 87 +++++++++++++++++++ 4 files changed, 91 insertions(+), 19 deletions(-) diff --git a/src/arcade/patch/agent/cell/PatchCell.java b/src/arcade/patch/agent/cell/PatchCell.java index 84c255eed..1c583c633 100644 --- a/src/arcade/patch/agent/cell/PatchCell.java +++ b/src/arcade/patch/agent/cell/PatchCell.java @@ -186,8 +186,10 @@ public PatchCell( MiniBox processBox = parameters.filter("(PROCESS)"); for (String processKey : processBox.getKeys()) { + System.out.println("processKey: " + processKey); ProcessDomain domain = Domain.valueOf(processKey); String version = processBox.get(processKey); + System.out.println("version: " + version); Process process = makeProcess(domain, version); processes.put(domain, process); } diff --git a/src/arcade/patch/agent/cell/PatchCellFactory.java b/src/arcade/patch/agent/cell/PatchCellFactory.java index 9062411df..471c2e657 100644 --- a/src/arcade/patch/agent/cell/PatchCellFactory.java +++ b/src/arcade/patch/agent/cell/PatchCellFactory.java @@ -63,9 +63,6 @@ public void initialize(Series series, MersenneTwisterFast random) { loadCells(series); } else { createCells(series); - // System.out.println("cells id: " + cells.get(1).id); - // System.out.println("cells size: " + cells.size()); - // System.out.println("cells volume: " + cells.get(1).volume); } } @@ -137,10 +134,6 @@ public void createCells(Series series) { int pop = population.getInt("CODE"); MiniBox populationParameters = popToParameters.get(pop); System.out.println(populationParameters.getKeys()); - System.out.println(populationParameters.getDouble("CELL_VOLUME")); - System.out.println(populationParameters.getDouble("CELL_VOLUME_MU")); - System.out.println(populationParameters.getDouble("CELL_VOLUME_SIGMA")); - for (int i = 0; i < init; i++) { PatchCellContainer container = createCellForPopulation(id, pop); cells.put(id, container); @@ -160,7 +153,6 @@ public void createCells(Series series) { public PatchCellContainer createCellForPopulation(int id, int pop) { MiniBox population = popToParameters.get(pop); Parameters parameters = new Parameters(population, null, random); - System.out.println(parameters.getDouble("CELL_VOLUME")); double compression = parameters.getDouble("COMPRESSION_TOLERANCE"); double volume = parameters.getDouble("CELL_VOLUME"); diff --git a/src/arcade/patch/agent/module/PatchModuleProliferation.java b/src/arcade/patch/agent/module/PatchModuleProliferation.java index e5134bf8b..572a6524f 100644 --- a/src/arcade/patch/agent/module/PatchModuleProliferation.java +++ b/src/arcade/patch/agent/module/PatchModuleProliferation.java @@ -8,7 +8,6 @@ import arcade.core.util.MiniBox; import arcade.core.util.Parameters; import arcade.patch.agent.cell.PatchCell; -import arcade.patch.agent.cell.PatchCellCART; import arcade.patch.agent.process.PatchProcess; import arcade.patch.env.grid.PatchGrid; import arcade.patch.env.location.PatchLocation; @@ -74,20 +73,12 @@ public void step(MersenneTwisterFast random, Simulation sim) { // space in neighborhood to divide into. Otherwise, check if double // volume has been reached, and if so, create a new cell. if (currentHeight > maxHeight) { - if (cell instanceof PatchCellCART) { - cell.setState(State.PAUSED); - } else { - cell.setState(State.QUIESCENT); - } + cell.setState(State.QUIESCENT); } else { PatchLocation newLocation = cell.selectBestLocation(sim, random); if (newLocation == null) { - if (cell instanceof PatchCellCART) { - cell.setState(State.PAUSED); - } else { - cell.setState(State.QUIESCENT); - } + cell.setState(State.QUIESCENT); } else if (cell.getVolume() >= targetVolume) { if (ticker > synthesisDuration) { diff --git a/test/arcade/patch/agent/cell/PatchCellTest.java b/test/arcade/patch/agent/cell/PatchCellTest.java index 63ccb0367..7d987d2b2 100644 --- a/test/arcade/patch/agent/cell/PatchCellTest.java +++ b/test/arcade/patch/agent/cell/PatchCellTest.java @@ -150,6 +150,93 @@ public void getBindingFlag_called_returnsFlag() { assertEquals(PatchEnums.AntigenFlag.BOUND_ANTIGEN, cell.getBindingFlag()); } + @Test + public void setState_proliferateWithIC_drawsFromDistribution() { + Schedule scheduleMock = mock(Schedule.class); + doReturn(cellID + 1).when(simMock).getID(); + doReturn(scheduleMock).when(simMock).getSchedule(); + doReturn(null).when(scheduleMock).scheduleRepeating(anyInt(), anyInt(), any()); + PatchCellFactory factoryMock = mock(PatchCellFactory.class); + MiniBox popParameters = new MiniBox(); + popParameters.put("(DISTRIBUTION)/NECROTIC_FRACTION", "NORMAL"); + popParameters.put("NECROTIC_FRACTION_MU", 0.5); + popParameters.put("NECROTIC_FRACTION_SIGMA", 0.1); + doReturn(popParameters).when(factoryMock).getParameters(anyInt()); + doReturn(factoryMock).when(simMock).getCellFactory(); + doReturn(0.5).when(randomMock).nextDouble(); + + MiniBox population = new MiniBox(); + double volume = 500; + population.put("COMPRESSION_TOLERANCE", 0); + population.put("(DISTRIBUTION)/NECROTIC_FRACTION", "NORMAL"); + population.put("NECROTIC_FRACTION_MU", 0.5); + population.put("NECROTIC_FRACTION_SIGMA", 0.1); + population.put("NECROTIC_FRACTION_IC", "MU"); + population.put("proliferation/SYNTHESIS_DURATION", 1); + population.put("SENESCENT_FRACTION", 0); + population.put("ENERGY_THRESHOLD", 0); + population.put("APOPTOSIS_AGE", 0); + population.put("ACCURACY", 0); + population.put("AFFINITY", 0); + population.put("DIVISION_POTENTIAL", 50); + population.put("MAX_DENSITY", 0); + population.put("CAR_ANTIGENS", 0); + population.put("SELF_TARGETS", 0); + + Parameters parameters = new Parameters(population, null, randomMock); + double critHeight = 10; + double critVolume = 250; + + doReturn(100.).when(locationMock).getArea(); + PatchCellContainer container = + new PatchCellContainer( + cellID, + cellParent, + cellPop, + cellAge, + cellDivisions, + cellState, + volume, + cellHeight, + critVolume, + critHeight); + PatchCellContainer daughterContainer = + new PatchCellContainer( + cellID + 1, + cellParent, + cellPop, + cellAge, + cellDivisions, + State.UNDEFINED, + volume, + cellHeight, + critVolume, + critHeight); + PatchCell cell = spy(new PatchCellMock(container, locationMock, parameters)); + PatchCellContainer containerMock = mock(PatchCellContainer.class); + PatchCell daughter = spy(new PatchCellMock(daughterContainer, locationMock, parameters)); + + doReturn(daughter) + .when(containerMock) + .convert(factoryMock, locationMock, randomMock, parameters); + doReturn(containerMock) + .when(cell) + .make(anyInt(), any(State.class), any(MersenneTwisterFast.class)); + doReturn(locationMock).when(cell).selectBestLocation(simMock, randomMock); + Bag locationBag = new Bag(); + locationBag.add(cell); + doReturn(locationBag).when(gridMock).getObjectsAtLocation(locationMock); + + cell.setState(State.PROLIFERATIVE); + cell.module.step(randomMock, simMock); + cell.module.step(randomMock, simMock); + cell.module.step(randomMock, simMock); + + assertEquals(State.UNDEFINED, cell.getState()); + assertEquals(250, cell.getVolume()); + assertEquals(0.5, daughter.getParameters().getDouble("NECROTIC_FRACTION")); + } + @Test public void setState_migration_movesCell() { doReturn(0.0).when(parametersMock).getDouble(any(String.class)); From fa84222ad4644d523dbaeb094be9f742c678da26 Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Sun, 27 Apr 2025 21:28:33 -0700 Subject: [PATCH 09/14] correct variance only parameter --- src/arcade/core/util/Parameters.java | 3 + .../agent/cell/PatchCellContainerTest.java | 144 ++++++++++++++++++ .../patch/agent/cell/PatchCellTest.java | 87 ----------- 3 files changed, 147 insertions(+), 87 deletions(-) create mode 100644 test/arcade/patch/agent/cell/PatchCellContainerTest.java diff --git a/src/arcade/core/util/Parameters.java b/src/arcade/core/util/Parameters.java index cb53ade5a..733571afa 100644 --- a/src/arcade/core/util/Parameters.java +++ b/src/arcade/core/util/Parameters.java @@ -42,6 +42,9 @@ public Parameters( Distribution distribution; if (cellParameters != null && cellParameters.distributions.containsKey(key)) { distribution = cellParameters.distributions.get(key).rebase(random); + if (distribution instanceof DegenerateDistribution) { + distribution = popParameters.getDistribution(key, random); + } } else if (popParameters.contains(key + "_IC")) { distribution = new DegenerateDistribution(key, popParameters, random); } else { diff --git a/test/arcade/patch/agent/cell/PatchCellContainerTest.java b/test/arcade/patch/agent/cell/PatchCellContainerTest.java new file mode 100644 index 000000000..de9806835 --- /dev/null +++ b/test/arcade/patch/agent/cell/PatchCellContainerTest.java @@ -0,0 +1,144 @@ +package arcade.patch.agent.cell; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import sim.engine.Schedule; +import ec.util.MersenneTwisterFast; +import arcade.core.agent.cell.CellState; +import arcade.core.env.location.*; +import arcade.core.util.MiniBox; +import arcade.core.util.Parameters; +import arcade.core.util.distributions.Distribution; +import arcade.core.util.distributions.NormalDistribution; +import arcade.patch.env.location.PatchLocation; +import arcade.patch.sim.PatchSimulation; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static arcade.core.ARCADETestUtilities.*; +import static arcade.patch.util.PatchEnums.State; + +public class PatchCellContainerTest { + static PatchSimulation simMock; + + static PatchLocation locationMock; + + static Parameters parametersMock; + + static MersenneTwisterFast randomMock; + + static int cellID = randomIntBetween(1, 10); + + static int cellParent = randomIntBetween(1, 10); + + static int cellPop = randomIntBetween(1, 10); + + static int cellAge = randomIntBetween(1, 1000); + + static int cellDivisions = randomIntBetween(1, 100); + + static double cellVolume = randomDoubleBetween(10, 100); + + static double cellHeight = randomDoubleBetween(10, 100); + + static double cellCriticalVolume = randomDoubleBetween(10, 100); + + static double cellCriticalHeight = randomDoubleBetween(10, 100); + + static State cellState = State.QUIESCENT; + + static PatchCellContainer baseContainer = + new PatchCellContainer( + cellID, + cellParent, + cellPop, + cellAge, + cellDivisions, + cellState, + cellVolume, + cellHeight, + cellCriticalVolume, + cellCriticalHeight); + + static class PatchCellMock extends PatchCellTissue { + PatchCellMock(PatchCellContainer container, Location location, Parameters parameters) { + super(container, location, parameters, null); + } + + @Override + public PatchCellContainer make(int newID, CellState newState, MersenneTwisterFast random) { + return new PatchCellContainer( + newID, + id, + pop, + age, + divisions, + newState, + volume, + height, + criticalVolume, + criticalHeight); + } + } + + @BeforeAll + public static void setupMocks() { + simMock = mock(PatchSimulation.class); + locationMock = mock(PatchLocation.class); + parametersMock = spy(new Parameters(new MiniBox(), null, null)); + randomMock = mock(MersenneTwisterFast.class); + } + + @Test + public void setState_proliferateWithIC_drawsFromDistribution() { + Schedule scheduleMock = mock(Schedule.class); + doReturn(cellID + 1).when(simMock).getID(); + doReturn(scheduleMock).when(simMock).getSchedule(); + doReturn(null).when(scheduleMock).scheduleRepeating(anyInt(), anyInt(), any()); + PatchCellFactory factoryMock = mock(PatchCellFactory.class); + doReturn(null).when(factoryMock).getLinks(anyInt()); + doReturn(factoryMock).when(simMock).getCellFactory(); + doReturn(0.5).when(randomMock).nextDouble(); + + MiniBox population = new MiniBox(); + double volume = 500; + population.put("CLASS", "tissue"); + population.put("COMPRESSION_TOLERANCE", 0); + population.put("(DISTRIBUTION)/NECROTIC_FRACTION", "NORMAL"); + population.put("NECROTIC_FRACTION_MU", 0.5); + population.put("NECROTIC_FRACTION_SIGMA", 0.1); + population.put("NECROTIC_FRACTION_IC", "MU"); + population.put("proliferation/SYNTHESIS_DURATION", 1); + population.put("SENESCENT_FRACTION", 0); + population.put("ENERGY_THRESHOLD", 0); + population.put("APOPTOSIS_AGE", 0); + population.put("ACCURACY", 0); + population.put("AFFINITY", 0); + population.put("DIVISION_POTENTIAL", 50); + population.put("MAX_DENSITY", 0); + population.put("CAR_ANTIGENS", 0); + population.put("SELF_TARGETS", 0); + doReturn(population).when(factoryMock).getParameters(anyInt()); + Parameters parameters = new Parameters(population, null, randomMock); + double critHeight = 10; + double critVolume = 250; + PatchCellContainer daughterContainer = + new PatchCellContainer( + cellID + 1, + cellParent, + cellPop, + cellAge, + cellDivisions, + State.UNDEFINED, + volume, + cellHeight, + critVolume, + critHeight); + PatchCell daughter = + (PatchCell) + daughterContainer.convert( + factoryMock, locationMock, randomMock, parameters); + Distribution dist = daughter.getParameters().getDistribution("NECROTIC_FRACTION"); + assertTrue(dist instanceof NormalDistribution); + } +} diff --git a/test/arcade/patch/agent/cell/PatchCellTest.java b/test/arcade/patch/agent/cell/PatchCellTest.java index 7d987d2b2..63ccb0367 100644 --- a/test/arcade/patch/agent/cell/PatchCellTest.java +++ b/test/arcade/patch/agent/cell/PatchCellTest.java @@ -150,93 +150,6 @@ public void getBindingFlag_called_returnsFlag() { assertEquals(PatchEnums.AntigenFlag.BOUND_ANTIGEN, cell.getBindingFlag()); } - @Test - public void setState_proliferateWithIC_drawsFromDistribution() { - Schedule scheduleMock = mock(Schedule.class); - doReturn(cellID + 1).when(simMock).getID(); - doReturn(scheduleMock).when(simMock).getSchedule(); - doReturn(null).when(scheduleMock).scheduleRepeating(anyInt(), anyInt(), any()); - PatchCellFactory factoryMock = mock(PatchCellFactory.class); - MiniBox popParameters = new MiniBox(); - popParameters.put("(DISTRIBUTION)/NECROTIC_FRACTION", "NORMAL"); - popParameters.put("NECROTIC_FRACTION_MU", 0.5); - popParameters.put("NECROTIC_FRACTION_SIGMA", 0.1); - doReturn(popParameters).when(factoryMock).getParameters(anyInt()); - doReturn(factoryMock).when(simMock).getCellFactory(); - doReturn(0.5).when(randomMock).nextDouble(); - - MiniBox population = new MiniBox(); - double volume = 500; - population.put("COMPRESSION_TOLERANCE", 0); - population.put("(DISTRIBUTION)/NECROTIC_FRACTION", "NORMAL"); - population.put("NECROTIC_FRACTION_MU", 0.5); - population.put("NECROTIC_FRACTION_SIGMA", 0.1); - population.put("NECROTIC_FRACTION_IC", "MU"); - population.put("proliferation/SYNTHESIS_DURATION", 1); - population.put("SENESCENT_FRACTION", 0); - population.put("ENERGY_THRESHOLD", 0); - population.put("APOPTOSIS_AGE", 0); - population.put("ACCURACY", 0); - population.put("AFFINITY", 0); - population.put("DIVISION_POTENTIAL", 50); - population.put("MAX_DENSITY", 0); - population.put("CAR_ANTIGENS", 0); - population.put("SELF_TARGETS", 0); - - Parameters parameters = new Parameters(population, null, randomMock); - double critHeight = 10; - double critVolume = 250; - - doReturn(100.).when(locationMock).getArea(); - PatchCellContainer container = - new PatchCellContainer( - cellID, - cellParent, - cellPop, - cellAge, - cellDivisions, - cellState, - volume, - cellHeight, - critVolume, - critHeight); - PatchCellContainer daughterContainer = - new PatchCellContainer( - cellID + 1, - cellParent, - cellPop, - cellAge, - cellDivisions, - State.UNDEFINED, - volume, - cellHeight, - critVolume, - critHeight); - PatchCell cell = spy(new PatchCellMock(container, locationMock, parameters)); - PatchCellContainer containerMock = mock(PatchCellContainer.class); - PatchCell daughter = spy(new PatchCellMock(daughterContainer, locationMock, parameters)); - - doReturn(daughter) - .when(containerMock) - .convert(factoryMock, locationMock, randomMock, parameters); - doReturn(containerMock) - .when(cell) - .make(anyInt(), any(State.class), any(MersenneTwisterFast.class)); - doReturn(locationMock).when(cell).selectBestLocation(simMock, randomMock); - Bag locationBag = new Bag(); - locationBag.add(cell); - doReturn(locationBag).when(gridMock).getObjectsAtLocation(locationMock); - - cell.setState(State.PROLIFERATIVE); - cell.module.step(randomMock, simMock); - cell.module.step(randomMock, simMock); - cell.module.step(randomMock, simMock); - - assertEquals(State.UNDEFINED, cell.getState()); - assertEquals(250, cell.getVolume()); - assertEquals(0.5, daughter.getParameters().getDouble("NECROTIC_FRACTION")); - } - @Test public void setState_migration_movesCell() { doReturn(0.0).when(parametersMock).getDouble(any(String.class)); From 3e0b20719897b326b73de610b374aed3ad2a02b0 Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Sun, 27 Apr 2025 21:36:24 -0700 Subject: [PATCH 10/14] formatting --- src/arcade/core/parameter.xml | 1 - src/arcade/core/sim/Series.java | 6 +-- .../distributions/DegenerateDistribution.java | 10 ++-- src/arcade/patch/agent/cell/PatchCell.java | 2 - .../patch/agent/cell/PatchCellFactory.java | 3 -- .../module/PatchModuleProliferation.java | 15 ++++-- src/arcade/patch/sim/PatchSeries.java | 8 --- test/arcade/core/sim/SeriesTest.java | 10 ++-- .../DegenerateDistributionTest.java | 1 + test_variance_only.xml | 52 ------------------- 10 files changed, 26 insertions(+), 82 deletions(-) delete mode 100644 test_variance_only.xml diff --git a/src/arcade/core/parameter.xml b/src/arcade/core/parameter.xml index ca51ca3b4..d1675a1d2 100644 --- a/src/arcade/core/parameter.xml +++ b/src/arcade/core/parameter.xml @@ -9,7 +9,6 @@ - diff --git a/src/arcade/core/sim/Series.java b/src/arcade/core/sim/Series.java index 3654a2850..413c82fa6 100644 --- a/src/arcade/core/sim/Series.java +++ b/src/arcade/core/sim/Series.java @@ -345,7 +345,7 @@ protected static void parseParameter( String defaultParameter, MiniBox values, MiniBox scales, - MiniBox ICs) { + MiniBox ics) { String value = values.contains(parameter) ? values.get(parameter) : defaultParameter; Matcher match = Pattern.compile(DISTRIBUTION_REGEX).matcher(value); @@ -361,8 +361,8 @@ protected static void parseParameter( box.put(parameter, box.getDouble(parameter) * scales.getDouble(parameter)); } } - if (ICs.contains(parameter)) { - box.put(parameter + "_IC", ICs.get(parameter)); + if (ics.contains(parameter)) { + box.put(parameter + "_IC", ics.get(parameter)); } } diff --git a/src/arcade/core/util/distributions/DegenerateDistribution.java b/src/arcade/core/util/distributions/DegenerateDistribution.java index 47c7e846d..8cae2495a 100644 --- a/src/arcade/core/util/distributions/DegenerateDistribution.java +++ b/src/arcade/core/util/distributions/DegenerateDistribution.java @@ -21,15 +21,15 @@ public DegenerateDistribution(String name, MiniBox parameters, MersenneTwisterFa /** Helper method to get the value from parameters based on IC type. */ private static double getValueFromParameters(String name, MiniBox parameters) { - String ic_type = parameters.get(name + "_IC"); - if (ic_type.equals("MU")) { + String icType = parameters.get(name + "_IC"); + if (icType.equals("MU")) { return parameters.getDouble(name + "_MU"); - } else if (ic_type.equals("MIN")) { + } else if (icType.equals("MIN")) { return parameters.getDouble(name + "_MIN"); - } else if (ic_type.equals("MAX")) { + } else if (icType.equals("MAX")) { return parameters.getDouble(name + "_MAX"); } else { - throw new IllegalArgumentException("Invalid IC: " + ic_type); + throw new IllegalArgumentException("Invalid IC: " + icType); } } diff --git a/src/arcade/patch/agent/cell/PatchCell.java b/src/arcade/patch/agent/cell/PatchCell.java index 1c583c633..84c255eed 100644 --- a/src/arcade/patch/agent/cell/PatchCell.java +++ b/src/arcade/patch/agent/cell/PatchCell.java @@ -186,10 +186,8 @@ public PatchCell( MiniBox processBox = parameters.filter("(PROCESS)"); for (String processKey : processBox.getKeys()) { - System.out.println("processKey: " + processKey); ProcessDomain domain = Domain.valueOf(processKey); String version = processBox.get(processKey); - System.out.println("version: " + version); Process process = makeProcess(domain, version); processes.put(domain, process); } diff --git a/src/arcade/patch/agent/cell/PatchCellFactory.java b/src/arcade/patch/agent/cell/PatchCellFactory.java index 471c2e657..8c053b746 100644 --- a/src/arcade/patch/agent/cell/PatchCellFactory.java +++ b/src/arcade/patch/agent/cell/PatchCellFactory.java @@ -132,8 +132,6 @@ public void createCells(Series series) { } int pop = population.getInt("CODE"); - MiniBox populationParameters = popToParameters.get(pop); - System.out.println(populationParameters.getKeys()); for (int i = 0; i < init; i++) { PatchCellContainer container = createCellForPopulation(id, pop); cells.put(id, container); @@ -154,7 +152,6 @@ public PatchCellContainer createCellForPopulation(int id, int pop) { MiniBox population = popToParameters.get(pop); Parameters parameters = new Parameters(population, null, random); double compression = parameters.getDouble("COMPRESSION_TOLERANCE"); - double volume = parameters.getDouble("CELL_VOLUME"); double height = parameters.getDouble("CELL_HEIGHT"); int age = parameters.getInt("CELL_AGE"); diff --git a/src/arcade/patch/agent/module/PatchModuleProliferation.java b/src/arcade/patch/agent/module/PatchModuleProliferation.java index 572a6524f..2763cb943 100644 --- a/src/arcade/patch/agent/module/PatchModuleProliferation.java +++ b/src/arcade/patch/agent/module/PatchModuleProliferation.java @@ -8,6 +8,7 @@ import arcade.core.util.MiniBox; import arcade.core.util.Parameters; import arcade.patch.agent.cell.PatchCell; +import arcade.patch.agent.cell.PatchCellCART; import arcade.patch.agent.process.PatchProcess; import arcade.patch.env.grid.PatchGrid; import arcade.patch.env.location.PatchLocation; @@ -73,12 +74,20 @@ public void step(MersenneTwisterFast random, Simulation sim) { // space in neighborhood to divide into. Otherwise, check if double // volume has been reached, and if so, create a new cell. if (currentHeight > maxHeight) { - cell.setState(State.QUIESCENT); - } else { + if (cell instanceof PatchCellCART) { + cell.setState(State.PAUSED); + } else { + cell.setState(State.QUIESCENT); + } } + else { PatchLocation newLocation = cell.selectBestLocation(sim, random); if (newLocation == null) { - cell.setState(State.QUIESCENT); + if (cell instanceof PatchCellCART) { + cell.setState(State.PAUSED); + } else { + cell.setState(State.QUIESCENT); + } } else if (cell.getVolume() >= targetVolume) { if (ticker > synthesisDuration) { diff --git a/src/arcade/patch/sim/PatchSeries.java b/src/arcade/patch/sim/PatchSeries.java index e5323f8bd..ff09aa71d 100644 --- a/src/arcade/patch/sim/PatchSeries.java +++ b/src/arcade/patch/sim/PatchSeries.java @@ -197,14 +197,6 @@ protected void updatePopulations( parameterScales, parameterICs); } - System.out.println(population.getKeys()); - System.out.println(population.get("SYNTHESIS_DURATION")); - System.out.println(population.getDouble("SYNTHESIS_DURATION")); - System.out.println(population.get("SYNTHESIS_DURATION_IC")); - System.out.println(population.getDouble("SYNTHESIS_DURATION_IC")); - System.out.println(population.get("(DISTRIBUTION)/proliferation/SYNTHESIS_DURATION")); - System.out.println( - population.getDouble("(DISTRIBUTION)/proliferation/SYNTHESIS_DURATION")); // Get list of links, if valid. MiniBox links = box.filterBoxByTag("LINK").getIdValForTagAtt("LINK", "weight"); for (String link : links.getKeys()) { diff --git a/test/arcade/core/sim/SeriesTest.java b/test/arcade/core/sim/SeriesTest.java index 83db9462c..adad02c57 100644 --- a/test/arcade/core/sim/SeriesTest.java +++ b/test/arcade/core/sim/SeriesTest.java @@ -701,9 +701,9 @@ public void parseParameter_withIC_putsICInBox() { MiniBox values = new MiniBox(); MiniBox scales = new MiniBox(); - MiniBox ICs = new MiniBox(); - ICs.put(parameter, "MU"); - Series.parseParameter(box, parameter, "" + defaultParameter, values, scales, ICs); + MiniBox ics = new MiniBox(); + ics.put(parameter, "MU"); + Series.parseParameter(box, parameter, "" + defaultParameter, values, scales, ics); assertEquals("MU", box.get(parameter + "_IC")); } @@ -716,9 +716,9 @@ public void parseParameter_withoutIC_doesNotPutICInBox() { MiniBox values = new MiniBox(); MiniBox scales = new MiniBox(); - MiniBox ICs = new MiniBox(); + MiniBox ics = new MiniBox(); - Series.parseParameter(box, parameter, "" + defaultParameter, values, scales, ICs); + Series.parseParameter(box, parameter, "" + defaultParameter, values, scales, ics); assertFalse(box.contains(parameter + "_IC")); } diff --git a/test/arcade/core/util/distributions/DegenerateDistributionTest.java b/test/arcade/core/util/distributions/DegenerateDistributionTest.java index 03f20eb48..5128664aa 100644 --- a/test/arcade/core/util/distributions/DegenerateDistributionTest.java +++ b/test/arcade/core/util/distributions/DegenerateDistributionTest.java @@ -7,6 +7,7 @@ import static arcade.core.ARCADETestUtilities.*; public class DegenerateDistributionTest { + private static final double EPSILON = 1E-5; private static final MersenneTwisterFast RANDOM = new MersenneTwisterFast(); diff --git a/test_variance_only.xml b/test_variance_only.xml deleted file mode 100644 index ae6ade9bf..000000000 --- a/test_variance_only.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 232766a86aca67436465f87acb9f82cf7de7ee3f Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Sun, 27 Apr 2025 21:38:30 -0700 Subject: [PATCH 11/14] spotless foramt --- src/arcade/patch/agent/module/PatchModuleProliferation.java | 4 ++-- .../core/util/distributions/DegenerateDistributionTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/arcade/patch/agent/module/PatchModuleProliferation.java b/src/arcade/patch/agent/module/PatchModuleProliferation.java index 2763cb943..e5134bf8b 100644 --- a/src/arcade/patch/agent/module/PatchModuleProliferation.java +++ b/src/arcade/patch/agent/module/PatchModuleProliferation.java @@ -78,8 +78,8 @@ public void step(MersenneTwisterFast random, Simulation sim) { cell.setState(State.PAUSED); } else { cell.setState(State.QUIESCENT); - } } - else { + } + } else { PatchLocation newLocation = cell.selectBestLocation(sim, random); if (newLocation == null) { diff --git a/test/arcade/core/util/distributions/DegenerateDistributionTest.java b/test/arcade/core/util/distributions/DegenerateDistributionTest.java index 5128664aa..d3d234dc0 100644 --- a/test/arcade/core/util/distributions/DegenerateDistributionTest.java +++ b/test/arcade/core/util/distributions/DegenerateDistributionTest.java @@ -7,7 +7,7 @@ import static arcade.core.ARCADETestUtilities.*; public class DegenerateDistributionTest { - + private static final double EPSILON = 1E-5; private static final MersenneTwisterFast RANDOM = new MersenneTwisterFast(); From 935ef23577c8ee60e0aaaa4394eb5d4e93f1a825 Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Sun, 27 Apr 2025 21:43:20 -0700 Subject: [PATCH 12/14] check style --- src/arcade/core/sim/Series.java | 2 +- .../core/util/distributions/DegenerateDistribution.java | 7 ++++++- .../util/distributions/DegenerateDistributionTest.java | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/arcade/core/sim/Series.java b/src/arcade/core/sim/Series.java index 413c82fa6..cbb09e325 100644 --- a/src/arcade/core/sim/Series.java +++ b/src/arcade/core/sim/Series.java @@ -337,7 +337,7 @@ protected static void parseParameter( * @param defaultParameter the default parameter value * @param values the map of parameter values * @param scales the map of parameter scaling - * @param ICs the map of initial condition parameters + * @param ics the map of initial condition parameters */ protected static void parseParameter( MiniBox box, diff --git a/src/arcade/core/util/distributions/DegenerateDistribution.java b/src/arcade/core/util/distributions/DegenerateDistribution.java index 8cae2495a..5ccf376e1 100644 --- a/src/arcade/core/util/distributions/DegenerateDistribution.java +++ b/src/arcade/core/util/distributions/DegenerateDistribution.java @@ -19,7 +19,12 @@ public DegenerateDistribution(String name, MiniBox parameters, MersenneTwisterFa this(getValueFromParameters(name, parameters)); } - /** Helper method to get the value from parameters based on IC type. */ + /** Helper method to get the value from parameters based on IC type. + * + * @param name the distribution parameter name + * @param parameters the distribution parameters dictionary + * @return the value of the distribution + */ private static double getValueFromParameters(String name, MiniBox parameters) { String icType = parameters.get(name + "_IC"); if (icType.equals("MU")) { diff --git a/test/arcade/core/util/distributions/DegenerateDistributionTest.java b/test/arcade/core/util/distributions/DegenerateDistributionTest.java index d3d234dc0..1845a80b4 100644 --- a/test/arcade/core/util/distributions/DegenerateDistributionTest.java +++ b/test/arcade/core/util/distributions/DegenerateDistributionTest.java @@ -9,6 +9,7 @@ public class DegenerateDistributionTest { private static final double EPSILON = 1E-5; + private static final MersenneTwisterFast RANDOM = new MersenneTwisterFast(); @Test From 746860a02dd4ed4a62f3b6d3770d444e506382cf Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Sun, 27 Apr 2025 21:45:26 -0700 Subject: [PATCH 13/14] spotless --- .../core/util/distributions/DegenerateDistribution.java | 5 +++-- .../core/util/distributions/DegenerateDistributionTest.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/arcade/core/util/distributions/DegenerateDistribution.java b/src/arcade/core/util/distributions/DegenerateDistribution.java index 5ccf376e1..a0a291fd9 100644 --- a/src/arcade/core/util/distributions/DegenerateDistribution.java +++ b/src/arcade/core/util/distributions/DegenerateDistribution.java @@ -19,8 +19,9 @@ public DegenerateDistribution(String name, MiniBox parameters, MersenneTwisterFa this(getValueFromParameters(name, parameters)); } - /** Helper method to get the value from parameters based on IC type. - * + /** + * Helper method to get the value from parameters based on IC type. + * * @param name the distribution parameter name * @param parameters the distribution parameters dictionary * @return the value of the distribution diff --git a/test/arcade/core/util/distributions/DegenerateDistributionTest.java b/test/arcade/core/util/distributions/DegenerateDistributionTest.java index 1845a80b4..b43e4df2f 100644 --- a/test/arcade/core/util/distributions/DegenerateDistributionTest.java +++ b/test/arcade/core/util/distributions/DegenerateDistributionTest.java @@ -9,7 +9,7 @@ public class DegenerateDistributionTest { private static final double EPSILON = 1E-5; - + private static final MersenneTwisterFast RANDOM = new MersenneTwisterFast(); @Test From eb36b3b1ecaf071175bb00509ca8c60e12ddc92a Mon Sep 17 00:00:00 2001 From: pohaoc2 Date: Tue, 29 Apr 2025 11:56:16 -0700 Subject: [PATCH 14/14] in addition to set MU/MIN/MAX, ic now can be set to a number --- .../distributions/DegenerateDistribution.java | 10 +- .../DegenerateDistributionTest.java | 12 ++ .../agent/cell/PatchCellFactoryTest.java | 114 +++++++++++++++++- 3 files changed, 134 insertions(+), 2 deletions(-) diff --git a/src/arcade/core/util/distributions/DegenerateDistribution.java b/src/arcade/core/util/distributions/DegenerateDistribution.java index a0a291fd9..2adb68547 100644 --- a/src/arcade/core/util/distributions/DegenerateDistribution.java +++ b/src/arcade/core/util/distributions/DegenerateDistribution.java @@ -35,7 +35,15 @@ private static double getValueFromParameters(String name, MiniBox parameters) { } else if (icType.equals("MAX")) { return parameters.getDouble(name + "_MAX"); } else { - throw new IllegalArgumentException("Invalid IC: " + icType); + try { + if (icType.contains(".")) { + return Double.parseDouble(icType); + } else { + return Integer.parseInt(icType); + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid IC value: " + icType, e); + } } } diff --git a/test/arcade/core/util/distributions/DegenerateDistributionTest.java b/test/arcade/core/util/distributions/DegenerateDistributionTest.java index b43e4df2f..1ae086288 100644 --- a/test/arcade/core/util/distributions/DegenerateDistributionTest.java +++ b/test/arcade/core/util/distributions/DegenerateDistributionTest.java @@ -35,6 +35,18 @@ public void constructor_withICMU_setsValueFromMU() { assertEquals(mu, dist.getDoubleValue(), EPSILON); } + @Test + public void constructor_withICNumber_setsValueFromNumber() { + MiniBox parameters = new MiniBox(); + String name = randomString().toUpperCase(); + String numberString = "50"; + parameters.put(name + "_IC", numberString); + + DegenerateDistribution dist = new DegenerateDistribution(name, parameters, RANDOM); + + assertEquals(50, dist.getDoubleValue(), EPSILON); + } + @Test public void constructor_withICMIN_setsValueFromMIN() { MiniBox parameters = new MiniBox(); diff --git a/test/arcade/patch/agent/cell/PatchCellFactoryTest.java b/test/arcade/patch/agent/cell/PatchCellFactoryTest.java index 844ca8175..5d1b29ae3 100644 --- a/test/arcade/patch/agent/cell/PatchCellFactoryTest.java +++ b/test/arcade/patch/agent/cell/PatchCellFactoryTest.java @@ -40,7 +40,7 @@ public void createCells_noPopulation_createsEmpty() { } @Test - public void createCells_withICParameters_createsList() { + public void createCells_withICEqualMU_createsList() { int count = randomIntBetween(1, 10); PatchSeries series = createSeries(new int[] {count}, new String[] {"COUNT"}); @@ -76,6 +76,118 @@ public void createCells_withICParameters_createsList() { } } + @Test + public void createCells_withICEqualNumber_createsList() { + int count = randomIntBetween(1, 10); + PatchSeries series = createSeries(new int[] {count}, new String[] {"COUNT"}); + + double volumeMu = randomDoubleBetween(1, 10); + double volumeSigma = randomDoubleBetween(1, 10); + double height = randomDoubleBetween(1, 10); + int age = randomIntBetween(1, 100); + double compression = randomDoubleBetween(1, 10); + String numberString = "50"; + + MiniBox parameters = new MiniBox(); + parameters.put("(DISTRIBUTION)/CELL_VOLUME", "NORMAL"); + parameters.put("CELL_VOLUME_MU", volumeMu); + parameters.put("CELL_VOLUME_SIGMA", volumeSigma); + parameters.put("CELL_VOLUME_IC", numberString); + parameters.put("CELL_HEIGHT", height); + parameters.put("CELL_AGE", age); + parameters.put("COMPRESSION_TOLERANCE", compression); + + PatchCellFactory factory = new PatchCellFactory(); + factory.popToIDs.put(1, new HashSet<>()); + factory.popToParameters.put(1, parameters); + factory.createCells(series); + + assertEquals(count, factory.cells.size()); + assertEquals(count, factory.popToIDs.get(1).size()); + + for (int i : factory.popToIDs.get(1)) { + PatchCellContainer patchCellContainer = factory.cells.get(i); + assertEquals(50, patchCellContainer.criticalVolume, EPSILON); + assertEquals(height + compression, patchCellContainer.criticalHeight, EPSILON); + assertEquals(age, patchCellContainer.age); + assertEquals(0, patchCellContainer.divisions); + } + } + + @Test + public void createCells_withICEqualMin_createsList() { + int count = randomIntBetween(1, 10); + PatchSeries series = createSeries(new int[] {count}, new String[] {"COUNT"}); + + double volumeMin = randomDoubleBetween(1, 10); + double volumeMax = randomDoubleBetween(1, 10); + double height = randomDoubleBetween(1, 10); + int age = randomIntBetween(1, 100); + double compression = randomDoubleBetween(1, 10); + + MiniBox parameters = new MiniBox(); + parameters.put("(DISTRIBUTION)/CELL_VOLUME", "UNIFORM"); + parameters.put("CELL_VOLUME_MIN", volumeMin); + parameters.put("CELL_VOLUME_MAX", volumeMax); + parameters.put("CELL_VOLUME_IC", "MIN"); + parameters.put("CELL_HEIGHT", height); + parameters.put("CELL_AGE", age); + parameters.put("COMPRESSION_TOLERANCE", compression); + + PatchCellFactory factory = new PatchCellFactory(); + factory.popToIDs.put(1, new HashSet<>()); + factory.popToParameters.put(1, parameters); + factory.createCells(series); + + assertEquals(count, factory.cells.size()); + assertEquals(count, factory.popToIDs.get(1).size()); + + for (int i : factory.popToIDs.get(1)) { + PatchCellContainer patchCellContainer = factory.cells.get(i); + assertEquals(volumeMin, patchCellContainer.criticalVolume, EPSILON); + assertEquals(height + compression, patchCellContainer.criticalHeight, EPSILON); + assertEquals(age, patchCellContainer.age); + assertEquals(0, patchCellContainer.divisions); + } + } + + @Test + public void createCells_withICNotMatchDistribution_returnsNaN() { + int count = randomIntBetween(1, 10); + PatchSeries series = createSeries(new int[] {count}, new String[] {"COUNT"}); + + double volumeMin = randomDoubleBetween(1, 10); + double volumeMax = randomDoubleBetween(1, 10); + double height = randomDoubleBetween(1, 10); + int age = randomIntBetween(1, 100); + double compression = randomDoubleBetween(1, 10); + + MiniBox parameters = new MiniBox(); + parameters.put("(DISTRIBUTION)/CELL_VOLUME", "UNIFORM"); + parameters.put("CELL_VOLUME_MIN", volumeMin); + parameters.put("CELL_VOLUME_MAX", volumeMax); + parameters.put("CELL_VOLUME_IC", "MU"); + parameters.put("CELL_HEIGHT", height); + parameters.put("CELL_AGE", age); + parameters.put("COMPRESSION_TOLERANCE", compression); + + PatchCellFactory factory = new PatchCellFactory(); + factory.popToIDs.put(1, new HashSet<>()); + factory.popToParameters.put(1, parameters); + factory.createCells(series); + + assertEquals(count, factory.cells.size()); + assertEquals(count, factory.popToIDs.get(1).size()); + + for (int i : factory.popToIDs.get(1)) { + PatchCellContainer patchCellContainer = factory.cells.get(i); + assertEquals(Double.NaN, patchCellContainer.criticalVolume, EPSILON); + assertEquals(height + compression, patchCellContainer.criticalHeight, EPSILON); + assertEquals(age, patchCellContainer.age); + assertEquals(0, patchCellContainer.divisions); + } + } + @Test public void createCells_onePopulationInitByCount_createsList() { int count = randomIntBetween(1, 10);