V_1.java [src/java/m/ewsf/esp] Revision: default  Date:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package m.ewsf.esp;

import csip.Config;
import java.io.File;
import java.io.IOException;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.Path;
import csip.ModelDataService;
import csip.api.server.ServiceException;
import csip.annotations.Polling;
import csip.annotations.Resource;
import csip.annotations.ResourceType;
import csip.annotations.Description;
import csip.annotations.Name;
import csip.annotations.VersionInfo;
import org.omscentral.modules.analysis.esp.EspUtils;
import oms3.io.CSTable;
import oms3.io.DataIO;
import oms3.util.Dates;
import oms3.util.ProcessExecution;
import org.omscentral.modules.analysis.esp.ESPTimeSeries;
import org.omscentral.modules.analysis.esp.EnsembleData;
import org.omscentral.modules.analysis.esp.ModelDateTime;
import org.omscentral.modules.analysis.esp.TimeSeriesCookie;

/**
 * PRMS service.
 *
 * @author od
 */
@Name("PRMS_ESP")
@Description("PRMS ensemble streamflow prediction service.")
@VersionInfo("1.0")
@Polling(first = 9000, next = 1000)

// missing
@Resource(file = "/bin/oms-all.jar", type = ResourceType.JAR, id = "oms_jar")
@Resource(file = "/bin/jcommon-1.0.15.jar", type = ResourceType.JAR, id = "jcommon_jar")
@Resource(file = "/bin/jfreechart-1.0.12.jar", type = ResourceType.JAR, id = "jfreechart_jar")
@Resource(file = "/bin/groovy-all-2.3.9.jar", type = ResourceType.JAR, id = "groovy_jar")
@Resource(file = "/bin/nwcc2013.jar", type = ResourceType.JAR, id = "nwcc_jar")

@Path("m/prms_esp/1.0")
public class V_1 extends ModelDataService {

  private String histYears;
  private String espDates;
  Date[] dates;
  int[] h_years;
  //
  String oms_java_home = Config.getString("oms.java.home", "/usr/bin");


  @Override
  protected void doProcess() throws Exception {
    histYears = parameter().getString(DataIO.KEY_HIST_YEARS);
    espDates = parameter().getString(DataIO.KEY_ESP_DATES);
    dates = Dates.parseESPDates(espDates);
    h_years = Dates.parseHistoricalYears(histYears);

    runESP(workspace().getDir(), espDates, histYears, workspace().getDir().toString() + "/params.csv",
        workspace().getDir().toString() + "/data.csv");
  }


  @Override
  protected void postProcess() throws Exception {
    File resultFile = new File(workspace().getDir(), "/result.csv");
    PrintWriter res = new PrintWriter(resultFile);
    res.println("@S, Result");
    res.println(" " + DataIO.KEY_ESP_DATES + ", " + espDates);
    res.println(" " + DataIO.KEY_HIST_YEARS + ", " + histYears);
    res.close();

    EnsembleData ensembledata = resultsSetUp();
    FileWriter w = new FileWriter(new File(workspace().getDir(), "esp_results.csv"));
    EspUtils.writeReport(w, ensembledata, new String[]{workspace().getDir() + "/data.csv", "obs", "runoff[0]"}, resultFile);
    w.close();

    results().put(new File("esp_results.csv"));
  }


  private EnsembleData resultsSetUp() throws IOException {
    String var = "basin_cfs";

    ESPTimeSeries init = getInitTimeSeries(var);
    ArrayList<ESPTimeSeries> output = new ArrayList<ESPTimeSeries>();

    for (int year = h_years[0]; year <= h_years[1]; year++) {
      ESPTimeSeries ts = getOutputTimeSeries(var, year);
      output.add(ts);
    }
    ArrayList<ESPTimeSeries> forecasts = new ArrayList<ESPTimeSeries>();
    for (int year = h_years[0]; year <= h_years[1]; year++) {
      ESPTimeSeries ts = getForecastTimeSeries(var, year);
      forecasts.add(ts);
    }
    EnsembleData ed = new EnsembleData(var, init, forecasts, output, null);
    TimeSeriesCookie forecastTS = (TimeSeriesCookie) (forecasts.get(0));

    ModelDateTime analysisStart = (ModelDateTime) forecastTS.getStart().clone();
    ModelDateTime analysisEnd = (ModelDateTime) forecastTS.getEnd().clone();

    //setDefaultDates();
    ed.setAnalysisPeriod(analysisStart, analysisEnd);
    return ed;
  }


  private String[] asSysProps(Map<String, String> m) {
    List<String> b = new ArrayList<String>();
    for (String key : m.keySet()) {
      String val = m.get(key);
      b.add("-D" + key + "=" + val);
    }
    return b.toArray(new String[b.size()]);
  }


  private String getJars(String[] jars, File dir) throws IOException, ServiceException {
    StringBuilder cp = new StringBuilder();
    for (int i = 0; i < jars.length; i++) {
//            File jar = Binaries.unpackResource("/" + jars[i] + "_", new File(dir, jars[i]));
      File jar = resources().getFile(jars[i] + "_");

      cp.append(jar.toString());
      if (i < jars.length - 1) {
        cp.append(File.pathSeparatorChar);
      }
    }
    return cp.toString();
  }


