Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev merge: connectivity and defaults for eggTemp, mortSal #6

Merged
merged 4 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions biotracker/Arrival.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,34 @@
* @author sa01ta
*/
public class Arrival {
private final int sourceLocation;
private final int arrivalLocation;
private final double arrivalTime;
private final String sourceSiteID;
private final String arrivalSiteID;
private final int arrivalStatus;
private final double arrivalDepth;
private final double arrivalDensity;

public Arrival(int sourceLocation, int arrivalLocation, double arrivalTime, double arrivalDensity) {
this.sourceLocation = sourceLocation;
this.arrivalLocation = arrivalLocation;
this.arrivalTime = arrivalTime;
public Arrival(String sourceSiteID, String arrivalSiteID, int arrivalStatus, double arrivalDepth, double arrivalDensity) {
this.sourceSiteID = sourceSiteID;
this.arrivalSiteID = arrivalSiteID;
this.arrivalStatus = arrivalStatus;
this.arrivalDepth = arrivalDepth;
this.arrivalDensity = arrivalDensity;
}

public int getSourceLocation() {
return this.sourceLocation;
public String getSourceSiteID() {
return this.sourceSiteID;
}

public int getArrivalLocation() {
return this.arrivalLocation;
public String getArrivalSiteID() {
return this.arrivalSiteID;
}

public double getArrivalTime() {
return this.arrivalTime;
public int getArrivalStatus() {
return this.arrivalStatus;
}

public double getArrivalDepth() {
return this.arrivalDepth;
}

public double getArrivalDensity() {
Expand Down
25 changes: 0 additions & 25 deletions biotracker/IOUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -994,31 +994,6 @@ public static void particleLocsToNetcdfFile() {
}


public static void arrivalToFile(Particle p, ISO_datestr currentDate, double currentTime, String filename, boolean append) {
try {
// Create file
FileWriter fstream = new FileWriter(filename, append);
PrintWriter out = new PrintWriter(fstream);
out.printf("%d,%s,%.2f,%s,%s,%.2f,%s,%f,%f\n",
p.getID(),
p.getStartDate().getDateStr(),
p.getStartTime(),
p.getStartID(),
currentDate.getDateStr(),
currentTime,
p.getLastArrival(),
p.getAge(),
p.getDensity()
);

//Close the output stream
out.close();
} catch (Exception e) {//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}


/**
* Print (append) single particle location to file
*/
Expand Down
29 changes: 9 additions & 20 deletions biotracker/ParallelParticleMover.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,11 @@ public static void move(Particle part, double elapsedHours, int hour, int step,

// Get local salinity, temperature
if (!rp.readHydroVelocityOnly) {
if (rp.fixDepth) {
if (rp.needS) {
localSalinity = hf.getAvgFromTrinodes(m, part.getLocation(), part.getDepthLayer(), part.getElem(), hour, "salinity", rp);
}
if (rp.needT) {
localTemperature = hf.getAvgFromTrinodes(m, part.getLocation(), part.getDepthLayer(), part.getElem(), hour, "temp", rp);
}
} else {
if (rp.needS) {
localSalinity = hf.getValueAtDepth(m, part, part.getLocation(), part.getDepth(), hour, "salinity", rp, nearestLayers);
}
if (rp.needT) {
localTemperature = hf.getValueAtDepth(m, part, part.getLocation(), part.getDepth(), hour, "temp", rp, nearestLayers);
}
if (rp.needS) {
localSalinity = hf.getValueAtDepth(m, part, part.getLocation(), part.getDepth(), hour, "salinity", rp, nearestLayers);
}
if (rp.needT) {
localTemperature = hf.getValueAtDepth(m, part, part.getLocation(), part.getDepth(), hour, "temp", rp, nearestLayers);
}
}

Expand Down Expand Up @@ -267,18 +258,16 @@ public static void move(Particle part, double elapsedHours, int hour, int step,
}

// **************** if able to settle, is it close to a possible settlement location? ******************************
if (part.isInfectious() || rp.connectImmature) {
if (rp.recordConnectivity && (part.isInfectious() || rp.connectImmature)) {
for (HabitatSite site : habitatEnd) {
double dist = Particle.distanceEuclid2(part.getLocation()[0], part.getLocation()[1],
site.getLocation()[0], site.getLocation()[1], rp.coordOS);
if (dist < rp.connectivityThresh && !part.hasSettledThisHour()) { // TODO: I think this doesn't make sense? Necessary for part.setLastArrival(site.getID()) for connectivity though.
if (rp.endOnArrival && part.isInfectious()) {
if (dist < rp.connectivityThresh) {
part.addArrival(new Arrival(part.getStartID(), site.getID(), part.getStatus(), part.getDepth(), part.getDensity() * subStepDt / rp.dt));
if (rp.endOnArrival) {
part.setArrived(true);
part.setStatus(3);
}
part.setSettledThisHour(true);
part.setLastArrival(site.getID());
break;
}
}
}
Expand Down
35 changes: 9 additions & 26 deletions biotracker/Particle.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,18 @@ public class Particle {
private boolean arrived = false;
private boolean viable = false;
private boolean free = false;
private boolean settledThisHour = false;
private boolean boundaryExit = false;

private String species = "sealice";

private String lastArrival = "0";

private double xTotal = 0;
private double yTotal = 0;
private double xyTotal = 0;
private double zTotal = 0;

// A list to store data on the arrivals made by each particle.
// If rp.endOnArrival=true, this will contain a maximum of one element.
// --- Not presently used ---
private List<Arrival> arrivals;
private ArrayList<Arrival> arrivals = new ArrayList<>();

public Particle(double xstart, double ystart, double startDepth, String startSiteID, int startIndex, int id, double mortalityRate,
ISO_datestr startDate, double startTime, boolean coordOS, String species) {
Expand Down Expand Up @@ -129,13 +125,16 @@ public String toString() {
return this.getID() + " " + Arrays.toString(this.xy);
}

// Not presently used
public void reportArrival(int sourceLocation, int arrivalLocation, double arrivalTime, double arrivalDensity) {
arrivals.add(new Arrival(sourceLocation, arrivalLocation, arrivalTime, arrivalDensity));
public ArrayList<Arrival> getArrivals() {
return this.arrivals;
}

public List<Arrival> getArrivals() {
return this.arrivals;
public void addArrival(Arrival arrival) {
this.arrivals.add(arrival);
}

public void clearArrivals() {
this.arrivals.clear();
}

public void setReleaseTime(double releaseTime) {
Expand Down Expand Up @@ -370,18 +369,6 @@ public void setArrived(boolean arrived) {
this.arrived = arrived;
}

public void setLastArrival(String loc) {
this.lastArrival = loc;
}

public String getLastArrival() {
return this.lastArrival;
}

public void setSettledThisHour(boolean settled) {
this.settledThisHour = settled;
}

public void setFree(boolean free) {
this.free = free;
}
Expand All @@ -398,10 +385,6 @@ public boolean hasArrived() {
return this.arrived;
}

public boolean hasSettledThisHour() {
return this.settledThisHour;
}

public boolean isFree() {
return this.free;
}
Expand Down
74 changes: 29 additions & 45 deletions biotracker/Particle_track.java
Original file line number Diff line number Diff line change
Expand Up @@ -358,45 +358,38 @@ public static void main(String[] args) throws Exception {
IOUtils.particlesToRestartFile(particles, currentHour, "locations_" + today + ".csv", true, rp, 1); // rp.nparts * rp.numberOfDays * 10
}


double elapsedHourRemainder = Math.round((elapsedHours % 1) * 100.0) / 100.0;
if (elapsedHourRemainder == 1 || elapsedHourRemainder == 0) {
// It's the end of an hour, so if particles are allowed to infect more than once, reactivate them
for (Particle part : particles) {
if (part.hasSettledThisHour()) {
if (part.isInfectious()) { // copepodids
// Save arrival
if (rp.recordArrivals) {
IOUtils.arrivalToFile(part, currentIsoDate, currentHour, "arrivals_" + today + ".csv", true);
}
// Add arrival to connectivity file
int destIndex = siteEndNames.indexOf(part.getLastArrival());
double pDepth = part.getDepth();
if (pDepth >= rp.connectDepth1_min && pDepth <= rp.connectDepth1_max) {
connectivity[part.getStartIndex()][destIndex] += (float) part.getDensity();
}
if (rp.recordConnectivityDepth2 && pDepth >= rp.connectDepth2_min && pDepth <= rp.connectDepth2_max) {
connectivityDepth2[part.getStartIndex()][destIndex] += (float) part.getDensity();
}
} else if (rp.connectImmature & part.getStatus()==1) { // nauplii
// Add arrival to connectivity file
int destIndex = siteEndNames.indexOf(part.getLastArrival());
double pDepth = part.getDepth();
if (pDepth >= rp.connectDepth1_min && pDepth <= rp.connectDepth1_max) {
connectivityImmature[part.getStartIndex()][destIndex] += (float) part.getDensity();
}
if (rp.recordConnectivityDepth2 && pDepth >= rp.connectDepth2_min && pDepth <= rp.connectDepth2_max) {
connectivityImmatureDepth2[part.getStartIndex()][destIndex] += (float) part.getDensity();
// update connectivity
if (rp.recordConnectivity) {
for (Particle particle : particles) {
if (particle.getArrivals() != null) {
for (Arrival arrival : particle.getArrivals()) {
int destIndex = siteEndNames.indexOf(arrival.getArrivalSiteID());
if (arrival.getArrivalStatus() == 2) { // copepodids
if (arrival.getArrivalDepth() >= rp.connectDepth1_min &&
arrival.getArrivalDepth() <= rp.connectDepth1_max) {
connectivity[particle.getStartIndex()][destIndex] += (float) arrival.getArrivalDensity();
}
if (rp.recordConnectivityDepth2 &&
arrival.getArrivalDepth() >= rp.connectDepth2_min &&
arrival.getArrivalDepth() <= rp.connectDepth2_max) {
connectivityDepth2[particle.getStartIndex()][destIndex] += (float) arrival.getArrivalDensity();
}
} else if (rp.connectImmature && arrival.getArrivalStatus() == 1) {
if (arrival.getArrivalDepth() >= rp.connectDepth1_min &&
arrival.getArrivalDepth() <= rp.connectDepth1_max) {
connectivityImmature[particle.getStartIndex()][destIndex] += (float) arrival.getArrivalDensity();
}
if (rp.recordConnectivityDepth2 &&
arrival.getArrivalDepth() >= rp.connectDepth2_min &&
arrival.getArrivalDepth() <= rp.connectDepth2_max) {
connectivityImmatureDepth2[particle.getStartIndex()][destIndex] += (float) arrival.getArrivalDensity();
}
}
}

// Reset ability to settle
part.setSettledThisHour(false);
}
}
}


// Hourly updates to pstep arrays
if (rp.recordPsteps) {
IOUtils.pstepsUpdater(particles, rp, pstepsMature, pstepsImmature, rp.dt);
Expand Down Expand Up @@ -431,6 +424,9 @@ public static void main(String[] args) throws Exception {
connectivityImmatureDepth2 = new float[habitat.size()][habitatEnd.size()];
}
}
for (Particle particle : particles) {
particle.clearArrivals();
}
}

if (rp.recordVertDistr) {
Expand Down Expand Up @@ -916,18 +912,6 @@ public static int[] particleCountStatus(List<Particle> parts, int[] previousStat
}


// calculate a connectivity matrix detailing the
public static double[][] connectFromParticleArrivals(List<Particle> particles, int nStartLocs, int nEndLocs, int npartsPerSite) {
double[][] connectMatrix = new double[nStartLocs][nEndLocs];
for (Particle part : particles) {
for (Arrival arrival : part.getArrivals()) {
connectMatrix[arrival.getSourceLocation()][arrival.getArrivalLocation()] += arrival.getArrivalDensity() / npartsPerSite;
}
}
return connectMatrix;
}


public static int[] nonZeroVals(int[] A) {
int count = 0;
for (int j : A) {
Expand Down
8 changes: 4 additions & 4 deletions biotracker/RunProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,13 @@ public RunProperties(String filename) {
case "constant" -> "28.2";
// Linear model comes from data in Kragesteen 2023 Table 1
// eggs_d = b[0] + b[1]*temperature
case "linear" -> "9.835,4.579";
case "linear" -> "8.27,3.79";
// Norwegian model uses Stien et al 2005
// eggs_d = b[0] * (temperature + b[1])^2
case "quadratic" -> "0.17,4.28";
case "quadratic" -> "0.109,8.54";
// Logistic model comes from data in Kragesteen 2023 Table 1
// eggs_d = b[0]/(1 + exp(-b[1] * (temperature - b[2]))) + b[3]
case "logistic" -> "85.94,0.4696,8.193,7.649";
case "logistic" -> "65.5,0.550,8.49,10.51";
default -> "28.2";
};
String eggTemp_b_Str = properties.getProperty("eggTemp_b", eggTemp_defaults);
Expand All @@ -233,7 +233,7 @@ public RunProperties(String filename) {
case "quadratic" -> "0.0011,1.1239,-0.07";
// estimated logistic fit to Bricknell et al. 2006 Table 1
// mort_h = b[0]/(1 + exp(-b[1] * (salinity - b[2]))) + b[3]
case "logistic" -> "0.9087,-0.6457,13.31,0.05071";
case "logistic" -> "0.941,-0.594,13.5,0.0205";
default -> "0.01";
};
String mortSal_b_Str = properties.getProperty("mortSal_b", mortSal_defaults);
Expand Down