V4_0.java [src/java/m/rusle2] Revision: default Date:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package m.rusle2;
import csip.Config;
import csip.annotations.Description;
import csip.annotations.Name;
import csip.annotations.Resource;
import static csip.annotations.ResourceType.ARCHIVE;
import static csip.annotations.ResourceType.FILE;
import static csip.annotations.ResourceType.REFERENCE;
import csip.annotations.State;
import static csip.annotations.State.DEVELOPMENT;
import csip.annotations.VersionInfo;
import csip.api.server.Executable;
import csip.api.server.PayloadMetaInfo;
import csip.api.server.ServiceException;
import csip.utils.Client;
import csip.utils.JSONUtils;
import database.ServiceResources;
import static database.ServiceResources.LMOD_ID;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.ws.rs.Path;
import static m.rusle2.V3_0.OUT_JSON_TEMPLATE_FILENAME;
import static m.rusle2.V3_0.PYROME;
import static m.rusle2.V3_0.PYROMESRC;
import static m.rusle2.V3_0.PYTHON;
import static m.rusle2.V3_0.PYTHONZIP;
import static m.rusle2.V3_0.REPORT_JSON_TEMPLATE_FILENAME;
import static m.rusle2.V3_0.REPORT_PY_FILENAME;
import static m.rusle2.V3_0.ROMEDLL;
import static m.rusle2.V3_0.potResults;
import nodes.Management;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import soils.Component;
import soils.MapUnit;
import soils.db.SOILS_DATA;
import soils.db.SOILS_DB_Factory;
import soils.utils.EvalResult;
import static util.Constants.*;
/**
*
* @author Brad
*/
@Name("Rusle2_Ann")
@Description("Calls the ann service to run R2")
@VersionInfo("4.0")
@State(DEVELOPMENT)
@Path("m/rusle2/4.0")
@Resource(from = ServiceResources.class)
@Resource(type = FILE, file = "/bin/win-x86/2.6.8.4/RomeDLL.dll", id = ROMEDLL)
@Resource(type = FILE, file = "/bin/win-x86/2.6.8.4/pyrome.py", id = PYROMESRC)
@Resource(type = FILE, file = "/bin/win-x86/2.6.8.4/_pyrome.pyd", id = PYROME)
@Resource(type = ARCHIVE, file = "/bin/win-x86/Python34.zip", id = PYTHONZIP)
@Resource(type = REFERENCE, file = "${csip.dir}/bin/win-x86/Python34/python.exe", wine = true, id = PYTHON)
@Resource(type = FILE, file = "/bin/win-x86/rusle2_report.py", id = REPORT_PY_FILENAME)
@Resource(type = FILE, file = "/bin/win-x86/Rusle2_Report.json", id = REPORT_JSON_TEMPLATE_FILENAME)
@Resource(type = FILE, file = "/bin/win-x86/Rusle2_out.json", id = OUT_JSON_TEMPLATE_FILENAME)
public class V4_0 extends V3_0 {
private Management man;
private Component comp;
private int contour = 0;
private double ann_erosion;
public static void checkValidResultRequest(PayloadMetaInfo metainfo, Collection<String> results) throws ServiceException {
String[] j = metainfo.getStringArray(KEY_REQUEST_RESULTS);
for (int i = 0; i < j.length; i++) {
String name = j[i];
if (!results.contains(name)) {
throw new ServiceException("unknown result request :" + name);
}
}
}
@Override
protected void preProcess() throws Exception {
r2run.setLogger(LOG);
try {
reqResults = metainfo().getStringArray(KEY_REQUEST_RESULTS);
LOG.info("\n" + metainfo().toString());
checkValidResultRequest(metainfo(), potResults);
} catch (ServiceException se) {
LOG.severe("\n\n\nERROR!!!\n\n\n" + se.toString());
LOG.warning("No Rusle2 return parameters requested! Will use defaults: SLOPE_DELIVERY, SLOPE_T_VALUE, SLOPE_DEGRAD");
List<String> params = new LinkedList<>();
params.add(RES_SLOPE_DELIVERY);
params.add(RES_SLOPE_T_VALUE);
params.add(RES_SLOPE_DEGRAD);
// check if these are being set
if (parameter().has(KEY_CONTOUR_SYSTEM_PTR)) {
params.add("CONTOUR_SYSTEM_PTR");
}
if (parameter().has(KEY_STRIP_BARRIER_SYSTEM_PTR)) {
params.add("STRIP_BARRIER_SYSTEM_PTR");
}
if (parameter().has(KEY_HYD_ELEM_SYSTEM_PTR)) {
params.add("HYD_ELEM_SYSTEM_PTR");
}
reqResults = params.toArray(new String[0]);
}
parameter().require(KEY_SOILS, KEY_LENGTH, KEY_STEEPNESS, KEY_MGMTS);
File r2script = new File(workspace().getDir(), R2_TMP_FILENAME + R2_TMP_FILEEXT);
createInputFile(r2script, getParamMap());
gatherAnnData();
}
protected void gatherAnnData() throws Exception {
// get management data
if (managements.length() > 1) {
throw new ServiceException("R2 Ann does not handle multiple managements yet.");
}
try (Connection connection = resources().getJDBC(LMOD_ID)) {
org.json.JSONObject managementCopy = new org.json.JSONObject(managements.getJSONObject(0).toString());
man = new Management(connection, managementCopy);
}
// get soil data
getSoilData(aSoils);
if (!(contourSystem.equals("") || contourSystem.equals("(none)"))) {
contour = 1;
}
getR_factor();
}
private void getSoilData(JSONArray cokeys) throws JSONException, Exception {
String cokey;
MapUnit mUnit;
cokey = cokeys.getString(0);
comp = new Component();
comp.cokey(cokey);
mUnit = getSoilMapUnit();
}
private MapUnit getSoilMapUnit() throws ServiceException, SQLException, Exception {
MapUnit mapUnit = new MapUnit(comp);
try (SOILS_DATA soilsDb = SOILS_DB_Factory.createEngine(getClass(), LOG, Config.getString("soils.gis.database.source"))) {
soilsDb.findHorizonsForCokey(mapUnit, comp);
}
comp.slopelenusle_r(verifyValue(comp.slopelenusle_l(), comp.slopelenusle_r(), comp.slopelenusle_h()));
comp.slope_r(verifyValue(comp.slope_l(), comp.slope_r(), comp.slope_h()));
return mapUnit;
}
private double verifyValue(double low_c, double regular_c, double high_c) {
double value;
if (EvalResult.testDefaultDouble(low_c)) {
low_c = 0; // this is an assumption about null values
}
if (EvalResult.testDefaultDouble(high_c)) {
high_c = 0; // this is an assumption about null values
}
if (EvalResult.testDefaultDouble(regular_c)) {
value = low_c + high_c / 2;
} else {
value = regular_c;
}
return value;
}
@Override
protected void doProcess() throws Exception {
try {
Executable python = resources().getExe(V3_0.PYTHON);
LOG.log(Level.INFO, "EXECUTING PYROME FROM doProcess()...");
int result = r2run.executePyrome(new File(workspace().getDir(), R2_TMP_FILENAME + R2_TMP_FILEEXT), python, getSUID());
callAnn();
} catch (Exception e) {
LOG.log(Level.SEVERE, "ERROR EXECUTING PYTHON-RUSLE2", e);
throw e;
}
}
private void callAnn() throws JSONException, Exception {
JSONObject annRequest = new JSONObject();
JSONObject meta = new JSONObject();
JSONArray paramObj = new JSONArray();
JSONObject jannName;
JSONObject jslope;
JSONObject jlength;
JSONObject jstir;
JSONObject jcontour;
JSONObject jkfact;
JSONObject jsand;
JSONObject jsilt;
JSONObject jclay;
JSONObject jbiomass;
JSONObject jr_factor;
JSONObject annResponse;
JSONArray resultArr;
JSONObject jresult;
JSONObject responseMeta;
Double stir;
annRequest.put(KEY_METAINFO, meta);
annRequest.put(KEY_PARAMETER, paramObj);
jannName = new JSONObject();
jannName.put(KEY_NAME, ANNNAME);
jannName.put(VALUE, Config.getString("ann.name"));
paramObj.put(jannName);
jslope = new JSONObject();
jslope.put(KEY_NAME, SLOPE);
jslope.put(VALUE, steepness);
paramObj.put(jslope);
jlength = new JSONObject();
jlength.put(KEY_NAME, LENGTH);
jlength.put(VALUE, length);
paramObj.put(jlength);
stir = man.calcAverageStir();
if (stir > 110) {
stir = 110.0;
}
jstir = new JSONObject();
jstir.put(KEY_NAME, STIR);
jstir.put(VALUE, stir);
paramObj.put(jstir);
jcontour = new JSONObject();
jcontour.put(KEY_NAME, CONTOUR);
jcontour.put(VALUE, contour);
paramObj.put(jcontour);
jkfact = new JSONObject();
jkfact.put(KEY_NAME, KFFACT);
jkfact.put(VALUE, comp.calculated_kffact());
paramObj.put(jkfact);
jsand = new JSONObject();
jsand.put(KEY_NAME, SAND);
jsand.put(VALUE, comp.calculated_sandtotal_r());
paramObj.put(jsand);
jsilt = new JSONObject();
jsilt.put(KEY_NAME, SILT);
jsilt.put(VALUE, comp.calculated_silttotal_r());
paramObj.put(jsilt);
jclay = new JSONObject();
jclay.put(KEY_NAME, CLAY);
jclay.put(VALUE, comp.calculated_claytotal_r());
paramObj.put(jclay);
jbiomass = new JSONObject();
jbiomass.put(KEY_NAME, BIOMASS);
jbiomass.put(VALUE, man.calcBiomass());
paramObj.put(jbiomass);
jr_factor = new JSONObject();
jr_factor.put(KEY_NAME, R_FACTOR);
jr_factor.put(VALUE, r_factor);
paramObj.put(jr_factor);
LOG.info("ANN Request: " + annRequest.toString());
annResponse = new Client().doPOST(Config.getString("r2.ann", "http://csip.engr.colostate.edu:8088/csip-ann/m/run/1.0"), annRequest);
LOG.info("ANN Response: " + annResponse.toString());
responseMeta = annResponse.getJSONObject(KEY_METAINFO);
if (!responseMeta.getString(KEY_STATUS).equalsIgnoreCase("Failed")) {
resultArr = annResponse.getJSONArray(KEY_RESULT);
jresult = resultArr.getJSONObject(0);
ann_erosion = jresult.getDouble(VALUE);
} else {
String error = responseMeta.getString(ERROR);
metainfo().appendWarning(error);
}
}
@Override
protected void postProcess() throws Exception {
int errors = 0;
for (int i = 0; i < operations.size(); i++) {
String op = operations.get(i);
if (r2run.isUrlReachable(op)) {
results().put("OPERATION_" + (i + 1), op, "operation is valid");
} else {
results().put("OPERATION_INVALID_" + (i + 1), op, "OPERATION IS MISSING!");
errors++;
}
}
for (int i = 0; i < vegetations.size(); i++) {
String vege = vegetations.get(i);
if (r2run.isUrlReachable(vege)) {
results().put("VEGETATION_" + (i + 1), vege, "vegetation is valid");
} else {
results().put("VEGETATION_INVALID_" + (i + 1), vege, "VEGETATION IS MISSING");
errors++;
}
}
for (int i = 0; i < residues.size(); i++) {
String res = residues.get(i);
if (r2run.isUrlReachable(res)) {
results().put("RESIDUE_" + (i + 1), res, "residue is valid");
} else {
results().put("RESIDUE_INVALID_" + (i + 1), res, "RESIDUE IS MISSING");
errors++;
}
}
for (String r : reqResults) {
if ((errors > 0) && (r.equals(RES_SLOPE_DEGRAD))) {
results().put(r, r2run.getResultPyrome(r), R2_MISSING_XML_FILES_WARNING_MSG);
} else {
results().put(r, r2run.getResultPyrome(r));
}
}
// Get erosion for segments
if (JSONUtils.checkKeyExistsB(getParamMap(), KEY_TOPO_LENGTH)) {
JSONArray aTopoLength = JSONUtils.getJSONArrayParam(getParamMap(), KEY_TOPO_LENGTH);
if (aTopoLength.length() > 0) {
JSONArray aSoilLoss = new JSONArray(r2run.getResultPyromeArray("SEG_SOIL_LOSS", false, false, true));
results().put("SEG_SOIL_LOSS", aSoilLoss);
results().put(KEY_CLIMATES, climate);
LOG.info("\n\n\n\n\n\nSEG SOIL OUTPUT=" + r2run.getResultPyromeArray("SEG_SOIL", true, true, true) + "\n\n\n\n");
LOG.info("\n\n\n\n\n\nSEG SOIL OUTPUT=" + r2run.getResultPyromeArray("SEG_MAN", true, true, true) + "\n\n\n\n");
results().put(KEY_SOILS, new JSONArray(r2run.getResultPyromeArray("SEG_SOIL", true, true, true)));
results().put(KEY_MANAGEMENTS, new JSONArray(r2run.getResultPyromeArray("SEG_MAN", true, true, true)));
if (JSONUtils.checkKeyExistsB(getParamMap(), KEY_DIVERSIONS)) {
results().put(KEY_DIVERSIONS, r2run.getResultPyromeArray("HYD_ELEM_SYS", true, true, true));
}
if (JSONUtils.checkKeyExistsB(getParamMap(), KEY_STRIP_BARRIER_SYSTEMS)) {
results().put(KEY_STRIP_BARRIER_SYSTEMS, r2run.getResultPyromeArray("STRIP_BARRIER_SYS", true, true, true));
}
}
} else {
results().put(KEY_CLIMATES, climate);
results().put(KEY_SOILS, new JSONArray(r2run.getResultPyromeArray("SEG_SOIL", true, true, true)));
results().put(KEY_MANAGEMENTS, new JSONArray(r2run.getResultPyromeArray("SEG_MAN", true, true, true)));
}
results().put(KEY_ANN_EROSION, ann_erosion);
}
@Override
protected Map<String, Object> getConfigInfo() {
return new LinkedHashMap<String, Object>() {
{
put(ROMEDLL, resources().getResolved(ROMEDLL));
}
};
}
}