diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index f6ee0922c..000000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-/idea/vcs.xml
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
deleted file mode 100644
index 919ce1f1f..000000000
--- a/.idea/codeStyles/Project.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
deleted file mode 100644
index a55e7a179..000000000
--- a/.idea/codeStyles/codeStyleConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index 36a3a10cb..000000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/hamcrest_core_1_3.xml b/.idea/libraries/hamcrest_core_1_3.xml
deleted file mode 100644
index ba798e5d1..000000000
--- a/.idea/libraries/hamcrest_core_1_3.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/junit_4_13_2.xml b/.idea/libraries/junit_4_13_2.xml
deleted file mode 100644
index 8fc914f23..000000000
--- a/.idea/libraries/junit_4_13_2.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 4e85f42b0..000000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 28c2a1165..000000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
deleted file mode 100644
index e96534fb2..000000000
--- a/.idea/uiDesigner.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
- -
-
-
- -
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1ddfb..000000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/colourPalettes/pairs.xml b/colourPalettes/pairs.xml
new file mode 100644
index 000000000..6be85a5a8
--- /dev/null
+++ b/colourPalettes/pairs.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/colourPalettes/singles.xml b/colourPalettes/singles.xml
new file mode 100644
index 000000000..db42c8722
--- /dev/null
+++ b/colourPalettes/singles.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/iDynoMiCS-2.iml b/iDynoMiCS-2.iml
index b1e9b8aa0..623d5cf0e 100644
--- a/iDynoMiCS-2.iml
+++ b/iDynoMiCS-2.iml
@@ -1,183 +1,14 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
\ No newline at end of file
diff --git a/protocol/stress_test_7cc.xml b/protocol/stress_test_7cc.xml
new file mode 100644
index 000000000..aeb68b9db
--- /dev/null
+++ b/protocol/stress_test_7cc.xml
@@ -0,0 +1,270 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/agent/Agent.java b/src/agent/Agent.java
index 144222f39..98c4022f8 100644
--- a/src/agent/Agent.java
+++ b/src/agent/Agent.java
@@ -42,6 +42,13 @@ public class Agent implements AspectInterface, Settable, Instantiable
protected static int UNIQUE_ID = 0;
protected int _uid;
+ public static class AgentComparator implements java.util.Comparator {
+ @Override
+ public int compare(Agent a, Agent b) {
+ return a._uid - b._uid;
+ }
+ }
+
/**
* The compartment the agent is currently in
*/
diff --git a/src/analysis/quantitative/Raster.java b/src/analysis/quantitative/Raster.java
index 2284078fb..387fb609a 100644
--- a/src/analysis/quantitative/Raster.java
+++ b/src/analysis/quantitative/Raster.java
@@ -60,7 +60,7 @@ public class Raster {
/**
* Include additional debug and visual analysis output
*/
- private boolean _verbose = false;
+ private boolean _verbose = true;
/* raster sizes including margins (rX and rY) and actual size */
private int rX, rY;
@@ -143,6 +143,8 @@ public Raster(Compartment compartment, boolean verbose)
*/
public void rasterize( double voxelLength )
{
+ /* ensure up-to-date spatial tree */
+ _agentContainer.refreshSpatialRegistry();
/* domain dimension lengths */
double[] dimLengths = _shape.getDimensionLengths();
@@ -177,7 +179,7 @@ public void rasterize( double voxelLength )
( (Body) a.get( AspectRef.agentBody ) ).getSurfaces() )
{
if ( _shape.getCollision().
- intersect( s, v, 0.0 ) &! colliders.contains(a) )
+ intersect( v, s,0.0 ) ) //&! colliders.contains(a)
{
colliders.add(a);
break;
diff --git a/src/compartment/Compartment.java b/src/compartment/Compartment.java
index 9e76d3d1d..66deae0f8 100644
--- a/src/compartment/Compartment.java
+++ b/src/compartment/Compartment.java
@@ -278,6 +278,7 @@ else if (simulatedLengths.length != 0)
*/
Spawner spawner;
TreeMap spawners = new TreeMap();
+ List spawnerList = new LinkedList();
for ( Element e : XmlHandler.getElements( xmlElem, XmlRef.spawnNode) )
{
if ( e.hasAttribute( XmlRef.classAttribute ) )
@@ -294,9 +295,12 @@ else if (simulatedLengths.length != 0)
+ "by simulator.");
}
spawners.put(priority, spawner);
+ spawnerList.add(spawner);
}
}
- /* verify whether this always returns in correct order (it should) */
+
+
+ Collections.sort(spawnerList, new Spawner.spawnComparator());
for( Spawner s : spawners.values() )
s.spawn();
diff --git a/src/compartment/agentStaging/Spawner.java b/src/compartment/agentStaging/Spawner.java
index 27f1d1f43..0e0ce6d26 100644
--- a/src/compartment/agentStaging/Spawner.java
+++ b/src/compartment/agentStaging/Spawner.java
@@ -54,6 +54,13 @@ public abstract class Spawner implements Settable, Instantiable, AspectInterface
* the Spawner super class.
*/
protected BoundingBox _spawnDomain = new BoundingBox();
+
+ public static class spawnComparator implements java.util.Comparator {
+ @Override
+ public int compare(Spawner a, Spawner b) {
+ return a.getPriority() - b.getPriority();
+ }
+ }
public void instantiate(Element xmlElem, Settable parent)
{
diff --git a/src/dataIO/DrawMediator.java b/src/dataIO/DrawMediator.java
index 1b3c1fbec..27de66cf1 100644
--- a/src/dataIO/DrawMediator.java
+++ b/src/dataIO/DrawMediator.java
@@ -1,5 +1,6 @@
package dataIO;
+import java.util.Collections;
import java.util.List;
import agent.Agent;
@@ -202,7 +203,9 @@ else if (_shape instanceof CylindricalShape)
/* Draw all located agents. */
- for ( Agent a: _agents.getAllLocatedAgents() )
+ List sortedAgents = _agents.getAllLocatedAgents();
+ Collections.sort(sortedAgents, new Agent.AgentComparator());
+ for ( Agent a: sortedAgents )
if ( a.isAspect(BODY) )
{
List surfaces = ((Body) a.getValue(BODY)).getSurfaces();
diff --git a/src/expression/Expression.java b/src/expression/Expression.java
index 6847cb7f5..651f15440 100644
--- a/src/expression/Expression.java
+++ b/src/expression/Expression.java
@@ -361,6 +361,9 @@ else if ( ! term.isEmpty() )
/*
* Do the operator stuff here, in the same order that they appear in
* OPERATORS.
+ * FIXME: we should group operators according to PEMDAS order instead of going 1 by 1
+ * eg. if multiplication comes after division in an expression it should not be handled first!
+ * for now always use breakets to make sure evaluation order is correct.
*/
for ( String oper : OPERATORS )
for ( Integer i : eval.keySet() )
diff --git a/src/gui/GuiMenu.java b/src/gui/GuiMenu.java
index ea08abdec..f5b593152 100644
--- a/src/gui/GuiMenu.java
+++ b/src/gui/GuiMenu.java
@@ -181,6 +181,11 @@ private static JMenu interactionMenu()
menuItem.getAccessibleContext().setAccessibleDescription(
"Draw raster to file");
menu.add(menuItem);
+
+ menuItem = new JMenuItem(new GuiMenu.OccuranceMap());
+ menuItem.getAccessibleContext().setAccessibleDescription(
+ "Draw agent occurance to file");
+ menu.add(menuItem);
/*
* Draw species diagram
*/
@@ -519,6 +524,39 @@ public void actionPerformed(ActionEvent e) {
}
}
+
+ public static class OccuranceMap extends AbstractAction
+ {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3011117385035501302L;
+
+ public OccuranceMap()
+ {
+ super("OccuranceMap");
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (Helper.compartmentAvailable())
+ {
+ if ( Helper.selectSpatialCompartment() == null )
+ Log.printToScreen("No spatial compartment available.",
+ false );
+ {
+ Raster raster = new Raster(
+ Helper.selectSpatialCompartment(), true );
+ raster.rasterize( Double.valueOf(
+ Helper.obtainInput( null, "Raster scale" ) ) );
+ raster.plot( raster.occuranceMap(Helper.obtainInput( null, "filter")) , 1.0,
+ Helper.obtainInput( null, "filename") );
+ }
+ }
+ }
+
+ }
public static class Draw extends AbstractAction
{
diff --git a/src/idynomics/Global.java b/src/idynomics/Global.java
index 02e7d91be..802ed45ca 100644
--- a/src/idynomics/Global.java
+++ b/src/idynomics/Global.java
@@ -131,7 +131,7 @@ public void updateSettings()
/**
* Version description.
*/
- public static String version_description = "July 2023";
+ public static String version_description = "November 2023";
/**
* Version number of this iteration of iDynoMiCS - required by update
@@ -139,7 +139,7 @@ public void updateSettings()
*
* suggested Major.Minor.YYMMDD
*/
- public static String version_number = "2.0.230703";
+ public static String version_number = "2.0.231109";
/**
* default output location
diff --git a/src/idynomics/Simulator.java b/src/idynomics/Simulator.java
index f7c451ee8..095f4c9a7 100644
--- a/src/idynomics/Simulator.java
+++ b/src/idynomics/Simulator.java
@@ -122,7 +122,7 @@ public void instantiate(Element xmlElem, Settable parent)
String seed = XmlHandler.gatherAttribute(xmlElem, XmlRef.seed);
if ( ! Helper.isNullOrEmpty(seed) )
- ExtraMath.initialiseRandomNumberGenerator(Long.valueOf(seed));
+ ExtraMath.initialiseRandomNumberGenerator(Double.valueOf(seed).longValue());
else
seed = String.valueOf( ExtraMath.seed );
Log.out("Random seed: " + seed);
diff --git a/src/idynomics/launchable/ProtocolLaunch.java b/src/idynomics/launchable/ProtocolLaunch.java
index 2b8ad9bdd..cb66cafd4 100644
--- a/src/idynomics/launchable/ProtocolLaunch.java
+++ b/src/idynomics/launchable/ProtocolLaunch.java
@@ -5,7 +5,7 @@
public class ProtocolLaunch implements Launchable {
@Override
- public void initialize(String[] args)
+ public void initialize(String[] args)
{
for ( int i = 1; i < args.length; i++ )
{
@@ -13,6 +13,11 @@ public void initialize(String[] args)
break;
Idynomics.setupSimulator( args[i] );
Idynomics.launchSimulator();
+ try {
+ Idynomics.simThread.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
}
}
diff --git a/src/idynomics/launchable/SamplerLaunch.java b/src/idynomics/launchable/SamplerLaunch.java
index 524608d31..45304ad24 100644
--- a/src/idynomics/launchable/SamplerLaunch.java
+++ b/src/idynomics/launchable/SamplerLaunch.java
@@ -16,7 +16,7 @@ public void initialize(String[] args)
boolean customSampling = false;
int p, r;
- if ( args == null || args.length == 1 || args[1] == null )
+ if ( args == null || args.length <= 1 || args[1] == null )
{
samplingChoice = Sampler.SampleMethod.valueOf(
Helper.obtainInput( Sampler.SampleMethod.values(),
@@ -25,7 +25,7 @@ public void initialize(String[] args)
else
samplingChoice = Sampler.SampleMethod.valueOf( args[1] );
- if ( args == null || args.length == 2 || args[2] == null )
+ if ( args == null || args.length <= 2 || args[2] == null )
{
if( Idynomics.global.protocolFile == null )
{
@@ -44,7 +44,7 @@ public void initialize(String[] args)
customSampling = true;
p = 0; /* not used */
}
- else if ( args == null || args.length == 3 || args[3] == null )
+ else if ( args == null || args.length <= 3 || args[3] == null )
{
p = Integer.valueOf( Helper.obtainInput("",
"Number sampling levels/ stripes: ",true) );
@@ -53,7 +53,7 @@ else if ( args == null || args.length == 3 || args[3] == null )
p = Integer.valueOf( args[3] );
if ( samplingChoice == Sampler.SampleMethod.MORRIS &&
- ( args == null || args.length == 4 || args[4] == null ) )
+ ( args == null || args.length <= 4 || args[4] == null ) )
{
r = Integer.valueOf( Helper.obtainInput("",
"Number of repetitions: ",true) );
@@ -61,7 +61,7 @@ else if ( args == null || args.length == 3 || args[3] == null )
}
else if ( ( samplingChoice == Sampler.SampleMethod.SIMPLE ||
samplingChoice == Sampler.SampleMethod.LHC ) &&
- ( args == null || args.length == 4 || args[4] == null ) )
+ ( args == null || args.length <= 4 || args[4] == null ) )
{
boolean force_round = Helper.obtainInput("Force rounding?",true);
if( force_round )
diff --git a/src/lib/jogl/gluegen-rt-natives-windows-amd64.jar b/src/lib/jogl/gluegen-rt-natives-windows-amd64.jar
index 992a56638..2ae552be1 100644
Binary files a/src/lib/jogl/gluegen-rt-natives-windows-amd64.jar and b/src/lib/jogl/gluegen-rt-natives-windows-amd64.jar differ
diff --git a/src/lib/jogl/gluegen-rt.jar b/src/lib/jogl/gluegen-rt.jar
index 2025bf878..51cd1a882 100644
Binary files a/src/lib/jogl/gluegen-rt.jar and b/src/lib/jogl/gluegen-rt.jar differ
diff --git a/src/lib/jogl/jogl-all-natives-windows-amd64.jar b/src/lib/jogl/jogl-all-natives-windows-amd64.jar
index d8f66a16a..7b8dcff73 100644
Binary files a/src/lib/jogl/jogl-all-natives-windows-amd64.jar and b/src/lib/jogl/jogl-all-natives-windows-amd64.jar differ
diff --git a/src/lib/jogl/jogl-all.jar b/src/lib/jogl/jogl-all.jar
index dc83f61bb..ab93476ac 100644
Binary files a/src/lib/jogl/jogl-all.jar and b/src/lib/jogl/jogl-all.jar differ
diff --git a/src/processManager/library/AgentScraper.java b/src/processManager/library/AgentScraper.java
index 05ef09e94..5f45e6e11 100644
--- a/src/processManager/library/AgentScraper.java
+++ b/src/processManager/library/AgentScraper.java
@@ -3,6 +3,7 @@
import java.util.LinkedList;
import java.util.List;
+import linearAlgebra.Vector;
import org.w3c.dom.Element;
import agent.Agent;
@@ -12,6 +13,8 @@
import processManager.ProcessDeparture;
import referenceLibrary.AspectRef;
import surface.Point;
+import surface.Surface;
+import surface.Voxel;
import utility.Helper;
@@ -19,7 +22,8 @@
* Simple process that removes agents above a certain height.
* This can be used to maintain a maximum thickness for a biofilm.
*
- * Author - Tim Foster trf896@student.bham.ac.uk
+ * Author - Tim Foster trf896@student.bham.ac.uk,
+ * Bastiaan Cockx @BastiaanCockx (baco@dtu.dk), DTU, Denmark.
*
*/
@@ -29,6 +33,8 @@ public class AgentScraper extends ProcessDeparture {
private String MAX_THICKNESS = AspectRef.maxThickness;
private double _maxThickness;
+
+ private boolean _centerPointRemoval;
public void init( Element xmlElem, EnvironmentContainer environment,
AgentContainer agents, String compartmentName)
@@ -38,29 +44,48 @@ public void init( Element xmlElem, EnvironmentContainer environment,
this._maxThickness = Helper.setIfNone(
this.getDouble( MAX_THICKNESS ),
agents.getShape().getDimensionLengths()[1] );
+
+ this._centerPointRemoval = Helper.setIfNone(
+ this.getBoolean( AspectRef.centerPointRemoval ),
+ false );
}
-
+
+ /**
+ *
+ * @return List of agents to be removed
+ *
+ * TODO: currently the agent scraper always considers dimension [1] for scraping, if this is made settable by the
+ * user, the scraper can also be used for other model configurations.
+ */
@Override
public LinkedList agentsDepart()
{
LinkedList departures = new LinkedList();
-
- List allAgents = this._agents.getAllAgents();
-
- for ( Agent a : allAgents )
- {
- List points = ((Body) a.getValue(AspectRef.agentBody)).
- getPoints();
- for (Point p: points)
- {
- if (p.getPosition()[1] > this._maxThickness)
- {
- departures.add(a);
- break;
+
+ /* scrape agents based on their mass point position */
+ if(this._centerPointRemoval) {
+ List allAgents = this._agents.getAllAgents();
+
+ for (Agent a : allAgents) {
+ List points = ((Body) a.getValue(AspectRef.agentBody)).
+ getPoints();
+ for (Point p : points) {
+ if (p.getPosition()[1] > this._maxThickness) {
+ departures.add(a);
+ break;
+ }
}
}
}
-
+ /* scrape agents based on agent-region collision */
+ else {
+ double[] dimLengths = this._agents.getShape().getDimensionLengths();
+ double[] lowerBounds = Vector.zeros(dimLengths);
+ lowerBounds[1] += this._maxThickness;
+ /* note that in this specific case we don't need additional steps to confirm actual collision as voxels is
+ identical to it's bounding box and we are looking at the full depth and with of the domain */
+ departures.addAll( this._agents.treeSearch(new Voxel(lowerBounds,dimLengths),0.0) );
+ }
return departures;
}
diff --git a/src/processManager/library/Analysis.java b/src/processManager/library/Analysis.java
new file mode 100644
index 000000000..046f03b99
--- /dev/null
+++ b/src/processManager/library/Analysis.java
@@ -0,0 +1,110 @@
+package processManager.library;
+
+import compartment.AgentContainer;
+import compartment.EnvironmentContainer;
+import org.w3c.dom.Element;
+
+import analysis.FilteredTable;
+import analysis.quantitative.Raster;
+import dataIO.CsvExport;
+import dataIO.Log;
+import dataIO.Log.Tier;
+import referenceLibrary.AspectRef;
+import utility.Helper;
+import idynomics.Idynomics;
+import linearAlgebra.Vector;
+import processManager.ProcessManager;
+
+/**
+ *
+ * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark.
+ *
+ */
+public class Analysis extends ProcessManager {
+
+
+ public static String FILE_PREFIX = AspectRef.filePrefix;
+
+ /**
+ * The CSV exporter.
+ */
+ protected CsvExport _csvExport = new CsvExport();
+
+ /**
+ * The prefix for the file output path.
+ */
+ protected String _prefix;
+
+ protected String[] header = new String[]{
+ "#",
+ "time"
+ };
+
+
+ /* ***********************************************************************
+ * CONSTRUCTORS
+ * **********************************************************************/
+
+ @Override
+ public void init(Element xmlElem, EnvironmentContainer environment,
+ AgentContainer agents, String compartmentName)
+ {
+ super.init(xmlElem, environment, agents, compartmentName);
+
+ this._prefix = this.getString(FILE_PREFIX);
+
+ /* Initiate new file. */
+ this._csvExport.createCustomFile(this._prefix);
+
+ this._csvExport.writeLine( getHeader() + Raster.getHeader() );
+
+ }
+
+
+ /* ***********************************************************************
+ * STEPPING
+ * **********************************************************************/
+
+ @Override
+ protected void internalStep()
+ {
+ Raster raster = new Raster( this._agents );
+
+ raster.rasterize( this.getDouble( AspectRef.rasterScale ) );
+
+ double[] time = new double[] {
+ Idynomics.simulator.timer.getCurrentIteration(),
+ this.getTimeForNextStep() };
+
+ String line = Vector.toString( time ) + "," + raster.toString();
+ this._csvExport.writeLine( line );
+
+ /* output table summary to log/console */
+ Log.out(Tier.EXPRESSIVE, "Structural analysis:\n" +
+ getHeader() + "," + Raster.getHeader() + "\n" + line );
+ }
+
+
+ public String getHeader()
+ {
+
+ StringBuilder builder = new StringBuilder();
+ for ( int i = 0; i < header.length; i++)
+ {
+ builder.append( header[i] );
+ builder.append( Vector.DELIMITER );
+ }
+ return builder.toString();
+ }
+
+ /**
+ * TODO this pm needs a post run call to properly close the file,
+ * alternatively we could open and close the file each time step.
+ * Doing neither should still release the file after the program is
+ * closed, but this is not a correct way of handling this.
+ */
+ protected void postRun()
+ {
+ this._csvExport.closeFile();
+ }
+ }
diff --git a/src/processManager/library/AnalysisTrait.java b/src/processManager/library/AnalysisTrait.java
new file mode 100644
index 000000000..e7bf8ca9b
--- /dev/null
+++ b/src/processManager/library/AnalysisTrait.java
@@ -0,0 +1,198 @@
+package processManager.library;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+
+import compartment.AgentContainer;
+import compartment.EnvironmentContainer;
+import org.w3c.dom.Element;
+
+
+import analysis.quantitative.Raster;
+import dataIO.CsvExport;
+import dataIO.Log;
+import dataIO.Log.Tier;
+import referenceLibrary.AspectRef;
+import utility.Helper;
+import idynomics.Idynomics;
+import linearAlgebra.Vector;
+import processManager.ProcessManager;
+
+/**
+ * FIXME AB and BA are inverted?
+ * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark.
+ *
+ */
+public class AnalysisTrait extends ProcessManager {
+
+ public static String FILE_PREFIX = AspectRef.filePrefix;
+
+ /**
+ * The CSV exporter.
+ */
+ protected CsvExport _csvExport = new CsvExport();
+
+ /**
+ * The prefix for the file output path.
+ */
+ protected String _prefix;
+
+ protected String[] filters;
+
+ protected int[] colocalizationSteps;
+
+ protected String[] header = new String[]{
+ "#",
+ "time"
+ };
+
+
+ /* ***********************************************************************
+ * CONSTRUCTORS
+ * **********************************************************************/
+
+ @Override
+ public void init(Element xmlElem, EnvironmentContainer environment,
+ AgentContainer agents, String compartmentName)
+ {
+ super.init(xmlElem, environment, agents, compartmentName);
+
+ this._prefix = this.getString(FILE_PREFIX);
+
+ /* Initiate new file. */
+ this._csvExport.createCustomFile(this._prefix);
+
+ filters = this.getStringA( AspectRef.filterSet );
+
+ String steps = Helper.setIfNone(
+ this.getString( AspectRef.colocalizationSteps ) , "1" );
+ this.colocalizationSteps = Vector.intFromString( steps );
+
+ this._csvExport.writeLine( getHeader() );
+ }
+
+
+ /* ***********************************************************************
+ * STEPPING
+ * **********************************************************************/
+
+ @Override
+ protected void internalStep()
+ {
+ Raster raster = new Raster( this._agents );
+
+ raster.rasterize( this.getDouble( AspectRef.rasterScale ) );
+
+ double[] time = new double[] {
+ Idynomics.simulator.timer.getCurrentIteration(),
+ this.getTimeForNextStep() };
+
+ StringBuilder builder = new StringBuilder();
+ builder.append( Vector.toString( time ) );
+ String line = "";
+
+ for ( int i = 0; i < this.filters.length; i++)
+ {
+ builder.append(Vector.DELIMITER);
+ builder.append( raster.averageDiffusionDistance(filters[i]));
+ }
+
+ LinkedList combList = combinations( filters );
+ for ( int i = 0; i < combList.size(); i++)
+ {
+ int[] distAB = raster.distanceVector(
+ combList.get(i)[0], combList.get(i)[1]);
+ int[] distBA = raster.distanceVector(
+ combList.get(i)[1], combList.get(i)[0]);
+
+ if( distAB != null ) {
+ builder.append(Vector.DELIMITER);
+ builder.append(raster.averageDist(distAB));
+ }
+ else
+ {
+ builder.append(Vector.DELIMITER);
+ builder.append(Double.NaN);
+ }
+
+ if( distBA != null ) {
+ builder.append( Vector.DELIMITER );
+ builder.append( raster.averageDist( distBA ) );
+ }
+ else
+ {
+ builder.append(Vector.DELIMITER);
+ builder.append(Double.NaN);
+ }
+
+ builder.append( Vector.DELIMITER );
+ for ( int j = 0; j < colocalizationSteps.length; j++)
+ builder.append(
+ (( distBA != null && distAB != null) ?
+ Vector.toString( raster.colocalization(
+ distAB, distBA, colocalizationSteps[j] ) )
+ : Double.NaN+Vector.DELIMITER+Double.NaN) +
+ (j < colocalizationSteps.length-1 ? Vector.DELIMITER : "" ) );
+
+ line = builder.toString().substring( 0, builder.length()-1 );
+ }
+
+
+ this._csvExport.writeLine( line );
+
+ /* output table summary to log/console */
+ Log.out(Tier.EXPRESSIVE, "Trait analysis:\n" +
+ getHeader() + "\n" + builder.toString() );
+ }
+
+ public LinkedList combinations( String[] input )
+ {
+ LinkedList out = new LinkedList();
+ for ( int i = 1; i < input.length; i++)
+ out.add( new String[] { input[0], input[i] } );
+ if( input.length > 2 )
+ out.addAll( combinations(
+ Arrays.copyOfRange( input, 1, input.length ) ) );
+ return out;
+ }
+
+ public String getHeader()
+ {
+
+ StringBuilder builder = new StringBuilder();
+ for ( int i = 0; i < header.length; i++)
+ {
+ builder.append( header[i] );
+ builder.append( Vector.DELIMITER );
+ }
+ for ( int i = 0; i < this.filters.length; i++)
+ {
+ builder.append( "average diff " + filters[i] );
+ builder.append(Vector.DELIMITER);
+ }
+ LinkedList combList = combinations( filters );
+ for ( int i = 0; i < combList.size(); i++)
+ {
+ builder.append( "average codist AB " + combList.get(i)[0] + " " + combList.get(i)[1] +
+ ", BA,");
+ for ( int j = 0; j < colocalizationSteps.length; j++)
+ {
+ builder.append( colocalizationSteps[j] + "AB, " +
+ colocalizationSteps[j] + "BA," );
+ }
+ }
+ String comb = builder.toString().substring( 0, builder.length()-1 );
+ return comb;
+ }
+
+ /**
+ * TODO this pm needs a post run call to properly close the file,
+ * alternatively we could open and close the file each time step.
+ * Doing neither should still release the file after the program is
+ * closed, but this is not a correct way of handling this.
+ */
+ protected void postRun()
+ {
+ this._csvExport.closeFile();
+ }
+}
diff --git a/src/processManager/library/GraphicalOutput.java b/src/processManager/library/GraphicalOutput.java
index 254b32dad..b079bd90a 100644
--- a/src/processManager/library/GraphicalOutput.java
+++ b/src/processManager/library/GraphicalOutput.java
@@ -2,10 +2,7 @@
import static grid.ArrayType.CONCN;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
import idynomics.Idynomics;
import org.w3c.dom.Element;
@@ -261,8 +258,10 @@ else if (_shape instanceof CylindricalShape)
/*
* ^^
*/
-
- for ( Agent a: _agents.getAllLocatedAgents() )
+ List sortedAgents = this._agents.getAllLocatedAgents();
+ Collections.sort(sortedAgents, new Agent.AgentComparator());
+
+ for ( Agent a: sortedAgents )
if ( a.isAspect(BODY) )
{
List surfaces = ((Body) a.getValue(BODY)).getSurfaces();
diff --git a/src/referenceLibrary/AspectRef.java b/src/referenceLibrary/AspectRef.java
index 10aba7670..741c37fd4 100644
--- a/src/referenceLibrary/AspectRef.java
+++ b/src/referenceLibrary/AspectRef.java
@@ -15,8 +15,7 @@
public class AspectRef
{
-
- public static String[] getAllOptions()
+ public static String[] getAllOptions()
{
Field[] fields = AspectRef.class.getFields();
String[] options = new String[fields.length];
@@ -560,7 +559,21 @@ public static String[] getAllOptions()
*/
public static final String regionDepth = "regionDepth";
-
+ /**
+ * specify target compartment by name.
+ */
+ public static final String compartmentName = "compartmentName";
+
+ /**
+ * Array of filters for spatial analysis
+ */
+ public static final String filterSet = "filterSet";
+
+ /**
+ * set of distances to do colocalization analysis for.
+ */
+ public static final String colocalizationSteps = "colocalizationSteps";
+
/**
* The name of a dimension (X, Y or Z)
*/
@@ -707,4 +720,6 @@ public static String[] getAllOptions()
public static String youngsModulus = "youngsModulus";
public static String poissonRatio = "poissonRatio";
+
+ public static String centerPointRemoval = "centerPointRemoval";
}
diff --git a/src/referenceLibrary/ClassRef.java b/src/referenceLibrary/ClassRef.java
index 9d371f6e2..5af99784b 100644
--- a/src/referenceLibrary/ClassRef.java
+++ b/src/referenceLibrary/ClassRef.java
@@ -491,6 +491,12 @@ public static String path(String name)
*/
public final static String agentsArriveInChemostat =
processManager.library.AgentsArriveInChemostat.class.getName();
+
+ public final static String analysis =
+ processManager.library.Analysis.class.getName();
+
+ public final static String analysisTrait =
+ processManager.library.AnalysisTrait.class.getName();
/* ************************************************************************
* IdynoMiCS main classes
diff --git a/src/render/AgentMediator.java b/src/render/AgentMediator.java
index 785db4d86..9586ceb91 100644
--- a/src/render/AgentMediator.java
+++ b/src/render/AgentMediator.java
@@ -5,12 +5,14 @@
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Collections;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.glu.GLUquadric;
import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.Vec3f;
import com.jogamp.opengl.util.gl2.GLUT;
import agent.Agent;
@@ -193,7 +195,7 @@ public void colStep()
/**
* assign agent container via the constructor
- * @param agents
+ * @param c: Compartment to be rendered.
*/
public AgentMediator(Compartment c)
{
@@ -267,9 +269,11 @@ public void draw(GLAutoDrawable drawable) {
* when we want to disable depth test we draw the domain here
*/
// draw(_shape);
-
+
+ List sortedAgents = this._agents.getAllLocatedAgents();
+ Collections.sort(sortedAgents, new Agent.AgentComparator());
/* get the surfaces from the agents */
- for ( Agent a : this._agents.getAllLocatedAgents() )
+ for ( Agent a : sortedAgents)
{
/* cycle through the agent surfaces */
@@ -578,10 +582,10 @@ private void glRotated(double[] direc){
Quaternion quat = new Quaternion();
/* this will create a quaternion, so that we rotate from looking
* along the Z-axis (which is the default orientation) */
- quat.setLookAt(Vector.toFloat(direc), _orthoZ, _orthoX, _orthoY, _orthoZ);
+ quat.setLookAt( new Vec3f(Vector.toFloat(direc)), new Vec3f(_orthoZ), new Vec3f(_orthoX), new Vec3f(_orthoY), new Vec3f(_orthoZ));
/* transform the quaternion into a rotation matrix and apply it */
//TODO: is there a way to make openGL use the quaternion directly?
- _gl.glMultMatrixf(quat.toMatrix(_rotTemp, 0), 0);
+ _gl.glMultMatrixf(quat.toMatrix(_rotTemp), 0);
}
private void drawVoxel(Shape shape, int[] coord)
diff --git a/src/render/Render.java b/src/render/Render.java
index 022d144cd..0c4e43ff5 100644
--- a/src/render/Render.java
+++ b/src/render/Render.java
@@ -133,7 +133,7 @@ public class Render implements GLEventListener, Runnable {
private boolean _dispFps = false;
private Font font = new Font("consolas", Font.PLAIN, 10);
- private TextRenderer textRenderer = new TextRenderer(font);
+
/*
* screendump
*/
@@ -171,6 +171,7 @@ public void display(GLAutoDrawable drawable) {
}
if ( this._dispFps )
{
+ TextRenderer textRenderer = new TextRenderer(font);
textRenderer.setColor(Color.YELLOW);
textRenderer.setSmoothing(true);
gl.glLoadIdentity();
diff --git a/src/utility/Helper.java b/src/utility/Helper.java
index 812748a40..a916cc955 100644
--- a/src/utility/Helper.java
+++ b/src/utility/Helper.java
@@ -296,7 +296,7 @@ else if ( input == null )
public static boolean confirmation(String input)
{
for ( String s : confirmations )
- if ( s == input )
+ if ( input.equals(s) )
return true;
return false;
}
@@ -309,7 +309,7 @@ public static boolean confirmation(String input)
public static boolean rejection(String input)
{
for ( String s : rejections )
- if ( s == input )
+ if ( input.equals(s) )
return true;
return false;
}
@@ -776,7 +776,7 @@ public static boolean expressionParseable(String strParse)
new Expression( strParse );
}
catch (NumberFormatException | StringIndexOutOfBoundsException
- | NullPointerException f)
+ | NullPointerException | StackOverflowError f)
{
return false;
}
@@ -794,7 +794,7 @@ public static boolean formatParseable(String strParse)
new Expression( strParse ).format( Idynomics.unitSystem );
}
catch (NumberFormatException | StringIndexOutOfBoundsException
- | NullPointerException f)
+ | NullPointerException | StackOverflowError f)
{
return false;
}