CliWindSoilFile.java [tools/GetLatLonCokey/src/getlatloncokey] Revision: 69ab6eb5379799363ea8548530ac0cb331f66446 Date: Fri Jan 10 11:03:01 MST 2020
/*
* 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 getlatloncokey;
import csip.ServiceException;
import csip.utils.JSONUtils;
import data.interpretors.CligenData;
import static data.interpretors.CligenData.OBS_MONTHLY_PRCP;
import static data.interpretors.CligenData.PRCP_INDEX;
import data.interpretors.WindGenData;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import soils.AoA;
import soils.Component;
import soils.MapUnit;
import soils.SoilsData;
import static soils.SoilsData.MAPUNIT_COMPONENT_LIST_NAME;
import soils.db.tables.TableComponent;
import soils.db.tables.TableComponentCalculations;
import soils.db.tables.TableHorizon;
import soils.db.tables.TableHorizonCalculations;
import soils.db.tables.TableMapUnit;
import soils.db.tables.TableMapUnitCalculations;
/**
*
* @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
*/
public class CliWindSoilFile {
protected static final String SOILS_RETURN = "soils.json";
protected static final String SOILS_REQUEST = "request.json";
protected static final String CLIMATE_FILE = ".cli";
protected static final String WIND_FILE = ".win";
protected static final String LATITUDE = "latitude";
protected static final String LONGITUDE = "longitude";
protected static final String COKEY = TableComponent.COKEY;
protected static final String SLOPE_R = TableComponent.SLOPE_R_NAME;
protected static final String LENGTH_R = TableComponentCalculations.LENGTH_R_NAME;
protected static final String WATER_CLAY_TOTAL = "water_" + TableHorizon.CLAYTOTAL_R;
protected static final String WATER_SAND_TOTAL = "water_" + TableHorizon.SANDTOTAL_R_NAME;
protected static final String WATER_OM_R = "water_" + TableHorizon.OM_R_NAME;
protected static final String WIND_CLAY_TOTAL = "wind_" + TableHorizon.CLAYTOTAL_R;
protected static final String WIND_SAND_TOTAL = "wind_" + TableHorizon.SANDTOTAL_R_NAME;
protected static final String WIND_OM_R = "wind_" + TableHorizon.OM_R_NAME;
protected static final String KFFACT = TableComponentCalculations.KFFACT_NAME;
protected static final String TILLAGE_LAYER_CLAY_TOTAL = TableComponentCalculations.TILLAGE_LAYER_CLAY_TOTAL;
protected static final String SIM_AVG_PRECIP = "100yr_avg_precip";
protected static final String SIM_OBS_AVG_PRECIP = "100yr_obs_avg_precip";
protected static final String SIM_AVG_WIND_ENERGY = "wind_energy_100yr_avg";
protected static final String ANNUAL_AVG_PRECIP = "annual_avg_precip";
protected static final String ANNUAL_OBS_AVG_PRECIP = "annual_obs_avg_precip";
protected static final String ANNUAL_WIND_ENERGY_AVG = "annual_wind_energy_avg";
protected static final String ANNUAL_WIND_ENEGERY_AVG_NON_ZERO = "annual_wind_energy_avg_non_zero";
protected static final String ANNUAL_WIND_ENERGY_AVG_PEAK = "annual_wind_energy_avg_peak";
protected static final String MONTHLY_AVG_PRECIP = "monthly_avg_precip";
protected static final String MONTLY_OBS_AVG_PRECIP = "monthly_obs_avg_precip";
protected static final String MONTHLY_WIND_ENGERY_AVG = "monthly_wind_energy_avg";
protected static final String MONTHLY_WIND_ENERGY_AVG_NON_ZERO = "monthly_wind_energy_avg_non_zero";
protected static final String MONTHLY_WIND_ENERGY_AVG_PEAK = "monthly_wind_energy_avg_peak";
public static final ArrayList<String> soilFields = new ArrayList<>(Arrays.asList(
LATITUDE,
LONGITUDE,
COKEY,
KFFACT,
SLOPE_R,
LENGTH_R,
WATER_CLAY_TOTAL,
WATER_SAND_TOTAL,
WATER_OM_R,
WIND_CLAY_TOTAL,
WIND_SAND_TOTAL,
WIND_OM_R,
TILLAGE_LAYER_CLAY_TOTAL
));
public static final ArrayList<String> simTotalFields = new ArrayList<>(Arrays.asList(
LATITUDE,
LONGITUDE,
COKEY,
KFFACT,
SLOPE_R,
LENGTH_R,
WATER_CLAY_TOTAL,
WATER_SAND_TOTAL,
WATER_OM_R,
WIND_CLAY_TOTAL,
WIND_SAND_TOTAL,
WIND_OM_R,
TILLAGE_LAYER_CLAY_TOTAL,
SIM_AVG_PRECIP,
SIM_OBS_AVG_PRECIP,
SIM_AVG_WIND_ENERGY
));
public static final ArrayList<String> annualAverageFields = new ArrayList<>(Arrays.asList(
LATITUDE,
LONGITUDE,
COKEY,
ANNUAL_AVG_PRECIP,
ANNUAL_OBS_AVG_PRECIP,
ANNUAL_WIND_ENERGY_AVG,
ANNUAL_WIND_ENEGERY_AVG_NON_ZERO,
ANNUAL_WIND_ENERGY_AVG_PEAK
));
public static final ArrayList<String> monthlyAverageFields = new ArrayList<>(Arrays.asList(
LATITUDE,
LONGITUDE,
COKEY,
MONTHLY_AVG_PRECIP,
MONTLY_OBS_AVG_PRECIP,
MONTHLY_WIND_ENGERY_AVG,
MONTHLY_WIND_ENERGY_AVG_NON_ZERO,
MONTHLY_WIND_ENERGY_AVG_PEAK
));
protected JSONArray soilsReturn;
protected JSONArray returnVal;
protected JSONObject request;
protected Double latitude = Double.NaN, longitude = Double.NaN;
protected String cokey = "";
protected soils.AoA aoa;
protected ArrayList<String> simFields;
protected ArrayList<String> annualFields;
protected ArrayList<String> monthlyFields;
protected Component maxComponent = null;
protected MapUnit maxMapUnit = null;
protected HashMap<String, Object> fieldData = new HashMap<>();
protected CligenData climateData;
protected WindGenData windData;
protected TableHorizon waterHorizon;
protected TableHorizon windHorizon;
protected boolean wroteHeader = false;
protected ArrayList<String> fields;
public CliWindSoilFile(File filename, ArrayList<String> _fields, boolean _wroteHeader) throws IOException, JSONException, ServiceException {
boolean gotSoilsResponse = false;
boolean gotRequest = false;
boolean gotWind = false;
boolean gotClimate = false;
boolean gotAllFields = true;
wroteHeader = _wroteHeader;
if (null == _fields) {
throw new ServiceException("No field names specified for extraction.");
} else {
fields = _fields;
}
//simTotalFields.
InputStream zipFile = new FileInputStream(filename);
try (ZipInputStream zin = new ZipInputStream(zipFile)) {
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) {
if (entry.getName().contains(SOILS_RETURN) && !gotSoilsResponse) {
returnVal = new JSONArray(readInputFile(zin));
//soilsReturn = returnVal.getJSONArray(KEY_RESULT).getJSONArray(0);
Map<String, JSONObject> inputMap = JSONUtils.preprocess(returnVal);
soils.AoA.setRequiredInputs(new ArrayList<>(Arrays.asList(AoA.MAP_UNIT_LIST)),
null, null, null);
MapUnit.setDefaultUsedColumns(new ArrayList<>(Arrays.asList(TableMapUnit.MUKEY, TableMapUnitCalculations.AREA_NAME, SoilsData.MAPUNIT_COMPONENT_LIST_NAME)));
Component.setDefaultUsedColumns(new ArrayList<>(Arrays.asList(TableComponent.COKEY, TableComponent.SLOPE_R_NAME,
TableComponent.HYDGRP_NAME, TableComponent.COMPPCT_R_NAME,
TableComponentCalculations.COMP_AREA_NAME, TableComponentCalculations.LENGTH_R_NAME, TableComponentCalculations.AREA_PCT_NAME,
TableComponentCalculations.TILLAGE_LAYER_CLAY_TOTAL, TableComponentCalculations.KFFACT_NAME)));
aoa = new soils.AoA(inputMap);
if (aoa.getMapUnits().size() <= 0) {
throw new ServiceException("Mapunits returned for this AoA did not match expected number of 1. Mapunit size is: " + aoa.getMapUnits().size());
}
maxMapUnit = null;
for (String mukey : aoa.getMapUnits().keySet()) {
MapUnit mapunit = aoa.getMapUnits().get(mukey);
if (null == maxMapUnit) {
maxMapUnit = mapunit;
} else {
if (mapunit.area() > maxMapUnit.area()) {
maxMapUnit = mapunit;
}
}
}
maxComponent = null;
if (null != maxMapUnit) {
for (String cokey : maxMapUnit.components().keySet()) {
Component component = maxMapUnit.components().get(cokey);
if (null == maxComponent) {
maxComponent = component;
} else {
if (component.area_pct() > maxComponent.area_pct()) {
maxComponent = component;
maxComponent.mukey(maxMapUnit.mukey());
}
}
}
} else {
throw new ServiceException("No max mapunit was found.");
}
if (null != maxComponent) {
cokey = maxComponent.cokey();
JSONArray map_units = JSONUtils.getJSONArrayParam(inputMap, AoA.MAP_UNIT_LIST);
for (int mapUnitIndex = 0; mapUnitIndex < map_units.length(); mapUnitIndex++) {
JSONArray map_unit = map_units.getJSONArray(mapUnitIndex);
Map<String, JSONObject> tmap_unit = JSONUtils.preprocess(map_unit);
String mukey = JSONUtils.getStringParam(tmap_unit, TableMapUnit.MUKEY, "");
if (!mukey.isEmpty()) {
if (mukey.equalsIgnoreCase(maxMapUnit.mukey())) {
JSONArray components = JSONUtils.getJSONArrayParam(tmap_unit, MAPUNIT_COMPONENT_LIST_NAME);
for (int componentIndex = 0; componentIndex < components.length(); componentIndex++) {
JSONArray component = components.getJSONArray(componentIndex);
Map<String, JSONObject> tcomponent = JSONUtils.preprocess(component);
String cokey = JSONUtils.getStringParam(tcomponent, TableComponent.COKEY, "");
if (!cokey.isEmpty()) {
if (cokey.equalsIgnoreCase(maxComponent.cokey())) {
JSONArray waterHorizons = JSONUtils.getJSONArrayParam(tcomponent, "water horizons");
JSONArray windHorizons = JSONUtils.getJSONArrayParam(tcomponent, "wind horizons");
if (waterHorizons.length() >= 1) {
JSONArray horizon = waterHorizons.getJSONArray(0);
waterHorizon = new TableHorizon();
waterHorizon.setUsedColumns(new ArrayList<>(Arrays.asList(
TableHorizon.CHKEY_NAME, TableHorizon.SANDTOTAL_R_NAME,
TableHorizon.SILTTOTAL_R, TableHorizon.CLAYTOTAL_R, TableHorizon.OM_R_NAME,
TableHorizon.HZTHK_R_NAME, TableHorizon.HZDEPB_R_NAME, TableHorizon.HZDEPT_R_NAME,
TableHorizonCalculations.FRAGVOL_R_NAME
)));
Map<String, JSONObject> horizonMap = JSONUtils.preprocess(horizon);
waterHorizon.readValuesFromJSON(horizonMap);
waterHorizon.cokey(cokey);
}
if (windHorizons.length() >= 1) {
JSONArray horizon = windHorizons.getJSONArray(0);
windHorizon = new TableHorizon();
windHorizon.setUsedColumns(new ArrayList<>(Arrays.asList(
TableHorizon.CHKEY_NAME, TableHorizon.SANDTOTAL_R_NAME,
TableHorizon.SILTTOTAL_R, TableHorizon.CLAYTOTAL_R, TableHorizon.OM_R_NAME,
TableHorizon.HZTHK_R_NAME, TableHorizon.HZDEPB_R_NAME, TableHorizon.HZDEPT_R_NAME,
TableHorizonCalculations.FRAGVOL_R_NAME
)));
Map<String, JSONObject> horizonMap = JSONUtils.preprocess(horizon);
windHorizon.readValuesFromJSON(horizonMap);
windHorizon.cokey(cokey);
}
if ((null != windHorizon) && (null != waterHorizon)) {
gotSoilsResponse = true;
}
}
}
}
}
}
}
}
}
if (entry.getName().contains(SOILS_REQUEST) && !gotRequest) {
request = new JSONObject(readInputFile(zin));
String coordinates = request.getString("coordinates");
String type = request.getString("type");
if (type.equalsIgnoreCase("point")) {
coordinates = coordinates.replace("[", " ");
coordinates = coordinates.replace("]", " ");
String[] coord = coordinates.split(",");
if (coord.length == 2) {
longitude = Double.parseDouble(coord[0]);
latitude = Double.parseDouble(coord[1]);
gotRequest = true;
}
}
}
if (entry.getName().contains(CLIMATE_FILE) && !gotClimate) {
climateData = new CligenData(readInputFile(zin));
if (!climateData.badClimateData()) {
gotClimate = true;
}
}
if (entry.getName().contains(WIND_FILE) && !gotWind) {
windData = new WindGenData(readInputFile(zin));
if (!windData.badWindData()) {
gotWind = true;
}
}
if (gotRequest && gotSoilsResponse && gotClimate && gotWind) {
break;
}
}
if (gotRequest && gotSoilsResponse && gotClimate && gotWind) {
for (String field : fields) {
switch (field) {
case LONGITUDE:
fieldData.put(LONGITUDE, longitude);
break;
case LATITUDE:
fieldData.put(LATITUDE, latitude);
break;
case COKEY:
fieldData.put(COKEY, cokey);
break;
case WATER_CLAY_TOTAL:
fieldData.put(WATER_CLAY_TOTAL, waterHorizon.claytotal_r());
break;
case WIND_CLAY_TOTAL:
fieldData.put(WIND_CLAY_TOTAL, windHorizon.claytotal_r());
break;
case WATER_SAND_TOTAL:
fieldData.put(WATER_SAND_TOTAL, waterHorizon.sandtotal_r());
break;
case WIND_SAND_TOTAL:
fieldData.put(WIND_SAND_TOTAL, windHorizon.sandtotal_r());
break;
case KFFACT:
fieldData.put(KFFACT, maxComponent.calculated_kffact());
break;
case WATER_OM_R:
fieldData.put(WATER_OM_R, waterHorizon.om_r());
break;
case WIND_OM_R:
fieldData.put(WIND_OM_R, windHorizon.om_r());
break;
case SLOPE_R:
fieldData.put(SLOPE_R, maxComponent.slope_r());
break;
case LENGTH_R:
fieldData.put(LENGTH_R, maxComponent.length_r());
break;
case TILLAGE_LAYER_CLAY_TOTAL:
fieldData.put(TILLAGE_LAYER_CLAY_TOTAL, maxComponent.calculated_tl_claytotal());
break;
case ANNUAL_AVG_PRECIP:
for (int i = 0; i < climateData.yearsInFile(); i++) {
fieldData.put(ANNUAL_AVG_PRECIP + "_" + (i + 1), climateData.yearlySummary(i, CligenData.PRCP_INDEX));
}
break;
case SIM_OBS_AVG_PRECIP:
fieldData.put(SIM_OBS_AVG_PRECIP, climateData.annualAvgPrecip());
break;
case ANNUAL_WIND_ENERGY_AVG:
for (int i = 0; i < windData.yearsInFile(); i++) {
fieldData.put(ANNUAL_WIND_ENERGY_AVG + "_" + (i + 1), windData.yearlyAverage(i));
}
break;
case SIM_AVG_WIND_ENERGY:
fieldData.put(SIM_AVG_WIND_ENERGY, windData.simulationAverage());
break;
case SIM_AVG_PRECIP:
fieldData.put(SIM_AVG_PRECIP, climateData.simulationAverage(PRCP_INDEX));
break;
case ANNUAL_OBS_AVG_PRECIP:
fieldData.put(ANNUAL_OBS_AVG_PRECIP, climateData.observedAnnualAverage(OBS_MONTHLY_PRCP));
break;
case MONTHLY_AVG_PRECIP:
for (int i = 0; i < 12; i++) {
fieldData.put(MONTHLY_AVG_PRECIP + "_" + (i + 1), climateData.monthlyAverages(i, PRCP_INDEX));
}
break;
case MONTLY_OBS_AVG_PRECIP:
for (int i = 0; i < 12; i++) {
fieldData.put(MONTLY_OBS_AVG_PRECIP + "_" + (i + 1), climateData.observedMonthlyAverages(i, OBS_MONTHLY_PRCP));
}
break;
case ANNUAL_WIND_ENEGERY_AVG_NON_ZERO:
break;
case ANNUAL_WIND_ENERGY_AVG_PEAK:
break;
case MONTHLY_WIND_ENGERY_AVG:
break;
case MONTHLY_WIND_ENERGY_AVG_NON_ZERO:
break;
case MONTHLY_WIND_ENERGY_AVG_PEAK:
break;
default:
gotAllFields = false;
}
}
}
if (!gotRequest || !gotSoilsResponse || !gotAllFields || !gotWind || !gotClimate) {
ArrayList<String> missingList = new ArrayList<>();
if (!gotRequest) {
missingList.add(" Request JSON");
}
if (!gotSoilsResponse) {
missingList.add(" Response JSON");
}
if (!gotAllFields) {
missingList.add(" Soils file and matching requested field names");
}
if (!gotWind) {
missingList.add(" Wind file" + ((null != windData) ? (": " + windData.windDataMessages()) : ""));
}
if (!gotClimate) {
missingList.add(" Climate file" + ((null != climateData) ? (": " + climateData.cligenDataMessages()) : ""));
}
throw new ServiceException("Could not parse all of the service zip file properly: " + filename + ". " + "Parse isses with: " + missingList);
}
}
}
protected String readInputFile(ZipInputStream zin) throws IOException {
String ret_val = "";
BufferedReader bReader = new BufferedReader(new InputStreamReader(zin));
StringBuilder fileContent = new StringBuilder();
String inputStr;
while ((inputStr = bReader.readLine()) != null) {
fileContent.append(inputStr + System.lineSeparator());
}
ret_val = fileContent.toString();
return ret_val;
}
public double latitude() {
return latitude;
}
public double longitude() {
return longitude;
}
public String cokey() {
return cokey;
}
public void writeCSV(BufferedWriter simAvg, BufferedWriter annualAvg, BufferedWriter monthlyAvg) throws IOException {
if (null != simAvg) {
if (!wroteHeader) {
// Write header
String header;
header = buildSimTotalHeader();
if ((null != header) && (!header.isEmpty())) {
simAvg.write(header + System.lineSeparator());
simAvg.flush();
}
header = buildAnnualTotalHeader();
if ((null != header) && (!header.isEmpty())) {
annualAvg.write(header + System.lineSeparator());
annualAvg.flush();
}
header = buildMonthlyTotalHeader();
if ((null != header) && (!header.isEmpty())) {
monthlyAvg.write(header + System.lineSeparator());
monthlyAvg.flush();
}
wroteHeader = true;
}
String outString;
outString = buildSimTotalsLine();
if ((null != outString) && (!outString.isEmpty())) {
simAvg.write(outString + System.lineSeparator());
simAvg.flush();
}
outString = buildAnnualTotalsLine();
if ((null != outString) && (!outString.isEmpty())) {
annualAvg.write(outString + System.lineSeparator());
annualAvg.flush();
}
outString = buildMonthlyTotalsLine();
if ((null != outString) && (!outString.isEmpty())) {
monthlyAvg.write(outString + System.lineSeparator());
monthlyAvg.flush();
}
}
}
protected String buildSimTotalHeader() {
String ret_val = "";
for (String key : simTotalFields) {
if (fields.contains(key)) {
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + key;
}
}
return ret_val;
}
protected String buildAnnualTotalHeader() {
String ret_val = "";
for (String key : annualAverageFields) {
if (fields.contains(key)) {
switch (key) {
case ANNUAL_AVG_PRECIP:
for (int i = 0; i < climateData.yearsSimulated(); i++) {
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + key + "_" + (i + 1);
}
break;
case ANNUAL_WIND_ENERGY_AVG:
case ANNUAL_WIND_ENEGERY_AVG_NON_ZERO:
case ANNUAL_WIND_ENERGY_AVG_PEAK:
for (int i = 0; i < windData.yearsSimulated(); i++) {
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + key + "_" + (i + 1);
}
break;
default:
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + key;
}
}
}
return ret_val;
}
protected String buildMonthlyTotalHeader() {
String ret_val = "";
for (String key : monthlyAverageFields) {
if (fields.contains(key)) {
switch (key) {
case MONTHLY_AVG_PRECIP:
case MONTLY_OBS_AVG_PRECIP:
case MONTHLY_WIND_ENGERY_AVG:
case MONTHLY_WIND_ENERGY_AVG_NON_ZERO:
case MONTHLY_WIND_ENERGY_AVG_PEAK:
for (int i = 0; i < 12; i++) {
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + key + "_" + (i + 1);
}
break;
default:
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + key;
}
}
}
return ret_val;
}
protected String buildSimTotalsLine() {
String ret_val = "";
for (String key : simTotalFields) {
if (fields.contains(key)) {
if (fieldData.containsKey(key)) {
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + fieldData.get(key);
}
}
}
return ret_val;
}
protected String buildAnnualTotalsLine() {
String ret_val = "";
for (String key : annualAverageFields) {
if (fields.contains(key)) {
switch (key) {
case ANNUAL_AVG_PRECIP:
for (int i = 0; i < climateData.yearsSimulated(); i++) {
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + fieldData.get(key + "_" + (i + 1));
}
break;
case ANNUAL_WIND_ENERGY_AVG:
case ANNUAL_WIND_ENEGERY_AVG_NON_ZERO:
case ANNUAL_WIND_ENERGY_AVG_PEAK:
for (int i = 0; i < windData.yearsSimulated(); i++) {
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + key + "_" + (i + 1);
}
break;
default:
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + fieldData.get(key);
}
}
}
return ret_val;
}
protected String buildMonthlyTotalsLine() {
String ret_val = "";
for (String key : monthlyAverageFields) {
if (fields.contains(key)) {
switch (key) {
case MONTHLY_AVG_PRECIP:
case MONTLY_OBS_AVG_PRECIP:
case MONTHLY_WIND_ENGERY_AVG:
case MONTHLY_WIND_ENERGY_AVG_NON_ZERO:
case MONTHLY_WIND_ENERGY_AVG_PEAK:
for (int i = 0; i < 12; i++) {
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + fieldData.get(key + "_" + (i + 1));
}
break;
default:
ret_val += ((!ret_val.isEmpty()) ? ", " : "") + fieldData.get(key);
}
}
}
return ret_val;
}
}