Interpolation.java [src/java/interpolation] Revision: default Date:
package interpolation;
import csip.Config;
import csip.api.server.Executable;
import csip.api.server.ServiceException;
import csip.SessionLogger;
import static csip.utils.JSONUtils.getValueByKey;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.logging.Level;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
/**
*
* @author Brad
*/
public class Interpolation {
protected class StationItem {
public String stationId;
public String stationWeight;
public StationItem(String id, String weight) {
stationId = id;
stationWeight = weight;
}
}
Executable interpolateExe;
Executable interp_wdb;
File workspaceDir;
SessionLogger LOG;
private ArrayList<String> stationNames;
public Interpolation(Executable interpolate_exe, Executable interp, File workspaceDir, SessionLogger log) {
interpolateExe = interpolate_exe;
interp_wdb = interp;
this.workspaceDir = workspaceDir;
LOG = log;
}
public File interpolate(double parmLat, double parmLon) throws ServiceException, IOException {
return interpolate(parmLat, parmLon, null, null, null);
}
public File interpolate_US_PR(double parmLat, double parmLon, String suffix) throws ServiceException, IOException {
String parmIdx = Config.getString("csip.dir") + "/data/wind_gen_his_upper_" + suffix + ".idx";
return interpolate(parmLat, parmLon, parmIdx, null, null);
}
public File interpolate(double parmLat, double parmLon, String parmIdxFile, String parmPolygonFile, String parmOutputFile) throws ServiceException, IOException {
File outputFile;
ArrayList<String> weightsParms;
if (interpolateExe == null) {
throw new ServiceException("no interpolate exe found.");
}
if (parmIdxFile == null) {
parmIdxFile = Config.getString("csip.dir") + "/data/wind_gen_his_upper_US_PR.idx";
}
if (parmPolygonFile == null) {
parmPolygonFile = Config.getString("csip.dir") + "/data/interpolation_boundary.pol";
}
if (parmOutputFile == null) {
parmOutputFile = "weights.txt";
}
// NOTE: this service .exe is very precise w/ input formats.
// Below is the only working format that I could find. Caveat Lector.
interpolateExe.setArguments(
"-f", parmIdxFile,
"-p", parmPolygonFile,
"-lat", parmLat,
"-lon", parmLon,
"-o", parmOutputFile
);
int ret = interpolateExe.exec();
if (ret != 0) {
throw new ServiceException("Error executing: " + interpolateExe);
}
outputFile = new File(workspaceDir + "/" + parmOutputFile);
return outputFile;
}
public File createInterpolatedWdb(String parmWeightsInFile) throws Exception {
return createInterpolatedWdb(parmWeightsInFile, null, null, null, null, null, null, null, null, null, null, null);
}
public File createInterpolatedWdb_US_PR(String parmWeightsInFile) throws Exception {
String parmWdb = Config.getString("csip.dir") + "/data/wind_gen_his_upper_US_PR.wdb";
return createInterpolatedWdb(parmWeightsInFile, parmWdb, null, null, null, null, null, null, null, null, null, null);
}
public File createInterpolatedWdb(String parmWeightsInFile,
String parmDBFileName,
String getStaDataIdx1, String parmIn1Weight,
String getStaDataIdx2, String parmIn2Weight,
String getStaDataIdx3, String parmIn3Weight,
String parmIn1File,
String parmIn2File,
String parmIn3File,
String parmWdbFile) throws ServiceException, Exception {
File wdbFile;
boolean getStaDataFlag = false;
if (interp_wdb == null) {
throw new ServiceException("no interp_wdb exe found.");
}
if (parmWdbFile == null) {
parmWdbFile = "test.wdb";
}
// The weights and indices to be combined can optionally specified in this input file
// which the output file from the interpolate endpoint
if (parmWeightsInFile == null) {
parmWeightsInFile = "";
}
if (parmWeightsInFile.length() > 0) {
File weightsFile = new File(workspaceDir + "/" + parmWeightsInFile);
//checkFileExists(weightsFile);
if (!weightsFile.exists()) {
throw new ServiceException("File does not exist, filename=" + weightsFile.getName());
}
ArrayList<String> weightsParms = parseWeightFile(weightsFile);
if (weightsParms.size() < 6) {
if (weightsParms.size() > 0) {
getStaDataIdx1 = weightsParms.get(0);
parmIn1Weight = weightsParms.get(1);
getStaDataIdx2 = weightsParms.get(0);
parmIn2Weight = weightsParms.get(1);
getStaDataIdx3 = weightsParms.get(0);
parmIn3Weight = ((Double) (1.0 - (Double.parseDouble(parmIn1Weight) + Double.parseDouble(parmIn2Weight)))).toString();
} else {
throw new ServiceException("Invalid weights file was generated by the interpolation executable. Expecting 5 entires, but found " + weightsParms.size());
}
} else {
getStaDataIdx1 = weightsParms.get(0);
parmIn1Weight = weightsParms.get(1);
getStaDataIdx2 = weightsParms.get(2);
parmIn2Weight = weightsParms.get(3);
getStaDataIdx3 = weightsParms.get(4);
parmIn3Weight = weightsParms.get(5);
}
getStaDataFlag = true;
} else {
// If no weights file, then weights must be specified
// If no weights file, indices have 2 choices:
// 1. specified as parms : stationIdx1
// 2. implied by the inputFile1 parm, which is the supplied data record for the index
if (getStaDataIdx1 == null) {
getStaDataIdx1 = "";
}
//checkParmExists("weight1");
if (parmIn1Weight == null) {
throw new ServiceException("File does not exist, filename=" + "weight1");
}
if (getStaDataIdx2 == null) {
getStaDataIdx2 = "";
}
//checkParmExists("weight2");
if (parmIn2Weight == null) {
throw new ServiceException("File does not exist, filename=" + "weight2");
}
if (getStaDataIdx3 == null) {
getStaDataIdx3 = "";
}
//checkParmExists("weight3");
if (parmIn3Weight == null) {
throw new ServiceException("File does not exist, filename=" + "weight3");
}
}
// If an index is specified, either directly or from the weights file, use it.
// If an index is specified, then that record must be extracted from the datafile.
// At this point, if there is no index, then there MUST be an inputFile parm.
if (getStaDataIdx1.length() > 0) {
parmIn1File = getStaDataIdx1;
getStaDataFlag = true;
} else {
//checkParmExists("inputFile1", "Must specify either inputFile1 or stationIdx1");
if (parmIn1File == null) {
throw new ServiceException("Must specify either inputFile1 or stationIdx1");
}
}
if (getStaDataIdx2.length() > 0) {
parmIn2File = getStaDataIdx2;
getStaDataFlag = true;
} else {
//checkParmExists("inputFile2", "Must specify either inputFile2 or stationIdx2");
if (parmIn2File == null) {
throw new ServiceException("Must specify either inputFile2 or stationIdx2");
}
}
if (getStaDataIdx3.length() > 0) {
parmIn3File = getStaDataIdx3;
getStaDataFlag = true;
} else {
//checkParmExists("inputFile3", "Must specify either inputFile3 or stationIdx3");
if (parmIn3File == null) {
throw new ServiceException("Must specify either inputFile3 or stationIdx3");
}
}
//
// Enter here if we need to get station data.
// I.e. all 3 station data records (inputFile1,2,3) have not been specified.
//
if (getStaDataFlag) {
// The data can come from one of 3 sources:
// 1. The internal database include with this endpoint
// 2. A supplied data file included with this request
// 3. Specified as individual file records with the inputFile1.2.3 parms
//if ( hasParam(PARMITEMDATAFILE) ) {
if (parmDBFileName == null) {
parmDBFileName = Config.getString("csip.dir") + "/data/wind_gen_his_upper_US.wdb";
}
getStationData(getStaDataIdx1, getStaDataIdx2, getStaDataIdx3, parmDBFileName);
}
//checkFileExists(workspace().getDir() + "/" + parmIn1File);
if (!(new File(workspaceDir + "/" + parmIn1File).exists())) {
throw new ServiceException("File does not exist, filename=" + parmIn1File);
}
//checkFileExists(workspace().getDir() + "/" + parmIn2File);
if (!(new File(workspaceDir + "/" + parmIn2File).exists())) {
throw new ServiceException("File does not exist, filename=" + parmIn2File);
}
//checkFileExists(workspace().getDir() + "/" + parmIn3File);
if (!(new File(workspaceDir + "/" + parmIn3File).exists())) {
throw new ServiceException("File does not exist, filename=" + parmIn3File);
}
interp_wdb.setArguments(parmWdbFile,
parmIn1File, parmIn1Weight,
parmIn2File, parmIn2Weight,
parmIn3File, parmIn3Weight
);
int ret = interp_wdb.exec();
if (ret != 0) {
throw new ServiceException("Error executing " + interp_wdb.toString());
}
wdbFile = new File(workspaceDir + "/" + parmWdbFile);
return wdbFile;
}
public File createInterpolatedWdbNew(String parmDBFileName,
JSONArray parmWeightsData,
String parmWdbFile
) throws ServiceException, Exception {
File wdbFile;
ArrayList<StationItem> stationData = getStationDataNew(parmWeightsData, parmDBFileName);
interp_wdb.setArguments(parmWdbFile);
for (StationItem dataItem : stationData) {
interp_wdb.addArguments(dataItem.stationId, dataItem.stationWeight);
}
int ret = interp_wdb.exec();
if (ret != 0) {
throw new ServiceException("Error executing " + interp_wdb.toString());
}
wdbFile = new File(workspaceDir + "/" + parmWdbFile);
return wdbFile;
}
//
// Source for this routine is : usda.weru.util.windgen.MakeInterpolatedStation.run() (line:288)
// note: possiblie Linux / Windows issues?
//
public ArrayList<String> parseWeightFile(File weightsInputFile) throws ServiceException {
BufferedReader br = null;
String inpLin = null;
ArrayList<String> stationsList;
stationsList = new ArrayList();
try {
br = new BufferedReader(new FileReader(weightsInputFile));
} catch (FileNotFoundException ex) {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("parseWeightFile : " + "IO Error (on new Reader): " + weightsInputFile.getAbsolutePath());
}
throw new ServiceException(ex);
}
try {
do {
try {
inpLin = br.readLine();
if (inpLin != null) {
inpLin = inpLin.trim();
if (!inpLin.startsWith("#")) {
String[] inpArr = inpLin.split(" +");
if (inpArr.length == 2) {
stationsList.add(inpArr[0]);
stationsList.add(String.valueOf(inpArr[1]));
}
}
}
} catch (IOException ex) {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("parseWeightFile : " + "IO Error (on readLine): " + weightsInputFile.getAbsolutePath());
}
inpLin = null;
}
} while (inpLin != null);
} finally {
try {
br.close();
} catch (IOException e) {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("parseWeightFile : " + "Unable to close stream: " + weightsInputFile.getAbsolutePath());
}
}
if (stationsList.size() != 6) {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("parseWeightFile : " + "Incorrect result size, should be 6: " + stationsList.size());
}
}
}
return stationsList;
}
protected void getStationData(String stationName1, String stationName2, String stationName3, String parmDBFileName) throws Exception {
//String parmDBFileName = csipDirName + "/d/windgenData/" + "wind_gen_his_upper_US.wdb";
if (parmDBFileName.length() > 0) {
File parmDBFile = new File(parmDBFileName);
//checkFileExists (parmDBFile);
if (!parmDBFile.exists()) {
throw new ServiceException("File does not exist, filename=" + parmDBFile.getName());
}
try {
extractStationFromWDB(parmDBFile, stationName1, stationName2, stationName3);
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
} else {
if (LOG.isLoggable(Level.INFO)) {
LOG.info("getStationData : " + "Need to get Station data and no file specified");
}
throw new ServiceException("Station database name is null in \"CSIP windgen interp_wdb");
}
}
protected ArrayList<StationItem> getStationDataNew(JSONArray stationData, String parmDBFileName) throws Exception {
JSONArray stationDataItem;
ArrayList<StationItem> stationArray = new ArrayList<>();
ArrayList<String> stationIdArray = new ArrayList<>();
if (parmDBFileName.length() > 0) {
File parmDBFile = new File(parmDBFileName);
if (!parmDBFile.exists()) {
throw new ServiceException("Interpolation data file does not exist, filename=" + parmDBFile.getName());
}
for (int i = 0; i < stationData.length(); i++) {
JSONObject o;
stationDataItem = stationData.getJSONArray(i);
String id = getValueByKey(stationDataItem, "stationId");
stationArray.add(new StationItem(id, getValueByKey(stationDataItem, "stationWeight")));
if (!stationIdArray.contains(id)) {
// this is for the extract function.
// It only needs to extract each record once.
stationIdArray.add(id);
}
}
try {
extractStationFromWDBNew(parmDBFile, stationIdArray);
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
throw new ServiceException("Station data extractionl in \"CSIP windgen interp_wdb", ex);
}
}
return stationArray;
}
//
// copied verbatum from usda.weru.uti.windgen.ExtractStationFromWdb.java
// (one change: TFile to File).
// (next change: copied the
// if (stat.equals(inpArr[1])) {
// block 3 times so that we can search for all 3 records with one pass through the data file)
// (next change: added the
// if (stat2.length() == 0 && stat3.length() == 0) {
// check so that we only break after all 3 stations are found.
//
// The 2 extractStationFromWDB routines extract the station records out of the
// specified wdb file and store them each in files in the CSIP working directory
// with the name of the file being the record id value.
// Those files, then, are read in by the interp_wdb function.
//
// one less than actual since 1st is already in inpLin
//
static int linesToCopy = 212;
protected void extractStationFromWDB(File wdb, String stat1, String stat2, String stat3) throws FileNotFoundException, IOException {
BufferedReader bfr = new BufferedReader(new FileReader(wdb), 32000); // each record is aprox. 20k
while (true) {
String inpLin = bfr.readLine();
if (inpLin == null) {
bfr.close();
throw new EOFException("station not found");
}
if (inpLin.length() > 10) {
String[] inpArr = inpLin.substring(0, 10).split(" ");
if ("#".equals(inpArr[0])) {
// System.out.println("inplin " + inpLin);
if (stat1.equals(inpArr[1])) {
try (PrintWriter pw = new PrintWriter(new File(workspaceDir, stat1))) {
pw.println(inpLin);
for (int idx = 0; idx < linesToCopy; idx++) {
inpLin = bfr.readLine();
pw.println(inpLin);
}
}
stat1 = "";
if (stat2.length() == 0 && stat3.length() == 0) {
bfr.close();
break;
}
} else if (stat2.equals(inpArr[1])) {
try (PrintWriter pw = new PrintWriter(new File(workspaceDir, stat2))) {
pw.println(inpLin);
for (int idx = 0; idx < linesToCopy; idx++) {
inpLin = bfr.readLine();
pw.println(inpLin);
}
}
stat2 = "";
if (stat1.length() == 0 && stat3.length() == 0) {
bfr.close();
break;
}
} else if (stat3.equals(inpArr[1])) {
try (PrintWriter pw = new PrintWriter(new File(workspaceDir, stat3))) {
pw.println(inpLin);
for (int idx = 0; idx < linesToCopy; idx++) {
inpLin = bfr.readLine();
pw.println(inpLin);
}
}
stat3 = "";
if (stat1.length() == 0 && stat2.length() == 0) {
bfr.close();
break;
}
}
}
}
}
}
protected void extractStationFromWDBNew(File wdb, ArrayList<String> stationIds) throws FileNotFoundException, IOException {
int stationCnt = stationIds.size();
BufferedReader bfr = new BufferedReader(new FileReader(wdb), 32000); // each record is aprox. 20k
while (true) {
String inpLin = bfr.readLine();
if (inpLin == null) {
bfr.close();
throw new EOFException("station not found");
}
if (inpLin.length() > 10) {
String[] inpArr = inpLin.substring(0, 10).split(" ");
if ("#".equals(inpArr[0])) {
if (stationIds.contains(inpArr[1])) {
try (PrintWriter pw = new PrintWriter(new File(workspaceDir, inpArr[1]))) {
pw.println(inpLin);
for (int idx = 0; idx < linesToCopy; idx++) {
inpLin = bfr.readLine();
pw.println(inpLin);
}
pw.close();
}
if (--stationCnt == 0) {
bfr.close();
break;
}
} else {
// Don't need to check for # on every line.
for (int idx = 0; idx < linesToCopy; idx++) {
inpLin = bfr.readLine();
}
}
}
}
}
}
}