From 879e09b67289271c76c263c7d2e7b04b74d9d070 Mon Sep 17 00:00:00 2001
From: Peter Powers <pmpowers@usgs.gov>
Date: Thu, 24 Mar 2016 15:08:49 -0600
Subject: [PATCH] hazard Results now handles annRate vs poissProb output from
 config

---
 etc/examples/2-custom-config/README.md   |   1 +
 etc/examples/2-custom-config/config.json |   1 +
 src/org/opensha2/calc/Results.java       | 111 +++++++----------------
 3 files changed, 33 insertions(+), 80 deletions(-)

diff --git a/etc/examples/2-custom-config/README.md b/etc/examples/2-custom-config/README.md
index cff4d28ec..10b3a22ac 100644
--- a/etc/examples/2-custom-config/README.md
+++ b/etc/examples/2-custom-config/README.md
@@ -12,6 +12,7 @@ hazard ../../peer/models/Set1-Case1 "San Francisco,-122.40,37.75" config.json
 In this example we've overridden the configuration supplied by the model. Specifically:
 
 * The upper end of each hazard curve has been truncated at 3 standard deviations.
+* Hazard curves have been saved as poisson probability instead of annual rate.
 * Hazard curves have been calculated for 3 `imts` ([intensity measures](http://usgs.github.io/nshmp-haz/javadoc/index.html?org/opensha2/gmm/Imt.html), or spectral periods).
 * The `imls` (intensity measure levels or x-values) of the resultant curves have been explicitely defined for each `imt`.
 
diff --git a/etc/examples/2-custom-config/config.json b/etc/examples/2-custom-config/config.json
index 36b538061..81bf35969 100644
--- a/etc/examples/2-custom-config/config.json
+++ b/etc/examples/2-custom-config/config.json
@@ -3,6 +3,7 @@
     "exceedanceModel": "TRUNCATION_UPPER_ONLY",
     "truncationLevel": 3.0,
     "imts": ["PGA", "SA0P2", "SA1P0"],
+    "valueType": "POISSON_PROBABILITY",
     "customImls": {
       "PGA":   [0.0050, 0.0070, 0.0098, 0.0137, 0.0192, 0.0269, 0.0376, 0.0527, 0.0738, 0.103, 0.145, 0.203, 0.284, 0.397, 0.556, 0.778, 1.09, 1.52, 2.2, 3.3],
       "SA0P2": [0.0050, 0.0075, 0.0113, 0.0169, 0.0253, 0.0380, 0.0570, 0.0854, 0.128, 0.192, 0.288, 0.432, 0.649, 0.973, 1.46, 2.19, 3.28, 4.92, 7.38],
diff --git a/src/org/opensha2/calc/Results.java b/src/org/opensha2/calc/Results.java
index 13e0e9901..782f62aae 100644
--- a/src/org/opensha2/calc/Results.java
+++ b/src/org/opensha2/calc/Results.java
@@ -19,13 +19,14 @@ import org.opensha2.data.XySequence;
 import org.opensha2.eq.model.Source;
 import org.opensha2.eq.model.SourceSet;
 import org.opensha2.eq.model.SourceType;
-import org.opensha2.geo.Location;
 import org.opensha2.gmm.Gmm;
 import org.opensha2.gmm.Imt;
+import org.opensha2.mfd.Mfds;
 import org.opensha2.util.Parsing;
 import org.opensha2.util.Parsing.Delimiter;
 
 import com.google.common.base.Function;
+import com.google.common.base.Functions;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
@@ -43,6 +44,28 @@ public class Results {
 	private static final String CURVE_FILE_SUFFIX = ".csv";
 	private static final String RATE_FMT = "%.8e";
 
+	/*
+	 * Individual Hazard results only contain data relevant to the site of
+	 * interest (e.g. for the NSHM WUS models, hazard in San Fancisco is
+	 * influenced by slab sources whereas hazard in Los Angeles is not because
+	 * it is too far away). For consistency when outputting batches of results,
+	 * files are written for all source types and ground motion models supported
+	 * by the HazardModel being used. This yields curve sets that are consistent
+	 * across all locations in a batch, however, some of the curves may be
+	 * empty. Depending on the extents of a map or list of sites, some curve
+	 * sets may consist exclusively of zero-valued curves.
+	 */
+
+	/*
+	 * TODO There is no good reason for this class to be public. It would be
+	 * better as a ResultsWriter, an instance of which would be obtained and
+	 * configured on a per-calculation basis to receive batches of results.
+	 * Although problems are unlikely, we're repeating a number of configuration
+	 * steps below and relying on the same config file coming with the first
+	 * result in each batch (below). We also wouldn't have to pass around
+	 * OpenOptions which are mildly confusing.
+	 */
+
 	/**
 	 * Write a {@code batch} of {@code HazardResult}s to files in the specified
 	 * directory, one for each {@link Imt} in the {@code batch}. See
@@ -59,96 +82,24 @@ public class Results {
 	 * @throws IOException if a problem is encountered
 	 * @see Files#write(Path, Iterable, java.nio.charset.Charset, OpenOption...)
 	 */
-	@Deprecated
-	public static void writeResultsOLD(Path dir, List<Hazard> batch, OpenOption... options)
-			throws IOException {
-
-		Function<Double, String> locFmtFunc = Parsing.formatDoubleFunction("%.5f");
-		Function<Double, String> rateFmtFunc = Parsing.formatDoubleFunction(RATE_FMT);
-
-		Hazard demo = batch.get(0);
-		boolean newFile = options.length == 0;
-		boolean namedSites = demo.site.name != Site.NO_NAME;
-
-		Map<Imt, List<String>> lineMap = new EnumMap<>(Imt.class);
-		for (Imt imt : demo.totalCurves.keySet()) {
-			List<String> lineList = new ArrayList<>();
-			// write header
-			if (newFile) {
-				List<String> headings = new ArrayList<>();
-				if (namedSites) headings.add("name");
-				headings.add("lon");
-				headings.add("lat");
-				Iterable<?> header = Iterables.concat(
-					headings,
-					demo.config.curve.modelCurves().get(imt).xValues());
-				lineList.add(Parsing.join(header, Delimiter.COMMA));
-			}
-			lineMap.put(imt, lineList);
-		}
-
-		for (Hazard result : batch) {
-			Iterable<String> locData = Iterables.transform(
-				Lists.newArrayList(
-					result.site.location.lon(),
-					result.site.location.lat()),
-				locFmtFunc);
-			String name = result.site.name;
-			for (Entry<Imt, XySequence> entry : result.totalCurves.entrySet()) {
-
-				// enable to output poisson probability - used when running
-				// PEER test cases - TODO should be configurable
-				// Function<Double, String> valueFunction = Functions.compose(
-				// rateFmtFunc,
-				// Mfds.rateToProbConverter());
-
-				// enable to output annual rate
-				Function<Double, String> valueFunction = rateFmtFunc;
-
-				Iterable<String> lineData = Iterables.concat(
-					locData,
-					Iterables.transform(
-						entry.getValue().yValues(),
-						valueFunction));
-
-				String line = Parsing.join(lineData, Delimiter.COMMA);
-				if (namedSites) line = name + "," + line;
-				lineMap.get(entry.getKey()).add(line);
-			}
-		}
-
-		for (Entry<Imt, List<String>> entry : lineMap.entrySet()) {
-			String filename = entry.getKey().name() + CURVE_FILE_SUFFIX;
-			Path file = dir.resolve(filename);
-			Files.write(file, entry.getValue(), US_ASCII, options);
-		}
-	}
-
-	/*
-	 * Individual Hazard results only contain data relevant to the site of
-	 * interest (e.g. for the NSHM WUS models, hazard in San Fancisco is
-	 * influenced by slab sources whereas hazard in Los Angeles is not because
-	 * it is too far away). For consistency when outputting batches of results,
-	 * files are written for all source types and ground motion models supported
-	 * by the HazardModel being used. This yields curve sets that are consistent
-	 * across all locations in a batch, however, some of the curves may be
-	 * empty. Depending on the extents of a map or list of sites, some curve
-	 * sets may consist exclusively of zero-valued curves.
-	 */
-
 	public static void writeResults(
 			Path dir,
 			List<Hazard> batch,
 			OpenOption... options) throws IOException {
 
-		Function<Double, String> formatter = Parsing.formatDoubleFunction(RATE_FMT);
-
 		Hazard demo = batch.get(0);
 		boolean newFile = options.length == 0;
 		boolean namedSites = demo.site.name != Site.NO_NAME;
 		boolean gmmCurves = demo.config.output.curveTypes.contains(CurveType.GMM);
 		boolean sourceCurves = demo.config.output.curveTypes.contains(CurveType.SOURCE);
 
+		Function<Double, String> formatter = Parsing.formatDoubleFunction(RATE_FMT);
+		if (demo.config.curve.valueType == CurveValue.POISSON_PROBABILITY) {
+			formatter = Functions.compose(
+				formatter,
+				Mfds.annualRateToProbabilityConverter());
+		}
+
 		Map<Imt, List<String>> totalLineMap = Maps.newEnumMap(Imt.class);
 		Map<Imt, Map<SourceType, List<String>>> sourceLineMap = Maps.newEnumMap(Imt.class);
 		Map<Imt, Map<Gmm, List<String>>> gmmLineMap = Maps.newEnumMap(Imt.class);
-- 
GitLab