diff --git a/src/main/java/gov/usgs/earthquake/nshmp/calc/EqRate.java b/src/main/java/gov/usgs/earthquake/nshmp/calc/EqRate.java index e451de5f73ef81f7a9b95a97c694c06fa0c26615..7a7071391118f125d948e11aba876bf488218bf0 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/calc/EqRate.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/calc/EqRate.java @@ -1,15 +1,14 @@ package gov.usgs.earthquake.nshmp.calc; -import static com.google.common.base.Preconditions.checkArgument; - +import java.util.ArrayList; import java.util.EnumMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.Callable; import java.util.function.Consumer; import com.google.common.base.Converter; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import gov.usgs.earthquake.nshmp.Maths; @@ -32,6 +31,8 @@ import gov.usgs.earthquake.nshmp.model.Source; import gov.usgs.earthquake.nshmp.model.SourceTree; import gov.usgs.earthquake.nshmp.model.SourceType; import gov.usgs.earthquake.nshmp.model.SystemRuptureSet; +import gov.usgs.earthquake.nshmp.model.TectonicSetting; +import gov.usgs.earthquake.nshmp.tree.Branch; /** * General purpose earthquake rate and probability data container. This class @@ -51,14 +52,19 @@ public class EqRate { /** The MFDs for each contributing source type. */ public final Map<SourceType, XySequence> typeMfds; + /** MFD contributions to total organized by source tree. */ + public final List<Contributor> mfds; + private EqRate( Site site, XySequence totalMfd, - Map<SourceType, XySequence> typeMfds) { + Map<SourceType, XySequence> typeMfds, + List<Contributor> mfds) { this.site = site; this.totalMfd = totalMfd; this.typeMfds = typeMfds; + this.mfds = mfds; } /** @@ -126,18 +132,32 @@ public class EqRate { typeMfdBuilders.put(type, IntervalArray.Builder.fromModel(modelMfd)); } + List<Contributor> mfds = new ArrayList<>(); + /* Populate builders. */ for (SourceTree tree : model) { - for (var branch : tree) { + + IntervalArray.Builder treeMfd = IntervalArray.Builder.fromModel(modelMfd); + + for (Branch<RuptureSet<? extends Source>> branch : tree) { RuptureSet<? extends Source> ruptures = branch.value(); IntervalArray rupturesMfd = mfd(ruptures, site.location(), distance, modelMfd); typeMfdBuilders.get(ruptures.type()).add(rupturesMfd); + treeMfd.add(rupturesMfd); } + + Contributor contrib = new Contributor( + tree.name(), + tree.id(), + tree.setting(), + tree.type(), + treeMfd.build().values()); + mfds.add(contrib); } /* Compute total and convert to sequences. */ IntervalArray.Builder totalMfd = IntervalArray.Builder.fromModel(modelMfd); - ImmutableMap.Builder<SourceType, XySequence> typeMfds = ImmutableMap.builder(); + Map<SourceType, XySequence> typeMfds = new EnumMap<>(SourceType.class); for (Entry<SourceType, IntervalArray.Builder> entry : typeMfdBuilders.entrySet()) { IntervalArray typeMfd = entry.getValue().build(); typeMfds.put(entry.getKey(), typeMfd.values()); @@ -147,7 +167,8 @@ public class EqRate { return new EqRate( site, totalMfd.build().values(), - typeMfds.build()); + typeMfds, + mfds); } /** @@ -158,16 +179,28 @@ public class EqRate { public static EqRate toCumulative(EqRate incremental) { XySequence cumulativeTotal = Sequences.toCumulative(incremental.totalMfd); - ImmutableMap.Builder<SourceType, XySequence> cumulativeTypes = ImmutableMap.builder(); + Map<SourceType, XySequence> cumulativeTypes = new EnumMap<>(SourceType.class); for (Entry<SourceType, XySequence> entry : incremental.typeMfds.entrySet()) { cumulativeTypes.put( entry.getKey(), Sequences.toCumulative(entry.getValue())); } + List<Contributor> cumulativeMfds = new ArrayList<>(); + for (Contributor incrContrib : incremental.mfds) { + Contributor cumContrib = new Contributor( + incrContrib.component, + incrContrib.id, + incrContrib.setting, + incrContrib.type, + Sequences.toCumulative(incrContrib.mfd)); + cumulativeMfds.add(cumContrib); + } + return new EqRate( incremental.site, cumulativeTotal, - cumulativeTypes.build()); + cumulativeTypes, + cumulativeMfds); } /** @@ -195,45 +228,24 @@ public class EqRate { .copyOf(entry.getValue()) .transform(pointConvert)); } - return new EqRate( - annualRates.site, - XySequence.copyOf(totalMfd), - Maps.immutableEnumMap(typeMfds)); - } - /** - * Create a new earthquake rate container with the sum of the supplied - * {@code rates}. - * - * <p><b>NOTE:</b> This operation is additive and will produce meaningless - * results if {@code rates} have already been converted to - * {@link #toPoissonProbability(EqRate, double) probabilities}, or are not all - * of {@link DistributionFormat#INCREMENTAL} or - * {@link DistributionFormat#CUMULATIVE} distribution format. - * - * <p>Buyer beware. - * - * @param rates to combine - */ - @Deprecated - public static EqRate combine(EqRate... rates) { - Site referenceSite = rates[0].site; - MutableXySequence totalMfd = MutableXySequence.emptyCopyOf(rates[0].totalMfd); - EnumMap<SourceType, MutableXySequence> typeMfds = new EnumMap<>(SourceType.class); - for (EqRate rate : rates) { - checkArgument( - rate.site.location().equals(referenceSite.location()), - "Site locations are not the same:\n\ts1: %s\n\ts2: %s", - referenceSite, rate.site); - totalMfd.add(rate.totalMfd); - for (Entry<SourceType, XySequence> entry : rate.typeMfds.entrySet()) { - XySequence.addToMap(entry.getKey(), typeMfds, entry.getValue()); - } + List<Contributor> cumulativeMfds = new ArrayList<>(); + for (Contributor incrContrib : annualRates.mfds) { + Contributor cumContrib = new Contributor( + incrContrib.component, + incrContrib.id, + incrContrib.setting, + incrContrib.type, + MutableXySequence.copyOf(incrContrib.mfd) + .transform(pointConvert)); + cumulativeMfds.add(cumContrib); } + return new EqRate( - referenceSite, + annualRates.site, XySequence.copyOf(totalMfd), - Maps.immutableEnumMap(typeMfds)); + Maps.immutableEnumMap(typeMfds), + cumulativeMfds); } private static IntervalArray mfd( @@ -368,4 +380,40 @@ public class EqRate { } } + /** + * A contributor to the total earthquake rate. Each contributor wraps the + * earthquake rate from an individual source tree in a model. + */ + public static final class Contributor { + + /** The contribution source tree name. */ + public final String component; + + /** The contribution source tree id. */ + public final Integer id; + + /** The contribution tectonic setting. */ + public final TectonicSetting setting; + + /** The contribution source type. */ + public final SourceType type; + + /** The contribution MFD. */ + public final XySequence mfd; + + Contributor( + String component, + Integer id, + TectonicSetting setting, + SourceType type, + XySequence mfd) { + + this.component = component; + this.id = id; + this.setting = setting; + this.type = type; + this.mfd = mfd; + } + } + }