diff --git a/data/input/fishTryRealBV_CC.xml b/data/input/fishTryRealBV_CC.xml index ab309702b509703b1857d1b5268ffeda032e6014..6236237886728ab546c03a51417852ddee2d881b 100644 --- a/data/input/fishTryRealBV_CC.xml +++ b/data/input/fishTryRealBV_CC.xml @@ -10,7 +10,7 @@ <linfVonBert>60.0</linfVonBert> <dMaxDisp>300.0</dMaxDisp> <lFirstMaturity>40.0</lFirstMaturity> - <fishNutrient> + <nutrientRoutine> <nutrientsOfInterest> <string>N</string> <string>P</string> @@ -30,6 +30,14 @@ <entry> <species.DiadromousFish_-Gender>MALE</species.DiadromousFish_-Gender> <hashtable> + <entry> + <string>bLW_Gonad</string> + <double>3.3838</double> + </entry> + <entry> + <string>aLW_Gonad</string> + <double>-8.8744</double> + </entry> <entry> <string>bLW</string> <double>2.1774</double> @@ -43,6 +51,14 @@ <entry> <species.DiadromousFish_-Gender>FEMALE</species.DiadromousFish_-Gender> <hashtable> + <entry> + <string>bLW_Gonad</string> + <double>2.6729</double> + </entry> + <entry> + <string>aLW_Gonad</string> + <double>-5.2425</double> + </entry> <entry> <string>bLW</string> <double>3.147</double> @@ -58,6 +74,14 @@ <entry> <species.DiadromousFish_-Gender>MALE</species.DiadromousFish_-Gender> <hashtable> + <entry> + <string>bLW_Gonad</string> + <double>3.8331</double> + </entry> + <entry> + <string>aLW_Gonad</string> + <double>-11.285</double> + </entry> <entry> <string>bLW</string> <double>2.9973</double> @@ -71,6 +95,14 @@ <entry> <species.DiadromousFish_-Gender>FEMALE</species.DiadromousFish_-Gender> <hashtable> + <entry> + <string>bLW_Gonad</string> + <double>2.8545</double> + </entry> + <entry> + <string>aLW_Gonad</string> + <double>-6.6234</double> + </entry> <entry> <string>bLW</string> <double>2.9418</double> @@ -92,16 +124,6 @@ <double>0.006986429759979109</double> </entry> </juvenileFeatures> - <spawnedGametesWeight class="hashtable"> - <entry> - <species.DiadromousFish_-Gender>MALE</species.DiadromousFish_-Gender> - <double>44.8</double> - </entry> - <entry> - <species.DiadromousFish_-Gender>FEMALE</species.DiadromousFish_-Gender> - <double>131.0</double> - </entry> - </spawnedGametesWeight> <compoCarcassPreSpawning class="hashtable"> <entry> <species.DiadromousFish_-Gender>MALE</species.DiadromousFish_-Gender> @@ -196,7 +218,8 @@ <double>0.02803</double> </entry> </compoJuvenile> - </fishNutrient> + </nutrientRoutine> + <fileNameInputForInitialObservation>data/input/reality/Obs1900.csv</fileNameInputForInitialObservation> <centileForRange>0.95</centileForRange> <parameterSetfileName>data/input/reality/parameterSet.csv</parameterSetfileName> @@ -245,19 +268,16 @@ <meanBvSurface>17351</meanBvSurface> <standardDeviationBvSurface>35594</standardDeviationBvSurface> <meanInterDistance>300.0</meanInterDistance> - <standardDeviationInterDistance>978.0 - </standardDeviationInterDistance> + <standardDeviationInterDistance>978.0</standardDeviationInterDistance> <pHomingForReachEquil>0.75</pHomingForReachEquil> <pHomingAfterEquil>0.75</pHomingAfterEquil> <NbYearForInstallPop>0</NbYearForInstallPop> <riverMigrationSeason>SPRING</riverMigrationSeason> <alpha2Rep>0.0</alpha2Rep> <meanSpawnersLengthAtRepro>45.0</meanSpawnersLengthAtRepro> - <standardDeviationOfSpawnersLengthAtRepro>2.0 - </standardDeviationOfSpawnersLengthAtRepro> + <standardDeviationOfSpawnersLengthAtRepro>2.0</standardDeviationOfSpawnersLengthAtRepro> <weightOfDeathBasin>0.4</weightOfDeathBasin> </species.DisperseAndMigrateToRiverWithMultiNomDistriAndDeathBasin> - <species.Survive> <synchronisationMode>ASYNCHRONOUS</synchronisationMode> <tempMinMortGenInRiv>10.0</tempMinMortGenInRiv> @@ -268,8 +288,6 @@ <mortalityRateInSea>0.4</mortalityRateInSea> <mortalityRateInOffshore>0.4</mortalityRateInOffshore> </species.Survive> - - <species.ReproduceAndSurviveAfterReproductionWithDiagnose> <synchronisationMode>ASYNCHRONOUS</synchronisationMode> <reproductionSeason>SPRING</reproductionSeason> @@ -314,8 +332,7 @@ </species.IdentifyPopulation> <species.TypeTrajectoryCV> <synchronisationMode>ASYNCHRONOUS</synchronisationMode> - <fileNameOutput>JeuParam100_2100RCP85_A_essai - </fileNameOutput> + <fileNameOutput>JeuParam100_2100RCP85_A_essai</fileNameOutput> </species.TypeTrajectoryCV> </processesAtEnd> diff --git a/src/main/java/species/DiadromousFishGroup.java b/src/main/java/species/DiadromousFishGroup.java index 49dab6f5048449929c030970a63a6136c886a5b2..67d2454f4b121b10f28ba7867b4a79d72e9e141a 100644 --- a/src/main/java/species/DiadromousFishGroup.java +++ b/src/main/java/species/DiadromousFishGroup.java @@ -62,7 +62,7 @@ public class DiadromousFishGroup extends AquaNismsGroup< DiadromousFish, BasinNe * Routine to compute nutrient fluxes operated by a single individual (TODO by a single super individual). * */ - private FishNutrient fishNutrient; + private NutrientRoutine nutrientRoutine; public String fileNameInputForInitialObservation = "data/input/reality/Obs1900.csv"; @@ -265,7 +265,7 @@ public class DiadromousFishGroup extends AquaNismsGroup< DiadromousFish, BasinNe - diadromousFishGroup.fishNutrient = new FishNutrient(nutrientsOfInterest,aResidenceTime, anExcretionRate, aFeaturePreSpawning, aFeaturePostSpawning, aGameteSpawned, + diadromousFishGroup.nutrientRoutine = new NutrientRoutine(nutrientsOfInterest,aResidenceTime, anExcretionRate, aFeaturePreSpawning, aFeaturePostSpawning, aCompoCarcassPreSpawning, aCompoCarcassPostSpawning, aCompoGametes, aJuvenileFeatures, aCompoJuveniles); @@ -507,9 +507,9 @@ public class DiadromousFishGroup extends AquaNismsGroup< DiadromousFish, BasinNe return lFirstMaturity; } - public FishNutrient getFishNutrient() { + public NutrientRoutine getNutrientRoutine() { - return fishNutrient; + return nutrientRoutine; } public void setlFirstMaturity(double lFirstMaturity) { diff --git a/src/main/java/species/FishNutrient.java b/src/main/java/species/FishNutrient.java deleted file mode 100644 index cd09d24a14ebe30747f1a78f2f19f6fbfea29081..0000000000000000000000000000000000000000 --- a/src/main/java/species/FishNutrient.java +++ /dev/null @@ -1,507 +0,0 @@ -/** - * - * @author Camille Poulet, Patrick Lambert - * @copyright Copyright (c) 2019, Irstea - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - - */ -package species; - -import environment.SeaBasin; -import fr.cemagref.simaqualife.pilot.Pilot; -import species.DiadromousFish.Gender; -import species.DiadromousFish.Stage; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.Map; - -import com.thoughtworks.xstream.XStream; -import com.thoughtworks.xstream.io.xml.DomDriver; - - -/** - * @author camille.poulet - * - */ -public class FishNutrient { - - - private static enum SpawningPosition {PRE,POST}; // on créer un static pour réserver une même classe mémoire pour toutes les instances - - //private static enum Gender {UNDIFFERENCIED, FEMALE, MALE}; - - private ArrayList<String> nutrientsOfInterest; - - private double residenceTime; - - private Map<String, Double> excretionRate; - - /** - * Main feature for weight (g) computation before spawning i.e. gametes expelling according to gender, for a given length (cm) - * //Voir pour un retour à la ligne lors du commentaire - * key gender - * value - * key feature - * value value - */ - private Map <DiadromousFish.Gender,Map<String, Double>> fishFeaturesPreSpawning; - - private Map <DiadromousFish.Gender, Map<String, Double>> fishFeaturesPostSpawning; - - private Map<String, Double> juvenileFeatures; - - - /** - * Weight of gametes spawned for both males and females - * key gender - * value g - * usually computed as the difference between unspawned gonad (inbound) and spawned gonad (outbound; "spent gonad") - */ - private Map <DiadromousFish.Gender, Double> spawnedGametesWeight; - - - /** - * chemical composition of carcass before gametes expelling (before spawning) i.e. soma + gonads + gametes - * <key> gender - * <value> - * <key> chemical element - * <value> value ratio element / (total wet weight) g/g - */ - private Map<DiadromousFish.Gender,Map<String,Double>> compoCarcassPreSpawning; - - //package permettant la création d'une table de hachage ie fonctionnant en clé -valeur. Clé unique, mais valeur peut être associée à plusieurs clés; - //La class d'objet Map a pour point faible la taille des données à stocker. Plus on a de valeur dans la table, plus c'est lourd et lent! Donc, trouver un compromis entre temps de calcul et espace. - //N'accepte pas la valeur nulle et thread safe i.e. utilisable simultanément par plusieurs éléments du programme. - - /** - * chemical composition of carcass after spawning i.e. soma + spent gonad (without gametes) - * <value> - * <key> chemical element - * <value> value - */ - private Map<DiadromousFish.Gender, Map<String, Double>> compoCarcassPostSpawning; - - /** - * chemical composition of gametes estimated from the MIGADO dataset (BDalosesBruch) - * <key> gender - * <value> - * <key> chemical element - * <value> value - */ - private Map<DiadromousFish.Gender, Map<String,Double>> compoGametes; - - // For juveniles - Based on Taverny (1991) - - /** - * chemical composition of juveniles - * <key> chemical element - * <value> value - */ - - private Map<String,Double> compoJuvenile; - - - - /** - * Constructor based on the 5 Map of fish composition - * @param fishFeaturesPreSpawning - * @param compoCarcassPreSpawning - * @param compoCarcassPostSpawning - * @param compoGametes - * @param compoJuvenile - */ - public FishNutrient(ArrayList<String> nutrientsOfInterest, - - double residenceTime, - Map <String, Double> excretionRate, - Map<DiadromousFish.Gender, Map<String, Double>> fishFeaturesPreSpawning, - Map<DiadromousFish.Gender, Map<String, Double>> fishFeaturesPostSpawning, - Map<DiadromousFish.Gender, Double> gameteSpawned, - Map<DiadromousFish.Gender, Map<String, Double>> compoCarcassPreSpawning, - Map<DiadromousFish.Gender, Map<String, Double>> compoCarcassPostSpawning, - Map<DiadromousFish.Gender, Map<String, Double>> compoGametes, - Map<String, Double> juvenileFeatures, - Map<String, Double> compoJuvenile) - { - super(); - this.nutrientsOfInterest = nutrientsOfInterest; - this.excretionRate = excretionRate; - this.residenceTime = residenceTime; - this.fishFeaturesPreSpawning = fishFeaturesPreSpawning; - this.fishFeaturesPostSpawning = fishFeaturesPostSpawning; - this.spawnedGametesWeight = gameteSpawned; - this.compoCarcassPreSpawning = compoCarcassPreSpawning; - this.compoCarcassPostSpawning = compoCarcassPostSpawning; - this.compoGametes = compoGametes; - this.juvenileFeatures = juvenileFeatures; - this.compoJuvenile = compoJuvenile; - - } - - /** - * compute the nutrient fluxes for a single fish (in the super individual) - * that dies before spawning - * @param fish - */ - public Map<String,Double> computeNutrientsInputForDeathBeforeSpawning(DiadromousFish fish, ArrayList<String> nutrientsOfInterest) { - - Map<String,Double> nutrientsInput = new Hashtable<String, Double>(); // On créer ici une Map, classe mère des hashtable (Homme = classe mere ie Map//Jules = hashtable) - for (String nutrient : nutrientsOfInterest) { - - if (fish.getStage()== Stage.MATURE) { - double totalWeightPre = this.getWeight(fish,SpawningPosition.PRE); - double carcass = totalWeightPre - * compoCarcassPreSpawning.get(fish.getGender()).get(nutrient); - double excretion = totalWeightPre - * residenceTime - * excretionRate.get(nutrient) ; - double nutrientImport = carcass + excretion; - - nutrientsInput.put(nutrient, nutrientImport); - } - else { - nutrientsInput.put(nutrient, 0.); - } - } - - //TODO Multiply by fish amount - return nutrientsInput; - } - - public Map<String,Double> computeNutrientsInputForDeathBeforeSpawning(DiadromousFish fish) { - - return computeNutrientsInputForDeathBeforeSpawning(fish,this.nutrientsOfInterest); - } - - /** - * compute the nutrient fluxes for a single fish (in the super individual) - * that dies after spawning (gametes expelling) - * @param fish - * @return nutrientsInput - */ - public Map<String, Double> computeNutrientsInputForDeathAfterSpawning(DiadromousFish fish, ArrayList<String> nutrientsOfInterest) { - - Map<String,Double> nutrientsInput = new Hashtable<String,Double>(); - for (String nutrient : nutrientsOfInterest) { - - if (fish.getStage()== Stage.MATURE) { - - double totalWeightPost = this.getWeight(fish, SpawningPosition.POST); - double carcass = totalWeightPost - * compoCarcassPostSpawning.get(fish.getGender()).get(nutrient); - //double gametes = (totalWeightPre - totalWeightPost) FAUX car perte de poids somatique due a la reproduction - double gametes = spawnedGametesWeight.get(fish.getGender()) - *compoGametes.get(fish.getGender()).get(nutrient); //TODO: FAUX ! Revoir comment calculer les gamètes - double excretion = totalWeightPost - * residenceTime - * excretionRate.get(nutrient); - double nutrientImport = carcass + gametes + excretion; - - nutrientsInput.put(nutrient,nutrientImport); - } - else { - nutrientsInput.put(nutrient,0.); - } - } - return nutrientsInput; - } - - public Map<String, Double> computeNutrientsInputForDeathAfterSpawning(DiadromousFish fish){ - - return computeNutrientsInputForDeathAfterSpawning(fish, this.nutrientsOfInterest); - } - /** - * compute the nutrient fluxes for a single fish (in the super individual) - * that survives after spawning - * Map: model output = element of interest ie string + double ie the quantification of this fluxes. - * @return nutrientsInput - */ - public Map<String,Double>computeNutrientsInputForSurvivalAfterSpawning(DiadromousFish fish, ArrayList<String> nutrientsOfInterest) { - - Map<String,Double> nutrientsInput = new Hashtable<String,Double>(); - for (String nutrient: nutrientsOfInterest) { - if (fish.getStage()==Stage.MATURE) { - - //TODO Fix with new data - double totalWeightPost = this.getWeight(fish, SpawningPosition.POST); - //Gamete compositions depends on sex. - double gametes = spawnedGametesWeight.get(fish.getGender()) - * compoGametes.get(fish.getGender()).get(nutrient); - double excretion = totalWeightPost - * residenceTime - * excretionRate.get(nutrient); - double nutrientImport = gametes + excretion; - - - - nutrientsInput.put(nutrient, nutrientImport); - } - else { - nutrientsInput.put(nutrient,0.); - } - } - return nutrientsInput; - } - - public Map<String,Double>computeNutrientsInputForSurvivalAfterSpawning(DiadromousFish fish) { - - return computeNutrientsInputForSurvivalAfterSpawning(fish, this.nutrientsOfInterest); - } - - - public Map<String,Double> computeNutrientsExportForJuveniles(DiadromousFish juvenileFish, ArrayList<String>nutrientsOfInterest) { - Map<String,Double> nutrientsExport = new Hashtable<String,Double>(); - for(String nutrient: nutrientsOfInterest) { - if(juvenileFish.getStage()==Stage.IMMATURE) { - - double JuvenileMass = this.getWeight(juvenileFish); - nutrientsExport.put(nutrient, JuvenileMass * compoJuvenile.get(nutrient)); - } - } - - return nutrientsExport; - } - - public Map<String,Double> computeNutrientsExportForJuveniles(DiadromousFish juvenileFish){ - return computeNutrientsExportForJuveniles(juvenileFish, this.nutrientsOfInterest); - - } - - /** - * Compute the weight for a fish with length (cm) - * @param fish - * @return weight (g) - */ - public double getWeight (DiadromousFish fish, SpawningPosition spawningPosition) { - - double weight = 0.; - if (fish.getStage()==Stage.IMMATURE) - weight = juvenileFeatures.get("aLW") * Math.pow(fish.getLength(),juvenileFeatures.get("bLW")); - else //Stage.MATURE - if (spawningPosition == SpawningPosition.PRE) - weight = fishFeaturesPreSpawning.get(fish.getGender()).get("aLW") * Math.pow(fish.getLength(), fishFeaturesPreSpawning.get(fish.getGender()).get("bLW") ); - else - weight = fishFeaturesPostSpawning.get(fish.getGender()).get("aLW") * Math.pow(fish.getLength(), fishFeaturesPostSpawning.get(fish.getGender()).get("bLW")); - - return weight; - } - - /** - * Compute the weight for a fish with length (cm) - * @param fish - * @return weight (g) - */ - public double getWeight (DiadromousFish fish) { - - return getWeight (fish, SpawningPosition.PRE); - } - - - -public ArrayList<String> getNutrientsOfInterest() { - return nutrientsOfInterest; - } - -/** - * @param args - */ -/** - * @param args - */ -/** - * @param args - */ -public static void main(String[] args) { - - - double aResidenceTime =30; - - System.out.println("aResidenceTime: " + aResidenceTime); // - - - Map <String, Double> anExcretionRate = new Hashtable <String, Double>(); - anExcretionRate.put("N", 24.71E-6); //values from Barber et al, Alosa sapidissima in ug/g wet mass/hour : convertit en g - anExcretionRate.put("P", 2.17E-6); //values from Barber et al, Alosa sapidissima in ug/g wet mass/hour: convertit en g - - System.out.println("anExcretionRate: " + anExcretionRate.toString()); // - - /* - * A feature pre spawning - */ - Map<Gender, Map<String, Double>> aFeaturePreSpawning = new Hashtable<DiadromousFish.Gender, Map<String,Double>>(); - - /* - * For females - */ - Map<String,Double> aFeature = new Hashtable<String,Double>(); - - aFeature.put("aLW", Math.exp(-4.9078)); //weight size relationship computed from BDalosesBruch - aFeature.put("bLW", 3.147); - //aFeature.put("bLW",3.3429);// parametre "b" de la relation taille/poids - Coefficient d'allometrie - //aFeature.put("aLW",1.2102E-6 * Math.pow(10., aFeature.get("bLW"))); // parametre "a" de la relation taille/poids en kg/cm- Traduit la condition - //aFeature.put("GSI",0.15); - aFeaturePreSpawning.put(Gender.FEMALE, aFeature); - - /* - * For males - */ - aFeature = new Hashtable<String,Double>(); - aFeature.put("aLW", Math.exp(-1.304)); - aFeature.put("bLW", 2.1774); - //aFeature.put("aLW",2.4386E-6 * Math.pow(10, aFeature.get("bLW"))); // Conversion des g/mm en g.cm (from Taverny, 1991) - //aFeature.put("GSI",.08); - aFeaturePreSpawning.put(Gender.MALE,aFeature); - - System.out.println("aFeaturePreSpawning: " + aFeaturePreSpawning.toString()); // - - /* - * a Feature post Spawning - */ - Map<Gender, Map<String, Double>> aFeaturePostSpawning = new Hashtable<DiadromousFish.Gender, Map<String,Double>>(); - - /* - * For females - */ - aFeature = new Hashtable<String,Double>(); - aFeature.put("aLW", Math.exp(-4.3276)); //weight size relationship computed from BDalosesBruch - aFeature.put("bLW", 2.9418); - //aFeature.put("GSI",0.10); //From BDalosesBruch - //aFeature.put("aLW",aFeaturePreSpawning.get(Gender.FEMALE).get("aLW")/(1+aFeature.get("GSI"))); // parametre "a" de la relation taille/poids avec Lt en cm - Traduit la condition - //aFeature.put("bLW",aFeaturePreSpawning.get(Gender.FEMALE).get("bLW"));// parametre "b" de la relation taille/poids - Coefficient d'allometrie - aFeaturePostSpawning.put(Gender.FEMALE, aFeature); - - /* - * For males - */ - aFeature = new Hashtable<String,Double>(); - - aFeature.put("aLW", Math.exp(-4.5675));// parametre "a" de la relation taille/poids - Coefficient d'allometrie - aFeature.put("bLW", 2.9973); - //aFeature.put("GSI",.05); From BDalosesBruch - //aFeature.put("aLW",aFeaturePreSpawning.get(Gender.MALE).get("aLW")/(1+aFeature.get("GSI"))); - //aFeature.put("bLW",aFeaturePreSpawning.get(Gender.MALE).get("bLW")); - aFeaturePostSpawning.put(Gender.MALE,aFeature); - - System.out.println("aFeaturePostSpawning: " + aFeaturePostSpawning.toString()); - - Map<Gender, Double> aGameteSpawned = new Hashtable <DiadromousFish.Gender,Double>(); - aGameteSpawned.put(Gender.FEMALE, 131.); // Compute from the difference between spawned and unspawned ovaries ie correspond to a mean weight of eggs spawned - aGameteSpawned.put(Gender.MALE, 44.8); // Compute from the difference between spawned and unspawned testes ie correspond to a mean weight of sperm spawned - - System.out.println("aGameteSpawned: " + aGameteSpawned.toString()); - - // carcass composition for fish before spawning - Map<Gender, Map<String, Double>> aCompoCarcassPreSpawning = new Hashtable<DiadromousFish.Gender,Map<String,Double>>(); - Map<String,Double> aCompo = new Hashtable<String,Double>(); - aCompo.put("N", 2.958 / 100.); //On remplit une collection avec un put. - aCompo.put("P", 0.673 / 100.); - aCompoCarcassPreSpawning.put(Gender.FEMALE,aCompo); - - aCompo = new Hashtable<String,Double>(); - aCompo.put("N", 2.941 / 100.); - aCompo.put("P", 0.666 / 100.); - aCompoCarcassPreSpawning.put(Gender.MALE,aCompo); - - System.out.println("aCompoCarcassPreSpawning: " + aCompoCarcassPreSpawning.toString()); // - - // carcass composition for fish after spawning - Map<Gender, Map<String, Double>> aCompoCarcassPostSpawning = new Hashtable<DiadromousFish.Gender,Map<String,Double>>(); - aCompo = new Hashtable<String,Double>(); - aCompo.put("N", 3.216 / 100.); //On remplit une collection avec un put. - aCompo.put("P", 0.997 / 100.); - aCompoCarcassPostSpawning.put(Gender.FEMALE,aCompo); - - aCompo = new Hashtable<String,Double>(); - aCompo.put("N", 2.790 / 100.); // From Haskel et al, 2017 - aCompo.put("P", 0.961 / 100.); - aCompoCarcassPostSpawning.put(Gender.MALE,aCompo); - - System.out.println("aCompoCarcassPostSpawning: " + aCompoCarcassPostSpawning.toString()); // - - // Gametes composition approximated by the difference between gonads weight before and after spawning. - Map<Gender, Map<String, Double>> aCompoGametes = new Hashtable<DiadromousFish.Gender,Map<String,Double>>(); - aCompo = new Hashtable<String,Double>(); - aCompo.put("N", 3.242 / 100.); //On remplit une collection avec un put. From Haskel et al, 2018. - aCompo.put("P", 0.320 / 100.); // Haskel = %P, N, ici ratio donc divise par 100 - aCompoGametes.put(Gender.FEMALE,aCompo); - - aCompo = new Hashtable<String,Double>(); - aCompo.put("N", 3.250 / 100.); - aCompo.put("P", 0.724 / 100.); - aCompoGametes.put(Gender.MALE,aCompo); - - System.out.println("aCompoGametes:" + aCompoGametes.toString()); // - - // features for juveniles - - Map<String,Double> aJuvenileFeatures = new Hashtable<String, Double>(); - aJuvenileFeatures.put("bLW",3.0306); - aJuvenileFeatures.put("aLW",Math.exp(-11.942) * Math.pow(10., aJuvenileFeatures.get("bLW"))); - - System.out.println("aJuvenileFeatures: " + aJuvenileFeatures.toString()); - - // carcass composition for juveniles fish - Map<String, Double> aCompoJuveniles = new Hashtable<String,Double>(); - aCompoJuveniles.put("N", 2.803 / 100.); //On remplit une collection avec un put. %N in wet weight (Haskell et al, 2017) on Alosa sapidissima - aCompoJuveniles.put("P", 0.887 / 100.); //%P in wet weight (from Haskell et al, 2017) on Alosa sapidissima - - System.out.println("aCompoJuveniles: " + aCompoJuveniles.toString()); - - ArrayList <String> nutrientsOfInterest= new ArrayList <String>(); - nutrientsOfInterest.add("N"); - nutrientsOfInterest.add("P"); - - System.out.println("nutrientsOfInterest: " + nutrientsOfInterest); - - - FishNutrient fn = new FishNutrient(nutrientsOfInterest,aResidenceTime, anExcretionRate, aFeaturePreSpawning, aFeaturePostSpawning, aGameteSpawned, - aCompoCarcassPreSpawning, aCompoCarcassPostSpawning, aCompoGametes, - aJuvenileFeatures, aCompoJuveniles); - - SeaBasin basin = new SeaBasin(0,"Bidon",10.,12., 14.,12.); //il faut aller dans "SeaBasin" dans "environement et regarder comment est construit le constructeur. Il lui faut ici un rang, un nom de bassin versant, et des température pour chaque saison - Pilot pilot = new Pilot (); - DiadromousFish fishFemale = new DiadromousFish (pilot, basin, 52., 1L, Gender.FEMALE); //Idem ici, on regarde comment est construit DiadromousFih et on lui donne les valeur de ce qu'il nous demande. - fishFemale.setStage(Stage.MATURE); - DiadromousFish fishMale = new DiadromousFish (pilot, basin, 47., 1L, Gender.MALE); //Idem ici, on regarde comment est construit DiadromousFih et on lui donne les valeur de ce qu'il nous demande. - fishMale.setStage(Stage.MATURE); - DiadromousFish juvenileFish = new DiadromousFish(pilot,basin,7.0,1L,Gender.UNDIFFERENCIED); - juvenileFish.setStage(Stage.IMMATURE); - - System.out.println(); // affiche une ligne blanche - System.out.println(fishFemale.getGender() + ": " + fishFemale.getLength() + " cm " + fn.getWeight(fishFemale, SpawningPosition.PRE)+ " g " + fn.getWeight(fishFemale, SpawningPosition.POST)); - System.out.println("\tNutrients Fluxes for death before spawning " + fn.computeNutrientsInputForDeathBeforeSpawning(fishFemale).toString()); - System.out.println("\tNutrients Fluxes for death after spawning " + fn.computeNutrientsInputForDeathAfterSpawning(fishFemale).toString()); - System.out.println("\tNutrients Fluxes for survival " + fn.computeNutrientsInputForSurvivalAfterSpawning(fishFemale).toString()); - - System.out.println(fishMale.getGender() + ": " + fishMale.getLength() + " cm " + fn.getWeight(fishMale, SpawningPosition.PRE)+ " g " + fn.getWeight(fishMale, SpawningPosition.POST)); - System.out.println("\tNutrients Fluxes for death before spawning " + fn.computeNutrientsInputForDeathBeforeSpawning(fishMale).toString()); - System.out.println("\tNutrients Fluxes for death after spawning " + fn.computeNutrientsInputForDeathAfterSpawning(fishMale).toString()); - System.out.println("\tNutrients Fluxes for survival " + fn.computeNutrientsInputForSurvivalAfterSpawning(fishMale).toString()); - - System.out.println(juvenileFish.getStage() + ": " + juvenileFish.getLength() + " cm " + fn.getWeight(juvenileFish)+ " g "); - System.out.println("\tNutrients Fluxes for juveniles " + fn.computeNutrientsExportForJuveniles(juvenileFish).toString()); - - - - - /* Create XML file - * - */ - System.out.println((new XStream(new DomDriver())).toXML(fn)); - -} -} - - diff --git a/src/main/java/species/MigrateToSea.java b/src/main/java/species/MigrateToSea.java index 95fbddeaec73451a1213cafe3d859af86596d9a5..206043342e5bf624554daa588f8c98e9f6c507ae 100644 --- a/src/main/java/species/MigrateToSea.java +++ b/src/main/java/species/MigrateToSea.java @@ -9,8 +9,13 @@ import environment.Time; import environment.Time.Season; import fr.cemagref.simaqualife.kernel.processes.AquaNismsGroupProcess; import java.util.ArrayList; +import java.util.Hashtable; import java.util.List; +import java.util.Map; + import miscellaneous.Duo; +import species.DiadromousFish.Stage; + import org.openide.util.lookup.ServiceProvider; @ServiceProvider(service = AquaNismsGroupProcess.class) @@ -28,19 +33,48 @@ public class MigrateToSea extends AquaNismsGroupProcess<DiadromousFish, Diadromo if (Time.getSeason(group.getPilot()) == seaMigrationSeason ){ Basin destination; - List<Duo<DiadromousFish,Basin>> fishesToMove = new ArrayList<Duo<DiadromousFish,Basin>>(); - for (int i = 0; i < group.getEnvironment().getRiverBasins().length; i++) { - RiverBasin basin = group.getEnvironment().getRiverBasins()[i]; - - List<DiadromousFish> fishes = basin.getFishs(group); - if (fishes!=null) for (DiadromousFish fish : fishes) { - destination = group.getEnvironment().getAssociatedSeaBasin(fish.getPosition()); - fishesToMove.add(new Duo<DiadromousFish, Basin>(fish, destination)); - } - } - for (Duo<DiadromousFish,Basin> duo : fishesToMove) { - duo.getFirst().moveTo(group.getPilot(), duo.getSecond(), group); - } - } + + //On créer la Map pour stocker les flux d'export + Map<String, Double> totalOutputFluxes = new Hashtable<String, Double>(); + + List<Duo<DiadromousFish,Basin>> fishesToMove = new ArrayList<Duo<DiadromousFish,Basin>>(); + for (int i = 0; i < group.getEnvironment().getRiverBasins().length; i++) { + RiverBasin basin = group.getEnvironment().getRiverBasins()[i]; + //Fish move to sea and compute the related export of nutrients + List<DiadromousFish> fishes = basin.getFishs(group); + + // ON ré-initialise notre map pour chauqe bassin + for (String nutrient : group.getNutrientRoutine().getNutrientsOfInterest()) { + totalOutputFluxes.put(nutrient, 0.); + } + totalOutputFluxes.put("biomass", 0.); //création de la biomasse + + if (fishes!=null) { + for (DiadromousFish fish : fishes) { + destination = group.getEnvironment().getAssociatedSeaBasin(fish.getPosition()); + fishesToMove.add(new Duo<DiadromousFish, Basin>(fish, destination)); //Mentionne la sortie d'un poisson de la boucle + + double biomass = group.getNutrientRoutine().getWeight(fish) * fish.getAmount(); + + if (fish.getStage()==Stage.IMMATURE) { + Map <String, Double> aFluxExportedByJuveniles= group.getNutrientRoutine().computeNutrientsExportForJuveniles(fish); + for (String nutrient: aFluxExportedByJuveniles.keySet()) { + totalOutputFluxes.put(nutrient,totalOutputFluxes.get(nutrient) + aFluxExportedByJuveniles.get(nutrient) * fish.getAmount()); + } + + totalOutputFluxes.put("biomass", totalOutputFluxes.get("biomass") + biomass); + } + } + } + + for (Duo<DiadromousFish,Basin> duo : fishesToMove) { + duo.getFirst().moveTo(group.getPilot(), duo.getSecond(), group); //on déplace les poissons dans le fichier MoveTo et on dénote la destination du poisson. + } + System.out.println(group.getPilot().getCurrentTime() + "; " + Time.getYear(group.getPilot()) + ";" + Time.getSeason(group.getPilot()) + ";EXPORT;" + + basin.getName() + "; " + totalOutputFluxes); + } + } + + } -} +} \ No newline at end of file diff --git a/src/main/java/species/NutrientRoutine.java b/src/main/java/species/NutrientRoutine.java new file mode 100644 index 0000000000000000000000000000000000000000..f3f26a36fe1717fc09b5dda2c33dc8b0863ac308 --- /dev/null +++ b/src/main/java/species/NutrientRoutine.java @@ -0,0 +1,533 @@ +/** + * + * @author Camille Poulet, Patrick Lambert + * @copyright Copyright (c) 2019, Irstea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + + */ +package species; + +import environment.SeaBasin; +import fr.cemagref.simaqualife.pilot.Pilot; +import species.DiadromousFish.Gender; +import species.DiadromousFish.Stage; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Map; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.DomDriver; + + +/** + * @author camille.poulet + * + */ +public class NutrientRoutine { + + + private static enum SpawningPosition {PRE,POST}; // on créer un static pour réserver une même classe mémoire pour toutes les instances + + //private static enum Gender {UNDIFFERENCIED, FEMALE, MALE}; + + private ArrayList<String> nutrientsOfInterest; + + private double residenceTime; + + private Map<String, Double> excretionRate; + + /** + * Main feature for weight (g) computation before spawning i.e. gametes expelling according to gender, for a given length (cm) + * //Voir pour un retour à la ligne lors du commentaire + * key gender + * value + * key feature + * value value + */ + private Map <DiadromousFish.Gender,Map<String, Double>> fishFeaturesPreSpawning; + + private Map <DiadromousFish.Gender, Map<String, Double>> fishFeaturesPostSpawning; + + private Map<String, Double> juvenileFeatures; + + + /** + * Weight of gametes spawned for both males and females + * key gender + * value g + * usually computed as the difference between unspawned gonad (inbound) and spawned gonad (outbound; "spent gonad") + */ + //private Map <DiadromousFish.Gender, Double> spawnedGametesWeight; + + + /** + * chemical composition of carcass before gametes expelling (before spawning) i.e. soma + gonads + gametes + * <key> gender + * <value> + * <key> chemical element + * <value> value ratio element / (total wet weight) g/g + */ + private Map<DiadromousFish.Gender,Map<String,Double>> compoCarcassPreSpawning; + + //package permettant la création d'une table de hachage ie fonctionnant en clé -valeur. Clé unique, mais valeur peut être associée à plusieurs clés; + //La class d'objet Map a pour point faible la taille des données à stocker. Plus on a de valeur dans la table, plus c'est lourd et lent! Donc, trouver un compromis entre temps de calcul et espace. + //N'accepte pas la valeur nulle et thread safe i.e. utilisable simultanément par plusieurs éléments du programme. + + /** + * chemical composition of carcass after spawning i.e. soma + spent gonad (without gametes) + * <value> + * <key> chemical element + * <value> value + */ + private Map<DiadromousFish.Gender, Map<String, Double>> compoCarcassPostSpawning; + + /** + * chemical composition of gametes estimated from the MIGADO dataset (BDalosesBruch) + * <key> gender + * <value> + * <key> chemical element + * <value> value + */ + private Map<DiadromousFish.Gender, Map<String,Double>> compoGametes; + + // For juveniles - Based on Taverny (1991) + + /** + * chemical composition of juveniles + * <key> chemical element + * <value> value + */ + + private Map<String,Double> compoJuvenile; + + + + /** + * Constructor based on the 5 Map of fish composition + * @param fishFeaturesPreSpawning + * @param compoCarcassPreSpawning + * @param compoCarcassPostSpawning + * @param compoGametes + * @param compoJuvenile + */ + public NutrientRoutine(ArrayList<String> nutrientsOfInterest, + + double residenceTime, + Map <String, Double> excretionRate, + Map<DiadromousFish.Gender, Map<String, Double>> fishFeaturesPreSpawning, + Map<DiadromousFish.Gender, Map<String, Double>> fishFeaturesPostSpawning, + Map<DiadromousFish.Gender, Map<String, Double>> compoCarcassPreSpawning, + Map<DiadromousFish.Gender, Map<String, Double>> compoCarcassPostSpawning, + Map<DiadromousFish.Gender, Map<String, Double>> compoGametes, + Map<String, Double> juvenileFeatures, + Map<String, Double> compoJuvenile) + { + super(); + this.nutrientsOfInterest = nutrientsOfInterest; + this.excretionRate = excretionRate; + this.residenceTime = residenceTime; + this.fishFeaturesPreSpawning = fishFeaturesPreSpawning; + this.fishFeaturesPostSpawning = fishFeaturesPostSpawning; + this.compoCarcassPreSpawning = compoCarcassPreSpawning; + this.compoCarcassPostSpawning = compoCarcassPostSpawning; + this.compoGametes = compoGametes; + this.juvenileFeatures = juvenileFeatures; + this.compoJuvenile = compoJuvenile; + + } + + /** + * compute the nutrient fluxes for a single fish (in the super individual) + * that dies before spawning + * @param fish + */ + public Map<String,Double> computeNutrientsInputForDeathBeforeSpawning(DiadromousFish fish, ArrayList<String> nutrientsOfInterest) { + + Map<String,Double> nutrientsInput = new Hashtable<String, Double>(); // On créer ici une Map, classe mère des hashtable (Homme = classe mere ie Map//Jules = hashtable) + for (String nutrient : nutrientsOfInterest) { + + if (fish.getStage()== Stage.MATURE) { + double totalWeightPre = this.getWeight(fish,SpawningPosition.PRE); + double carcass = totalWeightPre + * compoCarcassPreSpawning.get(fish.getGender()).get(nutrient); + double excretion = totalWeightPre + * residenceTime + * excretionRate.get(nutrient) ; + double nutrientImport = carcass + excretion; + + nutrientsInput.put(nutrient, nutrientImport); + } + else { + nutrientsInput.put(nutrient, 0.); + } + } + + //TODO Multiply by fish amount + return nutrientsInput; + } + + public Map<String,Double> computeNutrientsInputForDeathBeforeSpawning(DiadromousFish fish) { + + return computeNutrientsInputForDeathBeforeSpawning(fish,this.nutrientsOfInterest); + } + + /** + * compute the nutrient fluxes for a single fish (in the super individual) + * that dies after spawning (gametes expelling) + * @param fish + * @return nutrientsInput + */ + public Map<String, Double> computeNutrientsInputForDeathAfterSpawning(DiadromousFish fish, ArrayList<String> nutrientsOfInterest) { + + Map<String,Double> nutrientsInput = new Hashtable<String,Double>(); + for (String nutrient : nutrientsOfInterest) { + + if (fish.getStage()== Stage.MATURE) { + + double totalWeightPost = this.getWeight(fish, SpawningPosition.POST); + double carcass = totalWeightPost + * compoCarcassPostSpawning.get(fish.getGender()).get(nutrient); + //double gametes = (totalWeightPre - totalWeightPost) FAUX car perte de poids somatique due a la reproduction + double gametes = this.getGonadWeight(fish, SpawningPosition.PRE) - this.getGonadWeight(fish, SpawningPosition.POST) + *compoGametes.get(fish.getGender()).get(nutrient); + double excretion = totalWeightPost + * residenceTime + * excretionRate.get(nutrient); + double nutrientImport = carcass + gametes + excretion; + + nutrientsInput.put(nutrient,nutrientImport); + } + else { + nutrientsInput.put(nutrient,0.); + } + } + return nutrientsInput; + } + + public Map<String, Double> computeNutrientsInputForDeathAfterSpawning(DiadromousFish fish){ + + return computeNutrientsInputForDeathAfterSpawning(fish, this.nutrientsOfInterest); + } + /** + * compute the nutrient fluxes for a single fish (in the super individual) + * that survives after spawning + * Map: model output = element of interest ie string + double ie the quantification of this fluxes. + * @return nutrientsInput + */ + public Map<String,Double>computeNutrientsInputForSurvivalAfterSpawning(DiadromousFish fish, ArrayList<String> nutrientsOfInterest) { + + Map<String,Double> nutrientsInput = new Hashtable<String,Double>(); + for (String nutrient: nutrientsOfInterest) { + if (fish.getStage()==Stage.MATURE) { + + //TODO Fix with new data + double totalWeightPost = this.getWeight(fish, SpawningPosition.POST); + //Gamete compositions depends on sex. + + double gametes = this.getGonadWeight(fish, SpawningPosition.PRE) - this.getGonadWeight(fish, SpawningPosition.POST) + * compoGametes.get(fish.getGender()).get(nutrient); + double excretion = totalWeightPost + * residenceTime + * excretionRate.get(nutrient); + double nutrientImport = gametes + excretion; + + nutrientsInput.put(nutrient, nutrientImport); + } + else { + nutrientsInput.put(nutrient,0.); + } + } + return nutrientsInput; + } + + public Map<String,Double>computeNutrientsInputForSurvivalAfterSpawning(DiadromousFish fish) { + + return computeNutrientsInputForSurvivalAfterSpawning(fish, this.nutrientsOfInterest); + } + + + public Map<String,Double> computeNutrientsExportForJuveniles(DiadromousFish juvenileFish, ArrayList<String>nutrientsOfInterest) { + Map<String,Double> nutrientsExport = new Hashtable<String,Double>(); + for(String nutrient: nutrientsOfInterest) { + if(juvenileFish.getStage()==Stage.IMMATURE) { + + double JuvenileMass = this.getWeight(juvenileFish); + nutrientsExport.put(nutrient, JuvenileMass * compoJuvenile.get(nutrient)); + } + } + + return nutrientsExport; + } + + public Map<String,Double> computeNutrientsExportForJuveniles(DiadromousFish juvenileFish){ + return computeNutrientsExportForJuveniles(juvenileFish, this.nutrientsOfInterest); + + } + + /** + * Compute the weight for a fish with length (cm) + * @param fish + * @return weight (g) + */ + public double getWeight (DiadromousFish fish, SpawningPosition spawningPosition) { + + double weight = 0.; + if (fish.getStage()==Stage.IMMATURE) + weight = juvenileFeatures.get("aLW") * Math.pow(fish.getLength(),juvenileFeatures.get("bLW")); + else //Stage.MATURE + if (spawningPosition == SpawningPosition.PRE) + weight = fishFeaturesPreSpawning.get(fish.getGender()).get("aLW") * Math.pow(fish.getLength(), fishFeaturesPreSpawning.get(fish.getGender()).get("bLW") ); + else + weight = fishFeaturesPostSpawning.get(fish.getGender()).get("aLW") * Math.pow(fish.getLength(), fishFeaturesPostSpawning.get(fish.getGender()).get("bLW")); + + return weight; + } + + + /** + * Compute the weight for a fish with length (cm) + * @param fish + * @return weight (g) + */ + public double getWeight (DiadromousFish fish) { + + return getWeight (fish, SpawningPosition.PRE); + } + + public double getGonadWeight (DiadromousFish fish, SpawningPosition spawningPosition) { + + double gonadWeight = 0.; + if (fish.getStage()==Stage.MATURE); + if (spawningPosition == SpawningPosition.PRE) + gonadWeight = Math.exp(fishFeaturesPreSpawning.get(fish.getGender()).get("aLW_Gonad") + + fishFeaturesPreSpawning.get(fish.getGender()).get("bLW_Gonad") * Math.log(fish.getLength())); + else + gonadWeight = Math.exp(fishFeaturesPostSpawning.get(fish.getGender()).get("aLW_Gonad") + + fishFeaturesPostSpawning.get(fish.getGender()).get("bLW_Gonad") * Math.log(fish.getLength())); + + return gonadWeight; + } + + + /** + * Compute the gonad weight for a fish with length (cm) to compute the gamete emission (g). + * @param fish + * @return weight (g) + */ + public double getGonadWeight (DiadromousFish fish) { + + return getGonadWeight (fish, SpawningPosition.PRE); + } + + + + + public ArrayList<String> getNutrientsOfInterest() { + return nutrientsOfInterest; + } + + /** + * @param args + */ + /** + * @param args + */ + /** + * @param args + */ + public static void main(String[] args) { + + + double aResidenceTime =30; + + System.out.println("aResidenceTime: " + aResidenceTime); // + + + Map <String, Double> anExcretionRate = new Hashtable <String, Double>(); + anExcretionRate.put("N", 24.71E-6); //values from Barber et al, Alosa sapidissima in ug/g wet mass/hour : convertit en g + anExcretionRate.put("P", 2.17E-6); //values from Barber et al, Alosa sapidissima in ug/g wet mass/hour: convertit en g + + System.out.println("anExcretionRate: " + anExcretionRate.toString()); // + + /* + * A feature pre spawning + */ + Map<Gender, Map<String, Double>> aFeaturePreSpawning = new Hashtable<DiadromousFish.Gender, Map<String,Double>>(); + + /* + * For females + */ + Map<String,Double> aFeature = new Hashtable<String,Double>(); + + aFeature.put("aLW", Math.exp(-4.9078)); //weight size relationship computed from BDalosesBruch + aFeature.put("bLW", 3.147); + aFeature.put("aLW_Gonad", -5.2425); // issu de la relation taille - poids des gonades Bruch + aFeature.put("bLW_Gonad", 2.6729); // issu de la relation taille - poids des gonades Bruch + //aFeature.put("bLW",3.3429);// parametre "b" de la relation taille/poids - Coefficient d'allometrie + //aFeature.put("aLW",1.2102E-6 * Math.pow(10., aFeature.get("bLW"))); // parametre "a" de la relation taille/poids en kg/cm- Traduit la condition + //aFeature.put("GSI",0.15); + aFeaturePreSpawning.put(Gender.FEMALE, aFeature); + + /* + * For males + */ + aFeature = new Hashtable<String,Double>(); + aFeature.put("aLW", Math.exp(-1.304)); + aFeature.put("bLW", 2.1774); + aFeature.put("aLW_Gonad", -8.8744); + aFeature.put("bLW_Gonad", 3.3838); + //aFeature.put("aLW",2.4386E-6 * Math.pow(10, aFeature.get("bLW"))); // Conversion des g/mm en g.cm (from Taverny, 1991) + //aFeature.put("GSI",.08); + aFeaturePreSpawning.put(Gender.MALE,aFeature); + + System.out.println("aFeaturePreSpawning: " + aFeaturePreSpawning.toString()); // + + /* + * a Feature post Spawning + */ + Map<Gender, Map<String, Double>> aFeaturePostSpawning = new Hashtable<DiadromousFish.Gender, Map<String,Double>>(); + + /* + * For females + */ + aFeature = new Hashtable<String,Double>(); + aFeature.put("aLW", Math.exp(-4.3276)); //weight size relationship computed from BDalosesBruch + aFeature.put("bLW", 2.9418); + aFeature.put("aLW_Gonad", -6.6234); // issu de la relation taille - poids des gonades Bruch + aFeature.put("bLW_Gonad", 2.8545); // issu de la relation taille - poids des gonades Bruch + //aFeature.put("GSI",0.10); //From BDalosesBruch + //aFeature.put("aLW",aFeaturePreSpawning.get(Gender.FEMALE).get("aLW")/(1+aFeature.get("GSI"))); // parametre "a" de la relation taille/poids avec Lt en cm - Traduit la condition + //aFeature.put("bLW",aFeaturePreSpawning.get(Gender.FEMALE).get("bLW"));// parametre "b" de la relation taille/poids - Coefficient d'allometrie + aFeaturePostSpawning.put(Gender.FEMALE, aFeature); + + /* + * For males + */ + aFeature = new Hashtable<String,Double>(); + + aFeature.put("aLW", Math.exp(-4.5675));// parametre "a" de la relation taille/poids - Coefficient d'allometrie + aFeature.put("bLW", 2.9973); + aFeature.put("aLW_Gonad", -11.285); // issu de la relation taille - poids des gonades Bruch + aFeature.put("bLW_Gonad", 3.8331); // issu de la relation taille - poids des gonades Bruch + //aFeature.put("GSI",.05); From BDalosesBruch + //aFeature.put("aLW",aFeaturePreSpawning.get(Gender.MALE).get("aLW")/(1+aFeature.get("GSI"))); + //aFeature.put("bLW",aFeaturePreSpawning.get(Gender.MALE).get("bLW")); + aFeaturePostSpawning.put(Gender.MALE,aFeature); + + System.out.println("aFeaturePostSpawning: " + aFeaturePostSpawning.toString()); + + // carcass composition for fish before spawning + Map<Gender, Map<String, Double>> aCompoCarcassPreSpawning = new Hashtable<DiadromousFish.Gender,Map<String,Double>>(); + Map<String,Double> aCompo = new Hashtable<String,Double>(); + aCompo.put("N", 2.958 / 100.); //On remplit une collection avec un put. + aCompo.put("P", 0.673 / 100.); + aCompoCarcassPreSpawning.put(Gender.FEMALE,aCompo); + + aCompo = new Hashtable<String,Double>(); + aCompo.put("N", 2.941 / 100.); + aCompo.put("P", 0.666 / 100.); + aCompoCarcassPreSpawning.put(Gender.MALE,aCompo); + + System.out.println("aCompoCarcassPreSpawning: " + aCompoCarcassPreSpawning.toString()); // + + // carcass composition for fish after spawning + Map<Gender, Map<String, Double>> aCompoCarcassPostSpawning = new Hashtable<DiadromousFish.Gender,Map<String,Double>>(); + aCompo = new Hashtable<String,Double>(); + aCompo.put("N", 3.216 / 100.); //On remplit une collection avec un put. + aCompo.put("P", 0.997 / 100.); + aCompoCarcassPostSpawning.put(Gender.FEMALE,aCompo); + + aCompo = new Hashtable<String,Double>(); + aCompo.put("N", 2.790 / 100.); // From Haskel et al, 2017 + aCompo.put("P", 0.961 / 100.); + aCompoCarcassPostSpawning.put(Gender.MALE,aCompo); + + System.out.println("aCompoCarcassPostSpawning: " + aCompoCarcassPostSpawning.toString()); // + + // Gametes composition approximated by the difference between gonads weight before and after spawning. + Map<Gender, Map<String, Double>> aCompoGametes = new Hashtable<DiadromousFish.Gender,Map<String,Double>>(); + aCompo = new Hashtable<String,Double>(); + aCompo.put("N", 3.242 / 100.); //On remplit une collection avec un put. From Haskel et al, 2018. + aCompo.put("P", 0.320 / 100.); // Haskel = %P, N, ici ratio donc divise par 100 + aCompoGametes.put(Gender.FEMALE,aCompo); + + aCompo = new Hashtable<String,Double>(); + aCompo.put("N", 3.250 / 100.); // Approximée par la compo des gonades + aCompo.put("P", 0.724 / 100.); + aCompoGametes.put(Gender.MALE,aCompo); + + System.out.println("aCompoGametes:" + aCompoGametes.toString()); // + + // features for juveniles + + Map<String,Double> aJuvenileFeatures = new Hashtable<String, Double>(); + aJuvenileFeatures.put("bLW",3.0306); + aJuvenileFeatures.put("aLW",Math.exp(-11.942) * Math.pow(10., aJuvenileFeatures.get("bLW"))); + + System.out.println("aJuvenileFeatures: " + aJuvenileFeatures.toString()); + + // carcass composition for juveniles fish + Map<String, Double> aCompoJuveniles = new Hashtable<String,Double>(); + aCompoJuveniles.put("N", 2.803 / 100.); //On remplit une collection avec un put. %N in wet weight (Haskell et al, 2017) on Alosa sapidissima + aCompoJuveniles.put("P", 0.887 / 100.); //%P in wet weight (from Haskell et al, 2017) on Alosa sapidissima + + System.out.println("aCompoJuveniles: " + aCompoJuveniles.toString()); + + ArrayList <String> nutrientsOfInterest= new ArrayList <String>(); + nutrientsOfInterest.add("N"); + nutrientsOfInterest.add("P"); + + System.out.println("nutrientsOfInterest: " + nutrientsOfInterest); + + + NutrientRoutine fn = new NutrientRoutine(nutrientsOfInterest,aResidenceTime, anExcretionRate, aFeaturePreSpawning, aFeaturePostSpawning, + aCompoCarcassPreSpawning, aCompoCarcassPostSpawning, aCompoGametes, + aJuvenileFeatures, aCompoJuveniles); + + SeaBasin basin = new SeaBasin(0,"Bidon",10.,12., 14.,12.); //il faut aller dans "SeaBasin" dans "environement et regarder comment est construit le constructeur. Il lui faut ici un rang, un nom de bassin versant, et des température pour chaque saison + Pilot pilot = new Pilot (); + DiadromousFish fishFemale = new DiadromousFish (pilot, basin, 52., 1L, Gender.FEMALE); //Idem ici, on regarde comment est construit DiadromousFih et on lui donne les valeur de ce qu'il nous demande. + fishFemale.setStage(Stage.MATURE); + DiadromousFish fishMale = new DiadromousFish (pilot, basin, 47., 1L, Gender.MALE); //Idem ici, on regarde comment est construit DiadromousFih et on lui donne les valeur de ce qu'il nous demande. + fishMale.setStage(Stage.MATURE); + DiadromousFish juvenileFish = new DiadromousFish(pilot,basin,7.0,1L,Gender.UNDIFFERENCIED); + juvenileFish.setStage(Stage.IMMATURE); + + System.out.println(); // affiche une ligne blanche + System.out.println(fishFemale.getGender() + ": " + fishFemale.getLength() + " cm " + fn.getWeight(fishFemale, SpawningPosition.PRE)+ " g " + fn.getWeight(fishFemale, SpawningPosition.POST)); + System.out.println("\tNutrients Fluxes for death before spawning " + fn.computeNutrientsInputForDeathBeforeSpawning(fishFemale).toString()); + System.out.println("\tNutrients Fluxes for death after spawning " + fn.computeNutrientsInputForDeathAfterSpawning(fishFemale).toString()); + System.out.println("\tNutrients Fluxes for survival " + fn.computeNutrientsInputForSurvivalAfterSpawning(fishFemale).toString()); + + System.out.println(fishMale.getGender() + ": " + fishMale.getLength() + " cm " + fn.getWeight(fishMale, SpawningPosition.PRE)+ " g " + fn.getWeight(fishMale, SpawningPosition.POST)); + System.out.println("\tNutrients Fluxes for death before spawning " + fn.computeNutrientsInputForDeathBeforeSpawning(fishMale).toString()); + System.out.println("\tNutrients Fluxes for death after spawning " + fn.computeNutrientsInputForDeathAfterSpawning(fishMale).toString()); + System.out.println("\tNutrients Fluxes for survival " + fn.computeNutrientsInputForSurvivalAfterSpawning(fishMale).toString()); + + System.out.println(juvenileFish.getStage() + ": " + juvenileFish.getLength() + " cm " + fn.getWeight(juvenileFish)+ " g "); + System.out.println("\tNutrients Fluxes for juveniles " + fn.computeNutrientsExportForJuveniles(juvenileFish).toString()); + + + + + /* Create XML file + * + */ + System.out.println((new XStream(new DomDriver())).toXML(fn)); + + } +} + + diff --git a/src/main/java/species/ReproduceAndSurviveAfterReproduction.java b/src/main/java/species/ReproduceAndSurviveAfterReproduction.java index 8e8f773cbb3aa64198476c7b0995999594a281c2..21007cc5c241d066babeeea8d86a749b06d95a81 100644 --- a/src/main/java/species/ReproduceAndSurviveAfterReproduction.java +++ b/src/main/java/species/ReproduceAndSurviveAfterReproduction.java @@ -163,6 +163,7 @@ public class ReproduceAndSurviveAfterReproduction extends AquaNismsGroupProcess< survivalAmount = Miscellaneous.binomialForSuperIndividual(group.getPilot(), fish.getAmount(), survivalRateAfterReproduction); if (survivalAmount > 0) fish.setAmount(survivalAmount); + else deadFish.add(fish); } diff --git a/src/main/java/species/ReproduceAndSurviveAfterReproductionWithDiagnose.java b/src/main/java/species/ReproduceAndSurviveAfterReproductionWithDiagnose.java index f1ca10f624eb731cf2ff1a058f5065a97adc6429..20dd84d3ec092eacd6f6af7037d4e2241487290d 100644 --- a/src/main/java/species/ReproduceAndSurviveAfterReproductionWithDiagnose.java +++ b/src/main/java/species/ReproduceAndSurviveAfterReproductionWithDiagnose.java @@ -108,20 +108,23 @@ public class ReproduceAndSurviveAfterReproductionWithDiagnose extends AquaNismsG List<DiadromousFish> fishInBasin = riverBasin.getFishs(group); if (fishInBasin != null){ - - Map<String, Double> totalFluxes = new Hashtable<String, Double>(); //On cr�er la Map pour stocker les flux - - for (String nutrient : group.getFishNutrient().getNutrientsOfInterest()) { - - totalFluxes.put(nutrient, 0.); // ON MET A JOUR NOTRE map - + + //Initiate the total fluxes for this basin + Map<String, Map<String, Double>> totalInputFluxes = new Hashtable<String, Map <String, Double>>(); //On créer la Map pour stocker les flux + totalInputFluxes.put("autochtonous", new Hashtable < String, Double>()); + totalInputFluxes.put("allochtonous", new Hashtable < String, Double>()); + for (String origin: totalInputFluxes.keySet()) { + for (String nutrient : group.getNutrientRoutine().getNutrientsOfInterest()) { + totalInputFluxes.get(origin).put(nutrient, 0.); // ON MET A JOUR NOTRE map + } + totalInputFluxes.get(origin).put("biomass",0.); } // -------------------------------------------------------------------------------------------------- // definition of the stock recruiment relationship // -------------------------------------------------------------------------------------------------- - + // effective temperature for reproduction (priority to the ANG value) double tempEffectRep; if (Double.isNaN(group.getTempMinRep())){ @@ -152,7 +155,7 @@ public class ReproduceAndSurviveAfterReproductionWithDiagnose extends AquaNismsG // initilisation of the stock recruitment relationship stockRecruitmentRelationship.init(alpha, beta, S50, S95); - + // -------------------------------------------------------------------------------------------------- // calulation of the spawner number // -------------------------------------------------------------------------------------------------- @@ -162,15 +165,15 @@ public class ReproduceAndSurviveAfterReproductionWithDiagnose extends AquaNismsG // compute the number of spawners and keep the origines of the spawners for (DiadromousFish fish : fishInBasin){ - + if (fish.getGender() == Gender.FEMALE & fish.isMature()){ - + //System.out.println(fish.getAge() + " -> "+ fish.getLength() + " ("+fish.getStage()+")"); if (fish.getNumberOfReproduction() < 1) { numberOfFemaleSpawnerForFirstTime++; femaleSpawnersForFirstTimeAgesSum += fish.getAge(); } - numberOfFemaleGenitors += fish.getAmount() ; + numberOfFemaleGenitors += fish.getAmount() ; // on ajoute a chaque fois le fish.getAmount (CcumSum) // spawner per origine String basinName = fish.getBirthBasin().getName(); @@ -190,11 +193,49 @@ public class ReproduceAndSurviveAfterReproductionWithDiagnose extends AquaNismsG fish.incNumberOfReproduction(); // survival after reproduction (semelparity or iteroparity) of SI (change the amount of the SI) - survivalAmount = Miscellaneous.binomialForSuperIndividual(group.getPilot(), fish.getAmount(), survivalRateAfterReproduction); - if (survivalAmount > 0) - fish.setAmount(survivalAmount); + survivalAmount = Miscellaneous.binomialForSuperIndividual(group.getPilot(), fish.getAmount(), survivalRateAfterReproduction); + double biomass = 0.; + String origin; + if(fish.getBirthBasin()== riverBasin) + origin = "autochtonous"; else + origin = "allochtonous"; + if (survivalAmount > 0) {// SUperindividu est encore vivant mais il perd des effectifs + + //Export for fishes survived after spawning (survivalAmount) : excretion + gametes + Map <String, Double> aFluxAfterSurvival = group.getNutrientRoutine().computeNutrientsInputForSurvivalAfterSpawning(fish); + + //Export for fishes that dies after spawning (fish.getAmount - survivalAmount): excretion + gametes + carcasse + Map<String, Double> aFluxForDeadFish = group.getNutrientRoutine().computeNutrientsInputForDeathAfterSpawning(fish); + + for (String nutrient: aFluxAfterSurvival.keySet()) { + //For survival fish + totalInputFluxes.get(origin).put(nutrient,totalInputFluxes.get(origin).get(nutrient) + aFluxAfterSurvival.get(nutrient) * survivalAmount); + + //For dead fish + totalInputFluxes.get(origin).put(nutrient,totalInputFluxes.get(origin).get(nutrient) + aFluxForDeadFish.get(nutrient) * (fish.getAmount() - survivalAmount)); + } + + //compute biomass for dead fish + biomass = group.getNutrientRoutine().getWeight(fish) * (fish.getAmount() - survivalAmount); + totalInputFluxes.get(origin).put("biomass", totalInputFluxes.get(origin).get("biomass") + biomass); + + //update the amount of individual in the super-individual + fish.setAmount(survivalAmount); + } + else { + //Le superindividu est mort !!! deadFish.add(fish); + + //Export for fished died before spawning (fish.getAmount): carcasses + excretion + gametes + Map<String, Double> aFlux = group.getNutrientRoutine().computeNutrientsInputForDeathAfterSpawning(fish); // + + for (String nutrient: aFlux.keySet()) { + totalInputFluxes.get(origin).put(nutrient,totalInputFluxes.get(origin).get(nutrient) + aFlux.get(nutrient) * fish.getAmount()); //Fish.getAmount - survivalAmount = total fishes died. + } + biomass = group.getNutrientRoutine().getWeight(fish) * (fish.getAmount()); + totalInputFluxes.get(origin).put("biomass", totalInputFluxes.get(origin).get("biomass") + biomass); + } } } @@ -269,9 +310,9 @@ public class ReproduceAndSurviveAfterReproductionWithDiagnose extends AquaNismsG // -------------------------------------------------------------------------------------------------- // Reproduction process (number of recruits) // -------------------------------------------------------------------------------------------------- - + if (numberOfFemaleGenitors > 0.) { - + //BH Stock-Recruitment relationship with logistic depensation double meanNumberOfRecruit = stockRecruitmentRelationship.getRecruitment(numberOfFemaleGenitors); @@ -280,7 +321,7 @@ public class ReproduceAndSurviveAfterReproductionWithDiagnose extends AquaNismsG long numberOfRecruit = Math.round(Math.exp(genNormal.nextDouble()*sigmaRecruitment + muRecruitment)); //System.out.println(group.getPilot().getCurrentTime()+" "+Time.getSeason(group.getPilot())+" "+ riverBasin.getName()+": " + numberOfGenitors + " spwaners \tgive "+ numberOfRecruit + " recruits"); - + // keep last % of autochtone riverBasin.getLastPercentagesOfAutochtones().push(numberOfAutochtones * 100 / numberOfFemaleGenitors); @@ -350,28 +391,18 @@ public class ReproduceAndSurviveAfterReproductionWithDiagnose extends AquaNismsG // Remove deadfish and compute the related nutrient fluxes // -------------------------------------------------------------------------------------------------- for (DiadromousFish fish : deadFish){ - - Map<String, Double> aFlux = group.getFishNutrient().computeNutrientsInputForDeathAfterSpawning(fish); // - - for (String nutrient: aFlux.keySet()) { - - totalFluxes.put(nutrient,totalFluxes.get(nutrient) + aFlux.get(nutrient) * fish.getAmount()); - } - - - group.removeAquaNism(fish); } deadFish.clear(); - - //System.out.println(group.getPilot().getCurrentTime() + "; " + Time.getYear(group.getPilot()) + ";" + Time.getSeason(group.getPilot()) + ";" - //+ riverBasin.getName() + "; " + totalFluxes); - + + System.out.println(group.getPilot().getCurrentTime() + "; " + Time.getYear(group.getPilot()) + ";" + Time.getSeason(group.getPilot()) + ";IMPORT;" + + riverBasin.getName() + "; " + totalInputFluxes); + } else { riverBasin.setYearOfLastNulRep(Time.getYear(group.getPilot())); } - + // System.out.println("("+numberOfGenitors+")"); //System.out.println(" BEFORE " +riverBasin.getSpawnerOrigins().keySet());