  ProcessExecution createProcess(File work_dir, String loglevel, String dsl_name, String[] jars, Map<String, String> syprops) throws Exception {
    String[] jvmoptions = {};
    String binDir = Config.getString("m.bin.dir", "/tmp/csip/bin");
    String espthreads = Config.getString("oms.esp.threads", "4");
    if (!work_dir.exists()) {
      System.out.println("Working directory not found: " + work_dir + "\n");
      return null;
    }

//        File sim = Binaries.unpackResource("/" + dsl_name, work_dir);
    File sim = resources().getFile("/" + dsl_name);

    String[] sysprops_params = asSysProps(syprops);
    String classpath = getJars(jars, new File(binDir));

    ProcessExecution p = new ProcessExecution(new File(oms_java_home, "java"));
    Logger l = Logger.getAnonymousLogger();
    l.setLevel(Level.parse(loglevel));
    p.setWorkingDirectory(work_dir);
    p.setLogger(l);
    p.setArguments(jvmoptions,
        "-Desp.threads=" + espthreads,
        "-Doms3.work=" + work_dir,
        sysprops_params,
        "-cp", classpath,
        "oms3.CLI",
        "-l", loglevel,
        "-r", sim.toString());
    return p;
  }


  private int runESP(File ws, String esp_dates, String historical_years, String paramFile, String inputFile) throws Exception {
    // add prms to the path.
//        System.setProperty("oms.sim.resources", prms.toString());

    Map sysprops = new HashMap();
    sysprops.put("esp_dates", esp_dates);
    sysprops.put("historical_years", historical_years);
    sysprops.put("paramFile", paramFile);
    sysprops.put("inputFile", inputFile);

    ProcessExecution p = createProcess(ws, "OFF", "teton1.esp", new String[]{"oms-all.jar", "groovy-all-1.8.6.jar", "nwcc2013.jar"}, sysprops);
    // redirection
    // ..
    int result = p.exec();
    return result;
  }


  private ESPTimeSeries getInitTimeSeries(String var) throws IOException {
    String file = workspace().getDir() + "/output/esp_nwcc/out/esp-" + h_years[0] + "-out.csv";

    File filename = new File(file);
    CSTable table = DataIO.table(filename, "efc");

    double[] values = DataIO.getColumnDoubleValuesInterval(dates[0], Dates.dayBefore(dates[1]), table, var, DataIO.DAILY);
    double datesNum[] = new double[values.length];

    ModelDateTime start = new ModelDateTime();
    start.setTime(dates[0]);
    ModelDateTime end = new ModelDateTime();
    end.setTime(Dates.dayBefore(dates[1]));

    ModelDateTime current = new ModelDateTime();
    GregorianCalendar cal = new GregorianCalendar();
    cal.setTime(dates[0]);
    for (int i = 0; i < values.length; i++) {
      current.setTime(cal.getTime());
      datesNum[i] = current.getJulian();
      cal.add(Calendar.DATE, 1);
//            values[i] = (Double) table.getValueAt(i, col);
    }
    ESPTimeSeries ts = new ESPTimeSeries("init", datesNum, values, start, end, "", filename.toString(), "");
    return ts;
  }


  private ESPTimeSeries getOutputTimeSeries(String var, int y) throws IOException {

    String year = Integer.toString(y);
    File filename = new File(workspace().getDir() + "/output/esp_nwcc/out/esp-" + year + "-out.csv");
    CSTable table = DataIO.table(filename, "efc");

    Double v[] = DataIO.getColumnDoubleValues(table, var);
    Date d[] = DataIO.getColumnDateValues(table, "date");
    double values[] = new double[v.length];
    double datesNum[] = new double[v.length];

    ModelDateTime start = new ModelDateTime();
    start.setTime(dates[0]);

    ModelDateTime end = new ModelDateTime();
    end.setTime(dates[2]);

    ModelDateTime current = new ModelDateTime();
    for (int i = 0; i < datesNum.length; i++) {
      current.setTime(d[i]);
      datesNum[i] = current.getJulian();
      values[i] = v[i];
    }
    return new ESPTimeSeries(year, datesNum, values, start, end, "", filename.toString(), "");
  }


  private ESPTimeSeries getForecastTimeSeries(String var, int y) throws IOException {

    String year = Integer.toString(y);
    File filename = new File(workspace().getDir() + "/output/esp_nwcc/out/esp-" + year + "-out.csv");
    CSTable table = DataIO.table(filename, "efc");

    GregorianCalendar cal = new GregorianCalendar();
    cal.setTime(Dates.dayBefore(dates[1]));
    cal.add(Calendar.DATE, 1);

    double[] values = DataIO.getColumnDoubleValuesInterval(cal.getTime(), dates[2], table, var, DataIO.DAILY);
    double datesNum[] = new double[values.length];

    ModelDateTime start = new ModelDateTime();
    start.setTime(Dates.dayBefore(dates[1]));
    start.setJul2Greg(start.getJulian() + 1.0);

    ModelDateTime end = new ModelDateTime();
    end.setTime(dates[2]);

    ModelDateTime current = new ModelDateTime();
    for (int i = 0; i < datesNum.length; i++) {
      current.setTime(cal.getTime());
      datesNum[i] = current.getJulian();
      cal.add(Calendar.DATE, 1);
    }
    return new ESPTimeSeries(year, datesNum, values, start, end, "", filename.toString(), "");
  }

  // local testing
//    public static void main(String[] args) throws Exception {
//        V1esp_02 s = new V1esp_02();
//        s.runESP(new File("/tmp/csip/teton"), "2010-10-01/2013-02-15/2013-09-30", "1981/2012",
//                "/od/projects/brad/prms_all/test/esp/params.csv", "/od/projects/brad/prms_all/test/esp/data.csv");
//        V_1 v = new V_1();
//        v.setCachedFile(new File("/od/tmp/geowind03.zip"), 300);
//        String s = v.getSUID();
//        
//        File n = v.getCachedFile(s, "geowind03.zip");
//    }
}