V1_0.java [src/java/d/soils/aggsoilparams] 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 d.soils.aggsoilparams;
import csip.Config;
import csip.ModelDataService;
import csip.annotations.Description;
import csip.annotations.Name;
import csip.annotations.Resource;
import csip.api.server.ServiceException;
import csip.utils.JSONUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.ws.rs.Path;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import soils.Component;
import soils.Horizon;
import soils.MapUnit;
import soils.db.SOILS_DATA;
import soils.db.SOILS_DB_Factory;
import utils.EvalResult;
import java.util.LinkedHashMap;
import static soils.db.DBResources.SDM;
/**
*
* @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
*/
@Name("AggSoilParams")
@Description("Returns component horizon data aggrigated by horizon layers within upper, lower and sub root zones")
@Path("d/aggsoilparams/1.0")
@Resource(from = soils.db.DBResources.class)
public class V1_0 extends ModelDataService {
static final String KEY_COKEY = "cokey";
static final String KEY_URZ = "urz_bd";
static final String KEY_LRZ = "lrz_bd";
static final double DEFAULT_MISSING_VALUE = Double.NaN;
protected Component comp = null;
protected MapUnit mapUnit = null;
protected String cokey;
protected ArrayList<HorizonDataExt> extData = new ArrayList<>();
protected int urz_bd;
protected int lrz_bd;
@Override
protected void preProcess() throws Exception {
cokey = parameter().getString(KEY_COKEY);
urz_bd = parameter().getInt(KEY_URZ, 30);
lrz_bd = parameter().getInt(KEY_LRZ, 90);
}
@Override
protected Map<String, Object> getConfigInfo() {
return new LinkedHashMap<String, Object>() {
{
put("soils.gis.database.source", resources().getResolved("soils.gis.database.source"));
put(SDM, resources().getResolved(SDM));
put("fpp.version", "asp 1.0");
}
};
}
@Override
protected void doProcess() throws Exception {
comp = new Component();
comp.cokey(cokey);
// Get the WEPP filtered SOILS data for the cokey provided.
try (SOILS_DATA soilsDb = SOILS_DB_Factory.createEngine(getClass(), LOG, Config.getString("soils.gis.database.source"))) {
if (soilsDb.validateComponent(Integer.parseInt(comp.cokey()))) {
if (null == (mapUnit = soilsDb.findWEPPDataByCokey(comp))) {
throw new ServiceException("Could not retrieve the proper SDM soils data for this cokey");
}
retrieveExtraHorizonData(mapUnit.components().get(cokey), soilsDb.getConnection());
} else {
throw new ServiceException("The cokey value provided, " + comp.cokey() + ", does not exist in the SDM database. Cannot continue.");
}
}
}
@Override
protected void postProcess() throws Exception {
ZoneData urz = new ZoneData(0.0, urz_bd);
ZoneData lrz = new ZoneData(urz_bd, lrz_bd);
ZoneData srz = new ZoneData();
srz.top = lrz_bd;
Zones zones = new Zones();
zones.currentZone = urz;
zones.nextZone = lrz;
zones.lastZone = srz;
boolean foundRestrictingHorizon = false;
Horizon rHorizon = mapUnit.components().get(cokey).restrictingHorizon();
for (HorizonDataExt hzData : extData) {
// Did we reach a restricting horizon?
if (foundRestrictingHorizon) {
break;
}
if ((null != rHorizon) && (rHorizon.chkey() == hzData.chkey)) {
foundRestrictingHorizon = true;
}
fillRootZoneData(zones, hzData, 0.0);
}
srz.bottom = zones.lastDepth;
srz.thickness = srz.bottom - srz.top;
// Finish weighting the values
urz.weightValues();
lrz.weightValues();
srz.weightValues();
results().put("hydro_group", mapUnit.components().get(cokey).hydgrp());
results().put("drainage_class", mapUnit.components().get(cokey).drainagecl());
results().put("urz_aggr_data", urz.getJSONDataArray("urz"));
results().put("lrz_aggr_data", lrz.getJSONDataArray("lrz"));
results().put("srz_aggr_data", srz.getJSONDataArray("srz"));
}
void fillRootZoneData(Zones zones, HorizonDataExt hzData, double thicknessDiff) {
double thickness; // multiplier
double thicknessLeftover = 0.0;
boolean adjusted = false;
zones.lastDepth = hzData.bottom;
//Adjust multiplier
if (thicknessDiff == 0.0) {
if (hzData.bottom > zones.currentZone.bottom) {
thickness = zones.currentZone.bottom - hzData.top;
thicknessLeftover = hzData.bottom - zones.currentZone.bottom;
adjusted = true;
} else {
thickness = hzData.thickness;
}
} else {
if (thicknessDiff > zones.currentZone.thickness) {
adjusted = true;
thickness = zones.currentZone.thickness;
thicknessLeftover = thicknessDiff - thickness;
}
thickness = thicknessDiff;
}
// Set values
zones.currentZone.setValue("om", hzData.om, thickness);
zones.currentZone.setValue("ksat", hzData.ksat, thickness);
zones.currentZone.setValue("blkdens", hzData.blkdens, thickness);
zones.currentZone.setValue("wiltpt", hzData.wiltpt, thickness);
zones.currentZone.setValue("fldcp", hzData.fldcp, thickness);
zones.currentZone.setValue("clay", hzData.clay, thickness);
zones.currentZone.setValue("sand", hzData.sand, thickness);
zones.currentZone.setValue("silt", hzData.silt, thickness);
zones.currentZone.setValue("satwc", hzData.satwc, thickness);
zones.currentZone.setValue("awc", hzData.awc, thickness);
zones.currentZone.setValue("ec", hzData.ec, thickness);
zones.currentZone.setValue("caco3", hzData.caco3, thickness);
zones.currentZone.setValue("gypsum", hzData.gypsum, thickness);
zones.currentZone.setValue("sar", hzData.sar, thickness);
zones.currentZone.setValue("pbray1", hzData.pbray1, thickness);
zones.currentZone.setValue("ph2osoluble", hzData.ph2osoluble, thickness);
zones.currentZone.setValue("ptotal", hzData.ptotal, thickness);
zones.currentZone.setValue("ph", hzData.ph, thickness);
// Do we have extra left over?
if (adjusted) {
zones.currentZone = zones.nextZone;
zones.nextZone = zones.lastZone;
zones.lastZone = null;
fillRootZoneData(zones, hzData, thicknessLeftover);
}
}
void retrieveExtraHorizonData(Component comp, Connection conn) throws SQLException, ServiceException {
String query
= "SELECT chkey, gypsum_r, sar_r, pbray1_r, ph2osoluble_r, ptotal_r, "
+ " wsatiated_r, awc_r "
+ " FROM chorizon WHERE cokey=" + Integer.parseInt(comp.cokey())
+ " ORDER BY hzdept_r;";
try (Statement stmnt = conn.createStatement()) {
ResultSet results = stmnt.executeQuery(query);
while (results.next()) {
HorizonDataExt tData = new HorizonDataExt();
tData.readSQL(results, comp);
extData.add(tData);
}
}
}
protected double fixValue(double origVal, double newVal, double thickness) {
double result = origVal;
if (Double.isNaN(origVal)) {
if (!Double.isNaN(newVal)) {
result = newVal * thickness;
}
} else {
if (!Double.isNaN(newVal)) {
result += newVal * thickness;
}
}
return result;
}
public class Zones {
ZoneData currentZone;
ZoneData nextZone;
ZoneData lastZone;
double lastDepth;
}
public class ZoneData {
public class ValueData {
double value = Double.NaN;
double thickness = 0.0;
}
Map<String, ValueData> values = new HashMap<>();
boolean weighted = false;
double thickness = Double.NaN;
double top = Double.NaN;
double bottom = Double.NaN;
ZoneData(double _top, double _bottom) {
thickness = _bottom - _top;
bottom = _bottom;
top = _top;
initValues();
}
ZoneData() {
top = 0;
bottom = Double.MAX_VALUE;
thickness = Double.NaN;
initValues();
}
private void initValues() {
values.put("om", new ValueData());
values.put("ksat", new ValueData());
values.put("blkdens", new ValueData());
values.put("wiltpt", new ValueData());
values.put("fldcp", new ValueData());
values.put("clay", new ValueData());
values.put("sand", new ValueData());
values.put("silt", new ValueData());
values.put("satwc", new ValueData());
values.put("awc", new ValueData());
values.put("ec", new ValueData());
values.put("caco3", new ValueData());
values.put("gypsum", new ValueData());
values.put("sar", new ValueData());
values.put("pbray1", new ValueData());
values.put("ph2osoluble", new ValueData());
values.put("ptotal", new ValueData());
values.put("ph", new ValueData());
}
public void setValue(String name, double value, double thickness) {
double result = values.get(name).value;
if (Double.isNaN(result)) {
if (!Double.isNaN(value)) {
values.get(name).value = value * thickness;
values.get(name).thickness = thickness;
}
} else {
if (!Double.isNaN(value)) {
values.get(name).value += value * thickness;
values.get(name).thickness += thickness;
}
}
}
public void weightValues() throws ServiceException {
if (Double.isNaN(thickness)) {
throw new ServiceException("Cannot adjust weights, no thickness was calculated.");
}
if (!weighted) {
for (ValueData vData : values.values()) {
vData.value /= ((vData.thickness == 0.0) ? 1 : vData.thickness);
}
weighted = true;
}
}
public JSONArray getJSONDataArray(String prefix) throws JSONException {
JSONArray result = new JSONArray();
SortedSet<String> names = new TreeSet<>();
names.addAll(values.keySet());
result.put(JSONUtils.data("top", top));
result.put(JSONUtils.data("bottom", bottom));
result.put(JSONUtils.data("thickness", thickness));
for (String vName : names) {
result.put(JSONUtils.data(prefix + "_" + vName, EvalResult.writeDouble(values.get(vName).value, "%.2f")));
}
return result;
}
}
public class HorizonDataExt {
String chkey;
double thickness;
double top;
double bottom;
double om;
double ksat;
double blkdens;
double wiltpt;
double fldcp;
double clay;
double sand;
double silt;
double satwc;
double awc;
double ec;
double caco3;
double gypsum;
double sar;
double pbray1;
double ph2osoluble;
double ptotal;
double ph;
void readSQL(ResultSet results, Component comp) throws SQLException {
chkey = results.getString("chkey");
Horizon hz = comp.horizons().get(chkey);
thickness = hz.hzthk_r();
top = hz.hzdept_r();
bottom = hz.hzdepb_r();
om = hz.om_r();
ksat = hz.ksat_r();
blkdens = hz.dbthirdbar_r();
wiltpt = hz.wfifteenbar_r();
fldcp = hz.wthirdbar_r();
clay = hz.claytotal_r();
sand = hz.sandtotal_r();
silt = hz.silttotal_r();
ec = hz.ec_r();
caco3 = hz.caco3_r();
ph = hz.ph1to1h2o_r();
satwc = getDouble(results, "wsatiated_r", DEFAULT_MISSING_VALUE);
awc = getDouble(results, "awc_r", DEFAULT_MISSING_VALUE);
gypsum = getDouble(results, "gypsum_r", DEFAULT_MISSING_VALUE);
sar = getDouble(results, "sar_r", DEFAULT_MISSING_VALUE);
pbray1 = getDouble(results, "pbray1_r", DEFAULT_MISSING_VALUE);
ph2osoluble = getDouble(results, "ph2osoluble_r", DEFAULT_MISSING_VALUE);
ptotal = getDouble(results, "ptotal_r", DEFAULT_MISSING_VALUE);
}
protected double getDouble(ResultSet results, String name, double def) throws SQLException {
double value = EvalResult.getDouble(results, name);
return (EvalResult.testDefaultDouble(value) ? def : value);
}
}
}