package org.opensha2.calc; import static com.google.common.base.Preconditions.checkState; import static org.opensha2.data.XySequence.copyOf; import static org.opensha2.data.XySequence.immutableCopyOf; import org.opensha2.data.XySequence; import org.opensha2.gmm.Gmm; import org.opensha2.gmm.Imt; import com.google.common.base.Function; import com.google.common.collect.FluentIterable; import com.google.common.collect.Iterables; import java.util.EnumMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * Container class for the combined hazard curves derived from the * {@code Rupture}s in an individual {@code Source}, one for each * {@code GroundMotionModel} and {@code Imt} of interest. The curves will have * been scaled by the associated Mfd or rupture weights, but not by * {@code GroundMotionModel} weights. * * @author Peter Powers */ final class HazardCurves { final GroundMotions groundMotions; final Map<Imt, Map<Gmm, XySequence>> curveMap; private HazardCurves( GroundMotions groundMotions, Map<Imt, Map<Gmm, XySequence>> curveMap) { this.groundMotions = groundMotions; this.curveMap = curveMap; } static Builder builder(GroundMotions groundMotions) { return new Builder(groundMotions); } /* * Specialized constructor that creates a single HazardCurves from the results * of processing a partitioned InputList. */ static HazardCurves combine(InputList inputs, List<HazardCurves> curvesList) { List<GroundMotions> groundMotionsList = FluentIterable.from(curvesList) .transform(new Function<HazardCurves, GroundMotions>() { @Override public GroundMotions apply(HazardCurves curves) { return curves.groundMotions; } }) .toList(); GroundMotions groundMotions = GroundMotions.combine(inputs, groundMotionsList); return builder(groundMotions) .combine(curvesList) .build(); } static class Builder { private static final String ID = "HazardCurves.Builder"; private boolean built = false; private final GroundMotions groundMotions; private final Map<Imt, Map<Gmm, XySequence>> curveMap; private Builder(GroundMotions groundMotions) { this.groundMotions = groundMotions; curveMap = new EnumMap<>(Imt.class); for (Imt imt : groundMotions.gmMap.keySet()) { Map<Gmm, XySequence> gmmMap = new EnumMap<>(Gmm.class); curveMap.put(imt, gmmMap); } } /* Put an immutable copy of the supplied curve. */ Builder addCurve(Imt imt, Gmm gmm, XySequence curve) { curveMap.get(imt).put(gmm, immutableCopyOf(curve)); return this; } HazardCurves build() { checkState(!built, "This %s instance has already been used", ID); // TODO check that all gmms have been set? it'll be difficult to // track whether all curves for all inputs have been added built = true; return new HazardCurves(groundMotions, curveMap); } /* * For internal use only. Combines multiple ordered HazardCurves that result * from InputList partitioning. Can only be called once after intializing * the builder with a combined GroundMotions object previously created from * the supplied HazardCurves. */ private Builder combine(List<HazardCurves> curvesList) { Map<Imt, Map<Gmm, XySequence>> model = curvesList.get(0).curveMap; for (Entry<Imt, Map<Gmm, XySequence>> imtEntry : model.entrySet()) { Imt imt = imtEntry.getKey(); for (Entry<Gmm, XySequence> gmmEntry : imtEntry.getValue().entrySet()) { Gmm gmm = gmmEntry.getKey(); XySequence sequence = copyOf(gmmEntry.getValue()); for (HazardCurves curves : Iterables.skip(curvesList, 1)) { sequence.add(curves.curveMap.get(imt).get(gmm)); } addCurve(imt, gmm, sequence); } } return this; } } }