diff --git a/data/input/northeastamerica/fishRIOBasin_Sapidissima_Rjava.xml b/data/input/northeastamerica/fishRIOBasin_Sapidissima_Rjava.xml index 177e4b4fd382c5953d1e1f31ba78c3474ed47433..2678c280162c0308b89d371e7ea114427ca5eacf 100644 --- a/data/input/northeastamerica/fishRIOBasin_Sapidissima_Rjava.xml +++ b/data/input/northeastamerica/fishRIOBasin_Sapidissima_Rjava.xml @@ -288,7 +288,14 @@ <analysisSeason>SPRING</analysisSeason> <memorySize>30</memorySize> </species.AnalyseSpawnerFeatures> - + + <species.AnalyseFishDistribution> + <synchronisationMode>ASYNCHRONOUS</synchronisationMode> + <analysisSeason>SPRING</analysisSeason> + <memorySize>30</memorySize> + <minimumRecruitsForPopulatedBasin>50</minimumRecruitsForPopulatedBasin> + </species.AnalyseFishDistribution> + <species.ReproduceAndSurviveAfterReproductionWithDiagnose> <synchronisationMode>ASYNCHRONOUS</synchronisationMode> <reproductionSeason>SPRING</reproductionSeason> @@ -311,11 +318,6 @@ <displayFluxesOnConsole>false</displayFluxesOnConsole> </species.ReproduceAndSurviveAfterReproductionWithDiagnose> - <species.AnalyseFishDistribution> - <synchronisationMode>ASYNCHRONOUS</synchronisationMode> - <analysisSeason>SPRING</analysisSeason> - <minimumRecruitsForPopulatedBasin>50</minimumRecruitsForPopulatedBasin> - </species.AnalyseFishDistribution> <species.MigrateFromRiverToInshore> <synchronisationMode>ASYNCHRONOUS</synchronisationMode> @@ -340,11 +342,13 @@ </processesEachStep> <processesAtEnd> - <species.WriteBiomassFluxes> + <species.AnalyseLikelihoodOfPresence> <synchronisationMode>ASYNCHRONOUS</synchronisationMode> - <exportSeason>SPRING</exportSeason> - <fileNameOutput>biomassFluxes</fileNameOutput> - </species.WriteBiomassFluxes> + <presenceFileName>data/input/northeastamerica/nea_presence.csv</presenceFileName> + <period>obs_1900_1950</period> + <minimumRecruitsForPopulatedBasin>50</minimumRecruitsForPopulatedBasin> + <epsilon>0.001</epsilon> + </species.AnalyseLikelihoodOfPresence> <species.IdentifyPopulation> <synchronisationMode>ASYNCHRONOUS</synchronisationMode> diff --git a/src/main/java/miscellaneous/EasyRun.java b/src/main/java/miscellaneous/EasyRun.java index 2993abe42980a0ab5807bf23603179f67000d4fc..72bc04ca5fcd4b341cca391256bd7421eafda5b4 100644 --- a/src/main/java/miscellaneous/EasyRun.java +++ b/src/main/java/miscellaneous/EasyRun.java @@ -16,7 +16,6 @@ */ package miscellaneous; -import java.util.Arrays; import java.util.List; import fr.cemagref.simaqualife.extensions.pilot.BatchRunner; @@ -37,8 +36,8 @@ public class EasyRun { pilot.load(); // update the simulation parameters - ReflectUtils.setFieldValueFromPath(pilot.getAquaticWorld().getAquaNismsGroupsList().get(0), - "processes.processesAtEnd.0.fileNameOutput", outputfilename); + // ReflectUtils.setFieldValueFromPath(pilot.getAquaticWorld().getAquaNismsGroupsList().get(0), + // "processes.processesAtEnd.0.fileNameOutput", outputfilename); for (int i = 0; i < paramNames.length; i++) { ReflectUtils.setFieldValueFromPath(pilot.getAquaticWorld().getAquaNismsGroupsList().get(0), paramNames[i], paramValues[i]); @@ -75,36 +74,49 @@ public class EasyRun { } + public static double getSingleValueFromAquanismGroupProcess(String targetPath) throws Exception { + return (double) ReflectUtils.getValueFromPath(pilot.getAquaticWorld().getAquaNismsGroupsList().get(0), targetPath); + } + + public static void main(String[] args) throws Exception { - String[] batchArguments = ("-simDuration 100 -simBegin 1 -timeStepDuration 1 -RNGStatusIndex 1 " + String[] batchArguments = ("-simDuration 150 -simBegin 1 -timeStepDuration 1 -RNGStatusIndex 1 " + "-groups data/input/northeastamerica/fishRIOBasin_Sapidissima_Rjava.xml " + "-env data/input/northeastamerica/RIOBNneaBasins_Rjava.xml " + "-observers data/input/northeastamerica/RIO_obs_empty.xml").split("\\ "); - String[] parameterNames = new String[] { "processes.processesEachStep.9.tempMinRep", - "processes.processesEachStep.9.ratioS95_S50", "processes.processesEachStep.6.pHomingAfterEquil" }; + String[] parameterNames = new String[] { "processes.processesEachStep.10.tempMinRep", + "processes.processesEachStep.10.ratioS95_S50", "processes.processesEachStep.6.pHomingAfterEquil" }; double[] parameterValues = new double[] { 10, 2, 0.7 }; runSimulation(batchArguments, "tsointsoin", parameterNames, parameterValues); - double[][] spawnerRunResults = getValuesFromAquanismGroupProcess("processes.processesEachStep.8.exportToR"); - for (double[] result : spawnerRunResults) { - System.out.println(Arrays.toString(result)); - } - - double[][] distributionResults = getValuesFromAquanismGroupProcess("processes.processesEachStep.10.exportToR"); - for (double[] result : distributionResults) { - System.out.println(Arrays.toString(result)); - } - - // List truc = getAListFromAquanismGroupProcess("processes.processesAtEnd.1.getRecords"); + // System.out.println("\nAnalyseSpawnerFeatures"); + // System.out.println("basin_id, female_mean_age, male_mean_age, percent_primiparous"); + // double[][] spawnerRunResults = getValuesFromAquanismGroupProcess("processes.processesEachStep.8.exportToR"); + // for (double[] result : spawnerRunResults) { + // System.out.println(Arrays.toString(result)); + // } + // + // System.out.println("\nAnalyseFishDistribution"); + // System.out.println("southern_basin_id, northern_basin_id, basin_centroid_latitude, + // effective_centroid_latitude"); + // double[][] distributionResults = + // getValuesFromAquanismGroupProcess("processes.processesEachStep.9.exportToR"); + // for (double[] result : distributionResults) { + // System.out.println(Arrays.toString(result)); + // } + + System.out.println("\nAnalyseLikelihoodOfPresence"); + System.out.println(getSingleValueFromAquanismGroupProcess("processes.processesAtEnd.0.getLogLikelihood")); + + // List truc = getAListFromAquanismGroupProcess("processes.processesAtEnd.0.getRecords"); // System.out.println(truc.get(0).toString()); // System.out.println(getAListFromAquanismGroupProcess("processes.processesAtEnd.1.getRecords")); - System.out.println(Arrays.toString(getValuesFromEnvironment("getMeanLastPercOfAut"))); - - System.out.println(Arrays.toString(getValuesFromAquanismGroup("getRangeDistribution"))); + // System.out.println("\ngetMeanLastPercOfAut"); + // System.out.println(Arrays.toString(getValuesFromEnvironment("getMeanLastPercOfAut"))); } } diff --git a/src/main/java/species/AnalyseFishDistribution.java b/src/main/java/species/AnalyseFishDistribution.java index 4d8d337cda5889b0202a582d58fdb48444f2b9fb..70681aba2ecffae4529ab246df98cd419388db7b 100644 --- a/src/main/java/species/AnalyseFishDistribution.java +++ b/src/main/java/species/AnalyseFishDistribution.java @@ -19,8 +19,9 @@ */ package species; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; @@ -30,6 +31,7 @@ import environment.RiverBasin; import environment.Time.Season; import fr.cemagref.simaqualife.kernel.processes.AquaNismsGroupProcess; import fr.cemagref.simaqualife.pilot.Pilot; +import miscellaneous.QueueMemory; import miscellaneous.TreeMapForCentile; import observer.ObservableRecord; @@ -40,6 +42,8 @@ public class AnalyseFishDistribution extends AquaNismsGroupProcess<DiadromousFis private Season analysisSeason = Season.SPRING; + private int memorySize = 30; + /** * The minimum number of recruits to consider a basin as populated * @@ -47,16 +51,18 @@ public class AnalyseFishDistribution extends AquaNismsGroupProcess<DiadromousFis */ private int minimumRecruitsForPopulatedBasin = 50; - private transient List<FishDistributionRecord> records; + // private transient List<FishDistributionRecord> records; private transient double southernLimit; private transient double northernLimit; + private transient Map<RiverBasin, QueueMemory<Double>> lastSpawnerNumbersMemory; + @Override public void initTransientParameters(Pilot pilot) { super.initTransientParameters(pilot); - records = new ArrayList<FishDistributionRecord>(); + // records = new ArrayList<FishDistributionRecord>(); // define the latitude range of basin network southernLimit = 90.; @@ -71,78 +77,88 @@ public class AnalyseFishDistribution extends AquaNismsGroupProcess<DiadromousFis @Override public void doProcess(DiadromousFishGroup group) { - if (records == null) - initTransientParameters(group.getPilot()); + // first passage + if (lastSpawnerNumbersMemory == null) { + lastSpawnerNumbersMemory = new HashMap<RiverBasin, QueueMemory<Double>>(); + for (RiverBasin riverBasin : group.getEnvironment().getRiverBasins()) { + lastSpawnerNumbersMemory.put(riverBasin, new QueueMemory<>(memorySize)); + } + } - if (group.getEnvironment().getTime().getSeason(group.getPilot()) == analysisSeason) { - // initialise the distribution range - double southernEdge = northernLimit; - double northernEdge = southernLimit; - int southernId = -1; - int northernId = -1; - String southernName = ""; - String northernName = ""; - // initialise for centroid - TreeMapForCentile latitudeEffective = new TreeMapForCentile(); - TreeMapForCentile latitudePresence = new TreeMapForCentile(); + // if (records == null) + // initTransientParameters(group.getPilot()); + if (group.getEnvironment().getTime().getSeason(group.getPilot()) == analysisSeason) { for (RiverBasin riverBasin : group.getEnvironment().getRiverBasins()) { + double fluxBefore = riverBasin.getSpawnerNumberPerGroup(group); - if (riverBasin.getLastRecruitments().getMean() > minimumRecruitsForPopulatedBasin) { - // the river basin is consdered populated - - // NOTE : recruiit number is calulated after thermal tolerance impact - // (which is intreaged in the stock-recruitment relationship) - - // southern edge - if (riverBasin.getLatitude() < southernEdge) { - // the basin is the new southern edge - southernEdge = riverBasin.getLatitude(); - southernId = riverBasin.getBasin_id(); - southernName = riverBasin.getName(); - } - - // northern edge - if (riverBasin.getLatitude() > southernEdge) { - // the basin is the new northern edge - northernEdge = riverBasin.getLatitude(); - northernId = riverBasin.getBasin_id(); - northernName = riverBasin.getName(); - } - - // for distribution centroide computation - latitudePresence.putWithAdding(riverBasin.getLatitude(), 1L); - long effective = ((Double) riverBasin.getLastSpawnerNumbersBeforeReproduction().getMean()).longValue(); - latitudeEffective.putWithAdding(riverBasin.getLatitude(), effective); - } - } - // if the universe is empty - if (southernEdge == northernLimit & northernEdge == southernLimit) { - southernEdge = (northernLimit + southernLimit) / 2.; - northernEdge = southernEdge; + lastSpawnerNumbersMemory.get(riverBasin).push(fluxBefore); } - // distribution centroids computation - double basinCentroid = latitudePresence.calculateMedian(); - double effectiveCentroid = latitudeEffective.calculateMedian(); - - // add a record - FishDistributionRecord record = new FishDistributionRecord(southernId, southernName, southernEdge, northernId, - northernName, northernEdge, basinCentroid, effectiveCentroid); - - records.add(record); } } public double[][] exportToR() { - double[][] export = new double[records.size()][4]; - for (int i = 0; i < records.size(); i++) { - export[i][0] = records.get(i).southern_basin_id; - export[i][1] = records.get(i).northern_basin_id; - export[i][2] = records.get(i).basinCentroid_latitude; - export[i][3] = records.get(i).effectiveCentroid_latitude; + + // initialise the distribution range + double southernEdge = northernLimit; + double northernEdge = southernLimit; + int southernId = -1; + int northernId = -1; + // String southernName = ""; + // String northernName = ""; + // initialise for centroid + TreeMapForCentile latitudeEffective = new TreeMapForCentile(); + TreeMapForCentile latitudePresence = new TreeMapForCentile(); + + double[][] export = new double[1][4]; + int i = 0; + for (Entry<RiverBasin, QueueMemory<Double>> entry : lastSpawnerNumbersMemory.entrySet()) { + + if (entry.getValue().getMean() > minimumRecruitsForPopulatedBasin) { + // the river basin is considered populated + + // NOTE : recruiit number is calulated after thermal tolerance impact + // (which is intreaged in the stock-recruitment relationship) + + // southern edge + if (entry.getKey().getLatitude() < southernEdge) { + // the basin is the new southern edge + southernEdge = entry.getKey().getLatitude(); + southernId = entry.getKey().getBasin_id(); + // southernName = entry.getKey().getName(); + } + + // northern edge + if (entry.getKey().getLatitude() > northernEdge) { + // the basin is the new northern edge + northernEdge = entry.getKey().getLatitude(); + northernId = entry.getKey().getBasin_id(); + // northernName = entry.getKey().getName(); + } + + // for distribution centroide computation + latitudePresence.putWithAdding(entry.getKey().getLatitude(), 1L); + long effective = ((Double) entry.getValue().getMean()).longValue(); + latitudeEffective.putWithAdding(entry.getKey().getLatitude(), effective); + } + } + + // if the universe is empty (none of basins is populated) + if (southernEdge == northernLimit & northernEdge == southernLimit) { + southernEdge = (northernLimit + southernLimit) / 2.; + northernEdge = southernEdge; } + + // distribution centroids computation + double basinCentroid = latitudePresence.calculateMedian(); + double effectiveCentroid = latitudeEffective.calculateMedian(); + + export[0][0] = southernId; + export[0][1] = northernId; + export[0][2] = basinCentroid; + export[0][3] = effectiveCentroid; return export; } diff --git a/src/main/java/species/AnalyseLikelihoodOfPresence.java b/src/main/java/species/AnalyseLikelihoodOfPresence.java index fa663d89d0331e6be1ec357736dc7d57f9587c99..ca4a12344da3d34812486036a6b46d445f774415 100644 --- a/src/main/java/species/AnalyseLikelihoodOfPresence.java +++ b/src/main/java/species/AnalyseLikelihoodOfPresence.java @@ -47,6 +47,11 @@ public class AnalyseLikelihoodOfPresence extends AquaNismsGroupProcess<Diadromou */ private int minimumRecruitsForPopulatedBasin = 50; + /** + * to avoid log(0) in log-lokelihood + * + * @unit + */ private double epsilon = 1e-3; // map with presence @@ -62,6 +67,7 @@ public class AnalyseLikelihoodOfPresence extends AquaNismsGroupProcess<Diadromou if (Double.isNaN(epsilon)) epsilon = 1e-3; + // read the file of presence in river basin try { // open the file FileReader reader = new FileReader(presenceFileName); @@ -74,10 +80,16 @@ public class AnalyseLikelihoodOfPresence extends AquaNismsGroupProcess<Diadromou // read the headers String[] headers = scanner.nextLine().split(","); presences = new TreeMap<String, Map<String, Integer>>(); + boolean periodTest = false; for (int i = 2; i < headers.length; i++) { + if (period.equals(headers[i])) + periodTest = true; presences.put(headers[i], new TreeMap<String, Integer>()); } + // TODO send the error + if (periodTest == false) + System.out.println("The period " + period + " is not present in the file " + presenceFileName); // read the lines while (scanner.hasNextLine()) { String[] fields = scanner.nextLine().split(","); @@ -94,8 +106,8 @@ public class AnalyseLikelihoodOfPresence extends AquaNismsGroupProcess<Diadromou } } } - // reader.close(); - // scanner.close(); + reader.close(); + scanner.close(); } catch (Exception e) { e.printStackTrace(); } @@ -104,18 +116,24 @@ public class AnalyseLikelihoodOfPresence extends AquaNismsGroupProcess<Diadromou @Override public void doProcess(DiadromousFishGroup group) { + + // first passage for processesAtEnd + if (presences == null) + initTransientParameters(group.getPilot()); + logLikelihood = 0.; for (RiverBasin riverBasin : group.getEnvironment().getRiverBasins()) { double p_predit = (double) riverBasin.getLastRecruitments() .getNumberOfStriclyHigherValue(minimumRecruitsForPopulatedBasin) / (double) riverBasin.getLastRecruitments().size(); - int presence = presences.get(riverBasin.getName()).get(period); + int presence = presences.get(period).get(riverBasin.getName()); + // System.out.println(riverBasin.getName() + " " + presence + " " + p_predit); if (presence == 1) - logLikelihood += Math.log(p_predit) + epsilon; + logLikelihood += Math.log(p_predit + epsilon); else - logLikelihood += 1 - Math.log(p_predit) + epsilon; + logLikelihood += 1 - Math.log(p_predit + epsilon); } } diff --git a/src/main/java/species/AnalyseSpawnerFeatures.java b/src/main/java/species/AnalyseSpawnerFeatures.java index 8640ceda8845d830ca624ca0d260782bc40a4483..d3ddb75f99f6ba9184caead4df3dec284ace3277 100644 --- a/src/main/java/species/AnalyseSpawnerFeatures.java +++ b/src/main/java/species/AnalyseSpawnerFeatures.java @@ -130,6 +130,8 @@ public class AnalyseSpawnerFeatures extends AquaNismsGroupProcess<DiadromousFish result[i][1] = entry.getValue().getMean(); result[i][2] = maleAgeMemories.get(entry.getKey()).getMean(); result[i][3] = primiparousMemories.get(entry.getKey()).getMean(); + + i++; } return result;