WEPSServiceT.java [src/java/m/weps] Revision: c74837374670f76d3cc2468383e7a8dfb5f35f59 Date: Thu Sep 03 02:53:25 MDT 2015
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package m.weps;
import c.PostGIS;
import csip.Config;
import java.io.*;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import javax.ws.rs.Path;
import oms3.annotations.Description;
import oms3.annotations.Name;
import oms3.annotations.VersionInfo;
import oms3.util.ProcessComponent;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import csip.ModelDataService;
import static csip.ModelDataService.EXEC_FAILED;
import static csip.ModelDataService.EXEC_OK;
import static csip.ModelDataService.KEY_METAINFO;
import static csip.ModelDataService.KEY_PARAMETER;
import csip.utils.Services;
import csip.annotations.Polling;
import csip.utils.Binaries;
import csip.utils.JSONUtils;
import static m.weps.SciEnergyParser.LOG;
/**
* WEPS
*
* @author wlloyd, od
*/
@Name("WEPS")
@Description("WEPS")
@VersionInfo("1.0")
@Path("m/wepst/1.0")
@Polling(first = 25000, next = 2000)
public class WEPSServiceT extends ModelDataService {
String wepsdb = "";
static final String SOIL_FILE_EXT = ".ifc";
@Override
protected void preprocess() throws Exception {
if (JSONUtils.checkKeyExistsB(getParamMap(), ("climate"))) {
JSONUtils.checkFileExists(getParamMap().get("climate"), getWorkspaceDir());
}
JSONUtils.checkFileExists(getParamMap().get("management"), getWorkspaceDir());
if (JSONUtils.checkKeyExistsB(getParamMap(), ("soils"))) {
JSONUtils.checkFileExists(getParamMap().get("soils"), getWorkspaceDir());
}
if (JSONUtils.checkKeyExistsB(getParamMap(), ("wind"))) {
JSONUtils.checkFileExists(getParamMap().get("wind"), getWorkspaceDir());
}
// enforce default value for wepsrun if not provided
LOG.log(Level.INFO, "wepsrun key existence=" + JSONUtils.checkKeyExistsB(getParamMap(), "wepsrun"));
if (!JSONUtils.checkKeyExistsB(getParamMap(), "wepsrun")) {
getParamMap().put("wepsrun", JSONUtils.data("wepsrun", "weps.run"));
}
}
@Override
protected Callable<String> createCallable() throws Exception {
return new Callable<String>() {
@Override
public String call() throws Exception {
PostGIS db = PostGIS.singleton();
WepsModelRun wmr = new WepsModelRun();
String soilPtr = "";
String soilFilename = "";
String windDbPath = "";
String sWindgenStation = "";
wepsdb = Config.getString("weps.db", "http://oms-db.engr.colostate.edu/weps");
try {
File workDir = getWorkspaceDir();
ProcessComponent pc = new ProcessComponent();
// /weps -W1 -u0 -I2 -t1 -P./ >stdout.txt 2>stderr.txt
String binDir = Config.getString("m.bin.dir", "/tmp/csip/bin");
pc.exe = Binaries.unpackResource("/bin/" + Binaries.getArch() + "/weps", new File(binDir)).toString();
pc.args = new String[]{"-W1", "-u0", "-I2", "-t1", "-P./"};
pc.working_dir = workDir.toString();
if (JSONUtils.checkKeyExistsB(getParamMap(), "latitude")) {
wmr.setLat(JSONUtils.getValue(getParamMap().get("latitude")));
}
if (JSONUtils.checkKeyExistsB(getParamMap(), "longitude")) {
wmr.setLongitude(JSONUtils.getValue(getParamMap().get("longitude")));
}
if ((JSONUtils.checkKeyExistsB(getParamMap(), "latitude"))
&& (JSONUtils.checkKeyExistsB(getParamMap(), "longitude"))
&& (!(JSONUtils.checkKeyExistsB(getParamMap(), ("climate"))))) {
if (db != null) {
// get climate station for this lat / long
PostGIS.StationResult cligenStation = db.findCligenStation(Double.parseDouble(wmr.getLat()), Double.parseDouble(wmr.getLongitude()));
// generate cli file using this station
ProcessComponent pcCliGen = new ProcessComponent();
pcCliGen.exe = Binaries.unpackResource("/bin/" + Binaries.getArch() + "/cligen", new File(binDir)).toString();
String dbpath = Binaries.unpackResource("/bin/" + Binaries.getArch() + "/upd_US_cligen_stations.par", new File(binDir)).toString();
pcCliGen.args = new String[]{"-S" + cligenStation.state, "-s" + cligenStation.stationId, "-i" + dbpath, "-t5", "-I3", "-F", "-b01", "-y150", "-o" + pc.working_dir + "/cligen.cli"};
LOG.log(Level.INFO, "cligen args=" + pcCliGen.args.toString());
pcCliGen.working_dir = workDir.toString();
pcCliGen.execute();
// prefer lat/long generated climates file for weps run
wmr.setCliFile("cligen.cli");
}
}
// If no wind file, use wind station(s) to generate wind data
if ((JSONUtils.checkKeyExistsB(getParamMap(), "latitude"))
&& (JSONUtils.checkKeyExistsB(getParamMap(), "longitude"))
&& (!(JSONUtils.checkKeyExistsB(getParamMap(), ("wind"))))) {
if (db != null) {
double latitude = Double.parseDouble(wmr.getLat());
double longitude = Double.parseDouble(wmr.getLongitude());
// check if in the interpolation boundary shape, if so, interpolate 3 nearest wind stations
// to generate an interpolated station
LOG.log(Level.INFO, "Check if lat/long is in interpolation boundary");
if (db.IsInInterpolateBoundary(latitude, longitude)) {
LOG.log(Level.INFO, "YES! lat/long is in interpolation boundary");
// Generate wind station interpolation
// Generate weights file
ProcessComponent pcInterpolate = new ProcessComponent();
String exepath = Binaries.unpackResource("/bin/" + Binaries.getArch() + "/interpolate", new File(binDir)).toString();
String dbpath = Binaries.unpackResource("/bin/" + Binaries.getArch() + "/wind_gen_his_upper_US_NRCS.idx", new File(binDir)).toString();
String polygon = Binaries.unpackResource("/bin/" + Binaries.getArch() + "/WINDGEN_DEC_13_2011.pol", new File(binDir)).toString();
// Generate shell script to invoke interpolate
File interpolatesh = new File(workDir.toString() + "/interpolate.sh");
FileWriter fw = new FileWriter(interpolatesh);
String invokeInterpolate = exepath + " -f " + dbpath + " -p " + polygon + " -lat " + latitude + " -long " + longitude;
fw.write(invokeInterpolate);
interpolatesh.setExecutable(true);
fw.close();
pcInterpolate.working_dir = workDir.toString();
pcInterpolate.exe = "./interpolate.sh";
pcInterpolate.args = new String[]{};
pcInterpolate.execute();
WeightsParser wp = new WeightsParser();
wp.weightsFile = pcInterpolate.stdout;
wp.exitValue = pcInterpolate.exitValue;
wp.weightsErr = pcInterpolate.stderr;
// must process this monstrosity
wp.parse();
if ((wp.station1 > 0) & (wp.station2 > 0) && (wp.station3 > 0)) {
// If there are wind stations then, generate interpolate wind station wdb file
// Note the interp_wdb program is ancient Fortran and can not handle file paths of any length
// therefore everything has to be extracted to the workdir and done locally there.
// This is BAD (inefficient) because it is extra work to always extract wind station wdb's for every model run!
ProcessComponent pcInterpWdb = new ProcessComponent();
exepath = Binaries.unpackResource("/bin/" + Binaries.getArch() + "/interp_wdb", new File(binDir)).toString();
String station1Db = Binaries.unpackResourceAbsolute("/bin/" + Binaries.getArch() + "/windstations/" + wp.station1 + ".wdb", workDir.toString() + "/" + wp.station1 + ".wdb").toString();
String station2Db = Binaries.unpackResourceAbsolute("/bin/" + Binaries.getArch() + "/windstations/" + wp.station2 + ".wdb", workDir.toString() + "/" + wp.station2 + ".wdb").toString();
String station3Db = Binaries.unpackResourceAbsolute("/bin/" + Binaries.getArch() + "/windstations/" + wp.station3 + ".wdb", workDir.toString() + "/" + wp.station3 + ".wdb").toString();
// Generate shell script to invoke interpolate
File interpwdbsh = new File(workDir.toString() + "/interpwdb.sh");
fw = new FileWriter(interpwdbsh);
String invokeInterpWdb = exepath + " test.wdb" + " " + wp.station1 + ".wdb " + wp.weight1 + " " + wp.station2 + ".wdb " + wp.weight2 + " " + wp.station3 + ".wdb " + wp.weight3;
fw.write(invokeInterpWdb);
interpwdbsh.setExecutable(true);
fw.close();
pcInterpWdb.working_dir = workDir.toString();
pcInterpWdb.exe = "./interpwdb.sh";
pcInterpWdb.args = new String[]{};
pcInterpWdb.execute();
windDbPath = "test.wdb";
sWindgenStation = "999999"; // this is the magic number indicating its an interpolated wind station!
}
}
// otherwise, just use data from nearest wind station:
// If this is not using an interpolated wind station, then use the default one...
if (windDbPath.length() == 0) {
LOG.log(Level.INFO, "NO! lat/long is NOT in interpolation boundary");
// get wind generation station for this lat / long
PostGIS.StationResult windgenStation = db.findWindgenStation(Double.parseDouble(wmr.getLat()), Double.parseDouble(wmr.getLongitude()));
sWindgenStation = windgenStation.stationId.trim();
windDbPath = Binaries.unpackResource("/bin/" + Binaries.getArch() + "/wind_gen_his_upper_US.wdb", new File(binDir)).toString();
}
// generate win file using this station (or interpolated one)
ProcessComponent pcWindGen = new ProcessComponent();
String exepath = Binaries.unpackResource("/bin/" + Binaries.getArch() + "/wind_gen4", new File(binDir)).toString();
LOG.log(Level.INFO, "Using wind database:" + windDbPath);
// Generate shell script to invoke windgen
File windgensh = new File(workDir.toString() + "/windgen.sh");
FileWriter fw = new FileWriter(windgensh);
String invokeWinGen = exepath + " -f " + windDbPath + " -b 01 -y 150 -o thewind.win -s " + sWindgenStation;
fw.write(invokeWinGen);
windgensh.setExecutable(true);
fw.close();
pcWindGen.working_dir = workDir.toString();
String cmd = "./windgen.sh";
pcWindGen.args = new String[]{};
pcWindGen.exe = cmd;
pcWindGen.execute();
wmr.setWinFile("thewind.win");
}
}
// Get weps soils ifc file for lat & long
if ((JSONUtils.checkKeyExistsB(getParamMap(), "latitude"))
&& (JSONUtils.checkKeyExistsB(getParamMap(), "longitude"))
&& (!(JSONUtils.checkKeyExistsB(getParamMap(), ("soils"))))) {
if (db != null) {
PostGIS.FileQryResult soil = db.findSoilsWeps(Double.parseDouble(wmr.getLat()), Double.parseDouble(wmr.getLongitude()));
if (soil == null) {
LOG.log(Level.WARNING, "No soil for lat=" + wmr.getLat() + "\nfor long=" + wmr.getLongitude() + "\n");
soilPtr = "";
} else {
soilPtr = soil.file_path + "/" + soil.file_name + SOIL_FILE_EXT;
// Get soil file and write to temp space
String fileToGet = wepsdb + "/" + soilPtr;
LOG.log(Level.INFO, "soils file to get=" + fileToGet);
getFile(fileToGet, pc.working_dir, soil.file_name + SOIL_FILE_EXT);
// Prefer lat/long retrieved soils file
wmr.setSoilFile(soil.file_name + SOIL_FILE_EXT);
}
}
}
// Generate Weps Run file from JSON parameters if not provided
try {
JSONUtils.checkFileExists(getParamMap().get("wepsrun"), getWorkspaceDir());
} catch (Exception e) {
LOG.log(Level.INFO, "wepsrun file does not exist, creating it.");
// Only generate weps.run file if it wasn't provided
// Override default weps run configuration parameters here with values from JSON object
if (JSONUtils.checkKeyExistsB(getParamMap(), ("climate"))) {
wmr.setCliFile(JSONUtils.getValue(getParamMap().get("climate")));
}
wmr.setMgmtFile(JSONUtils.getValue(getParamMap().get("management")));
if (JSONUtils.checkKeyExistsB(getParamMap(), ("soils"))) {
wmr.setSoilFile(JSONUtils.getValue(getParamMap().get("soils")));
}
if (JSONUtils.checkKeyExistsB(getParamMap(), ("wind"))) {
wmr.setWinFile(JSONUtils.getValue(getParamMap().get("wind")));
}
String wepsrunFile = JSONUtils.getValue(getParamMap().get("wepsrun"));
LOG.log(Level.INFO, "weps run file name=" + wepsrunFile);
WepsRunFileGenerator.GenerateWepsRunFile(wmr, pc.working_dir, wepsrunFile);
}
System.out.println("exe " + pc.exe);
System.out.println("running.");
pc.execute();
System.out.println(pc.exitValue);
FileUtils.write(new File(workDir, "stdout.txt"), pc.stdout);
FileUtils.write(new File(workDir, "stderr.txt"), pc.stderr);
return pc.exitValue == 0 ? EXEC_OK : EXEC_FAILED;
} catch (Exception e) {
LOG.log(Level.SEVERE, e.toString());
LOG.log(Level.SEVERE, e.getStackTrace().toString());
throw new Exception(e);
//return -1;
}
}
};
}
private void getFile(String url, String destDir, String filename) {
FileOutputStream fos = null;
try {
HttpClient client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
HttpResponse response = client.execute((HttpUriRequest) httpget);
byte[] soilData = IOUtils.toByteArray(response.getEntity().getContent());
fos = new FileOutputStream(new File(destDir + "/" + filename));
fos.write(soilData);
fos.close();
} catch (IOException ie) {
LOG.log(Level.SEVERE, "ERROR GETTING SOILS IFC FILE!:" + ie.toString());
} finally {
if (fos != null) {
try {
fos.close();
} catch (Exception fe) {
}
}
}
}
@Override
protected File[] postprocess() throws Exception {
return Services.toFiles(
"stir_energy.out",
"sci_energy.out",
"stdout.txt",
"stderr.txt");
}
// @Override
// protected JSONObject describe() throws JSONException {
//
// JSONArray p = new JSONArray();
//
//// p.put(JSONUtils.data(KEY_CLIMATES, ""));
//// p.put(JSONUtils.data(KEY_SOILS, ""));
//// p.put(JSONUtils.data(KEY_MANAGEMENTS, ""));
//// p.put(JSONUtils.data(KEY_STEEPNESS, 3.0));
//// p.put(JSONUtils.data(KEY_LENGTH, 10.0));
//// p.put(JSONUtils.data(KEY_RESOLVE_LOCATION, true));
//// p.put(JSONUtils.data(KEY_LATITUDE, 36.250515));
//// p.put(JSONUtils.data(KEY_LONGITUDE, -84.026264));
////
// JSONObject metainfo = new JSONObject();
////// metainfo.put(KEY_REQUEST_RESULTS, new JSONArray(potResults));
//
// JSONObject model = new JSONObject();
// model.put(KEY_PARAMETER, p);
// model.put(KEY_METAINFO, metainfo);
// return model;
// }
}