DiadromousFishGroup.java 25.90 KiB
package species;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import environment.Basin;
import environment.BasinNetwork;
import environment.BasinNetworkReal;
import environment.RiverBasin;
import fr.cemagref.observation.kernel.Observable;
import fr.cemagref.simaqualife.kernel.AquaNismsGroup;
import fr.cemagref.simaqualife.kernel.Processes;
import fr.cemagref.simaqualife.pilot.Pilot;
import java.awt.Color;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import miscellaneous.Duo;
import miscellaneous.TreeMapForCentile;
import species.DiadromousFish.Gender;
import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = AquaNismsGroup.class)
public class DiadromousFishGroup extends AquaNismsGroup< DiadromousFish, BasinNetwork> implements Comparable<DiadromousFishGroup> {
	public String name = "species A";
	public Color color = Color.RED;
	/**
	 * L infinity of the van Bertalanffy growth curve
	 * L = Linf *(1-exp(-K*(t-t0))
	 * @unit cm
	public double linfVonBert = 60.;
	/**
	 *  ????
	 * @unit
	public double dMaxDisp = 300.;
	/**
	 *  length at first maturity. At that length the fish become Stage.MATURE
	 * @unit cm
	public double lFirstMaturity = 40.;
	/**
	 * Routine to compute nutrient fluxes operated by a single individual (TODO by a single super individual). 
	private  NutrientRoutine nutrientRoutine; 
	public String fileNameInputForInitialObservation = "data/input/reality/Obs1900.csv";
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
/** * centile to calucale the range of species distribution * @unit */ public double centileForRange = 0.95; /** * file with the calibated parameters (from baysian approach) * @unit */ private String parameterSetfileName= "data/input/reality/parameterSet.csv"; /** * line to use in the calibrated parameters file * @unit */ private int parameterSetLine =0; /** * year when the update of the basin should occur * @unit */ private long yearOfTheUpdate; /** * list of the basins to be updated * column 1: name of the basin * column 2: Pattractive: how the bassin become attractive (0 not attractive, 1 ??? normal weight associated to catchment size) * column 3: Paccessible: how the bassin become acesssible (0 not accessible, 1 ???normal weight to inter catchment distance ) * @unit */ private String basinsToUpdateFile = "data/input/reality/basinsToUpdate.csv"; private String outputPath = "data/output/"; private String fileNameFluxes = "fluxes"; private transient BufferedWriter bWForFluxes; private transient String sep; /** * map * <key> basin name * <value> Duo * <first> pAttractive * <second> pAccessible * @unit */ private transient Map<String, Duo<Double, Double>> basinsToUpdate; /** * Brody growth coefficient of the von Bertalanffy growth curve (from the parameterset file) * * L = Linf *(1-exp(-K*(t-t0)) * @unit year-1 */ private transient double kOpt; /** * minimum temperature for the reproduction (from the parameterset file) * @unit °C */ private transient double tempMinRep; //parametre de reproduction /** * list of the parameters provided by the calibration * @unit */ private transient List<Duo<Double, Double>> parameterSets;
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
public static void main(String[] args) { DiadromousFishGroup diadromousFishGroup = new DiadromousFishGroup(new Pilot(), null, null); double aResidenceTime =30; 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 /* * A feature pre spawning */ Map<DiadromousFish.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); /* * a Feature post Spawning */ Map<DiadromousFish.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);
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
Map<DiadromousFish.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 // carcass composition for fish before spawning Map<DiadromousFish.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); // carcass composition for fish after spawning Map<DiadromousFish.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); // Gametes composition approximated by the difference between gonads weight before and after spawning. Map<DiadromousFish.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); // 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"))); // 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 ArrayList <String> nutrientsOfInterest= new ArrayList <String>(); nutrientsOfInterest.add("N"); nutrientsOfInterest.add("P"); diadromousFishGroup.nutrientRoutine = new NutrientRoutine(nutrientsOfInterest,aResidenceTime, anExcretionRate, aFeaturePreSpawning, aFeaturePostSpawning, aCompoCarcassPreSpawning, aCompoCarcassPostSpawning, aCompoGametes, aJuvenileFeatures, aCompoJuveniles);
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
System.out.println((new XStream(new DomDriver())).toXML(diadromousFishGroup)); } public DiadromousFishGroup(Pilot pilot, BasinNetwork environment, Processes processes) { super(pilot, environment, processes); } public double getPattractive(String basinName){ // TODO pass in argument a Basin // remove "-s" of the sea basin name String shortBasinName = basinName.substring(0, basinName.length()-2); if (basinsToUpdate.containsKey(shortBasinName)) return basinsToUpdate.get(shortBasinName).getFirst(); else return Double.NaN; } public double getPaccessible(String basinName){ // TODO pass in argument a Basin //WHY not a short name if (basinsToUpdate.containsKey(basinName)) return basinsToUpdate.get(basinName).getSecond(); else return Double.NaN; } /** * @return the yearOfTheUpdate */ public long getYearOfTheUpdate() { return yearOfTheUpdate; } /* (non-Javadoc) * @see fr.cemagref.simaqualife.kernel.AquaNismsGroup#initTransientParameters(fr.cemagref.simaqualife.pilot.Pilot) */ @Override public void initTransientParameters(Pilot pilot) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { super.initTransientParameters(pilot); // basin to be updated if ( basinsToUpdate != null){ String subDir=basinsToUpdateFile; if (basinsToUpdateFile.lastIndexOf("/")!=-1) subDir=basinsToUpdateFile.substring(basinsToUpdateFile.lastIndexOf("/")+1, basinsToUpdateFile.length()); if (subDir.lastIndexOf(".")!=-1) subDir=subDir.substring(0, subDir.lastIndexOf(".")); outputPath= outputPath.concat(subDir).concat("/"); System.out.println(outputPath); basinsToUpdate = new HashMap<String, Duo<Double, Double>>(); FileReader reader; Scanner scanner; String basins; double pAttractive; double pAccessible; try { // open the file reader = new FileReader(basinsToUpdateFile); // Parsing the file scanner = new Scanner(reader); scanner.useLocale(Locale.ENGLISH); // to have a comma as decimal separator !!! scanner.useDelimiter(Pattern.compile("[;\r]")); scanner.nextLine();
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
while (scanner.hasNext()) { basins = scanner.next(); if (basins!= null) { pAttractive = scanner.nextDouble(); pAccessible = scanner.nextDouble(); scanner.nextLine(); Duo<Double, Double> duo=new Duo<Double, Double>(pAttractive, pAccessible); basinsToUpdate.put(basins, duo); } } reader.close(); } catch (Exception e) { e.printStackTrace(); } } // charge kopt et temMinRep depuis le fichier de parametre. Sinon (parameterSetLine<=0), ce sont les // valeur dasn le procoessus de reroduction qui sont utilis� kOpt=Double.NaN; tempMinRep =Double.NaN; if (parameterSetLine>0){ parameterSets = new ArrayList<Duo<Double,Double>>(10); // open the file FileReader reader1; Scanner scanner1; try { reader1 = new FileReader(parameterSetfileName); // Parsing the file scanner1 = new Scanner(reader1); scanner1.useLocale(Locale.ENGLISH); // to have a comma as decimal separator !!! scanner1.useDelimiter(Pattern.compile("[;\r]")); scanner1.nextLine(); // skip the first line while (scanner1.hasNext()) { String rien= scanner1.next(); // skip id //System.out.println(rien.compareTo("\n")); if(rien.compareTo("\n")!=0){ Duo<Double, Double> duo=new Duo<Double, Double>(scanner1.nextDouble(), scanner1.nextDouble()); //System.out.println(duo.toString()); parameterSets.add(duo); } } scanner1.close(); reader1.close(); } catch (Exception e) { e.printStackTrace(); } kOpt = parameterSets.get(parameterSetLine-1).getFirst(); tempMinRep = parameterSets.get(parameterSetLine-1).getSecond(); } // open an bufferad writer to export fluxes if (fileNameFluxes != null){ sep = ";"; new File(this.outputPath +fileNameFluxes).getParentFile().mkdirs(); try { bWForFluxes = new BufferedWriter(new FileWriter(new File(this.outputPath+ fileNameFluxes +this.getSimulationId() + ".csv"))); bWForFluxes.write("timestep"+sep+"year"+sep+"season"+sep+"basin" +sep+"abundance" + sep + "fluxType"+ sep + "origin" +sep+"biomass"); for (String nutrient : nutrientRoutine.getNutrientsOfInterest()) { bWForFluxes.write(sep+nutrient); } bWForFluxes.write("\n");
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
} catch (IOException e) { e.printStackTrace(); } } } /** * @return the bWForFluxes */ public BufferedWriter getbWForFluxes() { return bWForFluxes; } public double getKOpt(){ return kOpt; } public double getTempMinRep(){ return tempMinRep; } @Observable(description = "Nb of SI") public int getNbSI() { int nbSI = 0; for (Basin basin : this.getEnvironment().getBasins() ) { if (basin.getFishs(this) != null) nbSI += basin.getFishs(this).size(); } return nbSI; } @Observable(description = "Sizes mean of SI") public double getSizesMeanOfSI() { double totalEffective = 0; double nbSI =0; for (Basin basin : this.getEnvironment().getBasins() ) { if (basin.getFishs(this) != null) { nbSI += basin.getFishs(this).size(); for (DiadromousFish superFish : basin.getFishs(this)) { totalEffective += superFish.getAmount(); } } } if (nbSI >=0) return totalEffective /nbSI; else return Double.NaN; } @Observable(description = "# of SI with ind < 10") public double getNbLittleSI() { double nb = 0; for (Basin basin : this.getEnvironment().getBasins() ) { if (basin.getFishs(this) != null) { for (DiadromousFish superFish : basin.getFishs(this)) { if ( superFish.getAmount()<10L) nb++; } } } return nb; } public double getMeanLengthOfMatureFish(){ double sumOfLength = 0.; double numberOfMatureFish = 0.; for (Basin basin : this.getEnvironment().getBasins() ) { if (basin.getFishs(this) != null) {
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
for (DiadromousFish fish : basin.getFishs(this)) { if (fish.isMature()){ sumOfLength += fish.getAmount() * fish.getLength(); numberOfMatureFish += fish.getAmount(); } } } } return sumOfLength / numberOfMatureFish; } public double getStandardDeviationOfMatureFishLength(){ double standardDeviationOfMatureFishLength = 0.; double sumOfSquareLength = 0.; double numberOfMatureFish = 0.; double meanOfSquareLengthOfMatureFish = 0.; for (Basin basin : this.getEnvironment().getBasins() ) { if (basin.getFishs(this) != null) { for (DiadromousFish fish : basin.getFishs(this)) { if (fish.isMature()){ sumOfSquareLength += fish.getAmount() * fish.getLength() * fish.getLength(); numberOfMatureFish += fish.getAmount(); } } } meanOfSquareLengthOfMatureFish = sumOfSquareLength / numberOfMatureFish; double meanLength = getMeanLengthOfMatureFish(); standardDeviationOfMatureFishLength = Math.sqrt(meanOfSquareLengthOfMatureFish - meanLength * meanLength); } return standardDeviationOfMatureFishLength; } public String getName() { return name; } public Color getColor() { return color; } public double getLinfVonBert() { return linfVonBert; } public void setLinfVonBert(double linfVonBert) { this.linfVonBert = linfVonBert; } public double getdMaxDisp() { return dMaxDisp; } public double getlFirstMaturity() { return lFirstMaturity; } public NutrientRoutine getNutrientRoutine() { return nutrientRoutine; } public void setlFirstMaturity(double lFirstMaturity) { this.lFirstMaturity = lFirstMaturity; } // ================================================================ // statictis for calibration // ================================================================ @Observable(description="Spawners For First Time Summary Statistic")
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
public double computeSpawnerForFirstTimeSummaryStatistic() { double sum = 0; //TODO move TARGET to the right place double TARGET = 5.0; for (RiverBasin riverBasin : getEnvironment().getRiverBasins()) { if (riverBasin.getSpawnersForFirstTimeMeanAges().getMeanWithoutZero() > 0.) { double val = riverBasin.getSpawnersForFirstTimeMeanAges().getMeanWithoutZero() - TARGET; sum += val * val; } } return sum; } @Observable(description = "Likelihood Summary stat") public double computeLikelihood() throws IOException { // 1 : read input file of observation FileReader reader; Scanner scanner; //TODO move the obs1900 and the scanner Map<String, Integer> obs1900 = new HashMap<String, Integer>(); try { reader = new FileReader(fileNameInputForInitialObservation); // Parsing the file scanner = new Scanner(reader); scanner.useLocale(Locale.ENGLISH); // to have a comma as decimal separator !!! scanner.useDelimiter(Pattern.compile("[;\r]")); scanner.nextLine(); // to skip the file first line of entete while (scanner.hasNext()) { obs1900.put(scanner.next().replaceAll("\n", ""), scanner.nextInt()); } reader.close(); scanner.close(); } catch (IOException ex) { Logger.getLogger(DiadromousFishGroup.class.getName()).log(Level.SEVERE, null, ex); } int obsVal; double sumLogWherePres = 0.; double sumLogWhereAbs = 0.; final double[] probOfNonNulRecruitmentDuringLastYears = getEnvironment().getProbOfNonNulRecruitmentDuringLastYears(); final String[] finalStatesNames = getEnvironment().getRiverBasinNames(); for (int i = 0; i < finalStatesNames.length; i++) { if (obs1900.containsKey(finalStatesNames[i])) { obsVal = obs1900.get(finalStatesNames[i]); if (obsVal == 0) { sumLogWhereAbs += Math.log(1 - probOfNonNulRecruitmentDuringLastYears[i]); } else { sumLogWherePres += Math.log(probOfNonNulRecruitmentDuringLastYears[i]); } } } return sumLogWhereAbs + sumLogWherePres; } // ======================================================== // obeserver to explore the distribution // ======================================================== @Observable(description="Higher Populated Latitude") public double getHigherPopulatedLatitude() { double latitude = 0.0; RiverBasin[] basins = getEnvironment().getRiverBasins(); int[] finalStates = getEnvironment().getFinalStates(); for (int i = 0; i < finalStates.length; i++) { if ((finalStates[i] == 1) && (basins[i].getLatitude() > latitude)) {
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
latitude = basins[i].getLatitude(); } } return latitude; } @Observable(description="Number of colonized basins") public double getNbColonizedBasins() { int nb = 0; for (Basin seaBasin : getEnvironment().getSeaBasins()) { if (seaBasin.getFishs(this) != null) { if (!seaBasin.getFishs(this).isEmpty()) { nb++; } } } return nb; } @Observable(description="Northern colonized basins") public double getNorthernBasins() { int northernBasin = Integer.MAX_VALUE; for (Basin seaBasin : getEnvironment().getSeaBasins()) { if (seaBasin.getFishs(this) != null) { if (!seaBasin.getFishs(this).isEmpty()) { northernBasin = Math.min(northernBasin, getEnvironment().getAssociatedRiverBasin(seaBasin).getId()); } } } return northernBasin; } @Observable(description="Southern colonized basins") public double getSouthernBasins() { int southernBasin = Integer.MIN_VALUE; for (Basin seaBasin : getEnvironment().getSeaBasins()) { if (seaBasin.getFishs(this) != null) { if (!seaBasin.getFishs(this).isEmpty()) { southernBasin = Math.max(southernBasin, getEnvironment().getAssociatedRiverBasin(seaBasin).getId()); } } } return southernBasin; } @Observable(description = "Range distribution with latitude") public Double[] getRangeDistributionWithLat() { //TODO keep the extreme latitudes from the catchment double southernBasin = 35.; double northernBasin = 60.; RiverBasin riverBasin; TreeMapForCentile latitudeEffective = new TreeMapForCentile(); for (Basin seaBasin : getEnvironment().getSeaBasins()) { if (seaBasin.getFishs(this) != null) { if (!seaBasin.getFishs(this).isEmpty()) { riverBasin = (RiverBasin) getEnvironment().getAssociatedRiverBasin(seaBasin); long effective = 0; for (DiadromousFish fish : seaBasin.getFishs(this)){ effective += fish.getAmount(); } southernBasin = Math.max(southernBasin, riverBasin.getLatitude()); latitudeEffective.putWithAdding(riverBasin.getLatitude(), effective); northernBasin = Math.min(northernBasin, riverBasin.getLatitude()); } } }
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
Double[] rangeDistribution = new Double[4]; rangeDistribution[0]= (latitudeEffective.isEmpty() ? (southernBasin +northernBasin)/2. : latitudeEffective.calculateMedian()); rangeDistribution[1]= Math.min(southernBasin,northernBasin); rangeDistribution[2]= Math.max(southernBasin,northernBasin); rangeDistribution[3]= latitudeEffective.calculateCentile(centileForRange); return rangeDistribution; } @Observable(description = "Range distribution") public Double[] getRangeDistribution() { double southernBasin = 0; double nbBasin = getEnvironment().getNbBasin(); double northernBasin = nbBasin; Basin riverBasin; TreeMapForCentile latitudeEffective = new TreeMapForCentile(); for (Basin seaBasin : getEnvironment().getSeaBasins()) { if (seaBasin.getFishs(this) != null) { if (!seaBasin.getFishs(this).isEmpty()) { riverBasin = getEnvironment().getAssociatedRiverBasin(seaBasin); long effective = 0; for (DiadromousFish fish : seaBasin.getFishs(this)){ effective += fish.getAmount(); } latitudeEffective.putWithAdding(riverBasin.getId(), effective); southernBasin = Math.max(southernBasin, riverBasin.getId()); northernBasin = Math.min(northernBasin, riverBasin.getId()); } } } southernBasin = nbBasin - southernBasin; northernBasin = nbBasin - northernBasin; Double[] rangeDistribution = new Double[3]; rangeDistribution[0]= (latitudeEffective.isEmpty() ? (southernBasin +northernBasin)/2. : nbBasin - latitudeEffective.calculateMedian()); rangeDistribution[1]= Math.min(southernBasin,northernBasin); rangeDistribution[2]= Math.max(southernBasin,northernBasin); return rangeDistribution; } /** * @return sum of effectives in all the river basins */ @Observable(description = "Number of fishes in river basin") public double getFishEffective() { long eff = 0; for (RiverBasin basin : this.getEnvironment().getRiverBasins()){ if (basin.getFishs(this) != null) { for (DiadromousFish fish : basin.getFishs(this)) { eff += fish.getAmount(); } } } return eff; } @Override public void addAquaNism(DiadromousFish fish) { // avoid utilisation of global fishes list //super.addAquaNism(fish); fish.getPosition().addFish(fish, this); } @Override public void removeAquaNism(DiadromousFish fish) {
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
// avoid utilisation of global fishes list //super.removeAquaNism(fish); fish.getPosition().removeFish(fish, this); } @Override public int compareTo(DiadromousFishGroup t) { return name.compareTo(t.name); } /** * * concat at RngSatusIndex, temperatureCatchmentFile * @return simulation name */ public String getSimulationId(){ String id="_"; id=id.concat(Integer.toString(getPilot().getParameters().getRngStatusIndex())); String temperatureFile = ((BasinNetworkReal) getPilot().getAquaticWorld().getEnvironment()).getTemperatureCatchmentFile(); id=id.concat("-").concat(temperatureFile.substring(temperatureFile.length()-9, temperatureFile.length()-4)); if (parameterSetLine>0){ id=id.concat("-").concat(Integer.toString(parameterSetLine)); } return id ; } public boolean isThereBasinToUpdate(){ return basinsToUpdate != null; } /** * @return the outputPath */ public String getOutputPath() { return outputPath; } }