WSStatsV2_0.java [src/java/m/weppws/results] 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 m.weppws.results;

import csip.ModelDataService;
import csip.annotations.*;
import csip.utils.JSONUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.ws.rs.*;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import util.Extract;
import util.Extract.Summary;

@Name("wsstats")
@Description("WEPPWS complete output stats")
@Path("m/wsstats/2.0")
@Polling(first = 2000, next = 2000)
public class WSStatsV2_0 extends ModelDataService {

  static final double US_TON = 0.00110231;

  @Override
  protected void doProcess() throws Exception {

    // one HS output summary
    String hsSummaryFile = parameter().getString("hs_summary", "hs_outputsummary.json");

    // simulation years
    int years = parameter().getInt("years");

    // Hillslope processing
    JSONObject hsSum = new JSONObject(workspace().readString(hsSummaryFile));
    JSONArray hs = hsSum.getJSONArray("Representative hillslope subcatchment summary");

    // total area 
    double area = hsSum.getDouble("Field/Watershed Area (ac)");

    // Col 15
    results().put("area", area, "Field (AOI) area", "ac");

    // Col 2
    results().put("precip", hsSum.getDouble("Precipitation (in)"), "Annual site precipitation", "in/yr");

    // Col 3
    double irr_vol = Extract.getHSElementSum(hs, "Irrigation Volume (ft^3/yr)");
    irr_vol = 0.0002754821 * irr_vol;  // ft3 -> ac-in
    results().put("irr_vol", irr_vol, "Annual Site Irrigation", "ac-in/yr");

    // Col 4
    double runoff_vol = Extract.getHSElementSum(hs, "Runoff Volume (ft^3/yr)");
    runoff_vol = 0.0002754821 * runoff_vol;  // ft3 -> ac-in
    results().put("runoff_vol", runoff_vol, "Annual Site Runoff", "ac-in/yr");

    // Col 5
    double soil_loss = Extract.getHSElementSum(hs, "Soil Loss (ton/yr)");
    results().put("hs_soil_loss", soil_loss / area, "Interrill and Rill Erosion", "ton/ac/yr");

    // stats col 5
    DoubleSummaryStatistics soil_loss_stats = Extract.getHSElementStats(hs, "Soil Loss per Area (ton/ac/yr)");
    putStats("hs_soil_loss_stats", soil_loss_stats, "Interrill and Rill Erosion Stats per Hillslope", "ton/ac/yr");

    // Col 6, Jim-> TBD
    double soil_loss_cp = Extract.getHSElementSum(hs, "Soil Loss (ton/yr)");
    results().put("hs_soil_loss_cp", soil_loss_cp / area, "Interrill and Rill Erosion for Conservation Planning (TBD)", "ton/ac/yr");
    //
    // Col 7
    double hs_sed_yield = Extract.getHSElementSum(hs, "Sediment Yield (ton/yr)");
    results().put("hs_sed_yield", hs_sed_yield / area, "Sediment Yield from Interrill and Rill Erosion", "ton/ac/yr");

    // stats col 7
    DoubleSummaryStatistics hs_sed_yield_stats = Extract.getHSElementStats(hs, "Sediment Yield per Area (ton/ac/yr)");
    putStats("hs_sed_yield_stats", hs_sed_yield_stats, "Sediment Yield from Interrill and Rill Erosion Stats", "ton/ac/yr");

    JSONArray outlets = parameter().getJSONArray("outlets");

    double aoi_channelsoil_loss = 0.0;
    List<Double> aoi_soil_loss_stats = new ArrayList<>();

    double aoi_inlet_sed_yield = 0.0;
    List<Double> aoi_inlet_sed_yield_stats = new ArrayList<>();

    double aoi_channel_sed_yield = 0.0;

    for (int out = 0; out < outlets.length(); out++) {
      JSONObject outlet = outlets.getJSONObject(out);
      // multiple WS output summary/sloss as array
      String wsSummary = outlet.getString("summary");
      String wsLoss = outlet.getString("soilLoss");
      int[] chIds = JSONUtils.toIntArray(outlet.getJSONArray("chIds"));

      List<Integer> tdChIds = toIntList(chIds);
      Map<Integer, Integer> chIdMap = Extract.getChannelIdMap(workspace().getExistingFile(wsSummary));
      List<Integer> weChIds = Extract.getWeppIdList(chIdMap, tdChIds, "Channel");

      Summary summary = Extract.getChannelStats(workspace().getExistingFile(wsLoss), years);

      double channel_soil_loss = summary.getChannelSoilLoss(weChIds).getAverage();
      double channel_sed_yield = summary.getChannelSedYield(weChIds).getAverage();

      summary.collectChannelSoilLoss(aoi_soil_loss_stats, weChIds);

      aoi_channelsoil_loss += channel_soil_loss;
      aoi_channel_sed_yield += channel_sed_yield;

      JSONArray inlets = outlet.getJSONArray("inlets");
      for (int inl = 0; inl < inlets.length(); inl++) {
        JSONObject inlet = outlets.getJSONObject(inl);
        String inSumFile = inlet.getString("summary");

        JSONObject inSum = new JSONObject(workspace().readString(inSumFile));
        double inlet_sed_yield = inSum.getDouble("Watershed sediment yield (ton/yr)");
        aoi_inlet_sed_yield += inlet_sed_yield;
        aoi_inlet_sed_yield_stats.add(inlet_sed_yield);
      }
    }

    // Col 8
    results().put("channel_soil_loss", aoi_channelsoil_loss * US_TON, "Ephemeral Gully Erosion", "ton/yr");

    // stats col 8
    DoubleSummaryStatistics stats = aoi_soil_loss_stats.stream().mapToDouble(d -> d).summaryStatistics();
    putStats("channel_soil_loss_stats", stats, "Ephemeral Gully Erosion Stats", "ton/yr");

    // Col 9
    results().put("channel_soil_loss_aoi", (aoi_channelsoil_loss * US_TON) / area, "Ephemeral Gully Erosion for Conservation Planning", "ton/ac/yr");

    // stats col 9
    putStats("channel_soil_loss_aoi_stats", stats.getMin() / area, stats.getAverage() / area, stats.getMax() / area, "Ephemeral Gully Erosion for Conservation Planning Stats", "ton/ac/yr");

    // Col 10
    results().put("inlet_sed_yield_aoi", aoi_inlet_sed_yield, "Sediment delivery into AOI", "ton/yr");

    // stats Col 10
    stats = aoi_inlet_sed_yield_stats.stream().mapToDouble(d -> d).summaryStatistics();
    putStats("inlet_sed_yield_aoi_stats", stats, "Sediment delivery into AOI Stats", "ton/yr");

    // Col (11)
    results().put("sed_yield_aoi", aoi_channel_sed_yield / area, "Sediment yield from ephemeral gully erosion", "ton/ac/yr");

    // Col 11
    double tot_sed_yeild = hs_sed_yield + aoi_channel_sed_yield;
    results().put("tot_sed_yield_aoi", tot_sed_yeild / area, "Total Sediment", "ton/ac/yr");

    // Col 12
    results().put("sed_delivery_ratio", -1, "Sediment Delivery Ratio");

    // Col 13
    results().put("eg_poo", -1, "Eph. Gully Erosion Probability of Occurrence ", "% years");

    // Col 14
    results().put("avg_eph_gully_vol", -1, "Average volume of Ephemeral Gullies within AOI ", "ft3/ac/yr");
  }

  static List<Integer> toIntList(int[] i) {
    return Arrays.stream(i).boxed().collect(Collectors.toList());
  }

  private void putStats(String name, DoubleSummaryStatistics s, String descr, String unit) {
    results().put(name, new double[]{s.getMin(), s.getAverage(), s.getMax()}, descr, unit);
  }

  private void putStats(String name, double min, double average, double max, String descr, String unit) {
    results().put(name, new double[]{min, average, max}, descr, unit);
  }

}