From 418c01f73514b6df9f8c5a39a9c16a1d25d9bdb1 Mon Sep 17 00:00:00 2001 From: Peter Powers <pmpowers@usgs.gov> Date: Mon, 25 Jan 2016 14:40:30 -0700 Subject: [PATCH] updates to Results class and related changes --- src/org/opensha2/calc/CalcConfig.java | 17 +- src/org/opensha2/calc/CalcFactory.java | 3 +- src/org/opensha2/calc/HazardCurveSet.java | 20 +- src/org/opensha2/calc/Results.java | 269 +++++++++++++++++++-- src/org/opensha2/eq/model/HazardModel.java | 8 + src/org/opensha2/programs/HazardCalc.java | 25 +- src/org/opensha2/util/Parsing.java | 5 +- test/etc/SequenceBenchmark.java | 11 +- 8 files changed, 302 insertions(+), 56 deletions(-) diff --git a/src/org/opensha2/calc/CalcConfig.java b/src/org/opensha2/calc/CalcConfig.java index f686df122..8f070c487 100644 --- a/src/org/opensha2/calc/CalcConfig.java +++ b/src/org/opensha2/calc/CalcConfig.java @@ -6,7 +6,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static java.nio.charset.StandardCharsets.UTF_8; import static org.opensha2.util.TextUtils.format; - import static org.opensha2.data.XySequence.*; import java.io.IOException; @@ -19,6 +18,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.opensha2.calc.Results.HazardFormat; import org.opensha2.data.Data; import org.opensha2.data.XySequence; import org.opensha2.gmm.Imt; @@ -47,6 +47,8 @@ public final class CalcConfig { private final Map<Imt, double[]> customImls; private final boolean optimizeGrids; private final boolean gmmUncertainty; + + private final HazardFormat hazardFormat; private final DeaggData deagg; @@ -69,6 +71,7 @@ public final class CalcConfig { Map<Imt, double[]> customImls, boolean optimizeGrids, boolean gmmUncertainty, + HazardFormat hazardFormat, DeaggData deagg, SiteSet sites, Map<Imt, XySequence> modelCurves, @@ -82,6 +85,7 @@ public final class CalcConfig { this.customImls = customImls; this.optimizeGrids = optimizeGrids; this.gmmUncertainty = gmmUncertainty; + this.hazardFormat = hazardFormat; this.deagg = deagg; this.sites = sites; this.modelCurves = modelCurves; @@ -96,6 +100,7 @@ public final class CalcConfig { DEFAULT_IMLS, CUSTOM_IMLS, GMM_UNCERTAINTY, + HAZARD_FORMAT, OPTIMIZE_GRIDS, DEAGG, SITES; @@ -131,6 +136,7 @@ public final class CalcConfig { .append(customImlStr) .append(format(Key.OPTIMIZE_GRIDS)).append(optimizeGrids) .append(format(Key.GMM_UNCERTAINTY)).append(gmmUncertainty) + .append(format(Key.HAZARD_FORMAT)).append(hazardFormat) .append(format("Deaggregation R")) .append("min=").append(deagg.rMin).append(", ") .append("max=").append(deagg.rMax).append(", ") @@ -184,6 +190,9 @@ public final class CalcConfig { return gmmUncertainty; } + public HazardFormat hazardFormat() { + return hazardFormat; + } /** * Deaggregation configuration data. */ @@ -294,6 +303,7 @@ public final class CalcConfig { private Map<Imt, double[]> customImls; private Boolean optimizeGrids; private Boolean gmmUncertainty; + private HazardFormat hazardFormat; private DeaggData deagg; private SiteSet sites; @@ -310,6 +320,7 @@ public final class CalcConfig { this.customImls = config.customImls; this.optimizeGrids = config.optimizeGrids; this.gmmUncertainty = config.gmmUncertainty; + this.hazardFormat = config.hazardFormat; this.deagg = config.deagg; this.sites = config.sites; return this; @@ -329,6 +340,7 @@ public final class CalcConfig { this.customImls = Maps.newHashMap(); this.optimizeGrids = true; this.gmmUncertainty = false; + this.hazardFormat = HazardFormat.TOTAL; this.deagg = new DeaggData(); this.sites = new SiteSet(Lists.newArrayList(Site.builder().build())); return this; @@ -348,6 +360,7 @@ public final class CalcConfig { if (that.customImls != null) this.customImls = that.customImls; if (that.optimizeGrids != null) this.optimizeGrids = that.optimizeGrids; if (that.gmmUncertainty != null) this.gmmUncertainty = that.gmmUncertainty; + if (that.hazardFormat != null) this.hazardFormat = that.hazardFormat; if (that.deagg != null) this.deagg = that.deagg; if (that.sites != null) this.sites = that.sites; return this; @@ -397,6 +410,7 @@ public final class CalcConfig { checkNotNull(customImls, MSSG, buildId, Key.CUSTOM_IMLS); checkNotNull(optimizeGrids, MSSG, buildId, Key.OPTIMIZE_GRIDS); checkNotNull(gmmUncertainty, MSSG, buildId, Key.GMM_UNCERTAINTY); + checkNotNull(hazardFormat, MSSG, buildId, Key.HAZARD_FORMAT); checkNotNull(deagg, MSSG, buildId, Key.DEAGG); checkNotNull(sites, MSSG, buildId, Key.SITES); built = true; @@ -419,6 +433,7 @@ public final class CalcConfig { customImls, optimizeGrids, gmmUncertainty, + hazardFormat, deagg, sites, curves, logCurves); diff --git a/src/org/opensha2/calc/CalcFactory.java b/src/org/opensha2/calc/CalcFactory.java index 9e666e3aa..d52808ab9 100644 --- a/src/org/opensha2/calc/CalcFactory.java +++ b/src/org/opensha2/calc/CalcFactory.java @@ -162,8 +162,7 @@ final class CalcFactory { return transform( allAsList(curveSets), - new CurveSetConsolidator(model, config, site), - ex).get(); + new CurveSetConsolidator(model, config, site), ex).get(); } } diff --git a/src/org/opensha2/calc/HazardCurveSet.java b/src/org/opensha2/calc/HazardCurveSet.java index 77036e6e7..d3bfbed22 100644 --- a/src/org/opensha2/calc/HazardCurveSet.java +++ b/src/org/opensha2/calc/HazardCurveSet.java @@ -22,8 +22,8 @@ import org.opensha2.gmm.Imt; /** * Container class for hazard curves derived from a {@code SourceSet}. Class - * stores the {@code HazardGroundMotions}s associated with each {@code Source} - * used in a hazard calculation and the combined curves for each + * stores the {@code GroundMotions}s associated with each {@code Source} used in + * a hazard calculation and the individual curves for each * {@code GroundMotionModel} used. * * <p>The {@code Builder} for this class is used to aggregate the HazardCurves @@ -37,8 +37,8 @@ import org.opensha2.gmm.Imt; * including {@code ClusterSourceSet}s, which are handled differently in hazard * calculations. This container marks a point in the calculation pipeline where * results from cluster and other sources may be recombined into a single - * {@code HazardResult}, regardless of {@code SourceSet.type()} for all relevant - * {@code SourceSet}s.</p> + * {@code Hazard} result, regardless of {@code SourceSet.type()} for all + * relevant {@code SourceSet}s.</p> * * @author Peter Powers */ @@ -134,8 +134,10 @@ final class HazardCurveSet { Map<Gmm, XySequence> curveMapBuild = curveMap.get(imt); // loop Gmms based on what's supported at this distance for (Gmm gmm : gmmWeightMap.keySet()) { - double weight = gmmWeightMap.get(gmm); - curveMapBuild.get(gmm).add(copyOf(curveMapIn.get(gmm)).multiply(weight)); + double gmmWeight = gmmWeightMap.get(gmm); + curveMapBuild.get(gmm).add(copyOf(curveMapIn.get(gmm)) + .multiply(gmmWeight) + .multiply(sourceSet.weight())); } } return this; @@ -154,7 +156,9 @@ final class HazardCurveSet { // loop Gmms based on what's supported at this distance for (Gmm gmm : gmmWeightMap.keySet()) { double weight = gmmWeightMap.get(gmm) * clusterWeight; - curveMapBuild.get(gmm).add(copyOf(curveMapIn.get(gmm)).multiply(weight)); + curveMapBuild.get(gmm).add(copyOf(curveMapIn.get(gmm)) + .multiply(weight) + .multiply(sourceSet.weight())); } } return this; @@ -177,14 +181,12 @@ final class HazardCurveSet { * scaled by their weights while building (above). */ private void computeFinal() { - double sourceSetWeight = sourceSet.weight(); for (Entry<Imt, Map<Gmm, XySequence>> entry : curveMap.entrySet()) { Imt imt = entry.getKey(); XySequence totalCurve = emptyCopyOf(modelCurves.get(imt)); for (XySequence curve : entry.getValue().values()) { totalCurve.add(curve); } - totalCurve.multiply(sourceSetWeight); totalCurves.put(imt, immutableCopyOf(totalCurve)); } } diff --git a/src/org/opensha2/calc/Results.java b/src/org/opensha2/calc/Results.java index cb40d4e4f..703657ddf 100644 --- a/src/org/opensha2/calc/Results.java +++ b/src/org/opensha2/calc/Results.java @@ -11,6 +11,7 @@ import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collection; import java.util.EnumMap; import java.util.List; import java.util.Map; @@ -18,18 +19,26 @@ import java.util.Map.Entry; import java.util.Set; import org.opensha2.data.XySequence; +import org.opensha2.eq.model.HazardModel; +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.util.Parsing; import org.opensha2.util.Parsing.Delimiter; import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; +import com.google.common.primitives.Doubles; /** * Factory class for reducing and exporting various result types. @@ -38,9 +47,21 @@ import com.google.common.collect.Multimap; */ public class Results { - private static final String CURVE_FILE_SUFFIX = "-curves.csv"; + private static final String CURVE_FILE_SUFFIX = ".csv"; private static final String RATE_FMT = "%.8e"; + /** + * Output style. + */ + public enum HazardFormat { + + /** Total mean hazard only. */ + TOTAL, + + /** Additional curves by {@link Gmm} and {@link SourceType}. */ + DETAILED; + } + /** * Write a {@code batch} of {@code HazardResult}s to files in the specified * directory, one for each {@link Imt} in the {@code batch}. See @@ -57,7 +78,8 @@ public class Results { * @throws IOException if a problem is encountered * @see Files#write(Path, Iterable, java.nio.charset.Charset, OpenOption...) */ - public static void writeResults(Path dir, List<Hazard> batch, OpenOption... options) + @Deprecated + public static void writeResultsOLD(Path dir, List<Hazard> batch, OpenOption... options) throws IOException { Function<Double, String> locFmtFunc = Parsing.formatDoubleFunction(Location.FORMAT); @@ -76,7 +98,7 @@ public class Results { if (namedSites) headings.add("name"); headings.add("lon"); headings.add("lat"); - Iterable<? extends Object> header = Iterables.concat( + Iterable<?> header = Iterables.concat( headings, demo.config.modelCurves().get(imt).xValues()); lineList.add(Parsing.join(header, Delimiter.COMMA)); @@ -91,13 +113,13 @@ public class Results { result.site.location.lat()), locFmtFunc); String name = result.site.name; - for (Entry<Imt, ? extends XySequence> entry : result.totalCurves.entrySet()) { + 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()); + // Function<Double, String> valueFunction = Functions.compose( + // rateFmtFunc, + // Mfds.rateToProbConverter()); // enable to output annual rate Function<Double, String> valueFunction = rateFmtFunc; @@ -121,31 +143,232 @@ public class Results { } } - public static Map<Imt, Map<SourceType, XySequence>> totalsByType(Hazard hazard) { + /* + * 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); - ImmutableMap.Builder<Imt, Map<SourceType, XySequence>> imtMapBuilder = - ImmutableMap.builder(); + Hazard demo = batch.get(0); + boolean newFile = options.length == 0; + boolean namedSites = demo.site.name != Site.NO_NAME; + boolean detailed = demo.config.hazardFormat().equals(HazardFormat.DETAILED); - Map<Imt, XySequence> curves = hazard.curves(); - Set<Imt> imts = curves.keySet(); + Map<Imt, List<String>> totalLineMap = Maps.newEnumMap(Imt.class); + Map<Imt, Map<SourceType, List<String>>> typeLineMap = Maps.newEnumMap(Imt.class); + Map<Imt, Map<Gmm, List<String>>> gmmLineMap = Maps.newEnumMap(Imt.class); - for (Imt imt : imts) { + /* Initialize line maps for all types and gmms referenced by a model */ + for (Imt imt : demo.totalCurves.keySet()) { + List<String> lines = new ArrayList<>(); + if (newFile) { + Iterable<?> header = Iterables.concat( + Lists.newArrayList(namedSites ? "name" : null, "lon", "lat"), + demo.config.modelCurves().get(imt).xValues()); + lines.add(Parsing.join(header, Delimiter.COMMA)); + } + totalLineMap.put(imt, lines); - XySequence modelCurve = emptyCopyOf(curves.get(imt)); - Map<SourceType, XySequence> typeCurves = new EnumMap<>(SourceType.class); + if (detailed) { + + Map<SourceType, List<String>> typeLines = Maps.newEnumMap(SourceType.class); + for (SourceType type : demo.model.types()) { + typeLines.put(type, Lists.newArrayList(lines)); + } + typeLineMap.put(imt, typeLines); - Multimap<SourceType, HazardCurveSet> curveSets = hazard.sourceSetCurves; - for (SourceType type : curveSets.keySet()) { - XySequence typeCurve = copyOf(modelCurve); - for (HazardCurveSet curveSet : curveSets.get(type)) { - typeCurve.add(curveSet.totalCurves.get(imt)); + Map<Gmm, List<String>> gmmLines = Maps.newEnumMap(Gmm.class); + for (Gmm gmm : gmmSet(demo.model)) { + gmmLines.put(gmm, Lists.newArrayList(lines)); } - typeCurves.put(type, immutableCopyOf(typeCurve)); + gmmLineMap.put(imt, gmmLines); } - imtMapBuilder.put(imt, Maps.immutableEnumMap(typeCurves)); } - return imtMapBuilder.build(); + /* Process batch */ + for (Hazard hazard : batch) { + + String name = namedSites ? hazard.site.name : null; + List<String> locData = Lists.newArrayList( + name, + String.format(Location.FORMAT, hazard.site.location.lon()), + String.format(Location.FORMAT, hazard.site.location.lat())); + + Map<Imt, Map<SourceType, XySequence>> curvesByType = detailed ? + curvesByType(hazard) : null; + Map<Imt, Map<Gmm, XySequence>> curvesByGmm = detailed ? + curvesByGmm(hazard) : null; + + for (Entry<Imt, XySequence> imtEntry : hazard.totalCurves.entrySet()) { + Imt imt = imtEntry.getKey(); + + XySequence totalCurve = imtEntry.getValue(); + Iterable<Double> emptyValues = Doubles.asList(new double[totalCurve.size()]); + String emptyLine = toLine(locData, emptyValues, formatter); + + totalLineMap.get(imt).add(toLine( + locData, + imtEntry.getValue().yValues(), + formatter)); + + if (detailed) { + + Map<SourceType, XySequence> typeCurves = curvesByType.get(imt); + for (Entry<SourceType, List<String>> typeEntry : typeLineMap.get(imt) + .entrySet()) { + SourceType type = typeEntry.getKey(); + String typeLine = typeCurves.containsKey(type) ? + toLine(locData, typeCurves.get(type).yValues(), formatter) : + emptyLine; + typeEntry.getValue().add(typeLine); + } + + Map<Gmm, XySequence> gmmCurves = curvesByGmm.get(imt); + for (Entry<Gmm, List<String>> gmmEntry : gmmLineMap.get(imt).entrySet()) { + Gmm gmm = gmmEntry.getKey(); + String gmmLine = gmmCurves.containsKey(gmm) ? + toLine(locData, gmmCurves.get(gmm).yValues(), formatter) : + emptyLine; + gmmEntry.getValue().add(gmmLine); + } + } + } + } + + /* write/append */ + for (Entry<Imt, List<String>> totalEntry : totalLineMap.entrySet()) { + Imt imt = totalEntry.getKey(); + + Path imtDir = dir.resolve(imt.name()); + Files.createDirectories(imtDir); + Path totalFile = imtDir.resolve("total" + CURVE_FILE_SUFFIX); + Files.write(totalFile, totalEntry.getValue(), US_ASCII, options); + + if (detailed) { + + Path typeDir = imtDir.resolve("type"); + Files.createDirectories(typeDir); + for (Entry<SourceType, List<String>> typeEntry : typeLineMap.get(imt).entrySet()) { + Path typeFile = typeDir.resolve( + typeEntry.getKey().toString() + CURVE_FILE_SUFFIX); + Files.write(typeFile, typeEntry.getValue(), US_ASCII, options); + } + + Path gmmDir = imtDir.resolve("gmm"); + Files.createDirectories(gmmDir); + for (Entry<Gmm, List<String>> gmmEntry : gmmLineMap.get(imt).entrySet()) { + Path gmmFile = gmmDir.resolve(gmmEntry.getKey().name() + CURVE_FILE_SUFFIX); + Files.write(gmmFile, gmmEntry.getValue(), US_ASCII, options); + } + } + } + } + + private static String toLine( + Iterable<String> location, + Iterable<Double> values, + Function<Double, String> formatter) { + + return Parsing.join( + FluentIterable.from(location).append(Iterables.transform(values, formatter)), + Delimiter.COMMA); + } + + /** + * Derive maps of curves by source type for each Imt in a {@code Hazard} + * result. + */ + public static Map<Imt, Map<SourceType, XySequence>> curvesByType(Hazard hazard) { + + EnumMap<Imt, Map<SourceType, XySequence>> imtMap = Maps.newEnumMap(Imt.class); + + // initialize receiver + Set<SourceType> types = hazard.sourceSetCurves.keySet(); + for (Entry<Imt, XySequence> entry : hazard.curves().entrySet()) { + imtMap.put(entry.getKey(), initCurves(types, entry.getValue())); + } + + for (Entry<SourceType, HazardCurveSet> curveSet : hazard.sourceSetCurves.entries()) { + for (Entry<Imt, XySequence> typeTotals : curveSet.getValue().totalCurves.entrySet()) { + imtMap.get(typeTotals.getKey()) + .get(curveSet.getKey()) + .add(typeTotals.getValue()); + } + } + return Maps.immutableEnumMap(imtMap); } + /** + * Derive maps of curves by groudn motion model for each Imt in a + * {@code Hazard} result. + */ + public static Map<Imt, Map<Gmm, XySequence>> curvesByGmm(Hazard hazard) { + + EnumMap<Imt, Map<Gmm, XySequence>> imtMap = Maps.newEnumMap(Imt.class); + + // initialize receiver + Iterable<SourceSet<? extends Source>> sources = Iterables.transform( + hazard.sourceSetCurves.values(), + CURVE_SET_TO_SOURCE_SET); + Set<Gmm> gmms = gmmSet(sources); + for (Entry<Imt, XySequence> entry : hazard.curves().entrySet()) { + imtMap.put(entry.getKey(), initCurves(gmms, entry.getValue())); + } + + for (HazardCurveSet curveSet : hazard.sourceSetCurves.values()) { + for (Entry<Imt, Map<Gmm, XySequence>> imtEntry : curveSet.curveMap.entrySet()) { + for (Entry<Gmm, XySequence> gmmEntry : imtEntry.getValue().entrySet()) { + imtMap.get(imtEntry.getKey()).get(gmmEntry.getKey()).add(gmmEntry.getValue()); + } + } + } + return Maps.immutableEnumMap(imtMap); + } + + /* Scan the supplied source sets for the set of all GMMs used. */ + private static Set<Gmm> gmmSet(final Iterable<SourceSet<? extends Source>> sourceSets) { + return Sets.immutableEnumSet( + FluentIterable.from(sourceSets).transformAndConcat( + new Function<SourceSet<? extends Source>, Set<Gmm>>() { + @Override public Set<Gmm> apply(SourceSet<? extends Source> sourceSet) { + return sourceSet.groundMotionModels().gmms(); + } + }) + ); + } + + /* Initalize a map of curves, one entry for each of the supplied enum keys. */ + private static <K extends Enum<K>> Map<K, XySequence> initCurves( + final Set<K> keys, + final XySequence model) { + return Maps.immutableEnumMap( + FluentIterable.from(keys).toMap( + new Function<K, XySequence>() { + @Override public XySequence apply(K key) { + return emptyCopyOf(model); + } + }) + ); + } + + private static final Function<HazardCurveSet, SourceSet<? extends Source>> CURVE_SET_TO_SOURCE_SET = + new Function<HazardCurveSet, SourceSet<? extends Source>>() { + @Override public SourceSet<? extends Source> apply(HazardCurveSet curves) { + return curves.sourceSet; + } + }; + } diff --git a/src/org/opensha2/eq/model/HazardModel.java b/src/org/opensha2/eq/model/HazardModel.java index 52e6f1342..0a2e3ca59 100644 --- a/src/org/opensha2/eq/model/HazardModel.java +++ b/src/org/opensha2/eq/model/HazardModel.java @@ -7,6 +7,7 @@ import static org.opensha2.util.TextUtils.validateName; import java.nio.file.Path; import java.util.Iterator; +import java.util.Set; import org.opensha2.calc.CalcConfig; import org.opensha2.gmm.GroundMotionModel; @@ -99,6 +100,13 @@ public final class HazardModel implements Iterable<SourceSet<? extends Source>>, @Override public String name() { return name; } + + /** + * The set of {@code SourceType}s included in this model. + */ + public Set<SourceType> types() { + return sourceSetMap.keySet(); + } /** * Return the default calculation configuration. This may be overridden. diff --git a/src/org/opensha2/programs/HazardCalc.java b/src/org/opensha2/programs/HazardCalc.java index 03a792207..223b3824f 100644 --- a/src/org/opensha2/programs/HazardCalc.java +++ b/src/org/opensha2/programs/HazardCalc.java @@ -7,7 +7,6 @@ import static org.opensha2.util.TextUtils.NEWLINE; import static org.opensha2.util.TextUtils.format; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; @@ -100,7 +99,7 @@ public class HazardCalc { try { - log.info("Hazard curve: init..."); + log.info(PROGRAM + ": init..."); Path modelPath = Paths.get(args[0]); HazardModel model = HazardModel.load(modelPath); @@ -132,8 +131,8 @@ public class HazardCalc { } catch (Exception e) { return new StringBuilder() .append(NEWLINE) - .append("Hazard Curve: error").append(NEWLINE) - .append(" Arguments: ").append(Arrays.toString(args)).append(NEWLINE) + .append(PROGRAM + ": error").append(NEWLINE) + .append(" Arguments: ").append(Arrays.toString(args)).append(NEWLINE) .append(NEWLINE) .append(Throwables.getStackTraceAsString(e)).append(NEWLINE) .append(NEWLINE) @@ -157,15 +156,14 @@ public class HazardCalc { ExecutorService execSvc = createExecutor(); Optional<Executor> executor = Optional.<Executor> of(execSvc); - log.info("Hazard Curve: calculating ..."); + log.info(PROGRAM + ": calculating ..."); Stopwatch batchWatch = Stopwatch.createStarted(); Stopwatch totalWatch = Stopwatch.createStarted(); int count = 0; List<Hazard> results = new ArrayList<>(); boolean firstBatch = true; - Path dir = Paths.get(StandardSystemProperty.USER_DIR.value(), "results"); - Files.createDirectories(dir); + Path dir = Paths.get(StandardSystemProperty.USER_DIR.value()); for (Site site : sites) { Hazard result = calc(model, config, site, executor); @@ -175,7 +173,7 @@ public class HazardCalc { OpenOption[] opts = firstBatch ? WRITE_OPTIONS : APPEND_OPTIONS; firstBatch = false; Results.writeResults(dir, results, opts); - log.info(" batch: " + (count + 1) + " " + batchWatch + " total: " + + log.info(" batch: " + (count + 1) + " " + batchWatch + " total: " + totalWatch); results.clear(); batchWatch.reset(); @@ -188,7 +186,7 @@ public class HazardCalc { OpenOption[] opts = firstBatch ? WRITE_OPTIONS : APPEND_OPTIONS; Results.writeResults(dir, results, opts); } - log.info("Hazard Curve: " + count + " complete " + totalWatch); + log.info(PROGRAM + ": " + count + " complete " + totalWatch); execSvc.shutdown(); } @@ -229,12 +227,13 @@ public class HazardCalc { return newFixedThreadPool(getRuntime().availableProcessors()); } - private static final String USAGE_COMMAND = "java -cp nshmp-haz.jar org.opensha.programs.HazardCurve model [config [sites]]"; - private static final String USAGE_URL1 = "https://github.com/usgs/nshmp-haz/wiki/Earthquake-Source-Models"; - private static final String USAGE_URL2 = "https://github.com/usgs/nshmp-haz/wiki/Hazard-Calculations"; + private static final String PROGRAM = HazardCalc.class.getSimpleName(); + private static final String USAGE_COMMAND = "java -cp nshmp-haz.jar org.opensha.programs.HazardCalc model [config [sites]]"; + private static final String USAGE_URL1 = "https://github.com/usgs/nshmp-haz/wiki"; + private static final String USAGE_URL2 = "https://github.com/usgs/nshmp-haz/tree/master/etc"; static final String USAGE = new StringBuilder() - .append("HazardCurve usage:").append(NEWLINE) + .append(PROGRAM).append(" usage:").append(NEWLINE) .append(" ").append(USAGE_COMMAND).append(NEWLINE) .append(NEWLINE) .append("Where:").append(NEWLINE) diff --git a/src/org/opensha2/util/Parsing.java b/src/org/opensha2/util/Parsing.java index 01ca380e7..be5df9f26 100644 --- a/src/org/opensha2/util/Parsing.java +++ b/src/org/opensha2/util/Parsing.java @@ -829,7 +829,8 @@ public final class Parsing { /** * Returns a {@link Function} for converting {@code double}s to formatted - * strings. + * strings. If a value to format is 0.0, the format string is ignored in + * favor of always printing the often more compact string: "0.0". * * @param format a format string * @see String#format(String, Object...) @@ -846,7 +847,7 @@ public final class Parsing { } @Override public String apply(Double value) { - return String.format(format, value); + return (value == 0.0) ? "0.0" : String.format(format, value); } } diff --git a/test/etc/SequenceBenchmark.java b/test/etc/SequenceBenchmark.java index 558fcff63..7254ba081 100644 --- a/test/etc/SequenceBenchmark.java +++ b/test/etc/SequenceBenchmark.java @@ -46,8 +46,8 @@ class SequenceBenchmark { } for (int k = 0; k < numPoints; k++) { - double y = adfReceiver.get(k).getY(); - adfReceiver.set(k, copy.get(k).getY() + y); + double y = adfReceiver.getY(k); + adfReceiver.set(k, copy.getY(k) + y); } } System.out.println("Time: " + sw.stop()); @@ -76,8 +76,8 @@ class SequenceBenchmark { } for (int k = 0; k < numPoints; k++) { - double y = edfReceiver.get(k).getY(); - edfReceiver.set(k, copy.get(k).getY() + y); + double y = edfReceiver.getY(k); + edfReceiver.set(k, copy.getY(k) + y); } } System.out.println("Time: " + sw.stop()); @@ -91,8 +91,7 @@ class SequenceBenchmark { sw.reset().start(); for (int i = 0; i < its; i++) { XySequence copy = XySequence.copyOf(xy); - copy.multiply(xy); - xyReceiver.add(copy); + xyReceiver.add(copy.multiply(xy)); } System.out.println("Time: " + sw.stop()); System.out.println(xyReceiver); -- GitLab