public void updateBiomass( Ecosystem ecosystem, Map<Integer, SpeciesZoneType> nextSpeciesNodeList) { for (Entry<Integer, SpeciesZoneType> entry : nextSpeciesNodeList.entrySet()) { int species_id = entry.getKey(); SpeciesZoneType szt = entry.getValue(); int biomassValue = (int) entry.getValue().getCurrentBiomass(); Species species = ecosystem.getSpecies(szt.getSpeciesType().getID()); for (SpeciesGroup group : species.getGroups().values()) { group.setBiomass(biomassValue); EcoSpeciesDAO.updateBiomass(group.getID(), group.getBiomass()); } } }
public void setSpeciesBiomass( SpeciesZoneType szt, double perSpeciesBiomass, String ecosystemManipulationId) { // int node_id, int perSpeciesBiomass // If first time the ecosystemManipulationId may be null if (szt != null) { szt.setPerSpeciesBiomass(perSpeciesBiomass); } }
/** * Add multiple new nodes (SpeciesZoneType objects) to a manipulation and then submit. HJR * * @param manipSpeciesMap - species being added * @param fullSpeciesMap - full list; for predator/prey info * @param timestep * @param isFirstManipulation * @param networkOrManipulationId * @return manipulation ID (String) * @throws SimulationException */ public String addMultipleSpeciesType( HashMap<Integer, SpeciesZoneType> manipSpeciesMap, HashMap<Integer, SpeciesZoneType> fullSpeciesMap, int timestep, boolean isFirstManipulation, String networkOrManipulationId) { // job.setNode_Config("5, // [5],2000,1.000,1,K=9431.818,0, // [14],1751,20.000,1,X=0.273,0, // [31],1415,0.008,1,X=1.000,0, // [42],240,0.205,1,X=0.437,0, // [70],2494,13.000,1,X=0.155,0"); // In addMultipleSpeciesType: node [70], biomass 2494, K = -1, R = -1.0000, X = 0.1233 // In addMultipleSpeciesType: node [5], biomass 2000, K = 10000, R = 1.0000, X = 0.5000 // In addMultipleSpeciesType: node [42], biomass 240, K = -1, R = -1.0000, X = 0.3478 // In addMultipleSpeciesType: node [31], biomass 1415, K = -1, R = -1.0000, X = 0.7953 // In addMultipleSpeciesType: node [14], biomass 1752, K = -1, R = -1.0000, X = 0.0010 StringBuilder builder = new StringBuilder(); builder.append(fullSpeciesMap.size()).append(","); for (SpeciesZoneType species : fullSpeciesMap.values()) { System.out.printf( "In addMultipleSpeciesType: node [%d], " + "biomass %d, K = %d, R = %6.4f, X = %6.4f\n", species.getNodeIndex(), +(int) species.getCurrentBiomass(), (int) species.getParamK(), species.getParamR(), species.getParamX()); builder.append("[").append(species.getNodeIndex()).append("]").append(","); builder.append((int) species.getCurrentBiomass()).append(","); builder.append(roundToThreeDigits(species.getPerSpeciesBiomass())).append(","); String systemParam = this.setSystemParameters(species, fullSpeciesMap, timestep); builder.append(systemParam); System.out.println(builder); } String node_config = builder.substring(0, builder.length() - 1); // call processsim job here return node_config; }
/*5/5/14, JTC, added persistent species data for players; system parameter masterSpeciesList, replaces mSpecies. Get previous timestep biomass for all species from web service*/ public HashMap<Integer, SpeciesZoneType> getPrediction( String networkOrManipulationId, int startTimestep, int runTimestep, Map<Integer, Integer> addSpeciesNodeList, ZoneNodes zoneNodes) throws SimulationException { long milliseconds = System.currentTimeMillis(); Log.printf("\nPrediction at %d\n", startTimestep); // Get previous timestep biomass for all species from web service // JTC, use new HashMap containing all current settings from zoneNodes, masterSpeciesList // HJR changing to make a deep copy here , I am getting a null while iterating HashMap<Integer, SpeciesZoneType> masterSpeciesList = new HashMap<Integer, SpeciesZoneType>(zoneNodes.getNodes()); HashMap<Integer, SpeciesZoneType> mNewSpecies = new HashMap<Integer, SpeciesZoneType>(); // JTC, mUpdateBiomass renamed from mUpdateSpecies HashMap<Integer, SpeciesZoneType> mUpdateBiomass = new HashMap<Integer, SpeciesZoneType>(); // JTC, added new update type, mUpdateParams HashMap<Integer, SpeciesZoneType> mUpdateParams = new HashMap<Integer, SpeciesZoneType>(); SpeciesZoneType szt; String nodeConfig = null; SimJob job = new SimJob(); // {70=2494, 5=2000, 42=240, 14=1752, 31=1415} for (int node_id : addSpeciesNodeList.keySet()) { int addedBiomass = addSpeciesNodeList.get(node_id); if (!masterSpeciesList.containsKey(node_id)) { szt = createSpeciesZoneType(node_id, addedBiomass); mNewSpecies.put(node_id, szt); // jtc - 04/19/15 masterSpeciesList.put(node_id, szt); } else { szt = masterSpeciesList.get(node_id); szt.setCurrentBiomass(Math.max(0, szt.getCurrentBiomass() + addedBiomass)); szt.setBiomassUpdated(true); } } // //JTC, separated this to capture biomass updates made to ZoneNodes that // //are not received through addSpeciesNodeList (biomass and param updates) // for (SpeciesZoneType species : masterSpeciesList.values()) { // //param update also updates biomass, so insert into that list // //preferentially; o/w use biomass update list // if (species.paramUpdated) { // mUpdateParams.put(species.getNodeIndex(), species); // species.setParamUpdated(false); // } else if (species.biomassUpdated) { // mUpdateBiomass.put(species.getNodeIndex(), species); // species.setBiomassUpdated(false); // } // } // Insert new species using web services if (!mNewSpecies.isEmpty()) { zoneNodes.addNodes(mNewSpecies); } try { nodeConfig = addMultipleSpeciesType( mNewSpecies, masterSpeciesList, startTimestep, false, networkOrManipulationId); } catch (Exception ex) { Log.println_e(ex.getMessage()); } // // Update biomass changes to existing species using web services // if (!mUpdateBiomass.isEmpty()) { // List<NodeBiomass> lNodeBiomass = new ArrayList<NodeBiomass>(); // for (SpeciesZoneType s : mUpdateBiomass.values()) { // Log.printf("Updating Biomass: [%d] %s %f\n", s.getNodeIndex(), s.getName(), // s.getCurrentBiomass() / Constants.BIOMASS_SCALE); // lNodeBiomass.add(new NodeBiomass( // s.getCurrentBiomass() / Constants.BIOMASS_SCALE, s.getNodeIndex())); // } // try { //// updateBiomass(networkOrManipulationId, lNodeBiomass, startTimestep); // } catch (Exception ex) { // Log.println_e(ex.getMessage()); // } // } // // JTC Update changes to existing species parameters using web services (also // // resubmits biomass, but couldn't find a way to do params w/o biomass // if (!mUpdateParams.isEmpty()) { // try { //// increaseMultipleSpeciesType( //// mUpdateBiomass, //// masterSpeciesList, //// startTimestep, //// false, //// networkOrManipulationId //// ); // } catch (Exception ex) { // Log.println_e(ex.getMessage()); // } // } // run(startTimestep, runTimestep, networkOrManipulationId); // get new predicted biomass try { // JTC - changed variable from "mSpecies = " to "mUpdateBiomass = " // mUpdateBiomass = getBiomass(networkOrManipulationId, 0, startTimestep + runTimestep); if (!masterSpeciesList.isEmpty() || !mNewSpecies.isEmpty()) { mUpdateBiomass = submitManipRequest("ATN", nodeConfig, startTimestep + runTimestep, false, null); } } catch (Exception ex) { Log.println_e(ex.getMessage()); return null; } // getBiomassInfo(networkOrManipulationId); // JTC - add loop to update persistent player species biomass information SpeciesZoneType updS; for (SpeciesZoneType priorS : masterSpeciesList.values()) { System.out.println("priorS.nodeIndex " + priorS.nodeIndex); updS = mUpdateBiomass.get(priorS.nodeIndex); if (updS != null && updS.currentBiomass != 0) { masterSpeciesList .get(priorS.nodeIndex) .setCurrentBiomass(Math.ceil(updS.getCurrentBiomass())); } // else { // zoneNodes.removeNode(priorS.nodeIndex); // } } Log.printf( "Total Time (Get Prediction): %.2f seconds", Math.round((System.currentTimeMillis() - milliseconds) / 10.0) / 100.0); return (HashMap) zoneNodes.getNodes(); }
// loop through current job/results, assembling dataset private HashMap<Integer, SpeciesZoneType> genSpeciesDataset( SimJob job, EcosystemTimesteps ecosysTimesteps, Map<Integer, NodeRelationships> ecosysRelationships) { // calc information relevant to entire ecosystem int speciesCnt = ecosysTimesteps.getNodeList().size(); // Number of species int timesteps = ecosysTimesteps.getTimesteps(); // Maximum number of timesteps to run simulation int timestepsToSave = 0; // Number of timesteps of data to save to output file int[] matchingTimesteps = null; // Array of matching timesteps returned by findMatchingTimesteps() // read in link parameters; this was explicitly configured to allow // manipulation of link parameter values, but no manipulation is // performed in this version LinkParams lPs = new LinkParams(propertiesConfig); // loop through node values and assemble summary data int[] speciesID = new int[speciesCnt]; SimJobSZT[] sztArray = new SimJobSZT[speciesCnt]; int spNum = 0; for (NodeTimesteps nodeTimesteps : ecosysTimesteps.getTimestepMapValues()) { SimJobSZT sjSzt = job.getSpeciesZoneByNodeId(nodeTimesteps.getNodeId()); sztArray[spNum] = sjSzt; speciesID[spNum] = sjSzt.getNodeIndex(); spNum++; } // define objects to track species' contributions double[][][] contribs = new double[timesteps][speciesCnt][speciesCnt]; double[][] calcBiomass = new double[timesteps][speciesCnt]; double[][] contribsT; // current timestep // note: WebServices ATN Model uses B0 with default = 0.5. This presumes // that biomasses are small, i.e. < 1.0. Division by biomassScale // here is consistent with usage in WoB_Server.SimulationEngine to // normalize biomasses. // need to store bm as it varies over time through integration; // start with initial bm for each species double[] currBiomass = new double[speciesCnt]; for (int i = 0; i < speciesCnt; i++) { NodeTimesteps nodeTimeSteps = ecosysTimesteps.getTimestepMap().get(speciesID[i]); // manually set biomass vals for excluded initial timesteps; this // includes the first value to be used as input currBiomass[i] = nodeTimeSteps.getBiomass(initTimeIdx) / biomassScale; calcBiomass[0][i] = currBiomass[i]; } if (Constants.useCommonsMathIntegrator) { // Use Apache Commons Math GraggBulirschStoerIntegrator FirstOrderIntegrator integrator = new GraggBulirschStoerIntegrator( 1.0e-8, // minimal step 100.0, // maximal step ATNEquations.EXTINCT, // allowed absolute error 1.0e-10); // allowed relative error // Set up the ATN equations based on the current food web and parameters ATNEquations ode = new ATNEquations(sztArray, ecosysRelationships, lPs); ATNEventHandler eventHandler = new ATNEventHandler(ode); // FIXME: Choose best parameter values integrator.addEventHandler( new EventFilter(eventHandler, FilterType.TRIGGER_ONLY_DECREASING_EVENTS), 1, // maximal time interval between switching function checks (this interval prevents // missing sign changes in case the integration steps becomes very large) 0.0001, // convergence threshold in the event time search 1000, // upper limit of the iteration count in the event time search new BisectionSolver()); // Set up the StepHandler, which is triggered at each time step by the integrator, // and copies the current biomass of each species into calcBiomass[timestep]. // See the "Continuous Output" section of // https://commons.apache.org/proper/commons-math/userguide/ode.html FixedStepHandler fixedStepHandler = new FixedStepHandler() { public void init(double t0, double[] y0, double t) {} private int timestep = 0; public void handleStep(double t, double[] y, double[] yDot, boolean isLast) { // Ensure we don't go past the last time step due to rounding error if (timestep < calcBiomass.length) { System.arraycopy(y, 0, calcBiomass[timestep], 0, speciesCnt); } timestep++; } }; StepHandler stepHandler = new StepNormalizer(timeIntvl, fixedStepHandler); integrator.addStepHandler(stepHandler); // Run the integrator to compute the biomass time series integrator.integrate(ode, 0.0, currBiomass, timeIntvl * timesteps, currBiomass); if (eventHandler.integrationWasStopped()) { timestepsToSave = (int) (eventHandler.getTimeStopped() / timeIntvl); } else { // Check for an oscillating steady state, // and only save the data through the first period of the oscillation matchingTimesteps = findMatchingTimesteps(calcBiomass, timesteps - 1); System.err.println("\nmatchingTimesteps = " + Arrays.toString(matchingTimesteps)); // Save timesteps up through the second matching timestep, // or all timesteps if there was no second matching timestep. if (matchingTimesteps[1] != -1) { timestepsToSave = matchingTimesteps[1] + 1; } else { timestepsToSave = timesteps; } } } else { // Use BulirschStoerIntegration // create integration object boolean isTest = false; BulirschStoerIntegration bsi = new BulirschStoerIntegration( timeIntvl, speciesID, sztArray, ecosysRelationships, lPs, maxBSIErr, equationSet); // calculate delta-biomass and biomass "contributions" from each related // species for (int t = initTimeIdx + 1; t < timesteps; t++) { boolean success = bsi.performIntegration(time(initTime, t), currBiomass); if (!success) { System.out.printf("Integration failed to converge, t = %d\n", t); System.out.print(bsi.extrapArrayToString(biomassScale)); break; } currBiomass = bsi.getYNew(); System.arraycopy(currBiomass, 0, calcBiomass[t], 0, speciesCnt); contribsT = bsi.getContribs(); for (int i = 0; i < speciesCnt; i++) { System.arraycopy(contribsT[i], 0, contribs[t - 1][i], 0, speciesCnt); } } // timestep loop } if (useHDF5) { saveHDF5OutputFile( calcBiomass, speciesID, matchingTimesteps, job.getNode_Config(), timestepsToSave); return null; } double[][] webServicesData = new double[speciesCnt][timesteps]; if (Constants.useSimEngine) { // We need the webServicesData only for marginOfErrorCalculation // extract timestep data from CSV Functions.extractCSVDataRelns(job.getCsv(), ecosysTimesteps, ecosysRelationships); spNum = 0; for (NodeTimesteps nodeTimesteps : ecosysTimesteps.getTimestepMapValues()) { // copy nodetimestep data to local array for easier access System.arraycopy(nodeTimesteps.getBiomassArray(), 0, webServicesData[spNum], 0, timesteps); spNum++; } } // output data // A. print header psATN.printf("timesteps"); for (int i = 0; i < timesteps; i++) { psATN.printf(",%d", i); } psATN.println(); /* Convert to CSV String */ String biomassCSV = ""; biomassCSV = "Manipulation_id: " + job.getATNManipulationId() + "\n\n"; int maxTimestep = job.getTimesteps(); // Create Timestep Labels for (int j = 1; j <= maxTimestep; j++) { biomassCSV += "," + j; } HashMap<Integer, SpeciesZoneType> mSpecies = new HashMap<Integer, SpeciesZoneType>(); // loop through each species for (int i = 0; i < speciesCnt; i++) { if (Constants.useSimEngine) { psATN.printf("i.%d.sim", speciesID[i]); // B. print WebServices simulation data for species for (int t = 0; t < timesteps; t++) { psATN.printf(",%9.0f", webServicesData[i][t]); } psATN.println(); } // B. print combined biomass contributions (i.e. locally calculated biomass) // for current species. psATN.printf("i.%d.calc", speciesID[i]); for (int t = 0; t < timesteps; t++) { psATN.printf(",%9.0f", calcBiomass[t][i] * biomassScale); } psATN.println(); // //C. print individual biomass contributions from other species // for (int j = 0; j < speciesCnt; j++) { // psATN.printf("i.%d.j.%d.", speciesID[i], speciesID[j]); // for (int t = 0; t < timesteps; t++) { // psATN.printf(",%9.0f", contribs[t][i][j] * biomassScale); // } // psATN.println(); // } float extinction = 1.E-15f; SimJobSZT sjSzt = job.getSpeciesZoneByNodeId(speciesID[i]); // add nodes to list in the order that they are received from infos String name = sjSzt.getName().replaceAll(",", " ") + " [" + sjSzt.getNodeIndex() + "]"; String tempStr = name; for (int t = 0; t < maxTimestep; t++) { tempStr += ","; double biomass = calcBiomass[t][i] * biomassScale; if (biomass > 0) { tempStr += biomass > extinction ? Math.ceil(biomass) : 0; } if (t == maxTimestep - 1) { SpeciesZoneType szt = null; if (!mSpecies.containsKey(sjSzt.getNodeIndex())) { szt = new SpeciesZoneType(sjSzt.getName(), sjSzt.getNodeIndex(), 0, 0, biomass, null); mSpecies.put(sjSzt.getNodeIndex(), szt); } else { // update existing species current biomass szt = mSpecies.get(sjSzt.getNodeIndex()); szt.setCurrentBiomass(biomass); } } } biomassCSV += "\n" + tempStr; } // Append node config to the ATN CSV psATN.println(); psATN.println("\"node-config: " + job.getNode_Config() + "\""); biomassCSV += "\n\n"; biomassCSV += job.getConsumeMap().toString() + "\n\n"; biomassCSV += job.getPathTable().toString(); job.setBiomassCsv(biomassCSV); // System.out.println(biomassCSV); return mSpecies; }
/* Set all system parameters for a node (SpeciesZoneType) for a simulation run. HJR, original version of this, getSystemParameter() has some problems with how it submits link parameters. (1) orig uses call to SZT.getlPreyIndex(), which is not active (set by prior call to SpeciesType.getPreyIndex, which returns empty list) i.e. never actually submits any link params, default or otherwise! */ @SuppressWarnings("unused") private String setSystemParameters( SpeciesZoneType species, HashMap<Integer, SpeciesZoneType> fullSpeciesMap, int timestepIdx) { SpeciesTypeEnum type = species.getType(); int nodeIdx = species.getNodeIndex(); List<String> sParams = new ArrayList<String>(); StringBuilder builder = new StringBuilder(); if (type == SpeciesTypeEnum.PLANT) { // Carrying capacity(k) and GrowthRate(r) are only effective when species is plant // Higher Carrying capacity means higher biomass // for example, if carrying capacity is 10, maximum biomass of species is 10. // Higher growth rate means that species with higher growth rate will gain biomass faster. // Metabolic rate (x) are effective for both animals and plants // higher metabolic rate means that biomass of species will decrease compared to other species // YES, need to divide by Constants.BIOMASS_SCALE. setSystemParametersNode( sParams, timestepIdx, nodeIdx, species.getParamK(), ManipulatingParameterName.k, "carryingCapacityDefault"); if (false) { // HJR Currently I have turned off R and X setSystemParametersNode( sParams, timestepIdx, nodeIdx, species.getParamR(), ManipulatingParameterName.r, "growthRateDefault"); setSystemParametersNode( sParams, timestepIdx, nodeIdx, species.getParamX(), ManipulatingParameterName.x, "metabolicRateDefault"); } // Pack everything // [5],2000,1.000,1,K=9431.818,0, // [K=10.0, R=1.0, X=0.5] builder.append(sParams.size()).append(","); for (int i = 0; i < sParams.size(); i++) { builder.append(sParams.get(i)).append(","); } builder.append("0").append(","); } else if (type == SpeciesTypeEnum.ANIMAL) { // Metabolic rate (x) are effective for both animals and plants // higher metabolic rate means that biomass of species will decrease compared to other species // Assimilation efficiency (e) is only available for animals. // higher assimilation efficiency means that biomass of species will increase. setSystemParametersNode( sParams, timestepIdx, nodeIdx, species.getParamX(), ManipulatingParameterName.x, "metabolicRateDefault"); builder.append(sParams.size()).append(","); for (int i = 0; i < sParams.size(); i++) { builder.append(sParams.get(i)); builder.append(","); } sParams.clear(); // loop through prey, adding link parameters if (Integer.valueOf(propertiesConfig.getProperty("submitLinkParameterSettings")) == 1) { int preyCnt = species.getSpeciesType().getPreyNodeIDs().size(); for (int preyIdx : species.getSpeciesType().getPreyNodeIDs()) { if (fullSpeciesMap == null || !fullSpeciesMap.containsKey(preyIdx)) { continue; } /* separate note: there appear to be a limited number of link params that can be submitted, over which an "axis fault" error will occur. Varies with number of species in the ecosystem; on a test of a 15 species ecosystem, only 3 link params could be used. Have disabled all, as I am not using them at this time. Not fully evaluated, obviously, but these were not implemented at all previously. */ /* default values that mimic web-services internal defaults are: predatorInterferenceDefault = 0 assimilationEfficiencyAnimalDefault=1 assimilationEfficiencyPlantDefault=1 functionalResponseControlParameterDefault=0 halfSaturationDensityDefault=0.5 maximumIngestionRateDefault=6 >consistent default values were not found for the following and there is some confusion about their role - based on prior code, parameter "a" matches relativeHalfSaturationDensityDefault. parameter "a" does not appear in any of the equations that I've seen, (possibly omega - consumption rate?), but DOES impact the simulation results. No single value (0-1.0) gives result consistent to omitting the value, suggesting that species are distinguished somehow. Animal/Plant division was tested, but did not yield consistent results. relativeHalfSaturationDensityDefault=1.0 relativeHalfSaturationDensity = 0.01 */ //// sequence is // linkParamCnt,[prey_Id0],paramID0=value0,[prey_Id1],paramID1=value1,...[prey_IdN],paramIDN=valueN // setSystemParametersLink(sParams, timestepIdx, nodeIdx, preyIdx, // species.getParamA(preyIdx), // ManipulatingParameterName.a, "relativeHalfSaturationDensityDefault", preyCnt); if (false) { setSystemParametersLink( sParams, timestepIdx, nodeIdx, preyIdx, species.getParamB0(preyIdx), ManipulatingParameterName.b0, "halfSaturationDensityDefault", preyCnt); setSystemParametersLink( sParams, timestepIdx, nodeIdx, preyIdx, species.getParamD(preyIdx), ManipulatingParameterName.d, "predatorInterferenceDefault", preyCnt); setSystemParametersLink( sParams, timestepIdx, nodeIdx, preyIdx, species.getParamE(preyIdx), ManipulatingParameterName.e, "assimilationEfficiencyPlantDefault", preyCnt); setSystemParametersLink( sParams, timestepIdx, nodeIdx, preyIdx, species.getParamQ(preyIdx), ManipulatingParameterName.q, "functionalResponseControlParameterDefault", preyCnt); setSystemParametersLink( sParams, timestepIdx, nodeIdx, preyIdx, species.getParamY(preyIdx), ManipulatingParameterName.y, "maximumIngestionRateDefault", preyCnt); } } builder.append(sParams.size()).append(","); for (int i = 0; i < sParams.size(); i++) { builder.append(sParams.get(i)); builder.append(","); } System.out.println(builder); } } return builder.toString(); }