Skip to content
Snippets Groups Projects
CalcConfig.java 10.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • package org.opensha2.calc;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    
    
    import static com.google.common.base.CaseFormat.LOWER_CAMEL;
    import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
    import static com.google.common.base.Preconditions.checkNotNull;
    import static com.google.common.base.Preconditions.checkState;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    import static java.nio.charset.StandardCharsets.UTF_8;
    
    import static org.opensha2.util.TextUtils.format;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    
    
    import static org.opensha2.data.XySequence.*;
    
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    import java.io.IOException;
    import java.io.Reader;
    import java.nio.file.Files;
    import java.nio.file.Path;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    import java.util.Arrays;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    import java.util.EnumSet;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    import java.util.Map;
    import java.util.Map.Entry;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    import java.util.Set;
    
    import org.opensha2.data.DataUtils;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    import org.opensha2.data.XySequence;
    
    import org.opensha2.gmm.Imt;
    
    import org.opensha2.util.Parsing;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    
    
    import com.google.common.collect.Lists;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    import com.google.common.collect.Maps;
    
    import com.google.common.collect.Sets;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    
    /**
     * Calculation configuration.
    
     * 
     * All config fields are immutable and all methods return immutable objects.
     * 
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
     * @author Peter Powers
     */
    
    public final class CalcConfig {
    
    	/**
    	 * Returns models of the intensity measure levels for each {@code Imt}
    	 * adressed by this calculation. The {@code Map} returned by this method is
    	 * an immutable {@code EnumMap}.
    	 * 
    	 * @see Maps#immutableEnumMap(Map)
    	 */
    
    	/**
    	 * Returns models of the intensity measure levels for each {@code Imt}
    	 * adressed by this calculation. The x-values in each sequence are in
    	 * natural log space. The {@code Map} returned by this method is an
    	 * immutable {@code EnumMap}.
    	 * 
    	 * @see Maps#immutableEnumMap(Map)
    	 */
    
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	// TODO revisit privatization, comments, and immutability
    
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	static final String FILE_NAME = "config.json";
    
    
    	final Path resource;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    
    
    	final ExceedanceModel exceedanceModel;
    	final double truncationLevel;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	private final double[] defaultImls;
    	private final Map<Imt, double[]> customImls;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	private final SiteSet sites;
    
    	
    	final boolean optimizeGrids;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	final Map<Imt, XySequence> modelCurves;
    	final Map<Imt, XySequence> logModelCurves;
    
    	private static final Gson GSON = new GsonBuilder()
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    		.registerTypeAdapter(Site.class, new Site.Deserializer())
    		.registerTypeAdapter(SiteSet.class, new SiteSet.Deserializer())
    		.create();
    
    	private CalcConfig(
    			Path resource,
    			ExceedanceModel exceedanceModel,
    			double truncationLevel,
    			Set<Imt> imts,
    			double[] defaultImls,
    			Map<Imt, double[]> customImls,
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    			DeaggData deagg,
    
    			boolean optimizeGrids,
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    			Map<Imt, XySequence> modelCurves,
    			Map<Imt, XySequence> logModelCurves) {
    
    
    		this.resource = resource;
    		this.exceedanceModel = exceedanceModel;
    		this.truncationLevel = truncationLevel;
    		this.imts = imts;
    		this.defaultImls = defaultImls;
    		this.customImls = customImls;
    		this.deagg = deagg;
    		this.sites = sites;
    
    		this.optimizeGrids = optimizeGrids;
    
    		this.modelCurves = modelCurves;
    		this.logModelCurves = logModelCurves;
    
    	private enum Key {
    		RESOURCE,
    		EXCEEDANCE_MODEL,
    		TRUNCATION_LEVEL,
    		IMTS,
    		DEFAULT_IMLS,
    		CUSTOM_IMLS,
    		DEAGG,
    		SITES;
    
    		private String label;
    
    		private Key() {
    			this.label = UPPER_UNDERSCORE.to(LOWER_CAMEL, name());
    		}
    
    		@Override public String toString() {
    			return label;
    		}
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	@Override public String toString() {
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    		String customImlStr = "";
    		if (!customImls.isEmpty()) {
    			StringBuilder sb = new StringBuilder();
    			for (Entry<Imt, double[]> entry : customImls.entrySet()) {
    
    				String imtStr = "(override) " + entry.getKey().name();
    				sb.append(format(imtStr)).append(Arrays.toString(entry.getValue()));
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    			}
    			customImlStr = sb.toString();
    		}
    
    		return new StringBuilder("Calc config:")
    			.append(format(Key.RESOURCE)).append(resource)
    			.append(format(Key.EXCEEDANCE_MODEL)).append(exceedanceModel)
    			.append(format(Key.TRUNCATION_LEVEL)).append(truncationLevel)
    			.append(format(Key.IMTS)).append(Parsing.enumsToString(imts, Imt.class))
    			.append(format(Key.DEFAULT_IMLS)).append(Arrays.toString(defaultImls))
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    			.append(customImlStr)
    
    			.append(format("Deaggregation R"))
    
    			.append("min=").append(deagg.rMin).append(", ")
    			.append("max=").append(deagg.rMax).append(", ")
    			.append("Δ=").append(deagg.Δr)
    
    			.append(format("Deaggregation M"))
    
    			.append("min=").append(deagg.mMin).append(", ")
    			.append("max=").append(deagg.mMax).append(", ")
    			.append("Δ=").append(deagg.Δm)
    
    			.append(format("Deaggregation ε"))
    
    			.append("min=").append(deagg.εMin).append(", ")
    			.append("max=").append(deagg.εMax).append(", ")
    			.append("Δ=").append(deagg.Δε)
    
    			.append(format(Key.SITES)).append(sites)
    			.toString();
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	/**
    	 * Return an unmodifiable iterator over the {@code Site}s specified by this
    
    	 * configuration.
    	 */
    	public Iterable<Site> sites() {
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	}
    
    
    	/**
    	 * Return the unmodifiable {@code Set} of IMTs for which calculations should
    	 * be performed.
    	 */
    	public Set<Imt> imts() {
    		return imts;
    	}
    
    
    	 * Return an empty linear (i.e. not log) curve for the requested {@code Imt}
    	 * .
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	public XySequence modelCurve(Imt imt) {
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    	public static final class DeaggData {
    
    
    		public final double rMin;
    		public final double rMax;
    		public final double Δr;
    
    		public final double mMin;
    		public final double mMax;
    		public final double Δm;
    
    		public final double εMin;
    		public final double εMax;
    		public final double Δε;
    
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    		DeaggData() {
    
    			rMin = 0.0;
    			rMax = 100.0;
    			Δr = 10.0;
    
    			mMin = 5.0;
    			mMax = 7.0;
    			Δm = 0.1;
    
    			εMin = -3;
    			εMax = 3.0;
    			Δε = 0.5;
    		}
    
    	/**
    	 * Create a new calculation configuration builder from the resource at the
    	 * specified {@code path}.
    	 * 
    	 * @param path to configuration file or resource
    	 * @throws IOException
    	 */
    	public static Builder builder(Path path) throws IOException {
    		checkNotNull(path);
    		// TODO test with zip files
    		Path configPath = Files.isDirectory(path) ? path.resolve(FILE_NAME) : path;
    		Reader reader = Files.newBufferedReader(configPath, UTF_8);
    		Builder configBuilder = GSON.fromJson(reader, Builder.class);
    		configBuilder.resource = configPath;
    		reader.close();
    		return configBuilder;
    	}
    
    	/**
    	 * Create a new empty calculation configuration builder.
    	 */
    	public static Builder builder() {
    		return new Builder();
    	}
    
    	public static final class Builder {
    
    		private static final String ID = "CalcConfig.Builder";
    		private boolean built = false;
    
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    		private Path resource;
    		private ExceedanceModel exceedanceModel;
    		private Double truncationLevel;
    		private Set<Imt> imts;
    		private double[] defaultImls;
    		private Map<Imt, double[]> customImls;
    		private DeaggData deagg;
    		private SiteSet sites;
    
    		private Boolean optimizeGrids;
    
    
    		public Builder copy(CalcConfig config) {
    			checkNotNull(config);
    			this.resource = config.resource;
    			this.exceedanceModel = config.exceedanceModel;
    			this.truncationLevel = config.truncationLevel;
    			this.imts = config.imts;
    			this.defaultImls = config.defaultImls;
    			this.customImls = config.customImls;
    			this.deagg = config.deagg;
    			this.sites = config.sites;
    
    			this.optimizeGrids = config.optimizeGrids;
    
    			return this;
    		}
    
    		public Builder withDefaults() {
    			this.exceedanceModel = ExceedanceModel.TRUNCATION_UPPER_ONLY;
    			this.truncationLevel = 3.0;
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    			this.imts = EnumSet.of(Imt.PGA, Imt.SA0P2, Imt.SA1P0);
    
    			// Slightly modified version of NSHM 5Hz curve, size = 20
    			this.defaultImls = new double[] { 0.0025, 0.0045, 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 };
    			this.customImls = Maps.newHashMap();
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    			this.deagg = new DeaggData();
    
    			this.sites = new SiteSet(Lists.newArrayList(Site.builder().build()));
    
    			this.optimizeGrids = true;
    
    			return this;
    		}
    
    		public Builder extend(final Builder that) {
    			checkNotNull(that);
    			if (that.resource != null) this.resource = that.resource;
    			if (that.exceedanceModel != null) this.exceedanceModel = that.exceedanceModel;
    			if (that.truncationLevel != null) this.truncationLevel = that.truncationLevel;
    			if (that.imts != null) this.imts = that.imts;
    			if (that.defaultImls != null) this.defaultImls = that.defaultImls;
    			if (that.customImls != null) this.customImls = that.customImls;
    			if (that.deagg != null) this.deagg = that.deagg;
    			if (that.sites != null) this.sites = that.sites;
    
    			if (that.optimizeGrids != null) this.optimizeGrids = that.optimizeGrids;
    
    			return this;
    		}
    
    		public Builder imts(Set<Imt> imts) {
    			this.imts = checkNotNull(imts);
    			return this;
    		}
    
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    		private Map<Imt, XySequence> createLogCurveMap() {
    			Map<Imt, XySequence> curveMap = Maps.newEnumMap(Imt.class);
    
    			for (Imt imt : imts) {
    				double[] imls = imlsForImt(imt);
    				imls = Arrays.copyOf(imls, imls.length);
    				DataUtils.ln(imls);
    
    				curveMap.put(imt, immutableCopyOf(create(imls, null)));
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    		private Map<Imt, XySequence> createCurveMap() {
    			Map<Imt, XySequence> curveMap = Maps.newEnumMap(Imt.class);
    
    			for (Imt imt : imts) {
    				double[] imls = imlsForImt(imt);
    				imls = Arrays.copyOf(imls, imls.length);
    
    				curveMap.put(imt, immutableCopyOf(create(imls, null)));
    
    			}
    			return Maps.immutableEnumMap(curveMap);
    		}
    
    		private double[] imlsForImt(Imt imt) {
    			return customImls.containsKey(imt) ? customImls.get(imt) : defaultImls;
    		}
    
    
    		private static final String MSSG = "%s %s not set";
    
    		private void validateState(String buildId) {
    			checkState(!built, "This %s instance as already been used", buildId);
    			checkNotNull(exceedanceModel, MSSG, buildId, Key.EXCEEDANCE_MODEL);
    			checkNotNull(truncationLevel, MSSG, buildId, Key.TRUNCATION_LEVEL);
    			checkNotNull(imts, MSSG, buildId, Key.IMTS);
    			checkNotNull(defaultImls, MSSG, buildId, Key.DEFAULT_IMLS);
    			checkNotNull(customImls, MSSG, buildId, Key.CUSTOM_IMLS);
    			checkNotNull(deagg, MSSG, buildId, Key.DEAGG);
    			checkNotNull(sites, MSSG, buildId, Key.SITES);
    			built = true;
    		}
    
    		public CalcConfig build() {
    			validateState(ID);
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    			Set<Imt> finalImts = Sets.immutableEnumSet(imts);
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    			Map<Imt, XySequence> curves = createCurveMap();
    			Map<Imt, XySequence> logCurves = createLogCurveMap();
    
    			return new CalcConfig(
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    				resource, exceedanceModel, truncationLevel, finalImts,
    
    				defaultImls, customImls, deagg, sites, optimizeGrids,
    				curves, logCurves);
    
    Powers, Peter M.'s avatar
    Powers, Peter M. committed
    }