From c0b45e3c60c9b8f1824d2c850a34f082ecacb0ce Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 10 Mar 2026 14:07:31 -0700 Subject: [PATCH 01/71] tests for upstream --- .../nshm26/DownDipRupSetBuildingTests.java | 4 +- .../InterfaceSubSeisMoReductionTests.java | 133 ++++++++++++++++++ 2 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java diff --git a/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java b/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java index 62a691d8..d58f6f56 100644 --- a/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java +++ b/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java @@ -29,7 +29,7 @@ import org.opensha.sha.earthquake.faultSysSolution.ruptures.downDip.RectangularDownDipGrowingStrategy.NeighborOverlaps; import org.opensha.sha.earthquake.faultSysSolution.ruptures.util.GeoJSONFaultReader; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_SubductionInterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.faultSurface.GeoJSONFaultSection; @@ -48,7 +48,7 @@ public static void main(String[] args) throws IOException { // NSHM26_SubductionInterfaceFaultModels fm = NSHM26_SubductionInterfaceFaultModels.KERMADEC; // String prefix = "ker_slab2"; - NSHM26_SubductionInterfaceFaultModels fm = NSHM26_SubductionInterfaceFaultModels.MARIANA; + NSHM26_InterfaceFaultModels fm = NSHM26_InterfaceFaultModels.GNMI_V1; String prefix = "izu_slab2"; Range minSupraRange = Range.closed(10d, 40d); diff --git a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java new file mode 100644 index 00000000..0e0874de --- /dev/null +++ b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java @@ -0,0 +1,133 @@ +package scratch.kevin.nshm26; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.xyz.GriddedGeoDataSet; +import org.opensha.commons.eq.MagUtils; +import org.opensha.commons.geo.BorderType; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.LocationUtils; +import org.opensha.commons.geo.LocationUtils.LocationAverager; +import org.opensha.commons.geo.Region; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; +import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; +import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_DeclusteringAlgorithms; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_SeisRateModelBranch; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_SeisSmoothingAlgorithms; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.InterfaceGridAssociations; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_SeisPDF_Loader; +import org.opensha.sha.faultSurface.FaultSection; +import org.opensha.sha.faultSurface.FaultTrace; +import org.opensha.sha.faultSurface.RuptureSurface; +import org.opensha.sha.magdist.IncrementalMagFreqDist; +import org.opensha.sha.util.TectonicRegionType; + +public class InterfaceSubSeisMoReductionTests { + + public static void main(String[] args) throws IOException { + LogicTreeBranch branch = NSHM26_LogicTree.DEFAULT_GNMI_SUBDUCTION_INTERFACE; +// LogicTreeBranch branch = NSHM26_LogicTree.DEFAULT_AMSAM_SUBDUCTION_INTERFACE; + NSHM26_InterfaceFaultModels fm = branch.requireValue(NSHM26_InterfaceFaultModels.class); + NSHM26_InterfaceDeformationModels dm = branch.requireValue(NSHM26_InterfaceDeformationModels.class); + + NSHM26_SeismicityRegions reg = fm.getSeisReg(); + File pdfBaseDir = new File("/home/kevin/OpenSHA/nshm26/spatial_seis_pdfs/"+reg.name().toLowerCase()+"/2026_03_09-v1_2D/INTERFACE"); + + System.out.println("Branch: "+branch+"; reg="+reg); + + NSHM26_SeisRateModelBranch rateModel = NSHM26_SeisRateModelBranch.PREFFERRED; + NSHM26_DeclusteringAlgorithms decluster = NSHM26_DeclusteringAlgorithms.AVERAGE; + NSHM26_SeisSmoothingAlgorithms smooth = NSHM26_SeisSmoothingAlgorithms.AVERAGE; + double cutoffHorzDist = 50d; + + List sects = dm.build(branch); + Location[] middles = new Location[sects.size()]; + for (int i=0; i transColors = new ArrayList<>(sects.size()); + for (int i=0; i mappings = assoc.getSectionFracsOnNode(i); + for (int s : mappings.keySet()) + impliedMoments[s] += moSum*mappings.get(s); + } + + double[] moFracts = new double[sects.size()]; + MinMaxAveTracker track = new MinMaxAveTracker(); + for (int i=0; i Date: Fri, 13 Mar 2026 09:29:46 -0700 Subject: [PATCH 02/71] for upstream logic tree refactor --- .../HardcodedInversionFactoryRunner.java | 4 +- ..._LogicTreeInversionRunnerScriptWriter.java | 12 +- .../nshm23/RandSamplingTreeAddSamples.java | 22 +- .../RandomDefModSampleLevel.java | 21 +- .../RandomDefModSampleNode.java | 71 +----- ...GriddedRateDistributionSolutionWriter.java | 208 +++++------------- .../prvi25/figures/LogicTreeFigureWriter.java | 8 +- .../scratch/kevin/ucerf3/PureScratch.java | 14 +- 8 files changed, 114 insertions(+), 246 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index 86dfd98c..b7fc0359 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -10,7 +10,7 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeNode; -import org.opensha.commons.logicTree.LogicTreeNode.RandomlySampledNode; +import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; import org.opensha.commons.util.modules.OpenSHA_Module; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; @@ -350,7 +350,7 @@ public static void main(String[] args) throws IOException { for (int i=0; i 0d) { + if (!(node instanceof RandomlyGeneratedNode) && node.getNodeWeight(branch) > 0d) { // only include its name if there are other alternatives (unless we have chosen a zero-weight option) boolean hasOthers = false; for (LogicTreeNode oNode : branch.getLevel(i).getNodes()) { diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 9555c7d6..74c68877 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -32,8 +32,8 @@ import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; -import org.opensha.commons.logicTree.LogicTreeLevel.RandomlySampledLevel; -import org.opensha.commons.logicTree.LogicTreeNode.RandomlySampledNode; +import org.opensha.commons.logicTree.LogicTreeLevel.RandomlyGeneratedLevel; +import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.util.ClassUtils; import org.opensha.sha.earthquake.faultSysSolution.RupSetFaultModel; @@ -166,7 +166,7 @@ public static void main(String[] args) throws IOException { AttenRelRef[] gmpes = null; - List> individualRandomLevels = new ArrayList<>(); + List> individualRandomLevels = new ArrayList<>(); int samplingBranchCountMultiplier = 1; String dirName = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); @@ -797,8 +797,8 @@ public static void main(String[] args) throws IOException { int numBranches = logicTree.size()*samplingBranchCountMultiplier; System.out.println("\tnumBranches = "+logicTree.size()+" x "+samplingBranchCountMultiplier+" = "+numBranches); - List> levelNodes = new ArrayList<>(); - for (RandomlySampledLevel level : individualRandomLevels) { + List> levelNodes = new ArrayList<>(); + for (RandomlyGeneratedLevel level : individualRandomLevels) { level.buildNodes(rand, numBranches, 1d); levelNodes.add(level.getNodes()); } @@ -811,7 +811,7 @@ public static void main(String[] args) throws IOException { for (LogicTreeNode val : branch) modValues.add(val); int randIndex = modBranches.size(); - for (List randNodes : levelNodes) + for (List randNodes : levelNodes) modValues.add(randNodes.get(randIndex)); LogicTreeBranch modBranch = new LogicTreeBranch<>(modLevels, modValues); modBranch.setOrigBranchWeight(branch.getOrigBranchWeight()); diff --git a/src/main/java/scratch/kevin/nshm23/RandSamplingTreeAddSamples.java b/src/main/java/scratch/kevin/nshm23/RandSamplingTreeAddSamples.java index 8c961b5e..e72495b3 100644 --- a/src/main/java/scratch/kevin/nshm23/RandSamplingTreeAddSamples.java +++ b/src/main/java/scratch/kevin/nshm23/RandSamplingTreeAddSamples.java @@ -14,9 +14,9 @@ import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; -import org.opensha.commons.logicTree.LogicTreeLevel.RandomlySampledLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.RandomlyGeneratedLevel; import org.opensha.commons.logicTree.LogicTreeNode; -import org.opensha.commons.logicTree.LogicTreeNode.RandomlySampledNode; +import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; import org.opensha.commons.util.ExceptionUtils; import com.google.common.base.Preconditions; @@ -44,17 +44,17 @@ public static void main(String[] args) throws IOException { Random rand = new Random(987654321l); int numLevels = origTree.getLevels().size(); - List> randNodeStacks = new ArrayList<>(); + List> randNodeStacks = new ArrayList<>(); for (int l=0; l sourceLevel = origTree.getLevels().get(l); - if (sourceLevel instanceof RandomlySampledLevel) { + if (sourceLevel instanceof RandomlyGeneratedLevel) { System.out.println("Building node list for "+sourceLevel.getName()); HashSet prevSeeds = new HashSet<>(newSize); List seeds = new ArrayList<>(); // add the original nodes for (LogicTreeNode sourceNode : sourceLevel.getNodes()) { - Preconditions.checkState(sourceNode instanceof RandomlySampledNode); - RandomlySampledNode randNode = (RandomlySampledNode)sourceNode; + Preconditions.checkState(sourceNode instanceof RandomlyGeneratedNode); + RandomlyGeneratedNode randNode = (RandomlyGeneratedNode)sourceNode; Preconditions.checkState(!prevSeeds.contains(randNode.getSeed())); prevSeeds.add(randNode.getSeed()); seeds.add(randNode.getSeed()); @@ -67,9 +67,9 @@ public static void main(String[] args) throws IOException { seeds.add(seed); } try { - Constructor constructor = ((RandomlySampledLevel)sourceLevel).getClass().getConstructor(); + Constructor constructor = ((RandomlyGeneratedLevel)sourceLevel).getClass().getConstructor(); constructor.setAccessible(true); - RandomlySampledLevel modLevel = constructor.newInstance(); + RandomlyGeneratedLevel modLevel = constructor.newInstance(); modLevel.buildNodes(seeds, 1d); modLevels.add(modLevel); randNodeStacks.add(new LinkedList<>(modLevel.getNodes())); @@ -93,10 +93,10 @@ public static void main(String[] args) throws IOException { LogicTreeBranch modBranch = new LogicTreeBranch<>(modLevels); for (int l=0; l { +public class RandomDefModSampleLevel extends RandomlyGeneratedLevel { public RandomDefModSampleLevel() { @@ -30,7 +30,7 @@ public String getName() { @Override public RandomDefModSampleNode buildNodeInstance(int index, long seed, double weight) { - return new RandomDefModSampleNode(index, seed, weight); + return new RandomDefModSampleNode(getNodeName(index), getNodeShortName(index), getNodeFilePrefix(index), weight, seed); } @Override @@ -38,4 +38,19 @@ public Class getType() { return RandomDefModSampleNode.class; } + @Override + protected String getNodeNamePrefix() { + return "Deformation Model Sample "; + } + + @Override + protected String getNodeShortNamePrefix() { + return "DMSample"; + } + + @Override + protected String getNodeFilePrefix() { + return "DMSample"; + } + } diff --git a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleNode.java b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleNode.java index 858c8a55..fc2bf10c 100644 --- a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleNode.java +++ b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleNode.java @@ -5,7 +5,7 @@ import org.opensha.commons.logicTree.Affects; import org.opensha.commons.logicTree.DoesNotAffect; import org.opensha.commons.logicTree.LogicTreeBranch; -import org.opensha.commons.logicTree.LogicTreeNode.RandomlySampledNode; +import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; @@ -13,72 +13,13 @@ @DoesNotAffect(FaultSystemRupSet.RUP_SECTS_FILE_NAME) @DoesNotAffect(FaultSystemRupSet.RUP_PROPS_FILE_NAME) @Affects(FaultSystemSolution.RATES_FILE_NAME) -public class RandomDefModSampleNode implements RandomlySampledNode { +public class RandomDefModSampleNode extends RandomlyGeneratedNode { - private String name; - private String shortName; - private String prefix; - private double weight; - private long seed; - - @SuppressWarnings("unused") // for deserialization - private RandomDefModSampleNode() {} - - RandomDefModSampleNode(int index, long seed, double weight) { - init("Deformation Model Sample "+index, "DMSample"+index, "DMSample"+index, weight, seed); - } - - @Override - public double getNodeWeight(LogicTreeBranch fullBranch) { - return weight; - } - - @Override - public String getFilePrefix() { - return prefix; - } - - @Override - public String getShortName() { - return shortName; - } - - @Override - public String getName() { - return name; - } - - @Override - public long getSeed() { - return seed; - } - - @Override - public void init(String name, String shortName, String prefix, double weight, long seed) { - this.name = name; - this.shortName = shortName; - this.prefix = prefix; - this.weight = weight; - this.seed = seed; - } - - @Override - public int hashCode() { - return Objects.hash(name, prefix, seed, shortName, weight); + private RandomDefModSampleNode() { + super(); } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - RandomDefModSampleNode other = (RandomDefModSampleNode) obj; - return Objects.equals(name, other.name) && Objects.equals(prefix, other.prefix) && seed == other.seed - && Objects.equals(shortName, other.shortName) - && Double.doubleToLongBits(weight) == Double.doubleToLongBits(other.weight); + public RandomDefModSampleNode(String name, String shortName, String prefix, double weight, long seed) { + super(name, shortName, prefix, weight, seed); } - } diff --git a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java b/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java index e901b7eb..9f43bee3 100644 --- a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java +++ b/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java @@ -31,7 +31,7 @@ import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.logicTree.LogicTreeLevel.FileBackedLevel; import org.opensha.commons.logicTree.LogicTreeNode.FileBackedNode; -import org.opensha.commons.logicTree.LogicTreeNode.RandomlySampledNode; +import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.commons.util.io.archive.ArchiveOutput; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; @@ -513,13 +513,8 @@ public static List loadRates(File csvFile) throws IOException { @Affects(MFDGridSourceProvider.ARCHIVE_SUB_SEIS_FILE_NAME) @Affects(MFDGridSourceProvider.ARCHIVE_UNASSOCIATED_FILE_NAME) @Affects(GridSourceList.ARCHIVE_GRID_SOURCES_FILE_NAME) - private static class CrustalSamplingNode implements RandomlySampledNode { + private static class CrustalSamplingNode extends RandomlyGeneratedNode { - private String name; - private String shortName; - private String prefix; - private double weight; - private long seed; private double rate; private double b; @@ -528,53 +523,14 @@ private CrustalSamplingNode() { } private CrustalSamplingNode(String name, String shortName, String prefix, double weight, long seed, double rate, double b) { - super(); - this.name = name; - this.shortName = shortName; - this.prefix = prefix; - this.weight = weight; - this.seed = seed; + super(name, shortName, prefix, weight, seed); this.rate = rate; this.b = b; } - - @Override - public double getNodeWeight(LogicTreeBranch fullBranch) { - return weight; - } - - @Override - public String getFilePrefix() { - return prefix; - } - - @Override - public String getShortName() { - return shortName; - } - - @Override - public String getName() { - return name; - } - - @Override - public long getSeed() { - return seed; - } - - @Override - public void init(String name, String shortName, String prefix, double weight, long seed) { - this.name = name; - this.shortName = shortName; - this.prefix = prefix; - this.weight = weight; - this.seed = seed; - } } - private static class CrustalRateSamplingLevel extends LogicTreeLevel.RandomlySampledLevel { + private static class CrustalRateSamplingLevel extends LogicTreeLevel.RandomlyGeneratedLevel { private List samples; private List randomizedSamples; @@ -602,7 +558,7 @@ public CrustalSamplingNode buildNodeInstance(int index, long seed, double weight Collections.shuffle(randomizedSamples, new Random(seed)); } double[] sample = randomizedSamples.get(index); - return new CrustalSamplingNode("Crustal Sample "+index, "Crustal-Sample"+index, "crustal_sample_"+index, weight, seed, + return new CrustalSamplingNode(getNodeName(index), getNodeShortName(index), getNodeFilePrefix(index), weight, seed, sample[0], sample[1]); } @@ -610,6 +566,21 @@ public CrustalSamplingNode buildNodeInstance(int index, long seed, double weight public Class getType() { return CrustalSamplingNode.class; } + + @Override + protected String getNodeNamePrefix() { + return "Crustal Sample "; + } + + @Override + protected String getNodeShortNamePrefix() { + return "Crustal-Sample"; + } + + @Override + protected String getNodeFilePrefix() { + return "crustal_sample_"; + } } @@ -623,13 +594,7 @@ public Class getType() { @Affects(MFDGridSourceProvider.ARCHIVE_SUB_SEIS_FILE_NAME) @Affects(MFDGridSourceProvider.ARCHIVE_UNASSOCIATED_FILE_NAME) @Affects(GridSourceList.ARCHIVE_GRID_SOURCES_FILE_NAME) - private static class CarSlabSamplingNode implements RandomlySampledNode { - - private String name; - private String shortName; - private String prefix; - private double weight; - private long seed; + private static class CarSlabSamplingNode extends RandomlyGeneratedNode { private double slabRate; private double slabB; private double interfaceRate; @@ -637,60 +602,21 @@ private static class CarSlabSamplingNode implements RandomlySampledNode { private CarSlabSamplingNode() { - + super(); } private CarSlabSamplingNode(String name, String shortName, String prefix, double weight, long seed, double slabRate, double slabB, double interfaceRate, double interfaceB) { - super(); - this.name = name; - this.shortName = shortName; - this.prefix = prefix; - this.weight = weight; - this.seed = seed; + super(name, shortName, prefix, weight, seed); this.slabRate = slabRate; this.slabB = slabB; this.interfaceRate = interfaceRate; this.interfaceB = interfaceB; } - - @Override - public double getNodeWeight(LogicTreeBranch fullBranch) { - return weight; - } - - @Override - public String getFilePrefix() { - return prefix; - } - - @Override - public String getShortName() { - return shortName; - } - - @Override - public String getName() { - return name; - } - - @Override - public long getSeed() { - return seed; - } - - @Override - public void init(String name, String shortName, String prefix, double weight, long seed) { - this.name = name; - this.shortName = shortName; - this.prefix = prefix; - this.weight = weight; - this.seed = seed; - } } - private static class CarSlabRateSamplingLevel extends LogicTreeLevel.RandomlySampledLevel { + private static class CarSlabRateSamplingLevel extends LogicTreeLevel.RandomlyGeneratedLevel { private List slabSamples; private List interfaceSamples; @@ -727,7 +653,7 @@ public CarSlabSamplingNode buildNodeInstance(int index, long seed, double weight int randIndex = randomizedIndexes.get(index); double[] slabSample = slabSamples.get(randIndex); double[] interfaceSample = interfaceSamples.get(randIndex); - return new CarSlabSamplingNode("CAR Sample "+index, "CAR-Sample"+index, "car_sample_"+index, weight, seed, + return new CarSlabSamplingNode(getNodeName(index), getNodeShortName(index), getNodeFilePrefix(index), weight, seed, slabSample[0], slabSample[1], interfaceSample[0], interfaceSample[1]); } @@ -735,6 +661,21 @@ public CarSlabSamplingNode buildNodeInstance(int index, long seed, double weight public Class getType() { return CarSlabSamplingNode.class; } + + @Override + protected String getNodeNamePrefix() { + return "CAR Sample "; + } + + @Override + protected String getNodeShortNamePrefix() { + return "CAR-Sample"; + } + + @Override + protected String getNodeFilePrefix() { + return "car_sample_"; + } } @@ -748,13 +689,8 @@ public Class getType() { @Affects(MFDGridSourceProvider.ARCHIVE_SUB_SEIS_FILE_NAME) @Affects(MFDGridSourceProvider.ARCHIVE_UNASSOCIATED_FILE_NAME) @Affects(GridSourceList.ARCHIVE_GRID_SOURCES_FILE_NAME) - private static class MueSamplingNode implements RandomlySampledNode { - - private String name; - private String shortName; - private String prefix; - private double weight; - private long seed; + private static class MueSamplingNode extends RandomlyGeneratedNode { + private double slabRate; private double slabB; private double interfaceRate; @@ -766,55 +702,16 @@ private MueSamplingNode() { private MueSamplingNode(String name, String shortName, String prefix, double weight, long seed, double slabRate, double slabB, double interfaceRate, double interfaceB) { - super(); - this.name = name; - this.shortName = shortName; - this.prefix = prefix; - this.weight = weight; - this.seed = seed; + super(name, shortName, prefix, weight, seed); this.slabRate = slabRate; this.slabB = slabB; this.interfaceRate = interfaceRate; this.interfaceB = interfaceB; } - - @Override - public double getNodeWeight(LogicTreeBranch fullBranch) { - return weight; - } - - @Override - public String getFilePrefix() { - return prefix; - } - - @Override - public String getShortName() { - return shortName; - } - - @Override - public String getName() { - return name; - } - - @Override - public long getSeed() { - return seed; - } - - @Override - public void init(String name, String shortName, String prefix, double weight, long seed) { - this.name = name; - this.shortName = shortName; - this.prefix = prefix; - this.weight = weight; - this.seed = seed; - } } - private static class MueRateSamplingLevel extends LogicTreeLevel.RandomlySampledLevel { + private static class MueRateSamplingLevel extends LogicTreeLevel.RandomlyGeneratedLevel { private List slabSamples; private List interfaceSamples; @@ -851,7 +748,7 @@ public MueSamplingNode buildNodeInstance(int index, long seed, double weight) { int randIndex = randomizedIndexes.get(index); double[] slabSample = slabSamples.get(randIndex); double[] interfaceSample = interfaceSamples.get(randIndex); - return new MueSamplingNode("MUE Sample "+index, "MUE-Sample"+index, "mue_sample_"+index, weight, seed, + return new MueSamplingNode(getNodeName(index), getNodeShortName(index), getNodeFilePrefix(index), weight, seed, slabSample[0], slabSample[1], interfaceSample[0], interfaceSample[1]); } @@ -859,6 +756,21 @@ public MueSamplingNode buildNodeInstance(int index, long seed, double weight) { public Class getType() { return MueSamplingNode.class; } + + @Override + protected String getNodeNamePrefix() { + return "MUE Sample "; + } + + @Override + protected String getNodeShortNamePrefix() { + return "MUE-Sample"; + } + + @Override + protected String getNodeFilePrefix() { + return "mue_sample_"; + } } diff --git a/src/main/java/scratch/kevin/prvi25/figures/LogicTreeFigureWriter.java b/src/main/java/scratch/kevin/prvi25/figures/LogicTreeFigureWriter.java index dbc49ce3..65e64af2 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/LogicTreeFigureWriter.java +++ b/src/main/java/scratch/kevin/prvi25/figures/LogicTreeFigureWriter.java @@ -28,7 +28,7 @@ import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; -import org.opensha.commons.logicTree.LogicTreeLevel.RandomlySampledLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.RandomlyGeneratedLevel; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.util.ExceptionUtils; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.NSHM23_MaxMagOffFault; @@ -128,7 +128,7 @@ public static void main(String[] args) throws IOException { for (LogicTreeNode node : branch) crustalFaultNodesUsed.add(node); for (LogicTreeLevel level : crustalFaultTree.getLevels()) { - if (level instanceof RandomlySampledLevel) { + if (level instanceof RandomlyGeneratedLevel) { int numRand = level.getNodes().size(); texFW.write(LaTeXUtils.defineValueCommand("CrustalFaultBranchesNumRand", LaTeXUtils.groupedIntNumber(numRand))+"\n"); } else { @@ -251,7 +251,7 @@ public LogicTreeFigureWriter(LogicTree tree, boolean includeSingleChoice, Map includedLevels.add(level); includedLevelChoices.add(uniqueChoices); maxLevelFontWidth = Integer.max(maxLevelFontWidth, new JPanel().getFontMetrics(levelFont).stringWidth(remapped(level.getName()))); - if (!(level instanceof RandomlySampledLevel)) { + if (!(level instanceof RandomlyGeneratedLevel)) { maxNodes = Integer.max(maxNodes, uniqueChoices.size()); for (LogicTreeNode node : uniqueChoices) { String name = remapped(node.getShortName()); @@ -316,7 +316,7 @@ protected void paintComponent(Graphics g) { int botLineY = y+lineHeight; int topChoiceY = botLineY + lineGap; int topWeightY = topChoiceY + choiceFontHeight; - if (level instanceof RandomlySampledLevel && nodes.size() > maxNodes && includedLevels.size() > 1) { + if (level instanceof RandomlyGeneratedLevel && nodes.size() > maxNodes && includedLevels.size() > 1) { // figure out how many branches we have without this HashSet uniquesWithout = new HashSet<>(); for (LogicTreeBranch branch : tree) { diff --git a/src/main/java/scratch/kevin/ucerf3/PureScratch.java b/src/main/java/scratch/kevin/ucerf3/PureScratch.java index 811e7fba..dd553c9b 100644 --- a/src/main/java/scratch/kevin/ucerf3/PureScratch.java +++ b/src/main/java/scratch/kevin/ucerf3/PureScratch.java @@ -83,9 +83,9 @@ import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; -import org.opensha.commons.logicTree.LogicTreeLevel.RandomlySampledLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.RandomlyGeneratedLevel; import org.opensha.commons.logicTree.LogicTreeNode; -import org.opensha.commons.logicTree.LogicTreeNode.RandomlySampledNode; +import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; import org.opensha.commons.mapping.PoliticalBoundariesData; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.param.Parameter; @@ -712,10 +712,10 @@ private static void test263() throws IOException { System.out.println("\t\tAffected: "+level.getAffected()); System.out.println("\t\tNot affected: "+level.getNotAffected()); } - if (level instanceof RandomlySampledLevel) { + if (level instanceof RandomlyGeneratedLevel) { System.out.println("\tIt's a random level: "+level.getName()); - RandomlySampledLevel randLevel = (RandomlySampledLevel)level; - List nodes = randLevel.getNodes(); + RandomlyGeneratedLevel randLevel = (RandomlyGeneratedLevel)level; + List nodes = randLevel.getNodes(); System.out.println("\t\tNode count: "+nodes.size()); System.out.println("\t\tNode 0:\tseed="+nodes.get(0).getSeed()+"; weight="+nodes.get(0).getNodeWeight(null)); int lastIndex = nodes.size()-1; @@ -729,8 +729,8 @@ private static void test263() throws IOException { LogicTreeBranch branch = tree.getBranch(index); System.out.println("Branch "+index+": "+branch); for (LogicTreeNode val : branch) { - if (val instanceof RandomlySampledNode) { - RandomlySampledNode randNode = (RandomlySampledNode)val; + if (val instanceof RandomlyGeneratedNode) { + RandomlyGeneratedNode randNode = (RandomlyGeneratedNode)val; System.out.println("\t"+val.getName()+":\t"+randNode.getSeed()+"; weight="+(float)randNode.getNodeWeight(null)); } From 18330657740ad455a5af7e6b914eb37f8e9ed298 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 17 Mar 2026 10:07:53 -0700 Subject: [PATCH 03/71] updated random level/node classes & serialization --- ..._LogicTreeInversionRunnerScriptWriter.java | 2 +- .../nshm23/RandSamplingTreeAddSamples.java | 3 +- .../RandomDefModSampleLevel.java | 6 +- .../scratch/kevin/nshm26/SamplerTest.java | 136 ++++++++++++++ .../UpdatedRandTreeSerialzationTests.java | 172 ++++++++++++++++++ ...GriddedRateDistributionSolutionWriter.java | 6 +- .../scratch/kevin/ucerf3/PureScratch.java | 2 +- 7 files changed, 318 insertions(+), 9 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm26/SamplerTest.java create mode 100644 src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 74c68877..f0165405 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -799,7 +799,7 @@ public static void main(String[] args) throws IOException { List> levelNodes = new ArrayList<>(); for (RandomlyGeneratedLevel level : individualRandomLevels) { - level.buildNodes(rand, numBranches, 1d); + level.build(rand.nextLong(), numBranches); levelNodes.add(level.getNodes()); } diff --git a/src/main/java/scratch/kevin/nshm23/RandSamplingTreeAddSamples.java b/src/main/java/scratch/kevin/nshm23/RandSamplingTreeAddSamples.java index e72495b3..6d296bcf 100644 --- a/src/main/java/scratch/kevin/nshm23/RandSamplingTreeAddSamples.java +++ b/src/main/java/scratch/kevin/nshm23/RandSamplingTreeAddSamples.java @@ -70,9 +70,10 @@ public static void main(String[] args) throws IOException { Constructor constructor = ((RandomlyGeneratedLevel)sourceLevel).getClass().getConstructor(); constructor.setAccessible(true); RandomlyGeneratedLevel modLevel = constructor.newInstance(); - modLevel.buildNodes(seeds, 1d); +// modLevel.buildNodes(seeds, 1d); // TODO modLevels.add(modLevel); randNodeStacks.add(new LinkedList<>(modLevel.getNodes())); + throw new IllegalStateException("Not implemented"); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { throw ExceptionUtils.asRuntimeException(e); diff --git a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java index f0aaef26..a18a689b 100644 --- a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java +++ b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java @@ -11,11 +11,11 @@ public RandomDefModSampleLevel() { } public RandomDefModSampleLevel(int numSamples) { - this(numSamples, new Random()); + this(numSamples, new Random().nextLong()); } - public RandomDefModSampleLevel(int numSamples, Random r) { - buildNodes(r, numSamples); + public RandomDefModSampleLevel(int numSamples, long seed) { + build(seed, numSamples); } @Override diff --git a/src/main/java/scratch/kevin/nshm26/SamplerTest.java b/src/main/java/scratch/kevin/nshm26/SamplerTest.java new file mode 100644 index 00000000..1c488be4 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm26/SamplerTest.java @@ -0,0 +1,136 @@ +package scratch.kevin.nshm26; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.rng.simple.RandomSource; +import org.apache.commons.statistics.distribution.ContinuousDistribution; +import org.apache.commons.statistics.distribution.TruncatedNormalDistribution; +import org.jfree.chart.ui.RectangleAnchor; +import org.jfree.data.Range; +import org.apache.commons.statistics.distribution.ContinuousDistribution.Sampler; +import org.apache.commons.statistics.distribution.CorrTruncatedNormalDistribution; +import org.apache.commons.statistics.distribution.NormalDistribution; +import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; +import org.opensha.commons.data.function.DiscretizedFunc; +import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.function.HistogramFunction; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; + +import net.mahdilamb.colormap.Colors; + +public class SamplerTest { + + public static void main(String[] args) throws IOException { +// double mean = 1d; +// double sd = 0.1; +// double lower = 0.7; +// double upper = 1.3; + +// double mean = -1d; +// double sd = 0.1; +// double lower = -1.3; +// double upper = -0.7; + +// double mean = 1d; +// double sd = 0.1; +// double lower = 0.7; +// double upper = 1.3; + + double mean = 1d; + double sd = 0.1; + double lower = -0.1; + double upper = 1.3; + +// double mean = -1d; +// double sd = 0.1; +// double lower = -1d; +// double upper = -0.7; + +// double mean = -0.1d; +// double sd = 0.1; +// double lower = 0.01; +// double upper = 1d; + + int samples = 10000000; + + EvenlyDiscretizedFunc hist1 = HistogramFunction.getEncompassingHistogram(lower-0.1, upper+0.1, 0.01); + + ContinuousDistribution dist = TruncatedNormalDistribution.of(mean, sd, lower, upper); + + System.out.println("Reported dist params:"); + System.out.println("\tmean: "+dist.getMean()); + System.out.println("\tvar: "+dist.getVariance()); + System.out.println("\tsqrt(var): "+Math.sqrt(dist.getVariance())); + System.out.println("\tlower: "+dist.getSupportLowerBound()); + System.out.println("\tupper: "+dist.getSupportUpperBound()); + + Sampler sampler = dist.createSampler(RandomSource.XO_RO_SHI_RO_128_PP.create(123456l)); + for (int i=0; i 0) + pdfDensity.set(x, density); + } + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + hist1.setName("Current Rejection Sampler"); + funcs.add(hist1); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, Color.BLACK)); + + Color corrHistColor = Colors.tab_orange; + corrHistColor = new Color(corrHistColor.getRed(), corrHistColor.getGreen(), corrHistColor.getBlue(), 127); + hist2.setName("Corrected Rejection Sampler"); + funcs.add(hist2); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, corrHistColor)); + + pdfDensity.setName("PDF Density"); + funcs.add(pdfDensity); + chars.add(new PlotCurveCharacterstics(PlotLineType.DASHED, 3f, Colors.tab_blue)); + + double maxY = 0d; + for (DiscretizedFunc func : funcs) + maxY = Math.max(maxY, func.getMaxY()); + + String title = "μ="+(float)mean+", σ="+(float)sd+", bounds=["+(float)lower+", "+(float)upper+"]"; + + PlotSpec plot = new PlotSpec(funcs, chars, title, "X", "Density"); + plot.setLegendInset(RectangleAnchor.TOP_LEFT); + HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); + + gp.setLegendFontSize(16); + + gp.drawGraphPanel(plot, false, false, new Range(hist1.getMinX(), hist1.getMaxX()), new Range(0d, maxY*1.2)); + + String prefix = "trunc_dist_"+(float)mean+"_"+(float)sd+"_"+(float)lower+"_"+(float)upper; + + PlotUtils.writePlots(new File("/tmp"), prefix, gp, 700, 450, true, false, false); + } + +} diff --git a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java new file mode 100644 index 00000000..672d2c9b --- /dev/null +++ b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java @@ -0,0 +1,172 @@ +package scratch.kevin.nshm26; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.apache.commons.rng.simple.RandomSource; +import org.apache.commons.statistics.distribution.ContinuousDistribution; +import org.apache.commons.statistics.distribution.ContinuousDistribution.Sampler; +import org.apache.commons.statistics.distribution.CorrTruncatedNormalDistribution; +import org.apache.commons.statistics.distribution.TruncatedNormalDistribution; +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeLevel; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; +import org.opensha.commons.logicTree.LogicTreeNode.ValuedLogicTreeNode; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; + +import com.google.common.base.Preconditions; + +public class UpdatedRandTreeSerialzationTests { + + public static void main(String[] args) throws IOException { + List> inTrees = new ArrayList<>(); + + inTrees.add(LogicTree.read(new File("/home/kevin/OpenSHA/nshm23/batch_inversions/2025_01_17-prvi25_crustal_branches-dmSample10x/logic_tree.json"))); + + TestValuedLevel testValLevel = new TestValuedLevel(); + testValLevel.build(12345l, 1000); + inTrees.add(LogicTree.buildExhaustive(List.of(testValLevel), true)); + + ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(1d, 0.1, 0.7, 1.3); + Sampler sampler = dist.createSampler(RandomSource.XO_RO_SHI_RO_128_PP.create(123456l)); + MinMaxAveTracker sampleTrack = new MinMaxAveTracker(); + for (int i=0; i<100000; i++) { + sampleTrack.addValue(sampler.sample()); + } + System.out.println(sampleTrack); + System.out.println("Dist mean: "+dist.getMean()); + System.out.println("Dist bounds: "+dist.getSupportLowerBound()+", "+dist.getSupportUpperBound()); + TestDistLevel testDistLevel = new TestDistLevel(dist); + testDistLevel.build(12345l, 1000); + inTrees.add(LogicTree.buildExhaustive(List.of(testDistLevel), true)); + + for (int t=0; t tree = inTrees.get(t); + System.out.println("Processing tree "+t+" with "+tree.size()+" branches"); + + File treeOutFile = new File("/tmp/tree_out_"+t+".json"); + System.out.println("\tWriting tree to: "+treeOutFile.getAbsolutePath()); + tree.write(treeOutFile); + + File branchOutFile = new File("/tmp/branch_out_"+t+".json"); + System.out.println("\tWriting branch 0 to: "+branchOutFile.getAbsolutePath()); + tree.getBranch(0).writeToFile(branchOutFile); + + System.out.println("\tReading tree back in"); + LogicTree tree2 = LogicTree.read(treeOutFile); + + System.out.println("\tLevels:"); + for (LogicTreeLevel level : tree2.getLevels()) + System.out.println("\t\t"+level.getName()+" ("+level.getClass()+")"); + + System.out.println("\tReading branch 0 back in"); + LogicTreeBranch loadedBranch0 = LogicTreeBranch.read(branchOutFile); + for (int i=-1; i branch1, branch2; + if (i < 0) { + branch1 = tree.getBranch(0); + branch2 = loadedBranch0; + } else { + branch1 = tree.getBranch(i); + branch2 = tree2.getBranch(i); + } + List randGenNodes1 = branch1.getValues(RandomlyGeneratedNode.class); + List randGenNodes2 = branch2.getValues(RandomlyGeneratedNode.class); + if (randGenNodes1 == null) { + Preconditions.checkState(randGenNodes2 == null); + } else { + Preconditions.checkState(randGenNodes1.size() == randGenNodes2.size()); + for (int n=0; n> valNodes1 = branch1.getValues(ValuedLogicTreeNode.class); + List> valNodes2 = branch2.getValues(ValuedLogicTreeNode.class); + if (valNodes1 == null) { + Preconditions.checkState(valNodes2 == null); + } else { + Preconditions.checkState(valNodes1.size() == valNodes2.size(), + "Branch %s: Valued node list size mismatch: %s vs %s", i, valNodes1.size(), valNodes2.size()); + for (int n=0; n gen1 = valNodes1.get(n); + ValuedLogicTreeNode gen2 = valNodes2.get(n); + Preconditions.checkState(gen1.getValue().equals(gen2.getValue())); + Preconditions.checkState(gen1.equals(gen2)); + } + } + } + } + + } + + private static class TestValuedLevel extends LogicTreeLevel.RandomlySampledLevel { + + public TestValuedLevel() { + super("Test Valued Level", "TVL"); + } + + @Override + protected void doBuild(long seed, int numNodes, double weightEach) { + Random rand = new Random(seed); + super.build(()->rand.nextDouble(), numNodes, weightEach); + } + + @Override + protected String getNodeNamePrefix() { + return "Random Node "; + } + + @Override + protected String getNodeShortNamePrefix() { + return "RN"; + } + + @Override + protected String getNodeFilePrefix() { + return "RN"; + } + + @Override + public Class getValueType() { + return Double.class; + } + + } + + private static class TestDistLevel extends LogicTreeLevel.ContinuousDistributionSampledLevel { + + private TestDistLevel() { + this(null); + }; + + public TestDistLevel(ContinuousDistribution dist) { + super("Test Distribution Level", "TestDistLevel", dist); + } + + @Override + protected String getNodeNamePrefix() { + return "Distribution Sample "; + } + + @Override + protected String getNodeShortNamePrefix() { + return "DistSample"; + } + + @Override + protected String getNodeFilePrefix() { + return "DistSample"; + } + + } + +} + diff --git a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java b/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java index 9f43bee3..45cfe216 100644 --- a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java +++ b/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java @@ -149,15 +149,15 @@ public static void main(String[] args) throws IOException { fullRandLevels.add(crustalSmoothingLevel); fullRandLevels.add(PRVI25_LogicTree.MMAX_OFF); CrustalRateSamplingLevel crustalSampler = new CrustalRateSamplingLevel(crustalPairs); - crustalSampler.buildNodes(rand, numTotalSamples); + crustalSampler.build(rand.nextLong(), numTotalSamples); fullRandLevels.add(crustalSampler); fullRandLevels.add(interfaceDeclusterLevel); fullRandLevels.add(interfaceSmoothingLevel); fullRandLevels.add(PRVI25_LogicTree.SUB_SCALE); CarSlabRateSamplingLevel carSampler = new CarSlabRateSamplingLevel(carSlabPairs, carInterfacePairs); - carSampler.buildNodes(rand, numTotalSamples); + carSampler.build(rand.nextLong(), numTotalSamples); MueRateSamplingLevel mueSampler = new MueRateSamplingLevel(mueSlabPairs, mueInterfacePairs); - mueSampler.buildNodes(rand, numTotalSamples); + mueSampler.build(rand.nextLong(), numTotalSamples); fullRandLevels.add(carSampler); fullRandLevels.add(mueSampler); List> threeBranchLevels = new ArrayList<>(); diff --git a/src/main/java/scratch/kevin/ucerf3/PureScratch.java b/src/main/java/scratch/kevin/ucerf3/PureScratch.java index dd553c9b..f8b3700e 100644 --- a/src/main/java/scratch/kevin/ucerf3/PureScratch.java +++ b/src/main/java/scratch/kevin/ucerf3/PureScratch.java @@ -738,7 +738,7 @@ private static void test263() throws IOException { } RandomDefModSampleLevel level = new RandomDefModSampleLevel(); - level.buildNodes(new Random(), 10); + level.build(new Random().nextLong(), 10); System.out.println("Test level: "+level.getName()); System.out.println("\tAffected: "+level.getAffected()); System.out.println("\tNot affected: "+level.getNotAffected()); From d97435481b02c5716730bb4ac635608f97f881ab Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 17 Mar 2026 15:31:45 -0700 Subject: [PATCH 04/71] WIP on random sampling and branch/level serialization --- .../HardcodedInversionFactoryRunner.java | 5 ++- .../RandomDefModSampleLevel.java | 11 +----- .../InterfaceSubSeisMoReductionTests.java | 4 +-- .../UpdatedRandTreeSerialzationTests.java | 35 ++----------------- ...GriddedRateDistributionSolutionWriter.java | 35 +++---------------- .../prvi25/GriddedSeismicityMFDTests.java | 5 +-- .../kevin/prvi25/RateFileScale1973to1900.java | 5 +-- .../prvi25/RateModelAvgVsPreferredTest.java | 3 +- .../prvi25/figures/CombinedMFDsPlot.java | 12 +++---- .../prvi25/figures/IndividualMFDPlots.java | 4 +-- .../figures/ObsUncertaintyBoundsFigure.java | 10 +++--- .../prvi25/figures/RateEpochComparison.java | 6 ++-- .../prvi25/figures/RateModelComparison.java | 8 ++--- .../scratch/kevin/ucerf3/PureScratch.java | 4 +-- 14 files changed, 44 insertions(+), 103 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index b7fc0359..9ceab046 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -49,6 +49,7 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_LogicTreeBranch; import org.opensha.sha.earthquake.rupForecastImpl.nshm26.NSHM26_InvConfigFactory; import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.PRVI25_InvConfigFactory; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalDeformationModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalFaultModels; @@ -58,6 +59,7 @@ import org.opensha.sha.magdist.IncrementalMagFreqDist; import org.opensha.sha.magdist.SparseGutenbergRichterSolver; import org.opensha.sha.magdist.SparseGutenbergRichterSolver.SpreadingMethod; +import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; @@ -174,7 +176,8 @@ public static void main(String[] args) throws IOException { // LogicTreeBranch branch = NSHM26_LogicTree.DEFAULT_GNMI_SUBDUCTION_INTERFACE; // dirName += "-gnmi"; - LogicTreeBranch branch = NSHM26_LogicTree.DEFAULT_AMSAM_SUBDUCTION_INTERFACE; + LogicTreeBranch branch = NSHM26_LogicTree.buildInterfaceDefault( + NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); dirName += "-amsam"; branch.setValue(PRVI25_SubductionBValues.B_1p0); diff --git a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java index a18a689b..c3087519 100644 --- a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java +++ b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java @@ -15,19 +15,10 @@ public RandomDefModSampleLevel(int numSamples) { } public RandomDefModSampleLevel(int numSamples, long seed) { + super("Random Deformation Model Sample", "DMSample"); build(seed, numSamples); } - @Override - public String getShortName() { - return "DMSample"; - } - - @Override - public String getName() { - return "Random Deformation Model Sample"; - } - @Override public RandomDefModSampleNode buildNodeInstance(int index, long seed, double weight) { return new RandomDefModSampleNode(getNodeName(index), getNodeShortName(index), getNodeFilePrefix(index), weight, seed); diff --git a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java index 0e0874de..4acb93d6 100644 --- a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java +++ b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java @@ -41,8 +41,8 @@ public class InterfaceSubSeisMoReductionTests { public static void main(String[] args) throws IOException { - LogicTreeBranch branch = NSHM26_LogicTree.DEFAULT_GNMI_SUBDUCTION_INTERFACE; -// LogicTreeBranch branch = NSHM26_LogicTree.DEFAULT_AMSAM_SUBDUCTION_INTERFACE; + LogicTreeBranch branch = NSHM26_LogicTree.buildInterfaceDefault( + NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); NSHM26_InterfaceFaultModels fm = branch.requireValue(NSHM26_InterfaceFaultModels.class); NSHM26_InterfaceDeformationModels dm = branch.requireValue(NSHM26_InterfaceDeformationModels.class); diff --git a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java index 672d2c9b..6e809513 100644 --- a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java +++ b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java @@ -110,7 +110,7 @@ public static void main(String[] args) throws IOException { private static class TestValuedLevel extends LogicTreeLevel.RandomlySampledLevel { public TestValuedLevel() { - super("Test Valued Level", "TVL"); + super("Test Valued Level", "TVL", "Random Node ", "RN", "RN"); } @Override @@ -119,21 +119,6 @@ protected void doBuild(long seed, int numNodes, double weightEach) { super.build(()->rand.nextDouble(), numNodes, weightEach); } - @Override - protected String getNodeNamePrefix() { - return "Random Node "; - } - - @Override - protected String getNodeShortNamePrefix() { - return "RN"; - } - - @Override - protected String getNodeFilePrefix() { - return "RN"; - } - @Override public Class getValueType() { return Double.class; @@ -148,22 +133,8 @@ private TestDistLevel() { }; public TestDistLevel(ContinuousDistribution dist) { - super("Test Distribution Level", "TestDistLevel", dist); - } - - @Override - protected String getNodeNamePrefix() { - return "Distribution Sample "; - } - - @Override - protected String getNodeShortNamePrefix() { - return "DistSample"; - } - - @Override - protected String getNodeFilePrefix() { - return "DistSample"; + super("Test Distribution Level", "TestDistLevel", dist, + "Distribution Sample ", "DistSample", "DistSample"); } } diff --git a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java b/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java index 45cfe216..c854f425 100644 --- a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java +++ b/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java @@ -49,7 +49,6 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.gridded.NSHM23_SingleRegionGridSourceProvider; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.NSHM23_MaxMagOffFault; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.PRVI25_GridSourceBuilder; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.RateType; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_DeclusteringAlgorithms; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_LogicTree; @@ -67,6 +66,7 @@ import com.google.common.base.Stopwatch; import edu.usc.kmilner.mpj.taskDispatch.MPJTaskCalculator; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; public class GriddedRateDistributionSolutionWriter { @@ -538,19 +538,10 @@ private static class CrustalRateSamplingLevel extends LogicTreeLevel.RandomlyGen private CrustalRateSamplingLevel() {} public CrustalRateSamplingLevel(List samples) { + super("Crustal Rate/b Distribution Sampling", "Crustal-Sampling"); this.samples = samples; } - @Override - public String getShortName() { - return "Crustal-Sampling"; - } - - @Override - public String getName() { - return "Crustal Rate/b Distribution Sampling"; - } - @Override public CrustalSamplingNode buildNodeInstance(int index, long seed, double weight) { if (randomizedSamples == null) { @@ -625,6 +616,7 @@ private static class CarSlabRateSamplingLevel extends LogicTreeLevel.RandomlyGen private CarSlabRateSamplingLevel() {} public CarSlabRateSamplingLevel(List slabSamples, List interfaceSamples) { + super("CAR Rate/b Distribution Sampling", "CAR-Sampling"); TotalRateComparator comp = new TotalRateComparator(8d); Collections.sort(slabSamples, comp); Collections.sort(interfaceSamples, comp); @@ -632,16 +624,6 @@ public CarSlabRateSamplingLevel(List slabSamples, List inter this.interfaceSamples = interfaceSamples; } - @Override - public String getShortName() { - return "CAR-Sampling"; - } - - @Override - public String getName() { - return "CAR Rate/b Distribution Sampling"; - } - @Override public CarSlabSamplingNode buildNodeInstance(int index, long seed, double weight) { if (randomizedIndexes == null) { @@ -720,6 +702,7 @@ private static class MueRateSamplingLevel extends LogicTreeLevel.RandomlyGenerat private MueRateSamplingLevel() {} public MueRateSamplingLevel(List slabSamples, List interfaceSamples) { + super("MUE Rate/b Distribution Sampling", "MUE-Sampling"); TotalRateComparator comp = new TotalRateComparator(8d); Collections.sort(slabSamples, comp); Collections.sort(interfaceSamples, comp); @@ -727,16 +710,6 @@ public MueRateSamplingLevel(List slabSamples, List interface this.interfaceSamples = interfaceSamples; } - @Override - public String getShortName() { - return "MUE-Sampling"; - } - - @Override - public String getName() { - return "MUE Rate/b Distribution Sampling"; - } - @Override public MueSamplingNode buildNodeInstance(int index, long seed, double weight) { if (randomizedIndexes == null) { diff --git a/src/main/java/scratch/kevin/prvi25/GriddedSeismicityMFDTests.java b/src/main/java/scratch/kevin/prvi25/GriddedSeismicityMFDTests.java index 62978fd0..6637da50 100644 --- a/src/main/java/scratch/kevin/prvi25/GriddedSeismicityMFDTests.java +++ b/src/main/java/scratch/kevin/prvi25/GriddedSeismicityMFDTests.java @@ -17,8 +17,6 @@ import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.util.cpt.CPT; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.Exact; import org.opensha.sha.magdist.GutenbergRichterMagFreqDist; import org.opensha.sha.magdist.IncrementalMagFreqDist; import org.opensha.sha.magdist.SummedMagFreqDist; @@ -26,6 +24,9 @@ import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Exact; + public class GriddedSeismicityMFDTests { private static final double FAKE_MFD_TARGET_TOTAL = 2d; diff --git a/src/main/java/scratch/kevin/prvi25/RateFileScale1973to1900.java b/src/main/java/scratch/kevin/prvi25/RateFileScale1973to1900.java index 3d2746fb..953b860d 100644 --- a/src/main/java/scratch/kevin/prvi25/RateFileScale1973to1900.java +++ b/src/main/java/scratch/kevin/prvi25/RateFileScale1973to1900.java @@ -7,14 +7,15 @@ import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.uncertainty.UncertaintyBoundType; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.RateType; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateModel; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader.PRVI25_SeismicityRegions; import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; + public class RateFileScale1973to1900 { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/prvi25/RateModelAvgVsPreferredTest.java b/src/main/java/scratch/kevin/prvi25/RateModelAvgVsPreferredTest.java index c809c521..3f32205a 100644 --- a/src/main/java/scratch/kevin/prvi25/RateModelAvgVsPreferredTest.java +++ b/src/main/java/scratch/kevin/prvi25/RateModelAvgVsPreferredTest.java @@ -2,7 +2,6 @@ import java.io.IOException; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateModel; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionCaribbeanSeismicityRate; @@ -11,6 +10,8 @@ import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; + public class RateModelAvgVsPreferredTest { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java b/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java index 4ca9371e..601747b3 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java +++ b/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java @@ -40,12 +40,6 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupture; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.PRVI25_GridSourceBuilder; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.Direct; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.Exact; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.RateRecord; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.RateType; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateModel; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionCaribbeanSeismicityRate; @@ -57,6 +51,12 @@ import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Direct; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Exact; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateRecord; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import net.mahdilamb.colormap.Colors; import scratch.kevin.latex.LaTeXUtils; diff --git a/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java b/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java index dc173fa9..892b7d62 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java +++ b/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java @@ -48,8 +48,6 @@ import org.opensha.sha.earthquake.param.IncludeBackgroundOption; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.NSHM23_SegmentationModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.PRVI25_GridSourceBuilder; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.RateType; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateModel; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_DeclusteringAlgorithms; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeisSmoothingAlgorithms; @@ -68,6 +66,8 @@ import com.google.common.base.Preconditions; import com.google.common.primitives.Ints; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import gov.usgs.earthquake.nshmp.model.NshmErf; import net.mahdilamb.colormap.Colors; import scratch.kevin.latex.LaTeXUtils; diff --git a/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java b/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java index 59b560f2..0d9a8899 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java +++ b/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java @@ -31,11 +31,6 @@ import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.Exact; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.PureGR; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.RateRecord; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.RateType; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionCaribbeanSeismicityRate; @@ -45,6 +40,11 @@ import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Exact; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.PureGR; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateRecord; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import net.mahdilamb.colormap.Colors; import scratch.kevin.prvi25.GriddedRateDistributionSolutionWriter; diff --git a/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java b/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java index 26a4fe53..6c0b76f4 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java +++ b/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java @@ -20,9 +20,6 @@ import org.opensha.commons.gui.plot.PlotSpec; import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.Direct; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateModel; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionCaribbeanSeismicityRate; @@ -32,6 +29,9 @@ import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Direct; import net.mahdilamb.colormap.Colors; public class RateEpochComparison { diff --git a/src/main/java/scratch/kevin/prvi25/figures/RateModelComparison.java b/src/main/java/scratch/kevin/prvi25/figures/RateModelComparison.java index dfcfcdb3..69872450 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/RateModelComparison.java +++ b/src/main/java/scratch/kevin/prvi25/figures/RateModelComparison.java @@ -21,10 +21,6 @@ import org.opensha.commons.gui.plot.PlotSpec; import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.Direct; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.RateType; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateModel; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader.PRVI25_SeismicityRegions; @@ -32,6 +28,10 @@ import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Direct; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import net.mahdilamb.colormap.Colors; public class RateModelComparison { diff --git a/src/main/java/scratch/kevin/ucerf3/PureScratch.java b/src/main/java/scratch/kevin/ucerf3/PureScratch.java index f8b3700e..80836565 100644 --- a/src/main/java/scratch/kevin/ucerf3/PureScratch.java +++ b/src/main/java/scratch/kevin/ucerf3/PureScratch.java @@ -179,8 +179,6 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.random.BranchSamplingManager; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.PRVI25_GridSourceBuilder; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateFileLoader.RateType; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.SeismicityRateModel; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalDeformationModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalGMMs; @@ -228,6 +226,8 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import gov.usgs.earthquake.nshmp.gmm.Gmm; import gov.usgs.earthquake.nshmp.gmm.GmmInput; import gov.usgs.earthquake.nshmp.gmm.GroundMotion; From 9e422939fcff8fb6a6da1e447b355bb5a967d46b Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Wed, 18 Mar 2026 08:42:55 -0700 Subject: [PATCH 05/71] refactored to use json element data and skipping custom adapter logic --- .../RandomDefModSampleLevel.java | 18 +----- ...GriddedRateDistributionSolutionWriter.java | 58 +++---------------- 2 files changed, 11 insertions(+), 65 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java index c3087519..ae27afc6 100644 --- a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java +++ b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java @@ -15,7 +15,8 @@ public RandomDefModSampleLevel(int numSamples) { } public RandomDefModSampleLevel(int numSamples, long seed) { - super("Random Deformation Model Sample", "DMSample"); + super("Random Deformation Model Sample", "DMSample", + "Deformation Model Sample ", "DMSample", "DMSample"); build(seed, numSamples); } @@ -29,19 +30,4 @@ public Class getType() { return RandomDefModSampleNode.class; } - @Override - protected String getNodeNamePrefix() { - return "Deformation Model Sample "; - } - - @Override - protected String getNodeShortNamePrefix() { - return "DMSample"; - } - - @Override - protected String getNodeFilePrefix() { - return "DMSample"; - } - } diff --git a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java b/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java index c854f425..82da3f6e 100644 --- a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java +++ b/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java @@ -538,7 +538,8 @@ private static class CrustalRateSamplingLevel extends LogicTreeLevel.RandomlyGen private CrustalRateSamplingLevel() {} public CrustalRateSamplingLevel(List samples) { - super("Crustal Rate/b Distribution Sampling", "Crustal-Sampling"); + super("Crustal Rate/b Distribution Sampling", "Crustal-Sampling", + "Crustal Sample ", "Crustal-Sample", "crustal_sample_"); this.samples = samples; } @@ -557,21 +558,6 @@ public CrustalSamplingNode buildNodeInstance(int index, long seed, double weight public Class getType() { return CrustalSamplingNode.class; } - - @Override - protected String getNodeNamePrefix() { - return "Crustal Sample "; - } - - @Override - protected String getNodeShortNamePrefix() { - return "Crustal-Sample"; - } - - @Override - protected String getNodeFilePrefix() { - return "crustal_sample_"; - } } @@ -613,10 +599,13 @@ private static class CarSlabRateSamplingLevel extends LogicTreeLevel.RandomlyGen private List interfaceSamples; private List randomizedIndexes; - private CarSlabRateSamplingLevel() {} + private CarSlabRateSamplingLevel() { + super(); + } public CarSlabRateSamplingLevel(List slabSamples, List interfaceSamples) { - super("CAR Rate/b Distribution Sampling", "CAR-Sampling"); + super("CAR Rate/b Distribution Sampling", "CAR-Sampling", + "CAR Sample ", "CAR-Sample", "car_sample_"); TotalRateComparator comp = new TotalRateComparator(8d); Collections.sort(slabSamples, comp); Collections.sort(interfaceSamples, comp); @@ -643,21 +632,6 @@ public CarSlabSamplingNode buildNodeInstance(int index, long seed, double weight public Class getType() { return CarSlabSamplingNode.class; } - - @Override - protected String getNodeNamePrefix() { - return "CAR Sample "; - } - - @Override - protected String getNodeShortNamePrefix() { - return "CAR-Sample"; - } - - @Override - protected String getNodeFilePrefix() { - return "car_sample_"; - } } @@ -702,7 +676,8 @@ private static class MueRateSamplingLevel extends LogicTreeLevel.RandomlyGenerat private MueRateSamplingLevel() {} public MueRateSamplingLevel(List slabSamples, List interfaceSamples) { - super("MUE Rate/b Distribution Sampling", "MUE-Sampling"); + super("MUE Rate/b Distribution Sampling", "MUE-Sampling", + "MUE Sample ", "MUE-Sample", "mue_sample_"); TotalRateComparator comp = new TotalRateComparator(8d); Collections.sort(slabSamples, comp); Collections.sort(interfaceSamples, comp); @@ -729,21 +704,6 @@ public MueSamplingNode buildNodeInstance(int index, long seed, double weight) { public Class getType() { return MueSamplingNode.class; } - - @Override - protected String getNodeNamePrefix() { - return "MUE Sample "; - } - - @Override - protected String getNodeShortNamePrefix() { - return "MUE-Sample"; - } - - @Override - protected String getNodeFilePrefix() { - return "mue_sample_"; - } } From e187739577c90fd272aa35220e130e93341881fc Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Wed, 18 Mar 2026 13:48:27 -0700 Subject: [PATCH 06/71] more serialization/sampling improvements --- .../scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java | 2 +- .../kevin/nshm26/InterfaceSubSeisMoReductionTests.java | 2 +- .../kevin/nshm26/UpdatedRandTreeSerialzationTests.java | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index 9ceab046..a0d7abb5 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -176,7 +176,7 @@ public static void main(String[] args) throws IOException { // LogicTreeBranch branch = NSHM26_LogicTree.DEFAULT_GNMI_SUBDUCTION_INTERFACE; // dirName += "-gnmi"; - LogicTreeBranch branch = NSHM26_LogicTree.buildInterfaceDefault( + LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); dirName += "-amsam"; diff --git a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java index 4acb93d6..8aa26c53 100644 --- a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java +++ b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java @@ -41,7 +41,7 @@ public class InterfaceSubSeisMoReductionTests { public static void main(String[] args) throws IOException { - LogicTreeBranch branch = NSHM26_LogicTree.buildInterfaceDefault( + LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); NSHM26_InterfaceFaultModels fm = branch.requireValue(NSHM26_InterfaceFaultModels.class); NSHM26_InterfaceDeformationModels dm = branch.requireValue(NSHM26_InterfaceDeformationModels.class); diff --git a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java index 6e809513..a2e9e0bf 100644 --- a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java +++ b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java @@ -45,6 +45,10 @@ public static void main(String[] args) throws IOException { testDistLevel.build(12345l, 1000); inTrees.add(LogicTree.buildExhaustive(List.of(testDistLevel), true)); + LogicTree lastTree = inTrees.get(inTrees.size()-1); + for (int i=0; i tree = inTrees.get(t); System.out.println("Processing tree "+t+" with "+tree.size()+" branches"); From 9c62882b5978ec8a83c38645eed980ea0d90915c Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Thu, 19 Mar 2026 11:51:13 -0700 Subject: [PATCH 07/71] serialization cleanup progress --- .../HardcodedInversionFactoryRunner.java | 11 +- .../RandomDefModSampleLevel.java | 12 +- .../UpdatedRandTreeSerialzationTests.java | 1 + ...GriddedRateDistributionSolutionWriter.java | 788 ------------------ .../figures/ObsUncertaintyBoundsFigure.java | 28 +- .../scratch/kevin/ucerf3/PureScratch.java | 2 +- 6 files changed, 40 insertions(+), 802 deletions(-) delete mode 100644 src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index a0d7abb5..798a6cf0 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -175,12 +175,13 @@ public static void main(String[] args) throws IOException { // writeGridProv = true; // LogicTreeBranch branch = NSHM26_LogicTree.DEFAULT_GNMI_SUBDUCTION_INTERFACE; -// dirName += "-gnmi"; - LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( - NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); - dirName += "-amsam"; + LogicTreeBranch branch = NSHM26_LogicTree.buildDefault(NSHM26_SeismicityRegions.GNMI, TectonicRegionType.ACTIVE_SHALLOW, false); + dirName += "-gnmi"; +// LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( +// NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); +// dirName += "-amsam"; - branch.setValue(PRVI25_SubductionBValues.B_1p0); +// branch.setValue(PRVI25_SubductionBValues.B_1p0); // branch.setValue(NSHM23_SegmentationModels.NONE); // branch.setValue(SupraSeisBValues.B_0p0); diff --git a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java index ae27afc6..090bbf30 100644 --- a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java +++ b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java @@ -6,8 +6,8 @@ public class RandomDefModSampleLevel extends RandomlyGeneratedLevel { - public RandomDefModSampleLevel() { - + public RandomDefModSampleLevel(String name, String shortName) { + super(name, shortName); } public RandomDefModSampleLevel(int numSamples) { @@ -21,13 +21,13 @@ public RandomDefModSampleLevel(int numSamples, long seed) { } @Override - public RandomDefModSampleNode buildNodeInstance(int index, long seed, double weight) { - return new RandomDefModSampleNode(getNodeName(index), getNodeShortName(index), getNodeFilePrefix(index), weight, seed); + public Class getType() { + return RandomDefModSampleNode.class; } @Override - public Class getType() { - return RandomDefModSampleNode.class; + public RandomDefModSampleNode build(Long seed, double weight, String name, String shortName, String filePrefix) { + return new RandomDefModSampleNode(name, shortName, filePrefix, weight, seed); } } diff --git a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java index a2e9e0bf..9c1c97d3 100644 --- a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java +++ b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java @@ -16,6 +16,7 @@ import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; +import org.opensha.commons.logicTree.LogicTreeNode.SimpleValuedNode; import org.opensha.commons.logicTree.LogicTreeNode.ValuedLogicTreeNode; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; diff --git a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java b/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java deleted file mode 100644 index 82da3f6e..00000000 --- a/src/main/java/scratch/kevin/prvi25/GriddedRateDistributionSolutionWriter.java +++ /dev/null @@ -1,788 +0,0 @@ -package scratch.kevin.prvi25; - -import java.io.File; -import java.io.IOException; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.opensha.commons.data.CSVFile; -import org.opensha.commons.geo.GriddedRegion; -import org.opensha.commons.geo.Region; -import org.opensha.commons.geo.json.Feature; -import org.opensha.commons.hpc.JavaShellScriptWriter; -import org.opensha.commons.hpc.mpj.FastMPJShellScriptWriter; -import org.opensha.commons.hpc.mpj.MPJExpressShellScriptWriter; -import org.opensha.commons.hpc.mpj.NoMPJSingleNodeShellScriptWriter; -import org.opensha.commons.hpc.pbs.BatchScriptWriter; -import org.opensha.commons.hpc.pbs.USC_CARC_ScriptWriter; -import org.opensha.commons.logicTree.Affects; -import org.opensha.commons.logicTree.BranchWeightProvider; -import org.opensha.commons.logicTree.DoesNotAffect; -import org.opensha.commons.logicTree.LogicTreeBranch; -import org.opensha.commons.logicTree.LogicTreeLevel; -import org.opensha.commons.logicTree.LogicTreeNode; -import org.opensha.commons.logicTree.LogicTreeLevel.FileBackedLevel; -import org.opensha.commons.logicTree.LogicTreeNode.FileBackedNode; -import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; -import org.opensha.commons.util.DataUtils.MinMaxAveTracker; -import org.opensha.commons.util.io.archive.ArchiveOutput; -import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; -import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; -import org.opensha.sha.earthquake.faultSysSolution.hazard.mpj.MPJ_LogicTreeHazardCalc; -import org.opensha.sha.earthquake.faultSysSolution.hazard.mpj.MPJ_SingleSolHazardCalc; -import org.opensha.sha.earthquake.faultSysSolution.modules.FaultCubeAssociations; -import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList; -import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceProvider; -import org.opensha.sha.earthquake.faultSysSolution.modules.MFDGridSourceProvider; -import org.opensha.sha.earthquake.faultSysSolution.modules.SolutionLogicTree; -import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; -import org.opensha.sha.earthquake.faultSysSolution.util.SolLogicTreeSampler; -import org.opensha.sha.earthquake.param.IncludeBackgroundOption; -import org.opensha.sha.earthquake.rupForecastImpl.nshm23.gridded.NSHM23_SingleRegionGridSourceProvider; -import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.NSHM23_MaxMagOffFault; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.PRVI25_GridSourceBuilder; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_DeclusteringAlgorithms; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_LogicTree; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeisSmoothingAlgorithms; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionCaribbeanSeismicityRate; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionMuertosSeismicityRate; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader; -import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader.PRVI25_SeismicityRegions; -import org.opensha.sha.imr.AttenRelRef; -import org.opensha.sha.magdist.GutenbergRichterMagFreqDist; -import org.opensha.sha.magdist.IncrementalMagFreqDist; - -import com.google.common.base.Preconditions; -import com.google.common.base.Stopwatch; - -import edu.usc.kmilner.mpj.taskDispatch.MPJTaskCalculator; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; - -public class GriddedRateDistributionSolutionWriter { - - public static void main(String[] args) throws IOException { - File ratesDir = new File("/home/kevin/OpenSHA/nshm23/prvi/rate_raw_data"); - File invsDir = new File("/home/kevin/OpenSHA/nshm23/batch_inversions/"); - FaultSystemSolution baSol = FaultSystemSolution.load(new File(invsDir, -// "2025_01_17-prvi25_subduction_branches/results_PRVI_SUB_FM_LARGE_branch_averaged.zip")); - "2025_01_17-prvi25_crustal_subduction_combined_branches/combined_branch_averaged_solution.zip")); - FaultSystemSolution subLargeSol = FaultSystemSolution.load(new File(invsDir, - "2025_01_17-prvi25_subduction_branches/results_PRVI_SUB_FM_LARGE_branch_averaged.zip")); - FaultSystemSolution crustalBASol = FaultSystemSolution.load(new File(invsDir, - "2025_01_17-prvi25_crustal_branches-dmSample10x/results_PRVI_CRUSTAL_FM_V1p1_branch_averaged_gridded.zip")); - -// File fullRandOutDir = new File(invsDir, "2025_05_13-prvi_gridded_variability-full_random"); - File fullRandOutDir = null; -// File threeBranchOutDir = new File(invsDir, "2025_05_13-prvi_gridded_variability-three_branch"); -// File threeBranchOutDir = null; - boolean threeBranchCorrelateMueAndCar = true; - File threeBranchOutDir = new File(invsDir, "2025_05_13-prvi_gridded_variability-three_branch-corr_mue_car"); - - Preconditions.checkState(fullRandOutDir == null || fullRandOutDir.exists() || fullRandOutDir.mkdir()); - Preconditions.checkState(threeBranchOutDir == null || threeBranchOutDir.exists() || threeBranchOutDir.mkdir()); - - List crustalPairs = loadRates(new File(ratesDir, "rbpairs-Crustal-Full-v3.csv")); - List carInterfacePairs = loadRates(new File(ratesDir, "rbpairs-CAR Interface-Full-v3.csv")); - List mueInterfacePairs = loadRates(new File(ratesDir, "rbpairs-MUE Interface-Full-v3.csv")); - List carSlabPairs = loadRates(new File(ratesDir, "rbpairs-CAR Intraslab-Full-v3.csv")); - List mueSlabPairs = loadRates(new File(ratesDir, "rbpairs-MUE Intraslab-Full-v3.csv")); - int numSamplesPer = 100; - int numTotalSamples = numSamplesPer*3*2*3*3*2; // times declustering and smoothing branches - Preconditions.checkState(numTotalSamples <= crustalPairs.size(), "Have %s samples but want %s sampling nodes", - crustalPairs.size(), numTotalSamples); - System.out.println(numTotalSamples+" total samples"); -// System.exit(0); - Random rand = new Random(numTotalSamples); - - List origDeclusterNodes = new ArrayList<>(); - LogicTreeLevel origDeclusterLevel = PRVI25_LogicTree.SEIS_DECLUSTER; - List crustalDeclusterNodes = new ArrayList<>(); - List interfaceDeclusterNodes = new ArrayList<>(); - for (PRVI25_DeclusteringAlgorithms node : origDeclusterLevel.getNodes()) { - if (node.getNodeWeight(null) == 0d) - continue; - origDeclusterNodes.add(node); - crustalDeclusterNodes.add(new FileBackedNode("Crustal "+node.getName(), node.getShortName(), - node.getNodeWeight(null), "Crustal"+node.getFilePrefix())); - interfaceDeclusterNodes.add(new FileBackedNode("Interface "+node.getName(), node.getShortName(), - node.getNodeWeight(null), "Interface"+node.getFilePrefix())); - } - FileBackedLevel crustalDeclusterLevel = new FileBackedLevel("Crustal "+origDeclusterLevel.getName(), - "Crustal"+origDeclusterLevel.getShortName(), crustalDeclusterNodes); - crustalDeclusterLevel.setAffected(origDeclusterLevel.getAffected(), origDeclusterLevel.getNotAffected(), false); - FileBackedLevel interfaceDeclusterLevel = new FileBackedLevel("Interface "+origDeclusterLevel.getName(), - "Interface"+origDeclusterLevel.getShortName(), interfaceDeclusterNodes); - interfaceDeclusterLevel.setAffected(origDeclusterLevel.getAffected(), origDeclusterLevel.getNotAffected(), false); - - List origSmoothingNodes = new ArrayList<>(); - LogicTreeLevel origSmoothingLevel = PRVI25_LogicTree.SEIS_SMOOTH; - List crustalSmoothingNodes = new ArrayList<>(); - List interfaceSmoothingNodes = new ArrayList<>(); - for (PRVI25_SeisSmoothingAlgorithms node : origSmoothingLevel.getNodes()) { - if (node.getNodeWeight(null) == 0d) - continue; - origSmoothingNodes.add(node); - crustalSmoothingNodes.add(new FileBackedNode("Crustal "+node.getName(), node.getShortName(), - node.getNodeWeight(null), "Crustal"+node.getFilePrefix())); - interfaceSmoothingNodes.add(new FileBackedNode("Interface "+node.getName(), node.getShortName(), - node.getNodeWeight(null), "Interface"+node.getFilePrefix())); - } - FileBackedLevel crustalSmoothingLevel = new FileBackedLevel("Crustal "+origSmoothingLevel.getName(), - "Crustal"+origSmoothingLevel.getShortName(), crustalSmoothingNodes); - crustalSmoothingLevel.setAffected(origSmoothingLevel.getAffected(), origSmoothingLevel.getNotAffected(), false); - FileBackedLevel interfaceSmoothingLevel = new FileBackedLevel("Interface "+origSmoothingLevel.getName(), - "Interface"+origSmoothingLevel.getShortName(), interfaceSmoothingNodes); - interfaceSmoothingLevel.setAffected(origSmoothingLevel.getAffected(), origSmoothingLevel.getNotAffected(), false); - - List> fullRandLevels = new ArrayList<>(); - fullRandLevels.add(crustalDeclusterLevel); - fullRandLevels.add(crustalSmoothingLevel); - fullRandLevels.add(PRVI25_LogicTree.MMAX_OFF); - CrustalRateSamplingLevel crustalSampler = new CrustalRateSamplingLevel(crustalPairs); - crustalSampler.build(rand.nextLong(), numTotalSamples); - fullRandLevels.add(crustalSampler); - fullRandLevels.add(interfaceDeclusterLevel); - fullRandLevels.add(interfaceSmoothingLevel); - fullRandLevels.add(PRVI25_LogicTree.SUB_SCALE); - CarSlabRateSamplingLevel carSampler = new CarSlabRateSamplingLevel(carSlabPairs, carInterfacePairs); - carSampler.build(rand.nextLong(), numTotalSamples); - MueRateSamplingLevel mueSampler = new MueRateSamplingLevel(mueSlabPairs, mueInterfacePairs); - mueSampler.build(rand.nextLong(), numTotalSamples); - fullRandLevels.add(carSampler); - fullRandLevels.add(mueSampler); - List> threeBranchLevels = new ArrayList<>(); - threeBranchLevels.add(crustalDeclusterLevel); - threeBranchLevels.add(crustalSmoothingLevel); - threeBranchLevels.add(PRVI25_LogicTree.MMAX_OFF); - threeBranchLevels.add(PRVI25_LogicTree.CRUSTAL_SEIS_RATE); - threeBranchLevels.add(interfaceDeclusterLevel); - threeBranchLevels.add(interfaceSmoothingLevel); - threeBranchLevels.add(PRVI25_LogicTree.SUB_SCALE); - threeBranchLevels.add(PRVI25_LogicTree.CAR_SEIS_RATE); - threeBranchLevels.add(PRVI25_LogicTree.MUE_SEIS_RATE); - - Region reg = PRVI25_RegionLoader.loadPRVI_Tight(); - GriddedRegion gridReg = new GriddedRegion(reg, 0.05, GriddedRegion.ANCHOR_0_0); - System.out.println("Region has "+gridReg.getNodeCount()+" nodes"); - SolutionLogicTree.FileBuilder threeBranchBuilder = null; - if (threeBranchOutDir != null) { - baSol.write(new File(threeBranchOutDir, "full_branch_averaged.zip")); - writeHazardScripts(threeBranchOutDir, gridReg); - threeBranchBuilder = new SolutionLogicTree.FileBuilder( -// new ArchiveOutput.AsynchronousZipFileOutput(new File(threeBranchOutDir, "results.zip"))); - new ArchiveOutput.ParallelZipFileOutput(new File(threeBranchOutDir, "results.zip"), 20)); - threeBranchBuilder.setSerializeGridded(true); - } - SolutionLogicTree.FileBuilder fullRandBuilder = null; - if (fullRandOutDir != null) { - baSol.write(new File(fullRandOutDir, "full_branch_averaged.zip")); - writeHazardScripts(fullRandOutDir, gridReg); - fullRandBuilder = new SolutionLogicTree.FileBuilder( -// new ArchiveOutput.AsynchronousZipFileOutput(new File(fullRandOutDir, "results.zip"))); - new ArchiveOutput.ParallelZipFileOutput(new File(fullRandOutDir, "results.zip"), 20)); - fullRandBuilder.setSerializeGridded(true); - } - - List crustalSamples = crustalSampler.getNodes(); - List carSamples = carSampler.getNodes(); - List mueSamples = mueSampler.getNodes(); - - IncrementalMagFreqDist refMFD = FaultSysTools.initEmptyMFD(PRVI25_GridSourceBuilder.OVERALL_MMIN, 8.6); - - baSol.setVerbose(false); - DecimalFormat pDF = new DecimalFormat("0.0%"); - - PRVI25_SubductionScalingRelationships scale = PRVI25_SubductionScalingRelationships.LOGA_C4p0; - List> levelsForInterface = new ArrayList<>(); - levelsForInterface.add(PRVI25_LogicTree.SUB_SCALE); - levelsForInterface.addAll(PRVI25_LogicTree.levelsSubductionGridded); - - double slabMmax = 7.95; // TODO: use branches - - int sampleIndex = 0; - int threeBranchWriteCount = 0; - int sampleWriteCount = 0; - for (int i1=0; i1> futures = new ArrayList<>(); - for (PRVI25_CrustalSeismicityRate crustalRate : PRVI25_CrustalSeismicityRate.values()) { - if (crustalRate.getNodeWeight(null) == 0d) - continue; - for (PRVI25_SubductionCaribbeanSeismicityRate carRate : PRVI25_SubductionCaribbeanSeismicityRate.values()) { - if (carRate.getNodeWeight(null) == 0d) - continue; - for (PRVI25_SubductionMuertosSeismicityRate mueRate : PRVI25_SubductionMuertosSeismicityRate.values()) { - if (mueRate.getNodeWeight(null) == 0d) - continue; - - if (threeBranchCorrelateMueAndCar && !carRate.getShortName().equals(mueRate.getShortName())) - continue; - - LogicTreeBranch branch = new LogicTreeBranch<>(threeBranchLevels); - branch.setValue(crustalDeclusterNode); - branch.setValue(crustalSmoothingNode); - branch.setValue(mmaxOff); - branch.setValue(crustalRate); - branch.setValue(interfaceDeclusterNode); - branch.setValue(interfaceSmoothingNode); - branch.setValue(carRate); - branch.setValue(mueRate); - branch.setValue(scale); - - if (threeBranchCorrelateMueAndCar) { - // need to correct the weight to remove the influence of the muertos - // rate branch - double curWeight = branch.getBranchWeight(); - // remove meurtos - curWeight /= mueRate.getNodeWeight(branch); - branch.setOrigBranchWeight(curWeight); - } - - LogicTreeBranch branchForCrustal = new LogicTreeBranch<>(PRVI25_LogicTree.levelsCrustalOffFault); - branchForCrustal.setValue(crustalOrigDeclusterNode); - branchForCrustal.setValue(crustalOrigSmoothingNode); - branchForCrustal.setValue(crustalRate); - branchForCrustal.setValue(mmaxOff); - - LogicTreeBranch branchForInterface = new LogicTreeBranch<>(levelsForInterface); - branchForInterface.setValue(interfaceOrigDeclusterNode); - branchForInterface.setValue(interfaceOrigSmoothingNode); - branchForInterface.setValue(mueRate); - branchForInterface.setValue(carRate); - branchForInterface.setValue(scale); - - futures.add(CompletableFuture.supplyAsync(new Supplier() { - - @Override - public GridResult get() { - try { - GridSourceList crustal = PRVI25_GridSourceBuilder.buildCrustalGridSourceProv(crustalBASol, branchForCrustal); - GridSourceList sub = PRVI25_GridSourceBuilder.buildCombinedSubductionGridSourceList(subLargeSol, branchForInterface); - GridSourceList comb = GridSourceList.combine(crustal, sub); - return new GridResult(comb, branch); - } catch (IOException e) { - e.printStackTrace(); - System.exit(1); - return null; - } - } - })); - } - } - } - - for (CompletableFuture future : futures) { - GridResult result = future.join(); - baSol.setGridSourceProvider(result.gridList); - threeBranchBuilder.solution(baSol, result.branch); - System.out.println("Writing 3-branch "+(threeBranchWriteCount++)); - } - } - - if (fullRandBuilder != null) { - System.out.println("Building "+numSamplesPer+" for "+crustalOrigDeclusterNode+", "+crustalOrigSmoothingNode - +", "+interfaceOrigDeclusterNode+", "+interfaceOrigSmoothingNode); - -// CompletableFuture prevFuture = null; - - Stopwatch totalWatch = Stopwatch.createStarted(); - Stopwatch ioWatch = Stopwatch.createUnstarted(); - List> futures = new ArrayList<>(); - for (int s=0; s branch = new LogicTreeBranch<>(fullRandLevels); - branch.setValue(crustalDeclusterNode); - branch.setValue(crustalSmoothingNode); - branch.setValue(crustalSample); - branch.setValue(mmaxOff); - branch.setValue(interfaceDeclusterNode); - branch.setValue(interfaceSmoothingNode); - branch.setValue(carSample); - branch.setValue(mueSample); - branch.setValue(scale); - - LogicTreeBranch branchForCrustal = new LogicTreeBranch<>(PRVI25_LogicTree.levelsCrustalOffFault); - branchForCrustal.setValue(crustalOrigDeclusterNode); - branchForCrustal.setValue(crustalOrigSmoothingNode); - branchForCrustal.setValue(mmaxOff); - - LogicTreeBranch branchForInterface = new LogicTreeBranch<>(levelsForInterface); - branchForInterface.setValue(interfaceOrigDeclusterNode); - branchForInterface.setValue(interfaceOrigSmoothingNode); - branchForInterface.setValue(scale); - - futures.add(CompletableFuture.supplyAsync(new Supplier() { - - @Override - public GridResult get() { - try { - GutenbergRichterMagFreqDist carSlabGR = buildGR(carSample.slabRate, carSample.slabB, - slabMmax, 5d, refMFD); - GutenbergRichterMagFreqDist mueSlabGR = buildGR(mueSample.slabRate, mueSample.slabB, - slabMmax, 5d, refMFD); - - GridSourceList carSlabList = PRVI25_GridSourceBuilder.buildSlabGridSourceList( - branchForInterface, PRVI25_SeismicityRegions.CAR_INTRASLAB, carSlabGR); - GridSourceList mueSlabList = PRVI25_GridSourceBuilder.buildSlabGridSourceList( - branchForInterface, PRVI25_SeismicityRegions.MUE_INTRASLAB, mueSlabGR); - - GridSourceList combSlabList = GridSourceList.combine(carSlabList, mueSlabList); - - Function carMFDBuilderFunc = new Function() { - - @Override - public IncrementalMagFreqDist apply(Double mmax) { - return buildGR(carSample.interfaceRate, carSample.interfaceB, - mmax, 5d, refMFD); - } - }; - Function mueMFDBuilderFunc = new Function() { - - @Override - public IncrementalMagFreqDist apply(Double mmax) { - return buildGR(mueSample.interfaceRate, mueSample.interfaceB, - mmax, 5d, refMFD); - } - }; - - GridSourceList carInterfaceList = PRVI25_GridSourceBuilder.buildInterfaceGridSourceList( - subLargeSol, branchForInterface, PRVI25_SeismicityRegions.CAR_INTERFACE, - scale.getMagAreaRelationship(), carMFDBuilderFunc); - GridSourceList mueInterfaceList = PRVI25_GridSourceBuilder.buildInterfaceGridSourceList( - subLargeSol, branchForInterface, PRVI25_SeismicityRegions.MUE_INTERFACE, - scale.getMagAreaRelationship(), mueMFDBuilderFunc); - - GridSourceList combInterfaceList = GridSourceList.combine(carInterfaceList, mueInterfaceList); - - GridSourceList combSubList = GridSourceList.combine(combSlabList, combInterfaceList); - - GutenbergRichterMagFreqDist crustalGR = buildGR(crustalSample.rate, crustalSample.b, - mmaxOff.getMaxMagOffFault(), 5d, refMFD); - NSHM23_SingleRegionGridSourceProvider crustalMFD = PRVI25_GridSourceBuilder.buildCrustalGridSourceProv( - crustalBASol, branchForCrustal, crustalBASol.getRupSet().requireModule(FaultCubeAssociations.class), crustalGR); - GridSourceList crustalList = crustalMFD.convertToGridSourceList(5d); - - GridSourceList combList = GridSourceList.combine(crustalList, combSubList); - return new GridResult(combList, branch); - } catch (IllegalStateException | IOException e) { - e.printStackTrace(); - System.exit(1); - return null; - } - } - })); - -// if (prevFuture != null) { -// ioWatch.start(); -// prevFuture.join(); -// ioWatch.stop(); -// } -// -// prevFuture = CompletableFuture.runAsync(new Runnable() { -// -// @Override -// public void run() { -// baSol.setGridSourceProvider(combList); -// try { -// fullRandBuilder.solution(baSol, branch); -// } catch (IOException e) { -// e.printStackTrace(); -// System.exit(1); -// } -// } -// }); - } -// prevFuture.join(); - - for (CompletableFuture future : futures) { - GridResult result = future.join(); - baSol.setGridSourceProvider(result.gridList); - fullRandBuilder.solution(baSol, result.branch); - System.out.println("Writing sampled "+(sampleWriteCount++)); - } - - totalWatch.stop(); - } - } - } - } - } - } - - if (fullRandBuilder != null) - fullRandBuilder.close(); - if (threeBranchBuilder != null) { - if (threeBranchCorrelateMueAndCar) - threeBranchBuilder.setWeightProv(new BranchWeightProvider.OriginalWeights()); - threeBranchBuilder.close(); - } - Preconditions.checkState(fullRandBuilder == null || sampleIndex == numTotalSamples, - "Only used %s samples but expected %s", sampleIndex, numTotalSamples); - } - - private static class GridResult { - public final GridSourceList gridList; - public final LogicTreeBranch branch; - - private GridResult(GridSourceList gridList, LogicTreeBranch branch) { - super(); - this.gridList = gridList; - this.branch = branch; - } - } - - private static GutenbergRichterMagFreqDist buildGR(double rateAboveM1, double b, double mMax, double m1, IncrementalMagFreqDist refMFD) { - GutenbergRichterMagFreqDist gr = new GutenbergRichterMagFreqDist(refMFD.getMinX(), refMFD.size(), refMFD.getDelta()); - // this sets shape, min/max - // subtract a tiny amount from mMax so that if it's exactly at a bin edge, e.g. 7.9, it rounds down, e.g. to 7.85 - gr.setAllButTotCumRate(refMFD.getX(0), refMFD.getX(refMFD.getClosestXIndex(mMax-0.001)), 1e16, b); - // this scales it to match - // similarly, add a tiny amount to M1 so that if it's exactly at a bin edge (which it should be as it's determined - // using cumulative binning), it rounds up to the incremental bin for that cumulative edge - gr.scaleToCumRate(refMFD.getClosestXIndex(m1+0.001), rateAboveM1); - return gr; - } - - public static List loadRates(File csvFile) throws IOException { - CSVFile csv = CSVFile.readFile(csvFile, false); - - boolean reading = false; - List ret = new ArrayList<>(); - - MinMaxAveTracker rateTrack = new MinMaxAveTracker(); - MinMaxAveTracker bTrack = new MinMaxAveTracker(); - for (int row=0; row { - - private List samples; - private List randomizedSamples; - - private CrustalRateSamplingLevel() {} - - public CrustalRateSamplingLevel(List samples) { - super("Crustal Rate/b Distribution Sampling", "Crustal-Sampling", - "Crustal Sample ", "Crustal-Sample", "crustal_sample_"); - this.samples = samples; - } - - @Override - public CrustalSamplingNode buildNodeInstance(int index, long seed, double weight) { - if (randomizedSamples == null) { - randomizedSamples = new ArrayList<>(samples); - Collections.shuffle(randomizedSamples, new Random(seed)); - } - double[] sample = randomizedSamples.get(index); - return new CrustalSamplingNode(getNodeName(index), getNodeShortName(index), getNodeFilePrefix(index), weight, seed, - sample[0], sample[1]); - } - - @Override - public Class getType() { - return CrustalSamplingNode.class; - } - - } - - @DoesNotAffect(FaultSystemRupSet.SECTS_FILE_NAME) - @DoesNotAffect(FaultSystemRupSet.RUP_SECTS_FILE_NAME) - @DoesNotAffect(FaultSystemRupSet.RUP_PROPS_FILE_NAME) - @DoesNotAffect(FaultSystemSolution.RATES_FILE_NAME) - @DoesNotAffect(GridSourceProvider.ARCHIVE_GRID_REGION_FILE_NAME) - @DoesNotAffect(MFDGridSourceProvider.ARCHIVE_MECH_WEIGHT_FILE_NAME) - @DoesNotAffect(GridSourceList.ARCHIVE_GRID_LOCS_FILE_NAME) - @Affects(MFDGridSourceProvider.ARCHIVE_SUB_SEIS_FILE_NAME) - @Affects(MFDGridSourceProvider.ARCHIVE_UNASSOCIATED_FILE_NAME) - @Affects(GridSourceList.ARCHIVE_GRID_SOURCES_FILE_NAME) - private static class CarSlabSamplingNode extends RandomlyGeneratedNode { - private double slabRate; - private double slabB; - private double interfaceRate; - private double interfaceB; - - - private CarSlabSamplingNode() { - super(); - } - - private CarSlabSamplingNode(String name, String shortName, String prefix, double weight, long seed, - double slabRate, double slabB, double interfaceRate, double interfaceB) { - super(name, shortName, prefix, weight, seed); - this.slabRate = slabRate; - this.slabB = slabB; - this.interfaceRate = interfaceRate; - this.interfaceB = interfaceB; - } - - } - - private static class CarSlabRateSamplingLevel extends LogicTreeLevel.RandomlyGeneratedLevel { - - private List slabSamples; - private List interfaceSamples; - private List randomizedIndexes; - - private CarSlabRateSamplingLevel() { - super(); - } - - public CarSlabRateSamplingLevel(List slabSamples, List interfaceSamples) { - super("CAR Rate/b Distribution Sampling", "CAR-Sampling", - "CAR Sample ", "CAR-Sample", "car_sample_"); - TotalRateComparator comp = new TotalRateComparator(8d); - Collections.sort(slabSamples, comp); - Collections.sort(interfaceSamples, comp); - this.slabSamples = slabSamples; - this.interfaceSamples = interfaceSamples; - } - - @Override - public CarSlabSamplingNode buildNodeInstance(int index, long seed, double weight) { - if (randomizedIndexes == null) { - randomizedIndexes = new ArrayList<>(slabSamples.size()); - for (int i=0; i getType() { - return CarSlabSamplingNode.class; - } - - } - - @DoesNotAffect(FaultSystemRupSet.SECTS_FILE_NAME) - @DoesNotAffect(FaultSystemRupSet.RUP_SECTS_FILE_NAME) - @DoesNotAffect(FaultSystemRupSet.RUP_PROPS_FILE_NAME) - @DoesNotAffect(FaultSystemSolution.RATES_FILE_NAME) - @DoesNotAffect(GridSourceProvider.ARCHIVE_GRID_REGION_FILE_NAME) - @DoesNotAffect(MFDGridSourceProvider.ARCHIVE_MECH_WEIGHT_FILE_NAME) - @DoesNotAffect(GridSourceList.ARCHIVE_GRID_LOCS_FILE_NAME) - @Affects(MFDGridSourceProvider.ARCHIVE_SUB_SEIS_FILE_NAME) - @Affects(MFDGridSourceProvider.ARCHIVE_UNASSOCIATED_FILE_NAME) - @Affects(GridSourceList.ARCHIVE_GRID_SOURCES_FILE_NAME) - private static class MueSamplingNode extends RandomlyGeneratedNode { - - private double slabRate; - private double slabB; - private double interfaceRate; - private double interfaceB; - - private MueSamplingNode() { - - } - - private MueSamplingNode(String name, String shortName, String prefix, double weight, long seed, - double slabRate, double slabB, double interfaceRate, double interfaceB) { - super(name, shortName, prefix, weight, seed); - this.slabRate = slabRate; - this.slabB = slabB; - this.interfaceRate = interfaceRate; - this.interfaceB = interfaceB; - } - - } - - private static class MueRateSamplingLevel extends LogicTreeLevel.RandomlyGeneratedLevel { - - private List slabSamples; - private List interfaceSamples; - private List randomizedIndexes; - - private MueRateSamplingLevel() {} - - public MueRateSamplingLevel(List slabSamples, List interfaceSamples) { - super("MUE Rate/b Distribution Sampling", "MUE-Sampling", - "MUE Sample ", "MUE-Sample", "mue_sample_"); - TotalRateComparator comp = new TotalRateComparator(8d); - Collections.sort(slabSamples, comp); - Collections.sort(interfaceSamples, comp); - this.slabSamples = slabSamples; - this.interfaceSamples = interfaceSamples; - } - - @Override - public MueSamplingNode buildNodeInstance(int index, long seed, double weight) { - if (randomizedIndexes == null) { - randomizedIndexes = new ArrayList<>(slabSamples.size()); - for (int i=0; i getType() { - return MueSamplingNode.class; - } - - } - - private static class TotalRateComparator implements Comparator { - - private double mmax; - - public TotalRateComparator(double mmax) { - this.mmax = mmax; - } - - @Override - public int compare(double[] o1, double[] o2) { - GutenbergRichterMagFreqDist mfd1 = new GutenbergRichterMagFreqDist(5d, mmax, 10); - mfd1.setAllButTotMoRate(mfd1.getMinX(), mfd1.getMaxX(), o1[0], o1[1]); - GutenbergRichterMagFreqDist mfd2 = new GutenbergRichterMagFreqDist(5d, mmax, 10); - mfd2.setAllButTotMoRate(mfd2.getMinX(), mfd2.getMaxX(), o2[0], o2[1]); - return Double.compare(mfd1.calcSumOfY_Vals(), mfd2.calcSumOfY_Vals()); - } - - } - - private static void writeHazardScripts(File outputDir, GriddedRegion gridReg) throws IOException { - String dirName = outputDir.getName(); - File localDir = outputDir; - - File remoteMainDir = new File("/project2/scec_608/kmilner/fss_inversions"); - int remoteTotalThreads = 20; - int remoteTotalMemGB = 50; - String queue = "scec"; - int nodes = 36; -// JavaShellScriptWriter mpjWrite = new MPJExpressShellScriptWriter( -// USC_CARC_ScriptWriter.JAVA_BIN, remoteTotalMemGB*1024, null, USC_CARC_ScriptWriter.MPJ_HOME); - JavaShellScriptWriter mpjWrite = new FastMPJShellScriptWriter( - USC_CARC_ScriptWriter.JAVA_BIN, remoteTotalMemGB*1024, null, USC_CARC_ScriptWriter.FMPJ_HOME); -// JavaShellScriptWriter mpjWrite = new NoMPJSingleNodeShellScriptWriter(USC_CARC_ScriptWriter.JAVA_BIN, -// remoteTotalMemGB*1024, null); nodes = 1; remoteInversionsPerBundle = 2; - BatchScriptWriter pbsWrite = new USC_CARC_ScriptWriter(); - - mpjWrite.setEnvVar("MAIN_DIR", remoteMainDir.getAbsolutePath()); - String mainDirPath = "$MAIN_DIR"; - mpjWrite.setEnvVar("DIR", mainDirPath+"/"+dirName); - String dirPath = "$DIR"; - - List classpath = new ArrayList<>(); - classpath.add(new File(dirPath+"/opensha-dev-all.jar")); - if (mpjWrite instanceof NoMPJSingleNodeShellScriptWriter) - classpath.add(new File("/project2/scec_608/kmilner/git/opensha/lib/mpj-0.38.jar")); - - mpjWrite.setClasspath(classpath); - if (mpjWrite instanceof MPJExpressShellScriptWriter) - ((MPJExpressShellScriptWriter)mpjWrite).setUseLaunchWrapper(true); - else if (mpjWrite instanceof FastMPJShellScriptWriter) - ((FastMPJShellScriptWriter)mpjWrite).setUseLaunchWrapper(true); - - File gridRegFile = new File(outputDir, "gridded_region.geojson"); - Feature.write(gridReg.toFeature(), gridRegFile); - - Double sigmaTrunc = 3d; - - for (IncludeBackgroundOption bgOp : IncludeBackgroundOption.values()) { - String mapScriptName = "batch_hazard_"+bgOp.name()+".slurm"; - String argz = "--input-file "+dirPath+"/results.zip"; - argz += " --output-dir "+dirPath+"/results"; - argz += " --output-file "+dirPath+"/results_hazard_"+bgOp.name()+".zip"; - argz += " --gridded-seis "+bgOp.name(); - if (bgOp != IncludeBackgroundOption.ONLY) - argz += " --external-fss "+dirPath+"/full_branch_averaged.zip"; - argz += " --quick-grid-calc"; - argz += " --region "+dirPath+"/"+gridRegFile.getName(); - argz += " --gmpe "+AttenRelRef.USGS_PRVI_ACTIVE.name(); - argz += " --gmpe "+AttenRelRef.USGS_PRVI_INTERFACE.name(); - argz += " --gmpe "+AttenRelRef.USGS_PRVI_SLAB.name(); - if (sigmaTrunc != null) - argz += " --gmm-sigma-trunc-one-sided "+sigmaTrunc.floatValue(); - argz += " "+MPJTaskCalculator.argumentBuilder().minDispatch(1).maxDispatch(100).threads(remoteTotalThreads).build(); - List script = mpjWrite.buildScript(MPJ_LogicTreeHazardCalc.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, mapScriptName), script, 1440, nodes, remoteTotalThreads, queue); - } - } - -} diff --git a/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java b/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java index 0d9a8899..a351236f 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java +++ b/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java @@ -46,7 +46,6 @@ import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateRecord; import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import net.mahdilamb.colormap.Colors; -import scratch.kevin.prvi25.GriddedRateDistributionSolutionWriter; import static scratch.kevin.prvi25.figures.PRVI_Paths.*; @@ -280,7 +279,7 @@ public static void main(String[] args) throws IOException { PlotUtils.writePlots(outputDir, prefix, gp, 700, 650, true, true, false); if (ref && refRatePairsFile != null && !incremental) { - List ratePairs = GriddedRateDistributionSolutionWriter.loadRates(refRatePairsFile); + List ratePairs = loadRates(refRatePairsFile); Collections.shuffle(ratePairs, new Random(ratePairs.size())); // int c = 200; @@ -428,6 +427,31 @@ public static void main(String[] args) throws IOException { } } + public static List loadRates(File csvFile) throws IOException { + CSVFile csv = CSVFile.readFile(csvFile, false); + + boolean reading = false; + List ret = new ArrayList<>(); + + MinMaxAveTracker rateTrack = new MinMaxAveTracker(); + MinMaxAveTracker bTrack = new MinMaxAveTracker(); + for (int row=0; row Date: Fri, 20 Mar 2026 17:29:16 -0700 Subject: [PATCH 08/71] for upstream --- .../GriddedBranchMomentRatesFileWriter.java | 2 +- .../HardcodedInversionFactoryRunner.java | 61 +++++++--- ...gleSiteHazardAndDataComparisonPageGen.java | 6 +- .../ValidationEventsScalingWriter.java | 106 ++++++++++++++++++ .../nshm26/DownDipRupSetBuildingTests.java | 5 +- .../InterfaceSubSeisMoReductionTests.java | 5 +- 6 files changed, 162 insertions(+), 23 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm23/bbpScaling/ValidationEventsScalingWriter.java diff --git a/src/main/java/scratch/kevin/nshm23/GriddedBranchMomentRatesFileWriter.java b/src/main/java/scratch/kevin/nshm23/GriddedBranchMomentRatesFileWriter.java index d69d9dbe..d681b13a 100644 --- a/src/main/java/scratch/kevin/nshm23/GriddedBranchMomentRatesFileWriter.java +++ b/src/main/java/scratch/kevin/nshm23/GriddedBranchMomentRatesFileWriter.java @@ -24,7 +24,7 @@ public static void main(String[] args) throws IOException { for (LogicTreeBranch branch : slt.getLogicTree()) { System.out.println("Branch: "+branch); GridSourceProvider gridProv = slt.loadGridProvForBranch(branch); - GriddedGeoDataSet xyz = NucleationRatePlot.calcGriddedNucleationMomentRates(gridProv); + GriddedGeoDataSet xyz = NucleationRatePlot.calcGriddedNucleationMomentRates(gridProv, null); GriddedGeoDataSet.writeXYZFile(xyz, new File(outputDir, branch.buildFileName()+".xyz")); } } diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index 798a6cf0..760ded5d 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -27,6 +27,8 @@ import org.opensha.sha.earthquake.faultSysSolution.inversion.constraints.impl.SlipRateInversionConstraint; import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceProvider; import org.opensha.sha.earthquake.faultSysSolution.modules.InversionTargetMFDs; +import org.opensha.sha.earthquake.faultSysSolution.reports.ReportPageGen; +import org.opensha.sha.earthquake.faultSysSolution.reports.ReportPageGen.PlotLevel; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.NSHM23_InvConfigFactory; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.data.NSHM23_PaleoDataLoader; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.data.NSHM23_WasatchSegmentationData; @@ -48,7 +50,11 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_FaultModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_LogicTreeBranch; import org.opensha.sha.earthquake.rupForecastImpl.nshm26.NSHM26_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceMinSubSects; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceObsSeisDMAdjustment; import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_SeisRateModelBranch; import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.PRVI25_InvConfigFactory; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalDeformationModels; @@ -78,6 +84,8 @@ public static void main(String[] args) throws IOException { int threads = 16; boolean writeGridProv = false; + + PlotLevel plotLevel = null; String dirName = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); @@ -174,12 +182,22 @@ public static void main(String[] args) throws IOException { // branch.setValue(node); // writeGridProv = true; -// LogicTreeBranch branch = NSHM26_LogicTree.DEFAULT_GNMI_SUBDUCTION_INTERFACE; - LogicTreeBranch branch = NSHM26_LogicTree.buildDefault(NSHM26_SeismicityRegions.GNMI, TectonicRegionType.ACTIVE_SHALLOW, false); - dirName += "-gnmi"; // LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( -// NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); -// dirName += "-amsam"; +// NSHM26_SeismicityRegions.GNMI, TectonicRegionType.SUBDUCTION_INTERFACE, false); +//// LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( +//// NSHM26_SeismicityRegions.GNMI, TectonicRegionType.ACTIVE_SHALLOW, false); +// dirName += "-gnmi"; + LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( + NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); + dirName += "-amsam"; + +// branch.setValue(NSHM26_InterfaceObsSeisDMAdjustment.AVERAGE); + branch.setValue(NSHM26_InterfaceObsSeisDMAdjustment.SECTION_SPECIFIC); + branch.setValue(NSHM26_InterfaceMinSubSects.ONE); + branch.setValue(NSHM26_SeisRateModelBranch.HIGH); + branch.setValue(NSHM26_InterfaceDeformationModels.LOW_COUPLING); + + plotLevel = PlotLevel.REVIEW; // branch.setValue(PRVI25_SubductionBValues.B_1p0); @@ -382,16 +400,22 @@ public static void main(String[] args) throws IOException { System.out.println("Will save results in: "+outputDir.getAbsolutePath()); FaultSystemSolution solution; - if (writeRS) { - FaultSystemRupSet rupSet = factory.buildRuptureSet(branch, threads); - - Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); - - rupSet.write(new File(outputDir, "rupSet.zip")); - - solution = Inversions.run(rupSet, factory, branch, threads, null); - } else { - solution = Inversions.run(factory, branch, threads); + try { + if (writeRS) { + FaultSystemRupSet rupSet = factory.buildRuptureSet(branch, threads); + + Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); + + rupSet.write(new File(outputDir, "rupSet.zip")); + + solution = Inversions.run(rupSet, factory, branch, threads, null); + } else { + solution = Inversions.run(factory, branch, threads); + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + throw new IllegalStateException(); } Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); @@ -406,6 +430,13 @@ public static void main(String[] args) throws IOException { solution.write(new File(outputDir, "solution.zip")); + if (plotLevel != null) { + ReportPageGen reportGen = new ReportPageGen(solution.getRupSet(), solution, "Solution", + new File(outputDir, "report"), ReportPageGen.getDefaultSolutionPlots(plotLevel)); + reportGen.setReplot(true); + reportGen.generatePage(); + } + // System.out.println("Currently loaded modules:"); // IncrementalMagFreqDist target1 = null; // for (OpenSHA_Module module : solution.getRupSet().getModules(false)) { diff --git a/src/main/java/scratch/kevin/nshm23/SingleSiteHazardAndDataComparisonPageGen.java b/src/main/java/scratch/kevin/nshm23/SingleSiteHazardAndDataComparisonPageGen.java index 584759dd..a4b563b3 100644 --- a/src/main/java/scratch/kevin/nshm23/SingleSiteHazardAndDataComparisonPageGen.java +++ b/src/main/java/scratch/kevin/nshm23/SingleSiteHazardAndDataComparisonPageGen.java @@ -1066,7 +1066,7 @@ public static RegionalParticipationResult calcFSSFaultPartic(FaultSystemSolution double[] magThresholds, EvenlyDiscretizedFunc refMFD) { FaultSystemRupSet rupSet = sol.getRupSet(); FaultGridAssociations assoc = FaultGridAssociations.getIntersectionAssociations(rupSet, gridReg); - List sectNuclMFDs = NucleationRatePlot.calcNuclMFDs(sol); + List sectNuclMFDs = NucleationRatePlot.calcNuclMFDs(sol, null); GriddedGeoDataSet[] faultParticRates = new GriddedGeoDataSet[magThresholds.length]; for (int m=0; m names = new ArrayList<>(); + List mags = new ArrayList<>(); + List lengths = new ArrayList<>(); + List widths = new ArrayList<>(); + + names.add("ch_v14_2_2"); + mags.add(5.4); + lengths.add(6.3); + widths.add(4.6); + + names.add("m5_5_rv_socal"); + mags.add(5.5); + lengths.add(5.62); + widths.add(5.62); + + names.add("m6_2_ss_socal"); + mags.add(6.2); + lengths.add(17.8); + widths.add(8.9); + + names.add("m6_6_rv_socal"); + mags.add(6.6); + lengths.add(28.2); + widths.add(14.1); + + names.add("m6_6_ss_socal"); + mags.add(6.6); + lengths.add(28.2); + widths.add(14.1); + + names.add("nr_v14_02_1"); + mags.add(6.7); + lengths.add(20d); + widths.add(27d); + + CSVFile csv = new CSVFile<>(true); + + List header = new ArrayList<>(); + header.add("Event"); + header.add("Original Magnitude"); + header.add("Original Length"); + header.add("Original DDW"); + for (NSHM23_ScalingRelationships scale : scales) { + header.add(scale.getShortName()+" Magnitude"); + header.add(scale.getShortName()+" DDW for Original Magnitude"); + } + csv.addLine(header); + + for (int i=0; i line = new ArrayList<>(header.size()); + double mag = mags.get(i); + double length = lengths.get(i); + double width = widths.get(i); + line.add(names.get(i)); + line.add((float)mag+""); + line.add((float)length+""); + line.add((float)width+""); + + for (NSHM23_ScalingRelationships scale : scales) { + double scaledMag = scale.getMag(length*width*1e6, length*1e3, width*1e3, width*1e3, Double.NaN); + line.add((float)scaledMag+""); + double scaledWidth = width; + double testMag = scaledMag; + int iter = 0; + while (!Precision.equals(testMag, mag, 0.001)) { + double deltaMag = mag - testMag; + // width in km and mag aren't too far away in units + scaledWidth += 0.1*deltaMag; + testMag = scale.getMag(length*scaledWidth*1e6, length*1e3, scaledWidth*1e3, scaledWidth*1e3, Double.NaN); +// System.out.println("iter "+iter+" testMag="+testMag+", scaledWidth="+scaledWidth+", origScaleMag="+scaledMag+", origMag="+mag+", origWidth="+width); + iter++; +// if (iter > 50) +// System.exit(0); + } + line.add((float)scaledWidth+""); + } + csv.addLine(line); + } + csv.writeToFile(new File("/tmp/bbp_validation_events_nshm23_scaling.csv")); + } + +} diff --git a/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java b/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java index d58f6f56..19a63aec 100644 --- a/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java +++ b/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java @@ -51,7 +51,8 @@ public static void main(String[] args) throws IOException { NSHM26_InterfaceFaultModels fm = NSHM26_InterfaceFaultModels.GNMI_V1; String prefix = "izu_slab2"; - Range minSupraRange = Range.closed(10d, 40d); + Range minSupraRange = Range.closed(20d, 40d); + double maxSubSeisAspectRatio = 4d; File inDir = new File(baseOutputDir, prefix); List sects = fm.buildSubSects(fm); @@ -112,7 +113,7 @@ public static void main(String[] args) throws IOException { Color participatingColor = overlapCPT.getMaxColor(); Color otherColor = overlapCPT.getMinColor(); - RectangularDownDipGrowingStrategy growingStrat = new RectangularDownDipGrowingStrategy(minSupraRange); + RectangularDownDipGrowingStrategy growingStrat = new RectangularDownDipGrowingStrategy(minSupraRange, maxSubSeisAspectRatio); RupSetScalingRelationship scale = PRVI25_SubductionScalingRelationships.LOGA_C4p0; HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); diff --git a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java index 8aa26c53..f3b81b0e 100644 --- a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java +++ b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java @@ -42,12 +42,13 @@ public class InterfaceSubSeisMoReductionTests { public static void main(String[] args) throws IOException { LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( - NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); +// NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); + NSHM26_SeismicityRegions.GNMI, TectonicRegionType.SUBDUCTION_INTERFACE, false); NSHM26_InterfaceFaultModels fm = branch.requireValue(NSHM26_InterfaceFaultModels.class); NSHM26_InterfaceDeformationModels dm = branch.requireValue(NSHM26_InterfaceDeformationModels.class); NSHM26_SeismicityRegions reg = fm.getSeisReg(); - File pdfBaseDir = new File("/home/kevin/OpenSHA/nshm26/spatial_seis_pdfs/"+reg.name().toLowerCase()+"/2026_03_09-v1_2D/INTERFACE"); + File pdfBaseDir = new File("/home/kevin/OpenSHA/nshm26/data/spatial_seis_pdfs/"+reg.name().toLowerCase()+"/2026_03_09-v1_2D/INTERFACE"); System.out.println("Branch: "+branch+"; reg="+reg); From 882ef51ab6aea3fb48811075c7522a3ddaa94219 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 23 Mar 2026 10:17:49 -0700 Subject: [PATCH 09/71] now uses MergedSolutionCreator --- ..._LogicTreeInversionRunnerScriptWriter.java | 804 ++++++++++-------- .../UpdatedRandTreeSerialzationTests.java | 4 +- .../kevin/prvi25/BowinFaultAddTest.java | 11 +- .../CrustalSubductionTrueMeanCreator.java | 11 +- 4 files changed, 443 insertions(+), 387 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index f0165405..734fe20a 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -83,6 +83,9 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_FaultModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_LogicTreeBranch; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.NSHM26_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_LogicTree; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader; @@ -92,6 +95,7 @@ import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalRandomlySampledDeformationModelLevel; import org.opensha.sha.util.NEHRP_TestCity; +import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -168,6 +172,7 @@ public static void main(String[] args) throws IOException { List> individualRandomLevels = new ArrayList<>(); int samplingBranchCountMultiplier = 1; + LogicTree customTree = null; String dirName = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); // String dirName = "2024_12_12"; @@ -262,363 +267,363 @@ public static void main(String[] args) throws IOException { * NSHM23 logic tree * TODO (this is a just a marker to find this part quickly, not an actual todo) */ -// List> levels = NSHM23_U3_HybridLogicTreeBranch.levels; -// dirName += "-nshm23_u3_hybrid_branches"; -// double avgNumRups = 325000; - - List> levels = NSHM23_LogicTreeBranch.levelsOnFault; - dirName += "-nshm23_branches"; - double avgNumRups = 600000; - - dirSuffix = "-gridded_rebuild"; - -// List> levels = NSHM18_LogicTreeBranch.levels; -// dirName += "-nshm18_branches-wc_94"; -// double avgNumRups = 500000; - -// List> levels = NSHM18_LogicTreeBranch.levelsNewScale; -// dirName += "-nshm18_branches-new_scale"; -// double avgNumRups = 500000; - -// levels = new ArrayList<>(levels); -// for (int i=levels.size(); --i>=0;) -// if (levels.get(i).getType().isAssignableFrom(ShawSegmentationModels.class) -// || levels.get(i).getType().isAssignableFrom(NSHM23_SegmentationModels.class) -// || levels.get(i).getType().isAssignableFrom(SegmentationMFD_Adjustment.class) -// || levels.get(i).getType().isAssignableFrom(DistDependSegShift.class)) -// levels.remove(i); -// dirName += "-no_seg"; -//// levels.add(NSHM23_LogicTreeBranch.RUPS_THROUGH_CREEPING); -//// dirName += "-creep_branches"; -//// levels.add(NSHM23_LogicTreeBranch.MAX_DIST); -//// dirName += "-strict_cutoff_seg"; strictSeg = true; - - -// dirName += "-pre_zero_slip_parent_fix"; -// dirName += "-reweight_seg_2_3_4"; - -// levels = new ArrayList<>(levels); -// int origSize = levels.size(); -// for (int i=levels.size(); --i>=0;) -// if (levels.get(i).getType().isAssignableFrom(ScalingRelationships.class)) -// levels.remove(i); -// Preconditions.checkState(levels.size() < origSize); -// levels.add(NSHM23_LogicTreeBranch.SCALE); -// dirName += "-new_scale_rels"; -// dirName += "-full_set"; - -// levels = new ArrayList<>(levels); -// boolean dmReplaced = false; -// for (int l=levels.size(); --l >= 0;) { -// LogicTreeLevel level = levels.get(l); -// System.out.println("Level "+l+": name='"+level.getName()+"'; type='"+level.getType()+"'"); -// if (NSHM23_DeformationModels.class.isAssignableFrom(level.getType())) { -// dmReplaced = true; -// levels.set(l, LogicTreeLevel.forEnum(DevinModDeformationModels.class, "Custom Deformation Model", "CustomDM")); -// } else if (SlipAlongRuptureModels.class.isAssignableFrom(level.getType())) { -// levels.remove(l); -// } -// } -// Preconditions.checkState(dmReplaced); -// levels.add(LogicTreeLevel.forEnum(TaperOverrideSlipAlongRuptureModels.class, "Taper-Override Slip Along Rupture Models", "SlipAlong")); -// dirName += "-devin_tapered_slip_tests"; - - Class factoryClass = NSHM23_InvConfigFactory.class; - -// Class factoryClass = NSHM23_InvConfigFactory.MFDUncert0p1.class; -// dirName += "-mfd_uncert_0p1"; - -// Class factoryClass = NSHM23_InvConfigFactory.ConstantSlipRateStdDev0p1.class; -// dirName += "-const_slip_sd_0p1"; - -// Class factoryClass = NSHM23_InvConfigFactory.ConstantSlipRateStdDev0p2.class; -// dirName += "-const_slip_sd_0p2"; - -// Class factoryClass = NSHM23_InvConfigFactory.FullSysInv.class; -// dirName += "-full_sys_inv"; - -// Class factoryClass = NSHM23_InvConfigFactory.ClusterSpecific.class; -// dirName += "-cluster_specific_inversion"; - -// Class factoryClass = NSHM23_InvConfigFactory.SegWeight100.class; -// dirName += "-seg_weight_100"; - -// Class factoryClass = NSHM23_InvConfigFactory.SegWeight1000.class; -// dirName += "-seg_weight_1000"; - -// Class factoryClass = NSHM23_InvConfigFactory.SegWeight10000.class; -// dirName += "-seg_weight_10000"; - -// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevWeightAdjust.class; -// dirName += "-no_reweight_use_prev"; - -// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevWeightAdjustFullSys.class; -// dirName += "-full_sys_inv-no_reweight_use_prev"; - -// Class factoryClass = NSHM23_InvConfigFactory.HardcodedOrigWeights.class; -// dirName += "-no_reweight_use_orig"; - -// Class factoryClass = NSHM23_InvConfigFactory.HardcodedOrigWeightsFullSys.class; -// dirName += "-full_sys_inv-no_reweight_use_orig"; - -// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevAvgWeights.class; -// dirName += "-no_reweight_use_prev_avg"; - -// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevAvgWeightsFullSys.class; -// dirName += "-full_sys_inv-no_reweight_use_prev_avg"; - -// Class factoryClass = NSHM23_InvConfigFactory.NoPaleoParkfield.class; -// dirName += "-no_paleo_parkfield"; - -// Class factoryClass = NSHM23_InvConfigFactory.NoMFDScaleAdjust.class; -// dirName += "-no_scale_adj_mfds"; - -// Class factoryClass = NSHM23_InvConfigFactory.NoIncompatibleDataAdjust.class; -// dirName += "-no_mfd_sigma_data_adj"; - -// Class factoryClass = NSHM23_InvConfigFactory.ScaleLowerDepth1p3.class; -// dirName += "-scaleLowerDepth1.3"; - -// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevAsInitial.class; -// dirName += "-prev_as_initial"; - -// Class factoryClass = NSHM23_InvConfigFactory.NoAvg.class; -// dirName += "-no_avg"; - -// Class factoryClass = NSHM23_InvConfigFactory.ForceNewPaleo.class; -// dirName += "-new_paleo"; - -// Class factoryClass = NSHM23_InvConfigFactory.NewScaleUseOrigWidths.class; -// dirName += "-use_orig_widths"; - - // also set nonzero weights! -// Class factoryClass = NSHM23_InvConfigFactory.ForceWideSegBranches.class; -// dirName += "-wide_seg_branches"; - -// Class factoryClass = NSHM23_InvConfigFactory.ForceNoGhostTransient.class; -// dirName += "-no_ghost_trans"; - -// Class factoryClass = NSHM23_InvConfigFactory.ScaleSurfSlipUseActualWidths.class; -// dirName += "-surf_slip_use_actual_w"; - -// Class factoryClass = NSHM23_InvConfigFactory.RemoveIsolatedFaults.class; -// dirName += "-remove_isolated_faults"; - -// Class factoryClass = NSHM23_InvConfigFactory.RemoveProxyFaults.class; -// dirName += "-remove_proxy_faults"; - -// Class factoryClass = NSHM23_InvConfigFactory.NoPaleoSlip.class; -// dirName += "-no_paleo_slip"; - -// Class factoryClass = NSHM23_InvConfigFactory.PaleoSlipInequality.class; -// dirName += "-paleo_slip_ineq"; - -// Class factoryClass = NSHM23_InvConfigFactory.TenThousandItersPerRup.class; -// dirName += "-10000ip"; - -// Class factoryClass = NSHM23_InvConfigFactory.DM_OriginalWeights.class; -// dirName += "-dm_orig_weights"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; - -// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierlMinimizationWeights.class; -// dirName += "-dm_outlier_minimize_weights"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = false; - -// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierReplacementYc2p0.class; -// dirName += "-dm_outlier_sub_yc_2"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; - -// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierReplacementYc3p5.class; -// dirName += "-dm_outlier_sub_yc_3p5"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; - -// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierReplacementYc5p0.class; -// dirName += "-dm_outlier_sub_yc_5"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; - -// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierLogReplacementYc2p0.class; -// dirName += "-dm_outlier_log_sub_yc_2"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; - -// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierLogReplacementYc3p5.class; -// dirName += "-dm_outlier_log_sub_yc_3p5"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; - -// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierLogReplacementYc5p0.class; -// dirName += "-dm_outlier_log_sub_yc_5"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; - -// Class factoryClass = NSHM23_InvConfigFactory.SegModelLimitMaxLen.class; -// dirName += "-seg_limit_max_length"; - -// Class factoryClass = NSHM23_InvConfigFactory.SlipRateStdDevCeil0p1.class; -// dirName += "-slip_rate_sd_ceil_0p1"; - -// Class factoryClass = NSHM23_InvConfigFactory.SegModelMaxLen600.class; -// dirName += "-seg_limit_max_length_600"; - -// Class factoryClass = NSHM23_InvConfigFactory.SparseGRDontSpreadSingleToMulti.class; -// dirName += "-sparse_gr_dont_spread_single_multi"; - -// Class factoryClass = NSHM23_InvConfigFactory.ModDepthGV08.class; -// dirName += "-gv_08_mod_depth"; - -// Class factoryClass = NSHM23_InvConfigFactory.OrigDraftScaling.class; -// dirName += "-orig_draft_scaling"; - -// Class factoryClass = NSHM23_InvConfigFactory.ModScalingAdd4p3.class; -// dirName += "-mod_scaling"; - -// Class factoryClass = NSHM23_InvConfigFactory.NSHM18_UseU3Paleo.class; -// dirName += "-u3_paleo"; - -// Class factoryClass = NSHM23_InvConfigFactory.ModPitasPointDDW.class; -// dirName += "-mod_pitas_ddw"; - -// Class factoryClass = DefModSamplingEnabledInvConfig.ConnDistB0p5MidSegCorr.class; -// dirName += "-dm_sampling"; -// individualRandomLevels.add(new RandomDefModSampleLevel()); - -// Class factoryClass = DefModSamplingEnabledInvConfig.ConnDistB0p5MidSegCorrCapSigma.class; -// dirName += "-dm_sampling_cap_sigma"; -// individualRandomLevels.add(new RandomDefModSampleLevel()); - -// levels = new ArrayList<>(levels); -// boolean randB = true; -// boolean randSeg = true; -// int origSize = levels.size(); -// for (int i=levels.size(); --i>=0;) { -// if (randB && SupraSeisBValues.class.isAssignableFrom(levels.get(i).getType())) -// levels.remove(i); -// if (randSeg && SegmentationModelBranchNode.class.isAssignableFrom(levels.get(i).getType())) -// levels.remove(i); -// } -// Preconditions.checkState(levels.size() < origSize); -// if (randB) { -// samplingBranchCountMultiplier *= 5; // there were originally 5 each -// dirName += "-randB"; -// individualRandomLevels.add(new RandomBValSampler.Level()); -// } -// if (randSeg) { -// samplingBranchCountMultiplier *= 5; // there were originally 5 each -// dirName += "-randSeg"; -// individualRandomLevels.add(new RandomSegModelSampler.Level()); -// } - -// dirName += "-mini_one_fifth"; -// samplingBranchCountMultiplier /= 5; - -// dirName += "-u3_perturb"; -// extraArgs.add("--perturb "+GenerationFunctionType.UNIFORM_0p001.name()); -// dirName += "-exp_perturb"; -// extraArgs.add("--perturb "+GenerationFunctionType.EXPONENTIAL_SCALE.name()); -// dirName += "-limit_zeros"; -// extraArgs.add("--non-negativity "+NonnegativityConstraintType.LIMIT_ZERO_RATES.name()); -// dirName += "-classic_sa"; -// extraArgs.add("--cooling-schedule "+CoolingScheduleType.CLASSICAL_SA.name()); - -// levels = new ArrayList<>(levels); -// levels.add(NSHM23_LogicTreeBranch.SINGLE_STATES); -// dirName += "-single_state"; - -// dirName += "-mod_west_valley_ddw"; - -// dirName += "-mod_dm_weights"; - - forceHazardGridSpacing = 0.1; - - forceRequiredNonzeroWeight = true; - LogicTreeNode[] required = { - // FAULT MODELS -// FaultModels.FM3_1, -// FaultModels.FM3_2, -// NSHM18_FaultModels.NSHM18_WUS_NoCA, -// NSHM18_FaultModels.NSHM18_WUS_PlusU3_FM_3p1, -// NSHM23_FaultModels.FM_v1p4, -// NSHM23_FaultModels.FM_v2, - NSHM23_FaultModels.WUS_FM_v3, -// PRVI25_FaultModels.PRVI_FM_INITIAL, - -// // SINGLE STATE -// NSHM23_SingleStates.NM, -// NSHM23_SingleStates.UT, - - // RUPTURE SETS -// RupturePlausibilityModels.COULOMB, // default -// RupturePlausibilityModels.COULOMB_5km, -// RupturePlausibilityModels.AZIMUTHAL, -// RupturePlausibilityModels.SEGMENTED, -// RupturePlausibilityModels.UCERF3, -// RupturePlausibilityModels.UCERF3_REDUCED, - - // DEFORMATION MODELS -// U3_UncertAddDeformationModels.U3_ZENG, -// U3_UncertAddDeformationModels.U3_MEAN, -// NSHM18_DeformationModels.BRANCH_AVERAGED, -// NSHM23_DeformationModels.AVERAGE, -// NSHM23_DeformationModels.GEOLOGIC, -// NSHM23_DeformationModels.EVANS, -// NSHM23_DeformationModels.MEDIAN, -// DevinModDeformationModels.GEO_AVG_FROM_DEVIN, -// DevinModDeformationModels.GEO_FROM_DEVIN, - - // SCALING RELATIONSHIPS -// ScalingRelationships.SHAW_2009_MOD, -// ScalingRelationships.MEAN_UCERF3, -// NSHM23_ScalingRelationships.AVERAGE, -// NSHM23_ScalingRelationships.LOGA_C4p2_SQRT_LEN, -// NSHM23_ScalingRelationships.WIDTH_LIMITED_CSD, - - // SLIP ALONG RUPTURE -// NSHM23_SlipAlongRuptureModels.UNIFORM, -// NSHM23_SlipAlongRuptureModels.TAPERED, -// SlipAlongRuptureModels.UNIFORM, -// SlipAlongRuptureModels.TAPERED, -// TaperOverrideSlipAlongRuptureModels.UNIFORM, -// TaperOverrideSlipAlongRuptureModels.TAPER_OVERRIDE_COMBINED, -// TaperOverrideSlipAlongRuptureModels.TAPER_OVERRIDE_INDIVIDUAL, - - // SUB-SECT CONSTRAINT -// SubSectConstraintModels.TOT_NUCL_RATE, // default -// SubSectConstraintModels.NUCL_MFD, - - // SUB-SEIS MO REDUCTION -// SubSeisMoRateReductions.SUB_B_1, -// SubSeisMoRateReductions.NONE, // default -// SubSeisMoRateReductions.SYSTEM_AVG, -// SubSeisMoRateReductions.SYSTEM_AVG_SUB_B_1, - - // SUPRA-SEIS-B -// SupraSeisBValues.B_0p5, -// SupraSeisBValues.AVERAGE, - - // PALEO UNCERT -// NSHM23_PaleoUncertainties.EVEN_FIT, - - // SEGMENTATION -// SegmentationModels.SHAW_R0_3, -// NSHM23_SegmentationModels.AVERAGE, -// NSHM23_SegmentationModels.MID, -// NSHM23_SegmentationModels.CLASSIC, -// NSHM23_SegmentationModels.CLASSIC_FULL, - - // SEG-SHIFT -// DistDependSegShift.NONE, -// DistDependSegShift.ONE_KM, -// DistDependSegShift.TWO_KM, -// DistDependSegShift.THREE_KM, - - // SEG ADJUSTMENT -// SegmentationMFD_Adjustment.NONE, -// SegmentationMFD_Adjustment.JUMP_PROB_THRESHOLD_AVG, -// SegmentationMFD_Adjustment.REL_GR_THRESHOLD_AVG_SINGLE_ITER, -// SegmentationMFD_Adjustment.REL_GR_THRESHOLD_AVG, // default -// SegmentationMFD_Adjustment.CAPPED_REDIST, -// SegmentationMFD_Adjustment.CAPPED_REDIST_SELF_CONTAINED, -// SegmentationMFD_Adjustment.GREEDY, -// SegmentationMFD_Adjustment.GREEDY_SELF_CONTAINED, -// SegmentationMFD_Adjustment.JUMP_PROB_THRESHOLD_AVG_MATCH_STRICT, - - // CREEPING SECTION -// RupsThroughCreepingSect.INCLUDE, -// RupsThroughCreepingSect.EXCLUDE, - }; -// LogicTreeNode[] required = { FaultModels.FM3_1, SubSeisMoRateReductionNode.SYSTEM_AVG }; -// LogicTreeNode[] required = { FaultModels.FM3_1, SubSeisMoRateReductionNode.FAULT_SPECIFIC }; -// Class sortBy = SubSectConstraintModels.class; - Class sortBy = NSHM23_SegmentationModels.class; +//// List> levels = NSHM23_U3_HybridLogicTreeBranch.levels; +//// dirName += "-nshm23_u3_hybrid_branches"; +//// double avgNumRups = 325000; +// +// List> levels = NSHM23_LogicTreeBranch.levelsOnFault; +// dirName += "-nshm23_branches"; +// double avgNumRups = 600000; +// +// dirSuffix = "-gridded_rebuild"; +// +//// List> levels = NSHM18_LogicTreeBranch.levels; +//// dirName += "-nshm18_branches-wc_94"; +//// double avgNumRups = 500000; +// +//// List> levels = NSHM18_LogicTreeBranch.levelsNewScale; +//// dirName += "-nshm18_branches-new_scale"; +//// double avgNumRups = 500000; +// +//// levels = new ArrayList<>(levels); +//// for (int i=levels.size(); --i>=0;) +//// if (levels.get(i).getType().isAssignableFrom(ShawSegmentationModels.class) +//// || levels.get(i).getType().isAssignableFrom(NSHM23_SegmentationModels.class) +//// || levels.get(i).getType().isAssignableFrom(SegmentationMFD_Adjustment.class) +//// || levels.get(i).getType().isAssignableFrom(DistDependSegShift.class)) +//// levels.remove(i); +//// dirName += "-no_seg"; +////// levels.add(NSHM23_LogicTreeBranch.RUPS_THROUGH_CREEPING); +////// dirName += "-creep_branches"; +////// levels.add(NSHM23_LogicTreeBranch.MAX_DIST); +////// dirName += "-strict_cutoff_seg"; strictSeg = true; +// +// +//// dirName += "-pre_zero_slip_parent_fix"; +//// dirName += "-reweight_seg_2_3_4"; +// +//// levels = new ArrayList<>(levels); +//// int origSize = levels.size(); +//// for (int i=levels.size(); --i>=0;) +//// if (levels.get(i).getType().isAssignableFrom(ScalingRelationships.class)) +//// levels.remove(i); +//// Preconditions.checkState(levels.size() < origSize); +//// levels.add(NSHM23_LogicTreeBranch.SCALE); +//// dirName += "-new_scale_rels"; +//// dirName += "-full_set"; +// +//// levels = new ArrayList<>(levels); +//// boolean dmReplaced = false; +//// for (int l=levels.size(); --l >= 0;) { +//// LogicTreeLevel level = levels.get(l); +//// System.out.println("Level "+l+": name='"+level.getName()+"'; type='"+level.getType()+"'"); +//// if (NSHM23_DeformationModels.class.isAssignableFrom(level.getType())) { +//// dmReplaced = true; +//// levels.set(l, LogicTreeLevel.forEnum(DevinModDeformationModels.class, "Custom Deformation Model", "CustomDM")); +//// } else if (SlipAlongRuptureModels.class.isAssignableFrom(level.getType())) { +//// levels.remove(l); +//// } +//// } +//// Preconditions.checkState(dmReplaced); +//// levels.add(LogicTreeLevel.forEnum(TaperOverrideSlipAlongRuptureModels.class, "Taper-Override Slip Along Rupture Models", "SlipAlong")); +//// dirName += "-devin_tapered_slip_tests"; +// +// Class factoryClass = NSHM23_InvConfigFactory.class; +// +//// Class factoryClass = NSHM23_InvConfigFactory.MFDUncert0p1.class; +//// dirName += "-mfd_uncert_0p1"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ConstantSlipRateStdDev0p1.class; +//// dirName += "-const_slip_sd_0p1"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ConstantSlipRateStdDev0p2.class; +//// dirName += "-const_slip_sd_0p2"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.FullSysInv.class; +//// dirName += "-full_sys_inv"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ClusterSpecific.class; +//// dirName += "-cluster_specific_inversion"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.SegWeight100.class; +//// dirName += "-seg_weight_100"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.SegWeight1000.class; +//// dirName += "-seg_weight_1000"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.SegWeight10000.class; +//// dirName += "-seg_weight_10000"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevWeightAdjust.class; +//// dirName += "-no_reweight_use_prev"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevWeightAdjustFullSys.class; +//// dirName += "-full_sys_inv-no_reweight_use_prev"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.HardcodedOrigWeights.class; +//// dirName += "-no_reweight_use_orig"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.HardcodedOrigWeightsFullSys.class; +//// dirName += "-full_sys_inv-no_reweight_use_orig"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevAvgWeights.class; +//// dirName += "-no_reweight_use_prev_avg"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevAvgWeightsFullSys.class; +//// dirName += "-full_sys_inv-no_reweight_use_prev_avg"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.NoPaleoParkfield.class; +//// dirName += "-no_paleo_parkfield"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.NoMFDScaleAdjust.class; +//// dirName += "-no_scale_adj_mfds"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.NoIncompatibleDataAdjust.class; +//// dirName += "-no_mfd_sigma_data_adj"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ScaleLowerDepth1p3.class; +//// dirName += "-scaleLowerDepth1.3"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.HardcodedPrevAsInitial.class; +//// dirName += "-prev_as_initial"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.NoAvg.class; +//// dirName += "-no_avg"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ForceNewPaleo.class; +//// dirName += "-new_paleo"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.NewScaleUseOrigWidths.class; +//// dirName += "-use_orig_widths"; +// +// // also set nonzero weights! +//// Class factoryClass = NSHM23_InvConfigFactory.ForceWideSegBranches.class; +//// dirName += "-wide_seg_branches"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ForceNoGhostTransient.class; +//// dirName += "-no_ghost_trans"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ScaleSurfSlipUseActualWidths.class; +//// dirName += "-surf_slip_use_actual_w"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.RemoveIsolatedFaults.class; +//// dirName += "-remove_isolated_faults"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.RemoveProxyFaults.class; +//// dirName += "-remove_proxy_faults"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.NoPaleoSlip.class; +//// dirName += "-no_paleo_slip"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.PaleoSlipInequality.class; +//// dirName += "-paleo_slip_ineq"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.TenThousandItersPerRup.class; +//// dirName += "-10000ip"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.DM_OriginalWeights.class; +//// dirName += "-dm_orig_weights"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; +// +//// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierlMinimizationWeights.class; +//// dirName += "-dm_outlier_minimize_weights"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = false; +// +//// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierReplacementYc2p0.class; +//// dirName += "-dm_outlier_sub_yc_2"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; +// +//// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierReplacementYc3p5.class; +//// dirName += "-dm_outlier_sub_yc_3p5"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; +// +//// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierReplacementYc5p0.class; +//// dirName += "-dm_outlier_sub_yc_5"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; +// +//// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierLogReplacementYc2p0.class; +//// dirName += "-dm_outlier_log_sub_yc_2"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; +// +//// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierLogReplacementYc3p5.class; +//// dirName += "-dm_outlier_log_sub_yc_3p5"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; +// +//// Class factoryClass = NSHM23_InvConfigFactory.DM_OutlierLogReplacementYc5p0.class; +//// dirName += "-dm_outlier_log_sub_yc_5"; NSHM23_DeformationModels.ORIGINAL_WEIGHTS = true; +// +//// Class factoryClass = NSHM23_InvConfigFactory.SegModelLimitMaxLen.class; +//// dirName += "-seg_limit_max_length"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.SlipRateStdDevCeil0p1.class; +//// dirName += "-slip_rate_sd_ceil_0p1"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.SegModelMaxLen600.class; +//// dirName += "-seg_limit_max_length_600"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.SparseGRDontSpreadSingleToMulti.class; +//// dirName += "-sparse_gr_dont_spread_single_multi"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ModDepthGV08.class; +//// dirName += "-gv_08_mod_depth"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.OrigDraftScaling.class; +//// dirName += "-orig_draft_scaling"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ModScalingAdd4p3.class; +//// dirName += "-mod_scaling"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.NSHM18_UseU3Paleo.class; +//// dirName += "-u3_paleo"; +// +//// Class factoryClass = NSHM23_InvConfigFactory.ModPitasPointDDW.class; +//// dirName += "-mod_pitas_ddw"; +// +//// Class factoryClass = DefModSamplingEnabledInvConfig.ConnDistB0p5MidSegCorr.class; +//// dirName += "-dm_sampling"; +//// individualRandomLevels.add(new RandomDefModSampleLevel()); +// +//// Class factoryClass = DefModSamplingEnabledInvConfig.ConnDistB0p5MidSegCorrCapSigma.class; +//// dirName += "-dm_sampling_cap_sigma"; +//// individualRandomLevels.add(new RandomDefModSampleLevel()); +// +//// levels = new ArrayList<>(levels); +//// boolean randB = true; +//// boolean randSeg = true; +//// int origSize = levels.size(); +//// for (int i=levels.size(); --i>=0;) { +//// if (randB && SupraSeisBValues.class.isAssignableFrom(levels.get(i).getType())) +//// levels.remove(i); +//// if (randSeg && SegmentationModelBranchNode.class.isAssignableFrom(levels.get(i).getType())) +//// levels.remove(i); +//// } +//// Preconditions.checkState(levels.size() < origSize); +//// if (randB) { +//// samplingBranchCountMultiplier *= 5; // there were originally 5 each +//// dirName += "-randB"; +//// individualRandomLevels.add(new RandomBValSampler.Level()); +//// } +//// if (randSeg) { +//// samplingBranchCountMultiplier *= 5; // there were originally 5 each +//// dirName += "-randSeg"; +//// individualRandomLevels.add(new RandomSegModelSampler.Level()); +//// } +// +//// dirName += "-mini_one_fifth"; +//// samplingBranchCountMultiplier /= 5; +// +//// dirName += "-u3_perturb"; +//// extraArgs.add("--perturb "+GenerationFunctionType.UNIFORM_0p001.name()); +//// dirName += "-exp_perturb"; +//// extraArgs.add("--perturb "+GenerationFunctionType.EXPONENTIAL_SCALE.name()); +//// dirName += "-limit_zeros"; +//// extraArgs.add("--non-negativity "+NonnegativityConstraintType.LIMIT_ZERO_RATES.name()); +//// dirName += "-classic_sa"; +//// extraArgs.add("--cooling-schedule "+CoolingScheduleType.CLASSICAL_SA.name()); +// +//// levels = new ArrayList<>(levels); +//// levels.add(NSHM23_LogicTreeBranch.SINGLE_STATES); +//// dirName += "-single_state"; +// +//// dirName += "-mod_west_valley_ddw"; +// +//// dirName += "-mod_dm_weights"; +// +// forceHazardGridSpacing = 0.1; +// +// forceRequiredNonzeroWeight = true; +// LogicTreeNode[] required = { +// // FAULT MODELS +//// FaultModels.FM3_1, +//// FaultModels.FM3_2, +//// NSHM18_FaultModels.NSHM18_WUS_NoCA, +//// NSHM18_FaultModels.NSHM18_WUS_PlusU3_FM_3p1, +//// NSHM23_FaultModels.FM_v1p4, +//// NSHM23_FaultModels.FM_v2, +// NSHM23_FaultModels.WUS_FM_v3, +//// PRVI25_FaultModels.PRVI_FM_INITIAL, +// +//// // SINGLE STATE +//// NSHM23_SingleStates.NM, +//// NSHM23_SingleStates.UT, +// +// // RUPTURE SETS +//// RupturePlausibilityModels.COULOMB, // default +//// RupturePlausibilityModels.COULOMB_5km, +//// RupturePlausibilityModels.AZIMUTHAL, +//// RupturePlausibilityModels.SEGMENTED, +//// RupturePlausibilityModels.UCERF3, +//// RupturePlausibilityModels.UCERF3_REDUCED, +// +// // DEFORMATION MODELS +//// U3_UncertAddDeformationModels.U3_ZENG, +//// U3_UncertAddDeformationModels.U3_MEAN, +//// NSHM18_DeformationModels.BRANCH_AVERAGED, +//// NSHM23_DeformationModels.AVERAGE, +//// NSHM23_DeformationModels.GEOLOGIC, +//// NSHM23_DeformationModels.EVANS, +//// NSHM23_DeformationModels.MEDIAN, +//// DevinModDeformationModels.GEO_AVG_FROM_DEVIN, +//// DevinModDeformationModels.GEO_FROM_DEVIN, +// +// // SCALING RELATIONSHIPS +//// ScalingRelationships.SHAW_2009_MOD, +//// ScalingRelationships.MEAN_UCERF3, +//// NSHM23_ScalingRelationships.AVERAGE, +//// NSHM23_ScalingRelationships.LOGA_C4p2_SQRT_LEN, +//// NSHM23_ScalingRelationships.WIDTH_LIMITED_CSD, +// +// // SLIP ALONG RUPTURE +//// NSHM23_SlipAlongRuptureModels.UNIFORM, +//// NSHM23_SlipAlongRuptureModels.TAPERED, +//// SlipAlongRuptureModels.UNIFORM, +//// SlipAlongRuptureModels.TAPERED, +//// TaperOverrideSlipAlongRuptureModels.UNIFORM, +//// TaperOverrideSlipAlongRuptureModels.TAPER_OVERRIDE_COMBINED, +//// TaperOverrideSlipAlongRuptureModels.TAPER_OVERRIDE_INDIVIDUAL, +// +// // SUB-SECT CONSTRAINT +//// SubSectConstraintModels.TOT_NUCL_RATE, // default +//// SubSectConstraintModels.NUCL_MFD, +// +// // SUB-SEIS MO REDUCTION +//// SubSeisMoRateReductions.SUB_B_1, +//// SubSeisMoRateReductions.NONE, // default +//// SubSeisMoRateReductions.SYSTEM_AVG, +//// SubSeisMoRateReductions.SYSTEM_AVG_SUB_B_1, +// +// // SUPRA-SEIS-B +//// SupraSeisBValues.B_0p5, +//// SupraSeisBValues.AVERAGE, +// +// // PALEO UNCERT +//// NSHM23_PaleoUncertainties.EVEN_FIT, +// +// // SEGMENTATION +//// SegmentationModels.SHAW_R0_3, +//// NSHM23_SegmentationModels.AVERAGE, +//// NSHM23_SegmentationModels.MID, +//// NSHM23_SegmentationModels.CLASSIC, +//// NSHM23_SegmentationModels.CLASSIC_FULL, +// +// // SEG-SHIFT +//// DistDependSegShift.NONE, +//// DistDependSegShift.ONE_KM, +//// DistDependSegShift.TWO_KM, +//// DistDependSegShift.THREE_KM, +// +// // SEG ADJUSTMENT +//// SegmentationMFD_Adjustment.NONE, +//// SegmentationMFD_Adjustment.JUMP_PROB_THRESHOLD_AVG, +//// SegmentationMFD_Adjustment.REL_GR_THRESHOLD_AVG_SINGLE_ITER, +//// SegmentationMFD_Adjustment.REL_GR_THRESHOLD_AVG, // default +//// SegmentationMFD_Adjustment.CAPPED_REDIST, +//// SegmentationMFD_Adjustment.CAPPED_REDIST_SELF_CONTAINED, +//// SegmentationMFD_Adjustment.GREEDY, +//// SegmentationMFD_Adjustment.GREEDY_SELF_CONTAINED, +//// SegmentationMFD_Adjustment.JUMP_PROB_THRESHOLD_AVG_MATCH_STRICT, +// +// // CREEPING SECTION +//// RupsThroughCreepingSect.INCLUDE, +//// RupsThroughCreepingSect.EXCLUDE, +// }; +//// LogicTreeNode[] required = { FaultModels.FM3_1, SubSeisMoRateReductionNode.SYSTEM_AVG }; +//// LogicTreeNode[] required = { FaultModels.FM3_1, SubSeisMoRateReductionNode.FAULT_SPECIFIC }; +//// Class sortBy = SubSectConstraintModels.class; +// Class sortBy = NSHM23_SegmentationModels.class; /* * END NSHM23 logic tree */ @@ -734,6 +739,51 @@ public static void main(String[] args) throws IOException { /* * END PRVI25 logic tree */ + + /* + * NSHM26 logic tree + * TODO (this is a just a marker to find this part quickly, not an actual todo) + */ + + NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.AMSAM; +// NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.GNMI; + int numBranchSamples = 100; +// int numBranchSamples = 1000; +// int numBranchSamples = 10000; + TectonicRegionType trt = null; + + if (trt == null) + customTree = NSHM26_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, true); + else + customTree = NSHM26_LogicTree.buildLogicTree(seisReg, trt, numBranchSamples, true); + + hazardGridded = true; + + List> levels = new ArrayList<>(customTree.getLevels()); + dirName += "-nshm26-"+seisReg.name()+"-"+numBranchSamples+"samples"; + if (trt != null) + dirName += "-"+trt.name(); + double avgNumRups = 50000; + // TODO + System.err.println("WARNING: still using PRVI GMMs"); + gmpes = new AttenRelRef[] { AttenRelRef.USGS_PRVI_ACTIVE, AttenRelRef.USGS_PRVI_SLAB, AttenRelRef.USGS_PRVI_INTERFACE }; + + forceHazardReg = new GriddedRegion(seisReg.load(), 0.1, GriddedRegion.ANCHOR_0_0); +// forceHazardReg = new GriddedRegion(seisReg.load(), 0.025, GriddedRegion.ANCHOR_0_0); + sigmaTrunc = 3d; + + Class factoryClass = NSHM26_InvConfigFactory.class; + + forceHazardGridSpacing = 0.1; + nodeBAskipSectBySect = false; + + forceRequiredNonzeroWeight = true; + LogicTreeNode[] required = null; + Class sortBy = null; + /* + * END NSHM26 logic tree + */ + // TODO this is the end of the configurable section System.out.println("Instantiating factory class: "+factoryClass.getName()); @@ -746,7 +796,9 @@ public static void main(String[] args) throws IOException { } LogicTree logicTree; - if (forceRequiredNonzeroWeight) + if (customTree != null) + logicTree = customTree; + else if (forceRequiredNonzeroWeight) logicTree = LogicTree.buildExhaustive(levels, true, new BranchWeightProvider.NodeWeightOverrides(required, 1d), required); else logicTree = LogicTree.buildExhaustive(levels, true, required); @@ -1062,7 +1114,8 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) for (String varName : envVars.keySet()) javaWrite.setEnvVar(varName, envVars.get(varName)); - boolean griddedJob = GridSourceProviderFactory.class.isAssignableFrom(factoryClass); + boolean griddedJob = GridSourceProviderFactory.class.isAssignableFrom(factoryClass) + && !(GridSourceProviderFactory.Single.class.isAssignableFrom(factoryClass)); if (griddedJob) { LogicTree gridTree = ((GridSourceProviderFactory)factory).getGridSourceTree(logicTree); System.out.println("Will do gridded seismicity jobs. Grid tree has "+gridTree.size() @@ -1354,22 +1407,23 @@ else if (baFiles.size() == 1) if (logicTree.size() > 20) { // write out parallel version int totNum = MPJ_LogicTreeBranchAverageBuilder.buildCombinations(logicTree, 1).size(); - Preconditions.checkState(totNum > 1); - int myNodes = Integer.min(nodes, totNum); - - argz = "--input-dir "+resultsPath; - argz += " --logic-tree "+baLTPaths.get(n); - argz += " --output-dir "+baOutDirs.get(n); - if (nodeBAskipSectBySect) - argz += " --skip-sect-by-sect"; - argz += " --plot-level "+PlotLevel.REVIEW.name(); - argz += " --depth 1"; - if (baFile != null) - argz += " --compare-to "+dirPath+"/"+baFile.getName(); - argz += " "+MPJTaskCalculator.argumentBuilder().exactDispatch(1).threads(remoteTotalThreads).build(); - script = mpjWrite.buildScript(MPJ_LogicTreeBranchAverageBuilder.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, "batch_node_ba"+baJobSuffixes.get(n)+".slurm"), - script, mins, myNodes, remoteTotalThreads, queue); + if (totNum > 0) { + int myNodes = Integer.min(nodes, totNum); + + argz = "--input-dir "+resultsPath; + argz += " --logic-tree "+baLTPaths.get(n); + argz += " --output-dir "+baOutDirs.get(n); + if (nodeBAskipSectBySect) + argz += " --skip-sect-by-sect"; + argz += " --plot-level "+PlotLevel.REVIEW.name(); + argz += " --depth 1"; + if (baFile != null) + argz += " --compare-to "+dirPath+"/"+baFile.getName(); + argz += " "+MPJTaskCalculator.argumentBuilder().exactDispatch(1).threads(remoteTotalThreads).build(); + script = mpjWrite.buildScript(MPJ_LogicTreeBranchAverageBuilder.class.getName(), argz); + pbsWrite.writeScript(new File(localDir, "batch_node_ba"+baJobSuffixes.get(n)+".slurm"), + script, mins, myNodes, remoteTotalThreads, queue); + } } } diff --git a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java index 9c1c97d3..5eb0af62 100644 --- a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java +++ b/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java @@ -93,8 +93,8 @@ public static void main(String[] args) throws IOException { Preconditions.checkState(gen1.equals(gen2)); } } - List> valNodes1 = branch1.getValues(ValuedLogicTreeNode.class); - List> valNodes2 = branch2.getValues(ValuedLogicTreeNode.class); + List valNodes1 = branch1.getValues(ValuedLogicTreeNode.class); + List valNodes2 = branch2.getValues(ValuedLogicTreeNode.class); if (valNodes1 == null) { Preconditions.checkState(valNodes2 == null); } else { diff --git a/src/main/java/scratch/kevin/prvi25/BowinFaultAddTest.java b/src/main/java/scratch/kevin/prvi25/BowinFaultAddTest.java index 4f262e07..73a3b2e0 100644 --- a/src/main/java/scratch/kevin/prvi25/BowinFaultAddTest.java +++ b/src/main/java/scratch/kevin/prvi25/BowinFaultAddTest.java @@ -35,8 +35,9 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList; import org.opensha.sha.earthquake.faultSysSolution.modules.RupSetTectonicRegimes; import org.opensha.sha.earthquake.faultSysSolution.treeCombiners.SolutionLogicTreeCombinationProcessor; -import org.opensha.sha.earthquake.faultSysSolution.treeCombiners.SolutionLogicTreeCombinationProcessor.CombinedRupSetMappings; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.faultSysSolution.util.MergedSolutionCreator; +import org.opensha.sha.earthquake.faultSysSolution.util.MergedSolutionCreator.MergedRupSetMappings; import org.opensha.sha.earthquake.faultSysSolution.util.SolModuleStripper; import org.opensha.sha.earthquake.faultSysSolution.util.TrueMeanSolutionCreator; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; @@ -251,12 +252,12 @@ public static void main(String[] args) throws IOException { FaultSystemSolution subductionSol = subductionBASols.get(combBranch.requireValue(PRVI25_SubductionFaultModels.class)); Preconditions.checkState(subductionSol.getRupSet().hasModule(RupSetTectonicRegimes.class), "Subduction solution doesn't have TRTs"); - FaultSystemSolution combined = SolutionLogicTreeCombinationProcessor.combineSols(solution, subductionSol, true); + FaultSystemSolution combined = MergedSolutionCreator.merge(solution, subductionSol); Preconditions.checkState(combined.getRupSet().hasModule(RupSetTectonicRegimes.class), "Combined solution doesn't have TRTs"); GridSourceList subductionGridded = subductionSol.requireModule(GridSourceList.class); - CombinedRupSetMappings mappings = combined.getRupSet().requireModule(CombinedRupSetMappings.class); - crustalGridded = GridSourceList.remapAssociations(crustalGridded, mappings.getInnerSectMappings()); - subductionGridded = GridSourceList.remapAssociations(subductionGridded, mappings.getOuterSectMappings()); + MergedRupSetMappings mappings = combined.getRupSet().requireModule(MergedRupSetMappings.class); + crustalGridded = GridSourceList.remapAssociations(crustalGridded, mappings.getSectMappingsOldToNew(0)); + subductionGridded = GridSourceList.remapAssociations(subductionGridded, mappings.getSectMappingsOldToNew(1)); combined.setGridSourceProvider(GridSourceList.combine(subductionGridded, crustalGridded)); creator.addSolution(combined, combBranch); diff --git a/src/main/java/scratch/kevin/prvi25/CrustalSubductionTrueMeanCreator.java b/src/main/java/scratch/kevin/prvi25/CrustalSubductionTrueMeanCreator.java index 139a4044..3ff3102e 100644 --- a/src/main/java/scratch/kevin/prvi25/CrustalSubductionTrueMeanCreator.java +++ b/src/main/java/scratch/kevin/prvi25/CrustalSubductionTrueMeanCreator.java @@ -19,7 +19,8 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.ProxyFaultSectionInstances; import org.opensha.sha.earthquake.faultSysSolution.modules.RupSetTectonicRegimes; import org.opensha.sha.earthquake.faultSysSolution.treeCombiners.SolutionLogicTreeCombinationProcessor; -import org.opensha.sha.earthquake.faultSysSolution.treeCombiners.SolutionLogicTreeCombinationProcessor.CombinedRupSetMappings; +import org.opensha.sha.earthquake.faultSysSolution.util.MergedSolutionCreator; +import org.opensha.sha.earthquake.faultSysSolution.util.MergedSolutionCreator.MergedRupSetMappings; import org.opensha.sha.earthquake.faultSysSolution.util.SolModuleStripper; import org.opensha.sha.earthquake.faultSysSolution.util.TrueMeanSolutionCreator; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.gridded.NSHM23_SingleRegionGridSourceProvider; @@ -123,14 +124,14 @@ public static void main(String[] args) throws IOException { FaultSystemSolution subductionSol = subductionBASols.get(branch.requireValue(PRVI25_SubductionFaultModels.class)); Preconditions.checkState(subductionSol.getRupSet().hasModule(RupSetTectonicRegimes.class), "Subduction solution doesn't have TRTs"); - FaultSystemSolution combined = SolutionLogicTreeCombinationProcessor.combineSols(crustalSol, subductionSol, true); + FaultSystemSolution combined = MergedSolutionCreator.merge(subductionSol, crustalSol); Preconditions.checkState(combined.getRupSet().hasModule(RupSetTectonicRegimes.class), "Combined solution doesn't have TRTs"); if (gridded) { GridSourceList crustalGridded = crustalSol.requireModule(GridSourceList.class); GridSourceList subductionGridded = subductionSol.requireModule(GridSourceList.class); - CombinedRupSetMappings mappings = combined.getRupSet().requireModule(CombinedRupSetMappings.class); - crustalGridded = GridSourceList.remapAssociations(crustalGridded, mappings.getInnerSectMappings()); - Map subductionMappings = new HashMap<>(mappings.getOuterSectMappings()); + MergedRupSetMappings mappings = combined.getRupSet().requireModule(MergedRupSetMappings.class); + crustalGridded = GridSourceList.remapAssociations(crustalGridded, mappings.getSectMappingsOldToNew(1)); + Map subductionMappings = new HashMap<>(mappings.getSectMappingsOldToNew(0)); // add slab IDs Preconditions.checkState(!subductionMappings.containsKey( PRVI25_GridSourceBuilder.CAR_SLAB_ASSOC_ID)); From e6c013bb429143a4bf3c88cf4b8ccfc251655546 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 23 Mar 2026 15:26:40 -0700 Subject: [PATCH 10/71] updates for upstream --- .../MPJ_LogicTreeInversionRunnerScriptWriter.java | 11 ++++++++--- .../nshm23/MPJ_StrictSegLogicTreeTranslation.java | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 734fe20a..641dee78 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -129,6 +129,7 @@ public static void main(String[] args) throws IOException { Double forceHazardGridSpacing = null; GriddedRegion forceHazardReg = null; long randSeed = 12345678l; + boolean parallelBA = false; Double vs30 = null; Double sigmaTrunc = null; @@ -745,13 +746,15 @@ public static void main(String[] args) throws IOException { * TODO (this is a just a marker to find this part quickly, not an actual todo) */ - NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.AMSAM; -// NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.GNMI; +// NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.AMSAM; + NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.GNMI; int numBranchSamples = 100; // int numBranchSamples = 1000; // int numBranchSamples = 10000; TectonicRegionType trt = null; + parallelBA = true; + if (trt == null) customTree = NSHM26_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, true); else @@ -763,7 +766,7 @@ public static void main(String[] args) throws IOException { dirName += "-nshm26-"+seisReg.name()+"-"+numBranchSamples+"samples"; if (trt != null) dirName += "-"+trt.name(); - double avgNumRups = 50000; + double avgNumRups = 200000; // TODO System.err.println("WARNING: still using PRVI GMMs"); gmpes = new AttenRelRef[] { AttenRelRef.USGS_PRVI_ACTIVE, AttenRelRef.USGS_PRVI_SLAB, AttenRelRef.USGS_PRVI_INTERFACE }; @@ -1027,6 +1030,8 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) argz += " --completion "+completionArg; if (runsPerBranch > 1) argz += " --runs-per-branch "+runsPerBranch; + if (parallelBA) + argz += " --parallel-ba"; for (String arg : extraArgs) argz += " "+arg; argz += " "+MPJTaskCalculator.argumentBuilder().exactDispatch(remoteInversionsPerBundle).build(); diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_StrictSegLogicTreeTranslation.java b/src/main/java/scratch/kevin/nshm23/MPJ_StrictSegLogicTreeTranslation.java index 4b90d4a1..1adc9a21 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_StrictSegLogicTreeTranslation.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_StrictSegLogicTreeTranslation.java @@ -100,7 +100,7 @@ public MPJ_StrictSegLogicTreeTranslation(CommandLine cmd) throws IOException { private class AsyncLogicTreeWriter extends AbstractAsyncLogicTreeWriter { public AsyncLogicTreeWriter(SolutionProcessor processor) { - super(outputDir, processor, outputTree); + super(outputDir, processor, outputTree, true, size); } @Override From cc34ffe4fa7e6ddafb69f1c3a8f0bec6c17b82c3 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Thu, 26 Mar 2026 12:38:55 -0700 Subject: [PATCH 11/71] misc/diagnostics for upstream --- .../LogicTreePopulationHazardCurveCalc.java | 4 +- ..._LogicTreeInversionRunnerScriptWriter.java | 18 ++- .../kevin/nshm23/MultiRunSummaryCompare.java | 2 +- .../kevin/nshm26/DistSampleCountTests.java | 153 ++++++++++++++++++ .../scratch/kevin/nshm26/TreeBinCounts.java | 67 ++++++++ 5 files changed, 236 insertions(+), 8 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java create mode 100644 src/main/java/scratch/kevin/nshm26/TreeBinCounts.java diff --git a/src/main/java/scratch/kevin/nshm23/LogicTreePopulationHazardCurveCalc.java b/src/main/java/scratch/kevin/nshm23/LogicTreePopulationHazardCurveCalc.java index d93381c9..4f96bbf0 100644 --- a/src/main/java/scratch/kevin/nshm23/LogicTreePopulationHazardCurveCalc.java +++ b/src/main/java/scratch/kevin/nshm23/LogicTreePopulationHazardCurveCalc.java @@ -104,7 +104,7 @@ public static void main(String[] args) throws IOException { int exit = 0; try { mapper = new LogicTreeHazardCompare(solTree, tree, - hazardFile, rps, periods, spacing); + hazardFile, rps, periods, spacing, false, false); LogicTree compTree = null; if (compHazardFile != null) { @@ -120,7 +120,7 @@ public static void main(String[] args) throws IOException { // compTree.setWeightProvider(new BranchWeightProvider.CurrentWeights()); } comp = new LogicTreeHazardCompare(compSolTree, compTree, - compHazardFile, rps, periods, spacing); + compHazardFile, rps, periods, spacing, false, false); } Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 641dee78..c0e9d7b7 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -85,6 +85,7 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; import org.opensha.sha.earthquake.rupForecastImpl.nshm26.NSHM26_InvConfigFactory; import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_MapRegions; import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_LogicTree; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionFaultModels; @@ -746,11 +747,13 @@ public static void main(String[] args) throws IOException { * TODO (this is a just a marker to find this part quickly, not an actual todo) */ -// NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.AMSAM; - NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.GNMI; - int numBranchSamples = 100; + NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.AMSAM; +// NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.GNMI; +// int numBranchSamples = 100; // int numBranchSamples = 1000; +// int numBranchSamples = 2000; // int numBranchSamples = 10000; + int numBranchSamples = 100000; TectonicRegionType trt = null; parallelBA = true; @@ -771,8 +774,13 @@ public static void main(String[] args) throws IOException { System.err.println("WARNING: still using PRVI GMMs"); gmpes = new AttenRelRef[] { AttenRelRef.USGS_PRVI_ACTIVE, AttenRelRef.USGS_PRVI_SLAB, AttenRelRef.USGS_PRVI_INTERFACE }; - forceHazardReg = new GriddedRegion(seisReg.load(), 0.1, GriddedRegion.ANCHOR_0_0); -// forceHazardReg = new GriddedRegion(seisReg.load(), 0.025, GriddedRegion.ANCHOR_0_0); +// // full seis region +// Region mapRegion = seisReg.load(); + // smaller map region + Region mapRegion = NSHM26_MapRegions.valueOf(seisReg.name()).load(); + + forceHazardReg = new GriddedRegion(mapRegion, 0.1, GriddedRegion.ANCHOR_0_0); +// forceHazardReg = new GriddedRegion(mapRegion, 0.025, GriddedRegion.ANCHOR_0_0); sigmaTrunc = 3d; Class factoryClass = NSHM26_InvConfigFactory.class; diff --git a/src/main/java/scratch/kevin/nshm23/MultiRunSummaryCompare.java b/src/main/java/scratch/kevin/nshm23/MultiRunSummaryCompare.java index e0548adf..ed896a10 100644 --- a/src/main/java/scratch/kevin/nshm23/MultiRunSummaryCompare.java +++ b/src/main/java/scratch/kevin/nshm23/MultiRunSummaryCompare.java @@ -640,7 +640,7 @@ private static LogicTreeHazardCompare loadHaz(File dir, String name) throws IOEx } if (hasFM32) tree = tree.matchingAll(FaultModels.FM3_1); - return new LogicTreeHazardCompare(slt, tree, new File(dir, "results_hazard.zip"), rps, periods, spacing); + return new LogicTreeHazardCompare(slt, tree, new File(dir, "results_hazard.zip"), rps, periods, spacing, false, false); } private static FaultSystemSolution loadBA_Sol(File dir) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java b/src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java new file mode 100644 index 00000000..0a831720 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java @@ -0,0 +1,153 @@ +package scratch.kevin.nshm26; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.statistics.distribution.ContinuousDistribution; +import org.apache.commons.statistics.distribution.CorrTruncatedNormalDistribution; +import org.apache.commons.statistics.distribution.UniformContinuousDistribution; +import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; +import org.opensha.commons.data.function.DefaultXY_DataSet; +import org.opensha.commons.data.function.DiscretizedFunc; +import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.function.HistogramFunction; +import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotSymbol; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.logicTree.LogicTreeLevel.ContinuousDistributionBinnedLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.ContinuousDistributionSampledLevel; +import org.opensha.commons.logicTree.LogicTreeNode.SimpleValuedNode; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; + +import com.google.common.collect.Range; + +import net.mahdilamb.colormap.Colors; + +public class DistSampleCountTests { + + public static void main(String[] args) throws IOException { +// ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(7.6, 0.134, 7.15, 8.05); +//// ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(8, 0.2, 7.45, 8.55); +// int precisionScale = 1; + +// ContinuousDistribution dist = UniformContinuousDistribution.of(0d, 1d); +// ContinuousDistribution dist = UniformContinuousDistribution.of(0.5d, 1d); + ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(0.75, 0.5, 0d, 1.5); + int precisionScale = 2; + +// ContinuousDistribution dist = UniformContinuousDistribution.of(1000d, 1500d); +// int precisionScale = 2; + + int samples = 10000; + + ContinuousDistributionSampledLevel level = new ContinuousDistributionSampledLevel( + "Test level", "Level", dist, precisionScale, "Node ", "Node", "Node"); + + level.build(123456789l, samples); + + MinMaxAveTracker track = new MinMaxAveTracker(); + for (SimpleValuedNode node : level.getNodes()) + track.addValue(node.getValue()); + + double delta = 1d/Math.pow(10, precisionScale); + + System.out.println("Values: "+track); +// HistogramFunction hist = HistogramFunction.getEncompassingHistogram(track.getMin(), track.getMax(), delta); + EvenlyDiscretizedFunc hist = new EvenlyDiscretizedFunc(track.getMin(), track.getMax(), 1 + (int)(track.getLength()/delta + 0.5)); + + for (SimpleValuedNode node : level.getNodes()) + hist.add(hist.getClosestXIndex(node.getValue()), 1d); + + hist.scale(1d/(samples*hist.getDelta())); + + EvenlyDiscretizedFunc pdfDensity = new EvenlyDiscretizedFunc(track.getMin()-0.5*delta, track.getMax()+0.5*delta, 1000); + + for (int i=0; i 0) + pdfDensity.set(i, density); + } + + EvenlyDiscretizedFunc pdfCoarseDensity = new EvenlyDiscretizedFunc(hist.getMinX(), hist.getMaxX(), hist.size()); + for (int i=0; i 0) + pdfCoarseDensity.set(i, density); + } + + double histSum = hist.calcSumOfY_Vals(); + for (int i=0; i funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + funcs.add(hist); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, Colors.tab_blue)); + + funcs.add(pdfDensity); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, Color.BLACK)); + + funcs.add(pdfCoarseDensity); + chars.add(new PlotCurveCharacterstics(PlotSymbol.FILLED_CIRCLE, 5f, Color.BLACK)); + + for (int i=0; i<=3; i++) { + double x = dist.inverseCumulativeProbability(i/3d); + double y = dist.density(x); + DefaultXY_DataSet third = new DefaultXY_DataSet(x, 0, x, y); + + funcs.add(third); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, Colors.tab_green)); + + third = new DefaultXY_DataSet(x, y); + + funcs.add(third); + chars.add(new PlotCurveCharacterstics(PlotSymbol.FILLED_CIRCLE, 5f, Colors.tab_green)); + } + + ContinuousDistributionBinnedLevel binned = level.toBinnedLevel(); + List>> binNodes = binned.getNodes(); + for (int i=0; i> node = binNodes.get(i); + System.out.println("Bin node "+i+": "+node.getName()+" (wt="+(float)node.getNodeWeight()+")"); + if (i == binNodes.size()-1) + break; + double x = node.getValue().upperEndpoint(); + double y = dist.density(x); + DefaultXY_DataSet edge = new DefaultXY_DataSet(x, 0, x, y); + + funcs.add(edge); + chars.add(new PlotCurveCharacterstics(PlotLineType.DASHED, 2f, Colors.tab_orange)); + + edge = new DefaultXY_DataSet(x, y); + + funcs.add(edge); + chars.add(new PlotCurveCharacterstics(PlotSymbol.FILLED_CIRCLE, 5f, Colors.tab_orange)); + } + + PlotSpec plot = new PlotSpec(funcs, chars, samples+" samples", "X", "Density"); + + HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); + + gp.drawGraphPanel(plot); + + PlotUtils.writePlots(new File("/tmp"), "dist_test", gp, 800, 650, true, false, false); + } + +} diff --git a/src/main/java/scratch/kevin/nshm26/TreeBinCounts.java b/src/main/java/scratch/kevin/nshm26/TreeBinCounts.java new file mode 100644 index 00000000..476902da --- /dev/null +++ b/src/main/java/scratch/kevin/nshm26/TreeBinCounts.java @@ -0,0 +1,67 @@ +package scratch.kevin.nshm26; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeLevel; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.LogicTreeLevel.BinnableLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.BinnedLevel; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import gov.usgs.earthquake.nshmp.erf.logicTree.TectonicRegionBranchTreeNode; + +public class TreeBinCounts { + + public static void main(String[] args) throws IOException { + LogicTree tree = LogicTree.read(new File("/home/kevin/OpenSHA/nshm23/batch_inversions/" +// + "2026_03_23-nshm26-AMSAM-1000samples-gridded/logic_tree.json")); +// + "2026_03_25-nshm26-AMSAM-2000samples-gridded/logic_tree.json")); + + "2026_03_25-nshm26-AMSAM-100000samples-gridded/logic_tree.json")); + + System.out.println("Stats for "+tree.size()+" branches"); + + for (int t=0; t level = null; + boolean binned = false; + Map nodeWeights = new HashMap<>(); + double sumWeight = 0d; + for (int i=0; i branch = trtLevel.getNodes().get(i).getValue(); + double weight = branch.getOrigBranchWeight(); + sumWeight += weight; + if (i == 0) { + level = branch.getLevel(l); + if (level instanceof BinnableLevel) { + level = ((BinnableLevel)level).toBinnedLevel(); + binned = true; + } + } + LogicTreeNode node = branch.getValue(l); + if (binned) + node = ((BinnedLevel)level).getBinUnchecked(node); + if (nodeWeights.containsKey(node)) + nodeWeights.put(node, nodeWeights.get(node) + weight); + else + nodeWeights.put(node, weight); + } + System.out.println(level.getName()); + for (LogicTreeNode node : nodeWeights.keySet()) + System.out.println("\t"+node.getName()+":\t"+nodeWeights.get(node).floatValue()+"\t(nodeWeight="+node.getNodeWeight(null)+")"); + } + } + } + +} From 07f95fc0d80b0948168f763461d1190f80fe8c2f Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 27 Mar 2026 14:23:37 -0700 Subject: [PATCH 12/71] upstream and tests --- .../nshm23/LogicTreeBranchAverageWriter.java | 51 ++++++++++---- ..._LogicTreeInversionRunnerScriptWriter.java | 68 +++++++++++++++---- .../kevin/nshm26/DistSampleCountTests.java | 12 ++-- .../nshm26/InversionMinSubSectMagTests.java | 66 ++++++++++++++++++ .../scratch/kevin/nshm26/TreeBinCounts.java | 17 +++-- 5 files changed, 178 insertions(+), 36 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java diff --git a/src/main/java/scratch/kevin/nshm23/LogicTreeBranchAverageWriter.java b/src/main/java/scratch/kevin/nshm23/LogicTreeBranchAverageWriter.java index 8b92eb46..fceb0ad6 100644 --- a/src/main/java/scratch/kevin/nshm23/LogicTreeBranchAverageWriter.java +++ b/src/main/java/scratch/kevin/nshm23/LogicTreeBranchAverageWriter.java @@ -61,6 +61,8 @@ public static void main(String[] args) throws IOException { HashSet> restrictBAClasses = null; LogicTreeNode[] restrictNodes = null; + LogicTree analysisTree = null; + List>> skipModules = null; int totThreads = FaultSysTools.defaultNumThreads(); @@ -152,7 +154,7 @@ public static void main(String[] args) throws IOException { HazardMapPlot.SPACING_DEFAULT = 0.2; } else { - CommandLine cmd = FaultSysTools.parseOptions(createOptions(), args, ReportPageGen.class); + CommandLine cmd = FaultSysTools.parseOptions(createOptions(), args, LogicTreeBranchAverageWriter.class); File inputFile = new File(cmd.getOptionValue("input-file")); Preconditions.checkArgument(inputFile.exists(), "Input file doesn't exist: %s", inputFile.getAbsolutePath()); @@ -171,6 +173,10 @@ public static void main(String[] args) throws IOException { slt = SolutionLogicTree.load(inputFile); } + if (cmd.hasOption("analysis-logic-tree")) { + analysisTree = LogicTree.read(new File(cmd.getOptionValue("analysis-logic-tree"))); + } + if (cmd.hasOption("branch-averaged-file")) fullBAFile = new File(cmd.getOptionValue("branch-averaged-file")); @@ -210,10 +216,13 @@ public static void main(String[] args) throws IOException { FaultSystemSolution fullBA = fullBAFile == null ? null : FaultSystemSolution.load(fullBAFile); boolean compWithLoaded = false; - LogicTree tree = slt.getLogicTree(); + LogicTree sltTree = slt.getLogicTree(); - if (restrictNodes != null && restrictNodes.length > 0) - tree = tree.matchingAll(restrictNodes); + if (restrictNodes != null && restrictNodes.length > 0) { + Preconditions.checkState(analysisTree == null); + sltTree = sltTree.matchingAll(restrictNodes); + } + LogicTree outTree = analysisTree == null ? sltTree : analysisTree; // tree = tree.matchingAll(SupraSeisBValues.B_0p0, DeformationModels.GEOLOGIC, // SubSectConstraintModels.TOT_NUCL_RATE, SegmentationModels.SHAW_R0_3); @@ -225,13 +234,13 @@ public static void main(String[] args) throws IOException { // compWithLoaded = true; Map, HashSet> levelNodes = new HashMap<>(); - List> levels = tree.getLevels(); + List> levels = outTree.getLevels(); for (LogicTreeLevel level : levels) levelNodes.put(level, new HashSet<>()); Map> nodeLevels = new HashMap<>(); - for (LogicTreeBranch branch : tree) { + for (LogicTreeBranch branch : outTree) { for (int i=0; i> moduleClass : skipModules) creator.skipModule(moduleClass); @@ -265,19 +274,33 @@ public static void main(String[] args) throws IOException { int maxTasks = Integer.min(asyncThreads * 2, asyncThreads + 2); ExecutorService exec = ExecutorUtils.newBlockingThreadPool(asyncThreads, maxTasks); - int count = 0; List> futures = new ArrayList<>(); - for (LogicTreeBranch branch : tree) { - System.out.println("Processing branch "+(count++)+"/"+tree.size()+": "+branch); - FaultSystemSolution sol = slt.forBranch(branch); + for (int index=0; index outBranch = outTree.getBranch(index); + System.out.println("Processing branch "+index+"/"+outTree.size()+": "+outBranch); + LogicTreeBranch inBranch; + if (sltTree == outTree || sltTree.size() == outTree.size()) { + inBranch = sltTree.getBranch(index); + } else { + // need to match + String fName = outBranch.buildFileName(); + inBranch = null; + for (LogicTreeBranch oBranch : sltTree) { + if (oBranch.buildFileName().equals(fName)) { + Preconditions.checkState(inBranch == null); + inBranch = oBranch; + } + } + } + FaultSystemSolution sol = slt.forBranch(inBranch); futures.add(exec.submit(new Runnable() { @Override public void run() { - for (LogicTreeNode node : branch) + for (LogicTreeNode node : outBranch) if (nodeBACreators.containsKey(node)) - nodeBACreators.get(node).addSolution(sol, branch); + nodeBACreators.get(node).addSolution(sol, outBranch); } })); } @@ -383,6 +406,8 @@ public static Options createOptions() { + "for comparison in reports"); ops.addOption("lt", "logic-tree", true, "Path to logic tree JSON file, required if a results directory is " + "supplied with --input-file"); + ops.addOption(null, "analysis-logic-tree", true, "Path to separate logic tree used for analysis that should be used " + + "for writing the results."); ops.addRequiredOption("od", "output-dir", true, "Path to output directory"); ops.addOption(FaultSysTools.threadsOption()); ops.addOption("at", "async-threads", true, "Maximum number of asynchronous load/process threads, lower to " diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index c0e9d7b7..f668856f 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -175,6 +175,7 @@ public static void main(String[] args) throws IOException { List> individualRandomLevels = new ArrayList<>(); int samplingBranchCountMultiplier = 1; LogicTree customTree = null; + LogicTree analysisTree = null; String dirName = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); // String dirName = "2024_12_12"; @@ -751,17 +752,23 @@ public static void main(String[] args) throws IOException { // NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.GNMI; // int numBranchSamples = 100; // int numBranchSamples = 1000; -// int numBranchSamples = 2000; + int numBranchSamples = 2000; // int numBranchSamples = 10000; - int numBranchSamples = 100000; +// int numBranchSamples = 100000; TectonicRegionType trt = null; parallelBA = true; - if (trt == null) + if (trt == null) { customTree = NSHM26_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, true); - else + analysisTree = LogicTree.unrollTRTs(customTree); + Preconditions.checkNotNull(analysisTree); + } else { customTree = NSHM26_LogicTree.buildLogicTree(seisReg, trt, numBranchSamples, true); + analysisTree = customTree; + } + analysisTree = LogicTree.applyBinning(analysisTree); + Preconditions.checkNotNull(analysisTree); hazardGridded = true; @@ -1012,6 +1019,17 @@ else if (v2 == null) File localLogicTree = new File(localDir, "logic_tree.json"); logicTree.write(localLogicTree); + String ltPath = dirPath+"/"+localLogicTree.getName(); + + String ltAnalPath = null; + if (analysisTree != null) { + Preconditions.checkState(analysisTree.size() == logicTree.size()); + for (int i=0; i>> baPrefixes = AbstractAsyncLogicTreeWriter.getBranchAveragePrefixes(logicTree); + Map>> baPrefixes = AbstractAsyncLogicTreeWriter.getBranchAveragePrefixes( + analysisTree == null ? logicTree : analysisTree); List baLTPaths = new ArrayList<>(); List baJobSuffixes = new ArrayList<>(); List baOutDirs = new ArrayList<>(); if (baPrefixes.size() > 1) { // need to write them out piecewise + List> baLevels = analysisTree == null ? levels : analysisTree.getLevels(); for (String baPrefix : baPrefixes.keySet()) { List> plainBranches = new ArrayList<>(); for (LogicTreeBranch branch : baPrefixes.get(baPrefix)) { - LogicTreeBranch plainBranch = new LogicTreeBranch<>(levels); + LogicTreeBranch plainBranch = new LogicTreeBranch<>(baLevels); for (int i=0; i subLT = LogicTree.fromExisting(levels, plainBranches); + LogicTree subLT = LogicTree.fromExisting(baLevels, plainBranches); File subLogicTreeFile = new File(localDir, "sub_logic_tree_"+baPrefix+".json"); subLT.write(subLogicTreeFile); String subLTPath = dirPath+"/"+subLogicTreeFile.getName(); @@ -1364,7 +1393,10 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) } } else { // can do the full tree - baLTPaths.add(ltPath); + if (ltAnalPath != null) + baLTPaths.add(ltAnalPath); + else + baLTPaths.add(ltPath); baOutDirs.add(dirPath+"/node_branch_averaged"); baJobSuffixes.add(""); } @@ -1378,7 +1410,12 @@ else if (baFiles.size() == 1) else baFile = baFiles.get(baJobSuffixes.get(n)); argz = "--input-file "+resultsPath; - argz += " --logic-tree "+baLTPaths.get(n); + if (analysisTree == null) { + argz += " --logic-tree "+baLTPaths.get(n); + } else { + argz += " --logic-tree "+ltPath; + argz += " --analysis-logic-tree "+baLTPaths.get(n); + } argz += " --output-dir "+baOutDirs.get(n); argz += " --threads "+Integer.min(8, remoteTotalThreads); argz += " --async-threads "+nodeBAAsyncThreads; @@ -1419,12 +1456,17 @@ else if (baFiles.size() == 1) if (logicTree.size() > 20) { // write out parallel version - int totNum = MPJ_LogicTreeBranchAverageBuilder.buildCombinations(logicTree, 1).size(); + int totNum = MPJ_LogicTreeBranchAverageBuilder.buildCombinations(analysisTree == null ? logicTree : analysisTree, 1).size(); if (totNum > 0) { int myNodes = Integer.min(nodes, totNum); argz = "--input-dir "+resultsPath; - argz += " --logic-tree "+baLTPaths.get(n); + if (analysisTree == null) { + argz += " --logic-tree "+baLTPaths.get(n); + } else { + argz += " --logic-tree "+ltPath; + argz += " --analysis-logic-tree "+baLTPaths.get(n); + } argz += " --output-dir "+baOutDirs.get(n); if (nodeBAskipSectBySect) argz += " --skip-sect-by-sect"; diff --git a/src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java b/src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java index 0a831720..97764148 100644 --- a/src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java +++ b/src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java @@ -34,13 +34,13 @@ public class DistSampleCountTests { public static void main(String[] args) throws IOException { // ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(7.6, 0.134, 7.15, 8.05); -//// ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(8, 0.2, 7.45, 8.55); -// int precisionScale = 1; + ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(8, 0.2, 7.45, 8.55); + int precisionScale = 1; -// ContinuousDistribution dist = UniformContinuousDistribution.of(0d, 1d); -// ContinuousDistribution dist = UniformContinuousDistribution.of(0.5d, 1d); - ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(0.75, 0.5, 0d, 1.5); - int precisionScale = 2; +//// ContinuousDistribution dist = UniformContinuousDistribution.of(0d, 1d); +//// ContinuousDistribution dist = UniformContinuousDistribution.of(0.5d, 1d); +// ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(0.75, 0.5, 0d, 1.5); +// int precisionScale = 2; // ContinuousDistribution dist = UniformContinuousDistribution.of(1000d, 1500d); // int precisionScale = 2; diff --git a/src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java b/src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java new file mode 100644 index 00000000..f92e0140 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java @@ -0,0 +1,66 @@ +package scratch.kevin.nshm26; + +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.Map; + +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; +import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.NSHM26_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceMinSubSects; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; +import org.opensha.sha.util.TectonicRegionType; + +public class InversionMinSubSectMagTests { + + public static void main(String[] args) throws IOException { + NSHM26_InvConfigFactory factory = new NSHM26_InvConfigFactory(); + Map countMags = new HashMap<>(); + NSHM26_InterfaceMinSubSects[] minSects = NSHM26_InterfaceMinSubSects.values(); + for (NSHM26_InterfaceFaultModels fm : NSHM26_InterfaceFaultModels.values()) { + LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( + fm.getSeisReg(), TectonicRegionType.SUBDUCTION_INTERFACE, false); + branch.setValue(PRVI25_SubductionScalingRelationships.AVERAGE); + FaultSystemRupSet rupSet = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); + + int[] counts = new int[minSects.length]; + double[] magSums = new double[minSects.length]; + + for (int r=0; r tree = LogicTree.read(new File("/home/kevin/OpenSHA/nshm23/batch_inversions/" // + "2026_03_23-nshm26-AMSAM-1000samples-gridded/logic_tree.json")); // + "2026_03_25-nshm26-AMSAM-2000samples-gridded/logic_tree.json")); - + "2026_03_25-nshm26-AMSAM-100000samples-gridded/logic_tree.json")); +// + "2026_03_27-nshm26-AMSAM-2000samples-gridded/logic_tree.json")); + + "2026_03_27-nshm26-GNMI-2000samples-gridded/logic_tree.json")); System.out.println("Stats for "+tree.size()+" branches"); @@ -36,7 +38,7 @@ public static void main(String[] args) throws IOException { for (int l=0; l level = null; boolean binned = false; - Map nodeWeights = new HashMap<>(); + Map nodeWeights = new LinkedHashMap<>(); double sumWeight = 0d; for (int i=0; i branch = trtLevel.getNodes().get(i).getValue(); @@ -48,6 +50,8 @@ public static void main(String[] args) throws IOException { level = ((BinnableLevel)level).toBinnedLevel(); binned = true; } + for (LogicTreeNode node : level.getNodes()) + nodeWeights.put(node, 0d); } LogicTreeNode node = branch.getValue(l); if (binned) @@ -58,8 +62,13 @@ public static void main(String[] args) throws IOException { nodeWeights.put(node, weight); } System.out.println(level.getName()); - for (LogicTreeNode node : nodeWeights.keySet()) - System.out.println("\t"+node.getName()+":\t"+nodeWeights.get(node).floatValue()+"\t(nodeWeight="+node.getNodeWeight(null)+")"); + for (LogicTreeNode node : nodeWeights.keySet()) { + double weight = nodeWeights.get(node); + double nodeWeight = node.getNodeWeight(null); + if (weight > 0d || nodeWeight > 0d) + System.out.println("\t"+node.getName()+":\t"+(float)weight + +"\t(nodeWeight="+(float)nodeWeight+")"); + } } } } From 3d904ce180563fe4aa168efcb63bdc2180d2d956 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 30 Mar 2026 07:56:31 -0700 Subject: [PATCH 13/71] minor --- .../nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index f668856f..594ec89b 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -178,7 +178,7 @@ public static void main(String[] args) throws IOException { LogicTree analysisTree = null; String dirName = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); -// String dirName = "2024_12_12"; +// String dirName = "2026_03_27"; String dirSuffix = null; /* @@ -748,8 +748,8 @@ public static void main(String[] args) throws IOException { * TODO (this is a just a marker to find this part quickly, not an actual todo) */ - NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.AMSAM; -// NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.GNMI; +// NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.AMSAM; + NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.GNMI; // int numBranchSamples = 100; // int numBranchSamples = 1000; int numBranchSamples = 2000; From aea5696b7ae2e5526e04c91e5f79b7af331cbdc1 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 31 Mar 2026 09:04:12 -0700 Subject: [PATCH 14/71] logic tree figure --- .../kevin/nshm26/figures/LogicTreeFigure.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java diff --git a/src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java new file mode 100644 index 00000000..671fb479 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java @@ -0,0 +1,43 @@ +package scratch.kevin.nshm26.figures; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeFigureWriter; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; +import org.opensha.sha.util.TectonicRegionType; + +import com.google.common.base.Preconditions; + +public class LogicTreeFigure { + + public static void main(String[] args) throws IOException { + File outputDir = new File("/tmp/nshm26_logic_trees"); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); + + int samples = 10000; + boolean useLevelWeights = true; + + TectonicRegionType[] trts = {TectonicRegionType.SUBDUCTION_INTERFACE, TectonicRegionType.SUBDUCTION_SLAB, + TectonicRegionType.ACTIVE_SHALLOW}; + + for (NSHM26_SeismicityRegions seisReg : NSHM26_SeismicityRegions.values()) { + for (TectonicRegionType trt : trts) { + LogicTree tree = NSHM26_LogicTree.buildLogicTree(seisReg, trt, samples, true); + + LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(tree, false, useLevelWeights); + ltFig.write(outputDir, seisReg.name()+"_"+trt.name(), true, true); + } + + LogicTree multiTree = NSHM26_LogicTree.buildMultiRegimeTree(seisReg, samples, true); + LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(LogicTree.unrollTRTs(multiTree), false, useLevelWeights); + ltFig.write(outputDir, seisReg.name()+"_combined", true, true); + } + } + +} From 03648b8619ad2d79f658cdcbe79b6702f5835924 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 31 Mar 2026 09:05:15 -0700 Subject: [PATCH 15/71] scaling update --- .../ValidationEventsScalingWriter.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/scratch/kevin/nshm23/bbpScaling/ValidationEventsScalingWriter.java b/src/main/java/scratch/kevin/nshm23/bbpScaling/ValidationEventsScalingWriter.java index af5909e0..18e444e0 100644 --- a/src/main/java/scratch/kevin/nshm23/bbpScaling/ValidationEventsScalingWriter.java +++ b/src/main/java/scratch/kevin/nshm23/bbpScaling/ValidationEventsScalingWriter.java @@ -57,6 +57,26 @@ public static void main(String[] args) throws IOException { lengths.add(20d); widths.add(27d); + names.add("landers"); + mags.add(7.22); + lengths.add(80d); + widths.add(21d); + + names.add("ridgecrest_m6p4"); + mags.add(6.47); + lengths.add(16d); + widths.add(12d); + + names.add("ridgecrest_m7p2"); + mags.add(7.06); + lengths.add(52d); + widths.add(12d); + + names.add("whittier"); + mags.add(5.89); + lengths.add(10d); + widths.add(10d); + CSVFile csv = new CSVFile<>(true); List header = new ArrayList<>(); From 1edae47aa789a17d4f88d206a0b414740f24f857 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 31 Mar 2026 14:29:01 -0700 Subject: [PATCH 16/71] rename package to gov and nshm27 --- .../HardcodedInversionFactoryRunner.java | 14 +++++++------- ..._LogicTreeInversionRunnerScriptWriter.java | 8 ++++---- .../nshm26/DownDipRupSetBuildingTests.java | 2 +- .../InterfaceSubSeisMoReductionTests.java | 19 ++++++++++--------- .../nshm26/InversionMinSubSectMagTests.java | 9 +++++---- .../kevin/nshm26/figures/LogicTreeFigure.java | 5 +++-- 6 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index 760ded5d..0f811e5f 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -49,13 +49,6 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_DeformationModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_FaultModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_LogicTreeBranch; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.NSHM26_InvConfigFactory; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceDeformationModels; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceMinSubSects; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceObsSeisDMAdjustment; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_SeisRateModelBranch; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.PRVI25_InvConfigFactory; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalDeformationModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalFaultModels; @@ -69,6 +62,13 @@ import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM26_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceMinSubSects; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceObsSeisDMAdjustment; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_SeisRateModelBranch; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; import scratch.UCERF3.enumTreeBranches.ScalingRelationships; import scratch.UCERF3.inversion.U3InversionConfigFactory; import scratch.UCERF3.logicTree.U3LogicTreeBranch; diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 594ec89b..9c824aef 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -83,10 +83,6 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_FaultModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_LogicTreeBranch; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.NSHM26_InvConfigFactory; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_MapRegions; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_LogicTree; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader; @@ -102,6 +98,10 @@ import com.google.common.collect.ImmutableList; import edu.usc.kmilner.mpj.taskDispatch.MPJTaskCalculator; +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM26_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_RegionLoader.NSHM26_MapRegions; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; import scratch.UCERF3.enumTreeBranches.DeformationModels; import scratch.UCERF3.enumTreeBranches.FaultModels; import scratch.UCERF3.enumTreeBranches.ScalingRelationships; diff --git a/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java b/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java index 19a63aec..1de6c7bd 100644 --- a/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java +++ b/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java @@ -29,7 +29,6 @@ import org.opensha.sha.earthquake.faultSysSolution.ruptures.downDip.RectangularDownDipGrowingStrategy.NeighborOverlaps; import org.opensha.sha.earthquake.faultSysSolution.ruptures.util.GeoJSONFaultReader; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.faultSurface.GeoJSONFaultSection; @@ -37,6 +36,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Range; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceFaultModels; import net.mahdilamb.colormap.Colors; public class DownDipRupSetBuildingTests { diff --git a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java index f3b81b0e..2dbef614 100644 --- a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java +++ b/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java @@ -23,21 +23,22 @@ import org.opensha.commons.util.cpt.CPT; import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_DeclusteringAlgorithms; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_SeisRateModelBranch; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_SeisSmoothingAlgorithms; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceDeformationModels; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceFaultModels; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.InterfaceGridAssociations; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_SeisPDF_Loader; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.faultSurface.FaultTrace; import org.opensha.sha.faultSurface.RuptureSurface; import org.opensha.sha.magdist.IncrementalMagFreqDist; import org.opensha.sha.util.TectonicRegionType; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_DeclusteringAlgorithms; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceFaultModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_SeisRateModelBranch; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_SeisSmoothingAlgorithms; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.InterfaceGridAssociations; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_SeisPDF_Loader; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; + public class InterfaceSubSeisMoReductionTests { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java b/src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java index f92e0140..c7919ae9 100644 --- a/src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java +++ b/src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java @@ -9,13 +9,14 @@ import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.NSHM26_InvConfigFactory; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceFaultModels; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_InterfaceMinSubSects; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; import org.opensha.sha.util.TectonicRegionType; +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM26_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceFaultModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceMinSubSects; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_LogicTree; + public class InversionMinSubSectMagTests { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java index 671fb479..dc96ff40 100644 --- a/src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java +++ b/src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java @@ -8,12 +8,13 @@ import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeFigureWriter; import org.opensha.commons.logicTree.LogicTreeNode; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.logicTree.NSHM26_LogicTree; -import org.opensha.sha.earthquake.rupForecastImpl.nshm26.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; + public class LogicTreeFigure { public static void main(String[] args) throws IOException { From 1e287132093d10025439a492304abd5110a99cc2 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 31 Mar 2026 14:29:28 -0700 Subject: [PATCH 17/71] rename package to gov and nshm27 --- .../scratch/kevin/{nshm26 => nshm27}/DistSampleCountTests.java | 2 +- .../kevin/{nshm26 => nshm27}/DownDipInterfaceSubSectTests.java | 2 +- .../kevin/{nshm26 => nshm27}/DownDipRupSetBuildingTests.java | 2 +- .../java/scratch/kevin/{nshm26 => nshm27}/GeoJSON3DExample.java | 2 +- .../{nshm26 => nshm27}/InterfaceSubSeisMoReductionTests.java | 2 +- .../kevin/{nshm26 => nshm27}/InversionMinSubSectMagTests.java | 2 +- src/main/java/scratch/kevin/{nshm26 => nshm27}/SamplerTest.java | 2 +- .../scratch/kevin/{nshm26 => nshm27}/SlipProjectionTests.java | 2 +- .../java/scratch/kevin/{nshm26 => nshm27}/TreeBinCounts.java | 2 +- .../{nshm26 => nshm27}/UpdatedRandTreeSerialzationTests.java | 2 +- .../kevin/{nshm26 => nshm27}/figures/LogicTreeFigure.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/DistSampleCountTests.java (99%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/DownDipInterfaceSubSectTests.java (99%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/DownDipRupSetBuildingTests.java (99%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/GeoJSON3DExample.java (98%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/InterfaceSubSeisMoReductionTests.java (99%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/InversionMinSubSectMagTests.java (98%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/SamplerTest.java (99%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/SlipProjectionTests.java (98%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/TreeBinCounts.java (98%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/UpdatedRandTreeSerialzationTests.java (99%) rename src/main/java/scratch/kevin/{nshm26 => nshm27}/figures/LogicTreeFigure.java (97%) diff --git a/src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java b/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java similarity index 99% rename from src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java rename to src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java index 97764148..ad7b1187 100644 --- a/src/main/java/scratch/kevin/nshm26/DistSampleCountTests.java +++ b/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.awt.Color; import java.io.File; diff --git a/src/main/java/scratch/kevin/nshm26/DownDipInterfaceSubSectTests.java b/src/main/java/scratch/kevin/nshm27/DownDipInterfaceSubSectTests.java similarity index 99% rename from src/main/java/scratch/kevin/nshm26/DownDipInterfaceSubSectTests.java rename to src/main/java/scratch/kevin/nshm27/DownDipInterfaceSubSectTests.java index a0ade755..7b7e176e 100644 --- a/src/main/java/scratch/kevin/nshm26/DownDipInterfaceSubSectTests.java +++ b/src/main/java/scratch/kevin/nshm27/DownDipInterfaceSubSectTests.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.awt.Color; import java.io.BufferedReader; diff --git a/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java b/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java similarity index 99% rename from src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java rename to src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java index 1de6c7bd..2470fd08 100644 --- a/src/main/java/scratch/kevin/nshm26/DownDipRupSetBuildingTests.java +++ b/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.awt.Color; import java.awt.image.BufferedImage; diff --git a/src/main/java/scratch/kevin/nshm26/GeoJSON3DExample.java b/src/main/java/scratch/kevin/nshm27/GeoJSON3DExample.java similarity index 98% rename from src/main/java/scratch/kevin/nshm26/GeoJSON3DExample.java rename to src/main/java/scratch/kevin/nshm27/GeoJSON3DExample.java index 478180ca..4e259853 100644 --- a/src/main/java/scratch/kevin/nshm26/GeoJSON3DExample.java +++ b/src/main/java/scratch/kevin/nshm27/GeoJSON3DExample.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.io.File; import java.io.IOException; diff --git a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java similarity index 99% rename from src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java rename to src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java index 2dbef614..7c080e03 100644 --- a/src/main/java/scratch/kevin/nshm26/InterfaceSubSeisMoReductionTests.java +++ b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.awt.Color; import java.io.File; diff --git a/src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java b/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java similarity index 98% rename from src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java rename to src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java index c7919ae9..279b999a 100644 --- a/src/main/java/scratch/kevin/nshm26/InversionMinSubSectMagTests.java +++ b/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.io.IOException; import java.text.DecimalFormat; diff --git a/src/main/java/scratch/kevin/nshm26/SamplerTest.java b/src/main/java/scratch/kevin/nshm27/SamplerTest.java similarity index 99% rename from src/main/java/scratch/kevin/nshm26/SamplerTest.java rename to src/main/java/scratch/kevin/nshm27/SamplerTest.java index 1c488be4..f452ba08 100644 --- a/src/main/java/scratch/kevin/nshm26/SamplerTest.java +++ b/src/main/java/scratch/kevin/nshm27/SamplerTest.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.awt.Color; import java.io.File; diff --git a/src/main/java/scratch/kevin/nshm26/SlipProjectionTests.java b/src/main/java/scratch/kevin/nshm27/SlipProjectionTests.java similarity index 98% rename from src/main/java/scratch/kevin/nshm26/SlipProjectionTests.java rename to src/main/java/scratch/kevin/nshm27/SlipProjectionTests.java index dc8536c6..47cb1c35 100644 --- a/src/main/java/scratch/kevin/nshm26/SlipProjectionTests.java +++ b/src/main/java/scratch/kevin/nshm27/SlipProjectionTests.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.io.File; import java.io.IOException; diff --git a/src/main/java/scratch/kevin/nshm26/TreeBinCounts.java b/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java similarity index 98% rename from src/main/java/scratch/kevin/nshm26/TreeBinCounts.java rename to src/main/java/scratch/kevin/nshm27/TreeBinCounts.java index a58d391b..5d70c0e2 100644 --- a/src/main/java/scratch/kevin/nshm26/TreeBinCounts.java +++ b/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.io.File; import java.io.IOException; diff --git a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java b/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java similarity index 99% rename from src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java rename to src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java index 5eb0af62..db3f615b 100644 --- a/src/main/java/scratch/kevin/nshm26/UpdatedRandTreeSerialzationTests.java +++ b/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26; +package scratch.kevin.nshm27; import java.io.File; import java.io.IOException; diff --git a/src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java similarity index 97% rename from src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java rename to src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java index dc96ff40..4537945a 100644 --- a/src/main/java/scratch/kevin/nshm26/figures/LogicTreeFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java @@ -1,4 +1,4 @@ -package scratch.kevin.nshm26.figures; +package scratch.kevin.nshm27.figures; import java.io.File; import java.io.IOException; From f217683f2809f577be8d9ab79b7295e1b99e7e21 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Wed, 1 Apr 2026 08:03:34 -0700 Subject: [PATCH 18/71] renamed NSHM26 -> NSHM27 --- .../HardcodedInversionFactoryRunner.java | 28 +++++++-------- ..._LogicTreeInversionRunnerScriptWriter.java | 16 ++++----- .../nshm27/DownDipRupSetBuildingTests.java | 4 +-- .../InterfaceSubSeisMoReductionTests.java | 34 +++++++++---------- .../nshm27/InversionMinSubSectMagTests.java | 20 +++++------ .../kevin/nshm27/figures/LogicTreeFigure.java | 10 +++--- 6 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index 0f811e5f..d1720971 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -62,13 +62,13 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM26_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceMinSubSects; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceObsSeisDMAdjustment; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_SeisRateModelBranch; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceMinSubSects; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelBranch; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import scratch.UCERF3.enumTreeBranches.ScalingRelationships; import scratch.UCERF3.inversion.U3InversionConfigFactory; import scratch.UCERF3.logicTree.U3LogicTreeBranch; @@ -154,7 +154,7 @@ public static void main(String[] args) throws IOException { // dirName += "-prvi25-limit_below_obs"; // PRVI25_InvConfigFactory.SUB_SECT_DDW_FRACT = 0.25; dirName += "-quarter_len_sub_sects"; - NSHM26_InvConfigFactory factory = new NSHM26_InvConfigFactory(); + NSHM27_InvConfigFactory factory = new NSHM27_InvConfigFactory(); dirName += "-nshm26"; factory.setCacheDir(new File("/home/kevin/OpenSHA/nshm23/rup_sets/cache")); @@ -187,15 +187,15 @@ public static void main(String[] args) throws IOException { //// LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( //// NSHM26_SeismicityRegions.GNMI, TectonicRegionType.ACTIVE_SHALLOW, false); // dirName += "-gnmi"; - LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( - NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); + LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( + NSHM27_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); dirName += "-amsam"; // branch.setValue(NSHM26_InterfaceObsSeisDMAdjustment.AVERAGE); - branch.setValue(NSHM26_InterfaceObsSeisDMAdjustment.SECTION_SPECIFIC); - branch.setValue(NSHM26_InterfaceMinSubSects.ONE); - branch.setValue(NSHM26_SeisRateModelBranch.HIGH); - branch.setValue(NSHM26_InterfaceDeformationModels.LOW_COUPLING); + branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.SECTION_SPECIFIC); + branch.setValue(NSHM27_InterfaceMinSubSects.ONE); + branch.setValue(NSHM27_SeisRateModelBranch.HIGH); + branch.setValue(NSHM27_InterfaceDeformationModels.LOW_COUPLING); plotLevel = PlotLevel.REVIEW; diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 9c824aef..cc45f902 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -98,10 +98,10 @@ import com.google.common.collect.ImmutableList; import edu.usc.kmilner.mpj.taskDispatch.MPJTaskCalculator; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM26_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_RegionLoader.NSHM26_MapRegions; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM26_MapRegions; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import scratch.UCERF3.enumTreeBranches.DeformationModels; import scratch.UCERF3.enumTreeBranches.FaultModels; import scratch.UCERF3.enumTreeBranches.ScalingRelationships; @@ -749,7 +749,7 @@ public static void main(String[] args) throws IOException { */ // NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.AMSAM; - NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.GNMI; + NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.GNMI; // int numBranchSamples = 100; // int numBranchSamples = 1000; int numBranchSamples = 2000; @@ -760,11 +760,11 @@ public static void main(String[] args) throws IOException { parallelBA = true; if (trt == null) { - customTree = NSHM26_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, true); + customTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, true); analysisTree = LogicTree.unrollTRTs(customTree); Preconditions.checkNotNull(analysisTree); } else { - customTree = NSHM26_LogicTree.buildLogicTree(seisReg, trt, numBranchSamples, true); + customTree = NSHM27_LogicTree.buildLogicTree(seisReg, trt, numBranchSamples, true); analysisTree = customTree; } analysisTree = LogicTree.applyBinning(analysisTree); @@ -790,7 +790,7 @@ public static void main(String[] args) throws IOException { // forceHazardReg = new GriddedRegion(mapRegion, 0.025, GriddedRegion.ANCHOR_0_0); sigmaTrunc = 3d; - Class factoryClass = NSHM26_InvConfigFactory.class; + Class factoryClass = NSHM27_InvConfigFactory.class; forceHazardGridSpacing = 0.1; nodeBAskipSectBySect = false; diff --git a/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java b/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java index 2470fd08..8b268897 100644 --- a/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java +++ b/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java @@ -36,7 +36,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Range; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceFaultModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; import net.mahdilamb.colormap.Colors; public class DownDipRupSetBuildingTests { @@ -48,7 +48,7 @@ public static void main(String[] args) throws IOException { // NSHM26_SubductionInterfaceFaultModels fm = NSHM26_SubductionInterfaceFaultModels.KERMADEC; // String prefix = "ker_slab2"; - NSHM26_InterfaceFaultModels fm = NSHM26_InterfaceFaultModels.GNMI_V1; + NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; String prefix = "izu_slab2"; Range minSupraRange = Range.closed(20d, 40d); diff --git a/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java index 7c080e03..9a2c2c0a 100644 --- a/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java +++ b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java @@ -29,33 +29,33 @@ import org.opensha.sha.magdist.IncrementalMagFreqDist; import org.opensha.sha.util.TectonicRegionType; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_DeclusteringAlgorithms; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceFaultModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_SeisRateModelBranch; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_SeisSmoothingAlgorithms; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_DeclusteringAlgorithms; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelBranch; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisSmoothingAlgorithms; import gov.usgs.earthquake.nshmp.erf.nshm27.util.InterfaceGridAssociations; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_SeisPDF_Loader; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM26_RegionLoader.NSHM26_SeismicityRegions; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_SeisPDF_Loader; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; public class InterfaceSubSeisMoReductionTests { public static void main(String[] args) throws IOException { - LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( + LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( // NSHM26_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); - NSHM26_SeismicityRegions.GNMI, TectonicRegionType.SUBDUCTION_INTERFACE, false); - NSHM26_InterfaceFaultModels fm = branch.requireValue(NSHM26_InterfaceFaultModels.class); - NSHM26_InterfaceDeformationModels dm = branch.requireValue(NSHM26_InterfaceDeformationModels.class); + NSHM27_SeismicityRegions.GNMI, TectonicRegionType.SUBDUCTION_INTERFACE, false); + NSHM27_InterfaceFaultModels fm = branch.requireValue(NSHM27_InterfaceFaultModels.class); + NSHM27_InterfaceDeformationModels dm = branch.requireValue(NSHM27_InterfaceDeformationModels.class); - NSHM26_SeismicityRegions reg = fm.getSeisReg(); + NSHM27_SeismicityRegions reg = fm.getSeisReg(); File pdfBaseDir = new File("/home/kevin/OpenSHA/nshm26/data/spatial_seis_pdfs/"+reg.name().toLowerCase()+"/2026_03_09-v1_2D/INTERFACE"); System.out.println("Branch: "+branch+"; reg="+reg); - NSHM26_SeisRateModelBranch rateModel = NSHM26_SeisRateModelBranch.PREFFERRED; - NSHM26_DeclusteringAlgorithms decluster = NSHM26_DeclusteringAlgorithms.AVERAGE; - NSHM26_SeisSmoothingAlgorithms smooth = NSHM26_SeisSmoothingAlgorithms.AVERAGE; + NSHM27_SeisRateModelBranch rateModel = NSHM27_SeisRateModelBranch.PREFFERRED; + NSHM27_DeclusteringAlgorithms decluster = NSHM27_DeclusteringAlgorithms.AVERAGE; + NSHM27_SeisSmoothingAlgorithms smooth = NSHM27_SeisSmoothingAlgorithms.AVERAGE; double cutoffHorzDist = 50d; List sects = dm.build(branch); @@ -74,7 +74,7 @@ public static void main(String[] args) throws IOException { sectOutlines[s] = new Region(sectSurfs[s].getPerimeter(), BorderType.MERCATOR_LINEAR); } - GriddedGeoDataSet pdf = NSHM26_SeisPDF_Loader.load2D(pdfBaseDir, reg, decluster, smooth); + GriddedGeoDataSet pdf = NSHM27_SeisPDF_Loader.load2D(pdfBaseDir, reg, decluster, smooth); InterfaceGridAssociations assoc = new InterfaceGridAssociations(sects, pdf.getRegion()); double sumMapped = 0d; diff --git a/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java b/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java index 279b999a..fd1ec97a 100644 --- a/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java +++ b/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java @@ -12,19 +12,19 @@ import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; import org.opensha.sha.util.TectonicRegionType; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM26_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceFaultModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_InterfaceMinSubSects; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM26_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceMinSubSects; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; public class InversionMinSubSectMagTests { public static void main(String[] args) throws IOException { - NSHM26_InvConfigFactory factory = new NSHM26_InvConfigFactory(); - Map countMags = new HashMap<>(); - NSHM26_InterfaceMinSubSects[] minSects = NSHM26_InterfaceMinSubSects.values(); - for (NSHM26_InterfaceFaultModels fm : NSHM26_InterfaceFaultModels.values()) { - LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( + NSHM27_InvConfigFactory factory = new NSHM27_InvConfigFactory(); + Map countMags = new HashMap<>(); + NSHM27_InterfaceMinSubSects[] minSects = NSHM27_InterfaceMinSubSects.values(); + for (NSHM27_InterfaceFaultModels fm : NSHM27_InterfaceFaultModels.values()) { + LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( fm.getSeisReg(), TectonicRegionType.SUBDUCTION_INTERFACE, false); branch.setValue(PRVI25_SubductionScalingRelationships.AVERAGE); FaultSystemRupSet rupSet = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); @@ -51,7 +51,7 @@ public static void main(String[] args) throws IOException { DecimalFormat mDF = new DecimalFormat("0.0"); double[] avgMags = new double[minSects.length]; - for (NSHM26_InterfaceFaultModels fm : countMags.keySet()) { + for (NSHM27_InterfaceFaultModels fm : countMags.keySet()) { double[] mags = countMags.get(fm); System.out.println(fm.getName()); for (int m=0; m tree = NSHM26_LogicTree.buildLogicTree(seisReg, trt, samples, true); + LogicTree tree = NSHM27_LogicTree.buildLogicTree(seisReg, trt, samples, true); LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(tree, false, useLevelWeights); ltFig.write(outputDir, seisReg.name()+"_"+trt.name(), true, true); } - LogicTree multiTree = NSHM26_LogicTree.buildMultiRegimeTree(seisReg, samples, true); + LogicTree multiTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, samples, true); LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(LogicTree.unrollTRTs(multiTree), false, useLevelWeights); ltFig.write(outputDir, seisReg.name()+"_combined", true, true); } From 1b631e2701775bb45b1dbc8060c0014993c24643 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Wed, 1 Apr 2026 08:23:29 -0700 Subject: [PATCH 19/71] more nshm26-27 refactoring/cleanup --- .../nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index cc45f902..1338eedc 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -100,7 +100,7 @@ import edu.usc.kmilner.mpj.taskDispatch.MPJTaskCalculator; import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM26_MapRegions; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_MapRegions; import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import scratch.UCERF3.enumTreeBranches.DeformationModels; import scratch.UCERF3.enumTreeBranches.FaultModels; @@ -744,11 +744,11 @@ public static void main(String[] args) throws IOException { */ /* - * NSHM26 logic tree + * NSHM27 logic tree * TODO (this is a just a marker to find this part quickly, not an actual todo) */ -// NSHM26_SeismicityRegions seisReg = NSHM26_SeismicityRegions.AMSAM; +// NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.AMSAM; NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.GNMI; // int numBranchSamples = 100; // int numBranchSamples = 1000; @@ -784,7 +784,7 @@ public static void main(String[] args) throws IOException { // // full seis region // Region mapRegion = seisReg.load(); // smaller map region - Region mapRegion = NSHM26_MapRegions.valueOf(seisReg.name()).load(); + Region mapRegion = NSHM27_MapRegions.valueOf(seisReg.name()).load(); forceHazardReg = new GriddedRegion(mapRegion, 0.1, GriddedRegion.ANCHOR_0_0); // forceHazardReg = new GriddedRegion(mapRegion, 0.025, GriddedRegion.ANCHOR_0_0); From 806e36aecb5b946ddc9e1ceabf75ad530ba2807c Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Thu, 2 Apr 2026 11:05:23 -0700 Subject: [PATCH 20/71] figures and bathymetry data --- .../kevin/nshm27/BathymetryConvert.java | 78 ++++++++++ .../kevin/nshm27/SlipProjectionTests.java | 48 ------ .../CrustalNucleationAroundFaultZoom.java | 83 +++++++++++ .../kevin/nshm27/figures/LogicTreeFigure.java | 23 ++- .../nshm27/figures/NSHM27_PaperPaths.java | 10 ++ .../nshm27/figures/SlipProjectionFigures.java | 140 ++++++++++++++++++ 6 files changed, 332 insertions(+), 50 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm27/BathymetryConvert.java delete mode 100644 src/main/java/scratch/kevin/nshm27/SlipProjectionTests.java create mode 100644 src/main/java/scratch/kevin/nshm27/figures/CrustalNucleationAroundFaultZoom.java create mode 100644 src/main/java/scratch/kevin/nshm27/figures/NSHM27_PaperPaths.java create mode 100644 src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java diff --git a/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java b/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java new file mode 100644 index 00000000..a8f78e68 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java @@ -0,0 +1,78 @@ +package scratch.kevin.nshm27; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +import org.opensha.commons.data.xyz.GriddedGeoDataSet; +import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.LocationUtils; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.cpt.CPT; + +import com.google.common.base.Preconditions; + +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_GridSourceBuilder; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; +import net.mahdilamb.colormap.Colors; + +public class BathymetryConvert { + + public static void main(String[] args) throws IOException { + // data from https://www.ncei.noaa.gov/maps/grid-extract/ + // ETOPO 2022 layer (ice surface) + // converted from geotiff to xyz via gdal_translate -of XYZ exportImage gnmi_bathy.xyz + + NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.GNMI; + File inFile = new File("/home/kevin/Downloads/gnmi_bathy.xyz"); + +// NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.AMSAM; +// File inFile = new File("/home/kevin/Downloads/amsam_bathy.xyz"); + + GriddedRegion gridReg = NSHM27_GridSourceBuilder.initGridReg(seisReg); + GriddedGeoDataSet maxDists = new GriddedGeoDataSet(gridReg); + GriddedGeoDataSet depths = new GriddedGeoDataSet(gridReg); + for (int i=0; i= 0) { + Location gridLoc = gridReg.getLocation(index); + double dist = LocationUtils.cartesianDistanceSq(loc, gridLoc); + if (dist < maxDists.get(index)) { + maxDists.set(index, dist); + depths.set(index, depth); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + + GriddedGeoDataSet.writeXYZFile(depths, new File("/tmp/"+seisReg.name()+"_depths.xyz")); + GeographicMapMaker mapMaker = new GeographicMapMaker(gridReg); + CPT cpt = GMT_CPT_Files.SEQUENTIAL_NAVIA_UNIFORM.instance().reverse().rescale(0d, 10d); + cpt.setNanColor(Colors.tab_orange); + mapMaker.plotXYZData(depths, cpt, "NOAA ETOPO (2022) bathymetric depth (km)"); + mapMaker.plot(new File("/tmp"), seisReg.name()+"_depths", " "); + } + +} diff --git a/src/main/java/scratch/kevin/nshm27/SlipProjectionTests.java b/src/main/java/scratch/kevin/nshm27/SlipProjectionTests.java deleted file mode 100644 index 47cb1c35..00000000 --- a/src/main/java/scratch/kevin/nshm27/SlipProjectionTests.java +++ /dev/null @@ -1,48 +0,0 @@ -package scratch.kevin.nshm27; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -import org.opensha.commons.gui.plot.GeographicMapMaker; -import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; -import org.opensha.commons.util.cpt.CPT; -import org.opensha.sha.earthquake.faultSysSolution.ruptures.util.GeoJSONFaultReader; -import org.opensha.sha.faultSurface.FaultSection; -import org.opensha.sha.faultSurface.GeoJSONFaultSection; - -import com.google.common.base.Preconditions; - -public class SlipProjectionTests { - - public static void main(String[] args) throws IOException { - File baseOutputDir = new File("/home/kevin/OpenSHA/nshm26/down-dip-subsectioning"); - - String prefix = "ker_slab2"; -// String prefix = "izu_slab2"; - - File inDir = new File(baseOutputDir, prefix); - File subSectsFile = new File(inDir, prefix+"_sub_sects.geojson"); - List sects = GeoJSONFaultReader.readFaultSections(subSectsFile); - File outDir = new File(inDir, "slip_projection"); - Preconditions.checkState(outDir.exists() || outDir.mkdir()); - - CPT dipCPT = GMT_CPT_Files.SEQUENTIAL_LAJOLLA_UNIFORM.instance().reverse().rescale(0d, 60d); - double maxRatio = 1.5; - CPT ratioCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(0d, 2d).trim(1d, 2d).rescale(1d, maxRatio); - - GeographicMapMaker mapMaker = new GeographicMapMaker(sects); - mapMaker.setWriteGeoJSON(false); - mapMaker.setFillSurfaces(true); - - mapMaker.plotSectScalars(s->s.getAveDip(), dipCPT, "Dip (degrees)"); - mapMaker.plot(outDir, "dip", " "); - - // cos(dip) = horizontal / on-plane - // on-plane = horizontal / cos(dip) - mapMaker.plotSectScalars(s->1d/Math.cos(Math.toRadians(s.getAveDip())), - ratioCPT, "Projected / Horizontal Slip Rate Ratio (dead on)"); - mapMaker.plot(outDir, "slip_ratio_dead_on", " "); - } - -} diff --git a/src/main/java/scratch/kevin/nshm27/figures/CrustalNucleationAroundFaultZoom.java b/src/main/java/scratch/kevin/nshm27/figures/CrustalNucleationAroundFaultZoom.java new file mode 100644 index 00000000..4b643b4b --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/figures/CrustalNucleationAroundFaultZoom.java @@ -0,0 +1,83 @@ +package scratch.kevin.nshm27.figures; + +import java.io.File; +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.List; + +import org.opensha.commons.data.xyz.GriddedGeoDataSet; +import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.Region; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; +import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; +import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList; +import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupture; +import org.opensha.sha.earthquake.faultSysSolution.reports.plots.NucleationRatePlot; +import org.opensha.sha.magdist.IncrementalMagFreqDist; +import org.opensha.sha.util.TectonicRegionType; + +public class CrustalNucleationAroundFaultZoom { + + public static void main(String[] args) throws IOException { + Region reg = new Region(new Location(13, 144), new Location(16, 146)); + FaultSystemSolution sol = FaultSystemSolution.load(new File( + "/data/kevin/nshm23/batch_inversions/2026_03_27-nshm26-GNMI-2000samples-gridded/" + + "results_GNMI_V1_ACTIVE_SHALLOW_branch_averaged.zip")); + File outputDir = new File("/tmp"); + GridSourceList gridList = sol.requireModule(GridSourceList.class); + + GriddedRegion gridReg = new GriddedRegion(reg, 0.1, GriddedRegion.ANCHOR_0_0); + + double[] minMags = {5d, 6d, 6.5, 7d, 7.5}; + GriddedGeoDataSet[] gridXYZs = new GriddedGeoDataSet[minMags.length]; + GriddedGeoDataSet[] totXYZs = new GriddedGeoDataSet[minMags.length]; + for (int m=0; m= minMags[m]) { + gridXYZs[m].add(l, rup.rate); + totXYZs[m].add(l, rup.rate); + } + } + } + } + + List solNuclMFDs = NucleationRatePlot.calcNuclMFDs(sol, TectonicRegionType.ACTIVE_SHALLOW); + for (int m=0; m"+magDF.format(minMags[m])+")"); + mapMaker.plot(outputDir, "nshm27_crustal_grid_nucl_zoom_m"+magDF.format(minMags[m]), " "); + mapMaker.plotXYZData(totXYZs[m], cpt, "Crustal total nucleation rate (M>"+magDF.format(minMags[m])+")"); + mapMaker.plot(outputDir, "nshm27_crustal_nucl_zoom_m"+magDF.format(minMags[m]), " "); + } + } + +} diff --git a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java index af80e664..452110b6 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java @@ -1,24 +1,27 @@ package scratch.kevin.nshm27.figures; +import static scratch.kevin.nshm27.figures.NSHM27_PaperPaths.*; + import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.List; import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeFigureWriter; +import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; public class LogicTreeFigure { public static void main(String[] args) throws IOException { - File outputDir = new File("/tmp/nshm26_logic_trees"); + File outputDir = new File(FIGURES_DIR, "logic_trees"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); int samples = 10000; @@ -33,6 +36,22 @@ public static void main(String[] args) throws IOException { LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(tree, false, useLevelWeights); ltFig.write(outputDir, seisReg.name()+"_"+trt.name(), true, true); + + boolean doSeparate = trt == TectonicRegionType.SUBDUCTION_INTERFACE + || (trt == TectonicRegionType.ACTIVE_SHALLOW && seisReg == NSHM27_SeismicityRegions.GNMI); + if (doSeparate) { + List> levels = NSHM27_LogicTree.buildLevels(seisReg, trt, useLevelWeights, true, false); + tree = LogicTree.buildSampled(levels, samples, 123456l, NSHM27_InterfaceFaultModels.regionDefault(seisReg)); + + ltFig = new LogicTreeFigureWriter(tree, false, useLevelWeights); + ltFig.write(outputDir, seisReg.name()+"_"+trt.name()+"_inversion", true, true); + + levels = NSHM27_LogicTree.buildLevels(seisReg, trt, useLevelWeights, false, true); + tree = LogicTree.buildSampled(levels, samples, 123456l); + + ltFig = new LogicTreeFigureWriter(tree, false, useLevelWeights); + ltFig.write(outputDir, seisReg.name()+"_"+trt.name()+"_gridded", true, true); + } } LogicTree multiTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, samples, true); diff --git a/src/main/java/scratch/kevin/nshm27/figures/NSHM27_PaperPaths.java b/src/main/java/scratch/kevin/nshm27/figures/NSHM27_PaperPaths.java new file mode 100644 index 00000000..b24e1734 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/figures/NSHM27_PaperPaths.java @@ -0,0 +1,10 @@ +package scratch.kevin.nshm27.figures; + +import java.io.File; + +public class NSHM27_PaperPaths { + + public static final File PAPER_DIR =new File("/home/kevin/Documents/papers/2027_GNMI_AmSam_ERF/"); + public static final File FIGURES_DIR =new File(PAPER_DIR, "Figures"); + +} diff --git a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java new file mode 100644 index 00000000..f71eef8d --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java @@ -0,0 +1,140 @@ +package scratch.kevin.nshm27.figures; + +import static scratch.kevin.nshm27.figures.NSHM27_PaperPaths.*; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.math3.stat.StatUtils; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.LocationList; +import org.opensha.commons.geo.LocationUtils.LocationAverager; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.faultSysSolution.ruptures.util.GeoJSONFaultReader; +import org.opensha.sha.faultSurface.FaultSection; +import org.opensha.sha.faultSurface.GeoJSONFaultSection; +import org.opensha.sha.util.TectonicRegionType; + +import com.google.common.base.Preconditions; + +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels.DeformationFront; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; + +public class SlipProjectionFigures { + + public static void main(String[] args) throws IOException { + File outputDir = new File(FIGURES_DIR, "slip_projection"); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); + + NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; +// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; + + List sects = fm.buildSubSects(fm); + + CPT dipCPT = GMT_CPT_Files.SEQUENTIAL_LAJOLLA_UNIFORM.instance().reverse().rescale(0d, 60d); + double maxRatio = 1.5; + CPT ratioCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(0d, 2d).trim(1d, 2d).rescale(1d, maxRatio); + + NSHM27_InterfaceDeformationModels dm = fm.getDefaultDeformationModel(); + + GeographicMapMaker mapMaker = new GeographicMapMaker(sects); + mapMaker.setWriteGeoJSON(false); + mapMaker.setFillSurfaces(true); + + mapMaker.plotSectScalars(s->s.getAveDip(), dipCPT, "Dip (degrees)"); + mapMaker.plot(outputDir, fm.name()+"_dip", " "); + + // cos(dip) = horizontal / on-plane + // on-plane = horizontal / cos(dip) + mapMaker.plotSectScalars(s->1d/Math.cos(Math.toRadians(s.getAveDip())), + ratioCPT, "Projected / Horizontal Slip Rate Ratio"); + mapMaker.plot(outputDir, fm.name()+"_slip_proj_ratio", " "); + + LogicTreeBranch branch = NSHM27_LogicTree.buildDefault(fm.getSeisReg(), TectonicRegionType.SUBDUCTION_INTERFACE, false); + branch.setValue(NSHM27_InterfaceCouplingDepthModels.NONE); + + double maxSlip = maxSlip(dm.apply(fm, branch, sects)); + CPT slipCPT = GMT_CPT_Files.SEQUENTIAL_BATLOW_UNIFORM.instance().rescale(0d, maxSlip); + + DeformationFront df = dm.getDeformationFront(fm); + + for (NSHM27_InterfaceCouplingDepthModels depthCoupling : NSHM27_InterfaceCouplingDepthModels.values()) { + branch.setValue(depthCoupling); + List dmSects = dm.apply(fm, branch, sects); + mapMaker.setFaultSections(dmSects); + mapMaker.plotSectScalars(s->s.getReducedAveSlipRate(), + slipCPT, "Slip deficit rate (mm/yr)"); + + List traces = new ArrayList<>(); + List traceChars = new ArrayList<>(); + traces.add(df.trace()); + traceChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 10f, Color.BLACK)); + traces.add(df.trace()); + traceChars.add(new PlotCurveCharacterstics(PlotLineType.DASHED, 10f, Color.LIGHT_GRAY)); + for (int i=0; i dmSects = odm.apply(fm, branch, sects); + + mapMaker.setFaultSections(dmSects); + mapMaker.plotSectScalars(s->s.getReducedAveSlipRate(), + slipCPT, "Slip deficit rate (mm/yr)"); + + mapMaker.plot(outputDir, fm.name()+"_"+odm.name()+"_slip_deficit_rate", + odm.getShortName()+" DM, Average Taper"); + } + } + + private static double maxSlip(List sects) { + double maxSlip = sects.stream().mapToDouble(S->S.getOrigAveSlipRate()).max().getAsDouble(); + double div10 = maxSlip / 10d; + if (div10 % 1 < 0.4) + return Math.floor(div10)*10d; + return Math.ceil(div10)*10d; + } + + private static Location middle(Location l1, Location l2) { + return new LocationAverager().add(l1, 1d).add(l2, 1d).getAverage(); + } + +} From f4a9525980c53269108a83518f1ae27f3e9b7bff Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Thu, 2 Apr 2026 13:14:19 -0700 Subject: [PATCH 21/71] new latin hypercube sampling option --- ...MPJ_LogicTreeInversionRunnerScriptWriter.java | 16 +++++++++++----- .../java/scratch/kevin/nshm27/TreeBinCounts.java | 16 +++++++++++++--- .../nshm27/UpdatedRandTreeSerialzationTests.java | 4 ++-- .../kevin/nshm27/figures/LogicTreeFigure.java | 7 +++++-- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 1338eedc..1294d55a 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -33,6 +33,7 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeLevel.RandomlyGeneratedLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.util.ClassUtils; @@ -748,8 +749,8 @@ public static void main(String[] args) throws IOException { * TODO (this is a just a marker to find this part quickly, not an actual todo) */ -// NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.AMSAM; - NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.GNMI; + NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.AMSAM; +// NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.GNMI; // int numBranchSamples = 100; // int numBranchSamples = 1000; int numBranchSamples = 2000; @@ -759,12 +760,15 @@ public static void main(String[] args) throws IOException { parallelBA = true; +// SamplingMethod samplingMethod = SamplingMethod.MONTE_CARLO; + SamplingMethod samplingMethod = SamplingMethod.LATIN_HYPERCUBE; + if (trt == null) { - customTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, true); + customTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, true, samplingMethod); analysisTree = LogicTree.unrollTRTs(customTree); Preconditions.checkNotNull(analysisTree); } else { - customTree = NSHM27_LogicTree.buildLogicTree(seisReg, trt, numBranchSamples, true); + customTree = NSHM27_LogicTree.buildLogicTree(seisReg, trt, numBranchSamples, true, samplingMethod); analysisTree = customTree; } analysisTree = LogicTree.applyBinning(analysisTree); @@ -773,7 +777,9 @@ public static void main(String[] args) throws IOException { hazardGridded = true; List> levels = new ArrayList<>(customTree.getLevels()); - dirName += "-nshm26-"+seisReg.name()+"-"+numBranchSamples+"samples"; + dirName += "-nshm27-"+seisReg.name()+"-"+numBranchSamples+"samples"; + if (samplingMethod == SamplingMethod.LATIN_HYPERCUBE) + dirName += "-lhs"; if (trt != null) dirName += "-"+trt.name(); double avgNumRups = 200000; diff --git a/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java b/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java index 5d70c0e2..2408f497 100644 --- a/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java +++ b/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java @@ -25,7 +25,8 @@ public static void main(String[] args) throws IOException { // + "2026_03_23-nshm26-AMSAM-1000samples-gridded/logic_tree.json")); // + "2026_03_25-nshm26-AMSAM-2000samples-gridded/logic_tree.json")); // + "2026_03_27-nshm26-AMSAM-2000samples-gridded/logic_tree.json")); - + "2026_03_27-nshm26-GNMI-2000samples-gridded/logic_tree.json")); +// + "2026_03_27-nshm26-GNMI-2000samples-gridded/logic_tree.json")); + + "2026_04_02-nshm27-AMSAM-2000samples-lhs-gridded/logic_tree.json")); System.out.println("Stats for "+tree.size()+" branches"); @@ -50,12 +51,21 @@ public static void main(String[] args) throws IOException { level = ((BinnableLevel)level).toBinnedLevel(); binned = true; } - for (LogicTreeNode node : level.getNodes()) + for (LogicTreeNode node : level.getNodes()) { + Preconditions.checkNotNull(node, "Null node for level %s: %s", l, level.getName()); nodeWeights.put(node, 0d); + } } LogicTreeNode node = branch.getValue(l); - if (binned) + Preconditions.checkNotNull(node, "Null node for level %s: %s", l, level.getName()); + if (binned) { + LogicTreeNode oNode = node; node = ((BinnedLevel)level).getBinUnchecked(node); + Preconditions.checkNotNull(node, "Null binned node for level %s branch %s: %s, value: %s [%s]", + l, i, level.getName(), oNode.getName(), + oNode instanceof LogicTreeNode.ValuedLogicTreeNode ? + ((LogicTreeNode.ValuedLogicTreeNode)oNode).getValue() : ""); + } if (nodeWeights.containsKey(node)) nodeWeights.put(node, nodeWeights.get(node) + weight); else diff --git a/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java b/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java index db3f615b..885eb35a 100644 --- a/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java +++ b/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java @@ -119,9 +119,9 @@ public TestValuedLevel() { } @Override - protected void doBuild(long seed, int numNodes, double weightEach) { + protected void doBuild(long seed, int numNodes, SamplingMethod samplingMethod) { Random rand = new Random(seed); - super.build(()->rand.nextDouble(), numNodes, weightEach); + super.build(()->rand.nextDouble(), numNodes, 1d/numNodes); } @Override diff --git a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java index 452110b6..9e28ee86 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java @@ -9,6 +9,7 @@ import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeFigureWriter; import org.opensha.commons.logicTree.LogicTreeLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.sha.util.TectonicRegionType; @@ -30,9 +31,11 @@ public static void main(String[] args) throws IOException { TectonicRegionType[] trts = {TectonicRegionType.SUBDUCTION_INTERFACE, TectonicRegionType.SUBDUCTION_SLAB, TectonicRegionType.ACTIVE_SHALLOW}; + SamplingMethod samplingMethod = SamplingMethod.MONTE_CARLO; + for (NSHM27_SeismicityRegions seisReg : NSHM27_SeismicityRegions.values()) { for (TectonicRegionType trt : trts) { - LogicTree tree = NSHM27_LogicTree.buildLogicTree(seisReg, trt, samples, true); + LogicTree tree = NSHM27_LogicTree.buildLogicTree(seisReg, trt, samples, true, samplingMethod); LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(tree, false, useLevelWeights); ltFig.write(outputDir, seisReg.name()+"_"+trt.name(), true, true); @@ -54,7 +57,7 @@ public static void main(String[] args) throws IOException { } } - LogicTree multiTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, samples, true); + LogicTree multiTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, samples, true, samplingMethod); LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(LogicTree.unrollTRTs(multiTree), false, useLevelWeights); ltFig.write(outputDir, seisReg.name()+"_combined", true, true); } From 0f848dac8723a991043dc7726299e7709e84a6de Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 6 Apr 2026 09:43:32 -0700 Subject: [PATCH 22/71] now tracks sampling metadata --- .../nshm23/GMM_LogicTreeBranchAttach.java | 2 +- ...J_LogicTreeInversionRunnerScriptWriter.java | 18 +++++++++++------- .../TimJonEpistemicCalcSetup.java | 2 +- .../java/scratch/kevin/ucerf3/PureScratch.java | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/GMM_LogicTreeBranchAttach.java b/src/main/java/scratch/kevin/nshm23/GMM_LogicTreeBranchAttach.java index 2a1018e0..77418ac7 100644 --- a/src/main/java/scratch/kevin/nshm23/GMM_LogicTreeBranchAttach.java +++ b/src/main/java/scratch/kevin/nshm23/GMM_LogicTreeBranchAttach.java @@ -56,7 +56,7 @@ public static void main(String[] args) throws IOException { LogicTree origTree = slt.getLogicTree(); if (samples > 0) - origTree = origTree.sample(samples, true, new Random((long)origTree.size()*(long)samples)); + origTree = origTree.sample(samples, true, (long)origTree.size()*(long)samples); FileBuilder builder = new SolutionLogicTree.FileBuilder(slt.getProcessor(), resultsModFile); diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 1294d55a..866e52f2 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -753,22 +753,24 @@ public static void main(String[] args) throws IOException { // NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.GNMI; // int numBranchSamples = 100; // int numBranchSamples = 1000; - int numBranchSamples = 2000; +// int numBranchSamples = 2000; + int numBranchSamples = 5000; // int numBranchSamples = 10000; // int numBranchSamples = 100000; TectonicRegionType trt = null; parallelBA = true; + boolean deterministicSeed = true; // SamplingMethod samplingMethod = SamplingMethod.MONTE_CARLO; SamplingMethod samplingMethod = SamplingMethod.LATIN_HYPERCUBE; if (trt == null) { - customTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, true, samplingMethod); + customTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, deterministicSeed, samplingMethod); analysisTree = LogicTree.unrollTRTs(customTree); Preconditions.checkNotNull(analysisTree); } else { - customTree = NSHM27_LogicTree.buildLogicTree(seisReg, trt, numBranchSamples, true, samplingMethod); + customTree = NSHM27_LogicTree.buildLogicTree(seisReg, trt, numBranchSamples, deterministicSeed, samplingMethod); analysisTree = customTree; } analysisTree = LogicTree.applyBinning(analysisTree); @@ -780,6 +782,8 @@ public static void main(String[] args) throws IOException { dirName += "-nshm27-"+seisReg.name()+"-"+numBranchSamples+"samples"; if (samplingMethod == SamplingMethod.LATIN_HYPERCUBE) dirName += "-lhs"; + if (!deterministicSeed) + dirName += "-unique_seed"; if (trt != null) dirName += "-"+trt.name(); double avgNumRups = 200000; @@ -855,8 +859,6 @@ else if (forceRequiredNonzeroWeight) // int numSamples = 450; // int numSamples = 36*10; - Random rand = new Random(randSeed); - if (required != null && required.length > 0) { for (LogicTreeNode node : required) dirName += "-"+node.getFilePrefix(); @@ -873,6 +875,8 @@ else if (forceRequiredNonzeroWeight) int numBranches = logicTree.size()*samplingBranchCountMultiplier; System.out.println("\tnumBranches = "+logicTree.size()+" x "+samplingBranchCountMultiplier+" = "+numBranches); + Random rand = new Random(randSeed); + List> levelNodes = new ArrayList<>(); for (RandomlyGeneratedLevel level : individualRandomLevels) { level.build(rand.nextLong(), numBranches); @@ -940,10 +944,10 @@ else if (forceRequiredNonzeroWeight) logicTree.setWeightProvider(new BranchWeightProvider.OriginalWeights()); } else { System.out.println("Still doing random downsampling"); - logicTree = logicTree.sample(numSamples, true, rand); + logicTree = logicTree.sample(numSamples, true, randSeed); } } else { - logicTree = logicTree.sample(numSamples, true, rand); + logicTree = logicTree.sample(numSamples, true, randSeed); } } else { System.out.println("Won't sample logic tree, as tree has "+logicTree.size()+" values, which is fewer " diff --git a/src/main/java/scratch/kevin/nshm23/timJonEpistemic/TimJonEpistemicCalcSetup.java b/src/main/java/scratch/kevin/nshm23/timJonEpistemic/TimJonEpistemicCalcSetup.java index b34df13d..81f5e01c 100644 --- a/src/main/java/scratch/kevin/nshm23/timJonEpistemic/TimJonEpistemicCalcSetup.java +++ b/src/main/java/scratch/kevin/nshm23/timJonEpistemic/TimJonEpistemicCalcSetup.java @@ -74,7 +74,7 @@ public static void main(String[] args) throws IOException { LogicTree fullTree = LogicTree.fromExisting(allBranches.get(0).getLevels(), allBranches); if (downsample > 0 && downsample < numBranches) { - fullTree = fullTree.sample(downsample, false, new Random((long)downsample*(long)numBranches)); + fullTree = fullTree.sample(downsample, false, (long)downsample*(long)numBranches); System.out.println("Downsampled to "+fullTree.size()+" branches"); } diff --git a/src/main/java/scratch/kevin/ucerf3/PureScratch.java b/src/main/java/scratch/kevin/ucerf3/PureScratch.java index 14e1a007..bd33c8ad 100644 --- a/src/main/java/scratch/kevin/ucerf3/PureScratch.java +++ b/src/main/java/scratch/kevin/ucerf3/PureScratch.java @@ -2854,7 +2854,7 @@ private static void test325() throws IOException { File inFile = new File(dir, "logic_tree_full_gridded.json"); File outFile = new File(dir, "logic_tree_full_gridded_sampled_100k.json"); LogicTree tree = LogicTree.read(inFile); - tree = tree.sample(100000, true, new Random(tree.size()*100000l)); + tree = tree.sample(100000, true, tree.size()*100000l); tree.write(outFile); } From 0e58c31301fe2b749dd87d322ecc0905d022b29a Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 6 Apr 2026 13:17:19 -0700 Subject: [PATCH 23/71] obs mfd plots --- .../figures/ObsUncertaintyBoundsFigure.java | 382 ++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java diff --git a/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java b/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java new file mode 100644 index 00000000..5404bc76 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java @@ -0,0 +1,382 @@ +package scratch.kevin.nshm27.figures; + +import java.awt.Color; +import java.awt.Font; +import java.awt.geom.Point2D; +import java.io.File; +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.apache.commons.math3.util.Precision; +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.ui.TextAnchor; +import org.jfree.data.Range; +import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; +import org.opensha.commons.data.function.DefaultXY_DataSet; +import org.opensha.commons.data.function.DiscretizedFunc; +import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.function.HistogramFunction; +import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.magdist.GutenbergRichterMagFreqDist; +import org.opensha.sha.util.TectonicRegionType; + +import com.google.common.base.Preconditions; + +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelBranch; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelSamples; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Exact; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.PureGR; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateRecord; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; +import net.mahdilamb.colormap.Colors; + +import static scratch.kevin.nshm27.figures.NSHM27_PaperPaths.*; + +public class ObsUncertaintyBoundsFigure { + + public static void main(String[] args) throws IOException { + File outputDir = new File(FIGURES_DIR, "obs_mfd_bounds"); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); + + boolean incremental = false; + EvenlyDiscretizedFunc refMFD = FaultSysTools.initEmptyMFD(3.05, 10.95); + + Color[] colors = { + Colors.tab_blue, + Colors.tab_orange, + Colors.tab_green + }; + + PlotLineType[] lineTypes = { + PlotLineType.DASHED, + PlotLineType.SOLID, + PlotLineType.DOTTED + }; + + RateType[] types = { + RateType.M1, + RateType.M1_TO_MMAX, + RateType.EXACT + }; + + boolean includeWtMean = false; + + NSHM27_SeismicityRegions[] seisRegions = NSHM27_SeismicityRegions.values(); + TectonicRegionType[] trts = {TectonicRegionType.SUBDUCTION_INTERFACE, TectonicRegionType.SUBDUCTION_SLAB, TectonicRegionType.ACTIVE_SHALLOW}; + + double weightLow = NSHM27_SeisRateModelBranch.LOW.getNodeWeight(); + double weightPref = NSHM27_SeisRateModelBranch.PREFFERRED.getNodeWeight(); + double weightHigh = NSHM27_SeisRateModelBranch.HIGH.getNodeWeight(); + + for (NSHM27_SeismicityRegions seisReg : seisRegions) { + for (TectonicRegionType trt : trts) { + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + String prefix = seisReg.name()+"_"+trt.name(); + String title = seisReg.getShortName()+" ("+NSHM27_RegionLoader.getNameForTRT(trt)+")"; + + DecimalFormat oDF = new DecimalFormat("0.#"); + + Double m1 = null; + Double mMax = null; + Map typeMagFuncs = new HashMap<>(); + EvenlyDiscretizedFunc overallMean = null; + for (RateType type : types) { + SeismicityRateModel rateModel = NSHM27_SeisRateModelBranch.loadRateModel(seisReg, trt, type); + + RateRecord meanRec = rateModel.getMeanRecord(); + if (m1 == null) + m1 = meanRec.M1; + if (mMax == null && meanRec instanceof PureGR) + mMax = ((PureGR)meanRec).Mmax; + + EvenlyDiscretizedFunc meanMFD; + if (incremental) + meanMFD = SeismicityRateFileLoader.buildIncrementalMFD(meanRec, refMFD, refMFD.getMaxX()); + else + meanMFD = cmlMFD(meanRec, refMFD); + + if (funcs.isEmpty()) { + meanMFD.setName("Mean"); + funcs.add(meanMFD); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 4f, Color.BLACK)); + overallMean = meanMFD; + } + + Color color = colors[type.ordinal()]; + PlotLineType plt = lineTypes[type.ordinal()]; + RateRecord low = rateModel.getLowerRecord(); + RateRecord high = rateModel.getUpperRecord(); + + EvenlyDiscretizedFunc lowMFD; + EvenlyDiscretizedFunc highMFD; + if (incremental) { + lowMFD = SeismicityRateFileLoader.buildIncrementalMFD(low, refMFD, refMFD.getMaxX()); + highMFD = SeismicityRateFileLoader.buildIncrementalMFD(high, refMFD, refMFD.getMaxX()); + } else { + lowMFD = cmlMFD(low, refMFD); + highMFD = cmlMFD(high, refMFD); + } + + typeMagFuncs.put(type, new EvenlyDiscretizedFunc[] {lowMFD, highMFD}); + + lowMFD.setName(type.toString().replace("Branches", "branches")); + funcs.add(lowMFD); + chars.add(new PlotCurveCharacterstics(plt, 3f, color)); + highMFD.setName(null); + funcs.add(highMFD); + chars.add(new PlotCurveCharacterstics(plt, 3f, color)); + + if (includeWtMean && type == RateType.M1_TO_MMAX) { + EvenlyDiscretizedFunc weightAvg = new EvenlyDiscretizedFunc(meanMFD.getMinX(), meanMFD.size(), meanMFD.getDelta()); + Preconditions.checkState((float)meanMFD.getMinX() == (float)lowMFD.getMinX()); + Preconditions.checkState((float)meanMFD.getMinX() == (float)highMFD.getMinX()); + for (int i=0; i5: "+(float)weightAvg.getY(weightAvg.getClosestXIndex(5.01))); + System.out.println("\tM>6: "+(float)weightAvg.getY(weightAvg.getClosestXIndex(6.01))); + System.out.println("\tM>6 snapped: "+(float)weightAvg.getX(weightAvg.getClosestXIndex(6.01))); + System.out.println("\tM1="+m1.floatValue()); + System.out.println("\tMmax="+mMax.floatValue()); + } + + weightAvg.setName(type.toString()+" Average"); + funcs.add(weightAvg); + chars.add(new PlotCurveCharacterstics(plt, 3f, Color.DARK_GRAY)); + } + } + + for (XY_DataSet func : funcs) { + if (func.getName() != null && func.getName().contains("M1")) + func.setName(func.getName().replace("M1", "M₁")); + if (func.getName() != null && func.getName().contains("Mmax")) + func.setName(func.getName().replace("Mmax", "Mₘₐₓ")); + } + + Range xRange = new Range(4d, 8d); + Range yRange = incremental ? new Range(1e-4, 1e2) : new Range(1e-3, 1e3); + + List anns = new ArrayList<>(); + Font annFont = new Font(Font.SANS_SERIF, Font.PLAIN, 22); + + DefaultXY_DataSet m1Line = new DefaultXY_DataSet(); + m1Line.set(m1, yRange.getLowerBound()); + m1Line.set(m1, yRange.getUpperBound()); + funcs.add(m1Line); + chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 2f, Color.DARK_GRAY)); + + DefaultXY_DataSet mMaxLine = new DefaultXY_DataSet(); + mMaxLine.set(mMax, yRange.getLowerBound()); + mMaxLine.set(mMax, yRange.getUpperBound()); + funcs.add(mMaxLine); + chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 2f, Color.DARK_GRAY)); + + XYTextAnnotation m1Ann = new XYTextAnnotation(" M₁=5", m1, yRange.getUpperBound()); + m1Ann.setFont(annFont); + m1Ann.setTextAnchor(TextAnchor.TOP_LEFT); + anns.add(m1Ann); + + XYTextAnnotation mMaxAnn = new XYTextAnnotation("Mₘₐₓ="+mMax.floatValue()+" ", mMax, yRange.getLowerBound()); + mMaxAnn.setFont(annFont); + mMaxAnn.setTextAnchor(TextAnchor.BOTTOM_RIGHT); + anns.add(mMaxAnn); + + PlotSpec plot = new PlotSpec(funcs, chars, title, "Magnitude", incremental ? "Incremental Rate (1/yr)" : "Cumulative Rate (1/yr)"); + plot.setLegendInset(true); + plot.setPlotAnnotations(anns); + + HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); + + gp.drawGraphPanel(plot, false, true, xRange, yRange); + + PlotUtils.writePlots(outputDir, prefix, gp, 700, 650, true, true, false); + + if (!incremental) { + List samples = new NSHM27_SeisRateModelSamples(seisReg, trt).loadOrigSamples(); + Collections.shuffle(samples, new Random(samples.size())); + +// int c = 200; +// int a = 127; +// int c = 150; +// int a = 80; + int c = 180; + int a = 60; + PlotCurveCharacterstics indvChar = new PlotCurveCharacterstics(PlotLineType.SOLID, 1f, new Color(c, c, c, a)); + int maxNumRates = 1000; + int numRates = Integer.min(maxNumRates, samples.size()); + GutenbergRichterMagFreqDist[] rateMFDs = new GutenbergRichterMagFreqDist[samples.size()]; + for (int i=0; i(); + chars = new ArrayList<>(); + + linearHist.setName("Sampled Distribution"); + funcs.add(linearHist); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, Color.GRAY)); + + + DefaultXY_DataSet meanXY = new DefaultXY_DataSet(); + meanXY.set(meanValue, 0d); + meanXY.set(meanValue, maxY); + meanXY.setName("Mean"); + funcs.add(meanXY); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Color.BLACK)); + + for (int t=0; t"+oDF.format(histMag)+" Rate", "Sample Count"); + plot.setLegendInset(true); + + gp.drawGraphPanel(plot, true, false, new Range(Math.pow(10, logMinRate), Math.pow(10, logMaxRate)), new Range(0d, maxY)); + + PlotUtils.writePlots(outputDir, prefix+"_hist_m"+oDF.format(histMag), gp, 700, 650, true, true, false); + } + } + } + + } + } + + private static EvenlyDiscretizedFunc cmlMFD(RateRecord record, EvenlyDiscretizedFunc refMFD) { + if (record.type == RateType.EXACT) + return ((Exact)record).cumulativeDist; + Preconditions.checkState(record instanceof PureGR); + PureGR grRec = (PureGR)record; + // fake a cml GR + GutenbergRichterMagFreqDist grMFD = new GutenbergRichterMagFreqDist( + grRec.b, 1d, refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + grMFD.scaleToIncrRate(grMFD.getX(grMFD.getClosestXIndex(grRec.M1+0.01)), grRec.rateAboveM1); + + EvenlyDiscretizedFunc cmlGR = new EvenlyDiscretizedFunc( + refMFD.getMinX()-0.5*refMFD.getDelta(), refMFD.size(), refMFD.getDelta()); + for (int i=0; i Date: Mon, 13 Apr 2026 16:10:23 -0700 Subject: [PATCH 24/71] LHS-pairwise figures and tests --- .../kevin/ltSampling/LHSExampleFigures.java | 486 ++++++++++++++++++ ..._LogicTreeInversionRunnerScriptWriter.java | 15 +- .../kevin/nshm23/NSHM23LogicTreeFigure.java | 26 + .../kevin/nshm27/DistSampleCountTests.java | 3 +- 4 files changed, 525 insertions(+), 5 deletions(-) create mode 100644 src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java create mode 100644 src/main/java/scratch/kevin/nshm23/NSHM23LogicTreeFigure.java diff --git a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java new file mode 100644 index 00000000..2964743e --- /dev/null +++ b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java @@ -0,0 +1,486 @@ +package scratch.kevin.ltSampling; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.apache.commons.statistics.distribution.ContinuousDistribution; +import org.apache.commons.statistics.distribution.CorrTruncatedNormalDistribution; +import org.apache.commons.statistics.distribution.UniformContinuousDistribution; +import org.jfree.chart.annotations.XYAnnotation; +import org.jfree.chart.annotations.XYBoxAnnotation; +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.plot.DatasetRenderingOrder; +import org.jfree.chart.ui.TextAnchor; +import org.jfree.data.Range; +import org.opensha.commons.data.function.DefaultXY_DataSet; +import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotSymbol; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeFigureWriter; +import org.opensha.commons.logicTree.LogicTreeLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.ContinuousDistributionSampledLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.LogicTreeNode.SimpleValuedNode; +import org.opensha.commons.logicTree.LogicTreeNode.ValuedLogicTreeNode; +import org.opensha.commons.logicTree.LogicTreePairwiseLHSIteration; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.cpt.CPT; + +import com.google.common.base.Preconditions; + +import net.mahdilamb.colormap.Colors; + +public class LHSExampleFigures { + + public static void main(String[] args) throws IOException { +// int samples = 30; +// int samples = 100; + int samples = 1000; +// int samples = 2000; + + int dpi = 300; + + File outputDir = new File("/tmp/lhs_samples"); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir(), "Can't create output dir: %s", outputDir.getAbsolutePath()); + + outputDir = new File(outputDir, samples+"_samples"); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir(), "Can't create output dir: %s", outputDir.getAbsolutePath()); + + List> levels = new ArrayList<>(); + levels.add(LogicTreeLevel.forEnum(DefModelEnum.class, "Deformation Model", "Deformation Model")); + levels.add(LogicTreeLevel.forEnum(ScaleEnum.class, "Scaling Relationship", "Scaling Relationship")); + levels.add(new ContinuousDistributionSampledLevel( + "GR b-value", "GR b-value", UniformContinuousDistribution.of(0d, 1d), "Sample ", "Sample", "Sample")); + levels.add(new ContinuousDistributionSampledLevel( + "Off-fault Mmax", "Off-fault Mmax", CorrTruncatedNormalDistribution.of(7.6, 0.2, 7.15, 8.05), -1, "Sample ", "Sample", "Sample")); + + long seed = 123456789l; + + CPT tab10cpt = GMT_CPT_Files.CATEGORICAL_TAB10.instance(); + Color[] tab10 = new Color[tab10cpt.size()]; + for (int i=0; i nodeColors = new HashMap<>(); + int colorI = 0; + for (LogicTreeLevel level : levels) { + if (!(level instanceof ContinuousDistributionSampledLevel)) { + for (LogicTreeNode node : level.getNodes()) + nodeColors.put(node, tab10[colorI++ % tab10.length]); + } + } + + Color[] distColors = new Color[levels.size()]; + CPT[] distCPTs = new CPT[levels.size()]; + boolean useDistCPTforPDF = true; + + for (int l=0; l tree = LogicTree.buildSampled(levels, samples, seed, sm); + if (sm == SamplingMethod.MONTE_CARLO) { + // write tree plot + LogicTreeFigureWriter tfw = new LogicTreeFigureWriter(tree, false, true); + tfw.write(outputDir, "logic_tree", true, true); + } + + for (int l=0; l level = levels.get(l); + + String samplePrefix = level.getFilePrefix()+"_samples_"+sm.name(); + + if (level instanceof ContinuousDistributionSampledLevel) { + ContinuousDistributionSampledLevel distLevel = (ContinuousDistributionSampledLevel)level; + ContinuousDistribution dist = distLevel.getDistribution(); + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + Range xRange = new Range(dist.getSupportLowerBound(), dist.getSupportUpperBound()); + EvenlyDiscretizedFunc densityFunc = new EvenlyDiscretizedFunc(xRange.getLowerBound(), xRange.getUpperBound(), 1000); + for (int i=0; i> nodes = distLevel.getNodes(); + + double maxY; + if (samples < 200) { + maxY = Math.max(2d, densityFunc.getMaxY()*1.1); + + funcs.add(densityFunc); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 0.5f, Color.GRAY)); + + if (sm.isLHS()) { + // draw ticks + double tickDelta = maxY*0.05; + EvenlyDiscretizedFunc binEdges = new EvenlyDiscretizedFunc( + 0d, 1d, nodes.size()+1); + PlotCurveCharacterstics tickChar = new PlotCurveCharacterstics(PlotLineType.SOLID, 0.7f, Color.BLACK); + for (int i=0; i node : nodes) { + DefaultXY_DataSet xy = new DefaultXY_DataSet(); + double x = node.getValue(); + double y = dist.density(x); + xy.set(x, y); + + Color color = useDistCPTforPDF ? distCPTs[l].getColor(dist.cumulativeProbability(x)) : distColors[l]; + + funcs.add(xy); + chars.add(new PlotCurveCharacterstics(PlotSymbol.FILLED_CIRCLE, symbolWidth, color)); + + funcs.add(xy); + chars.add(new PlotCurveCharacterstics(PlotSymbol.CIRCLE, symbolWidth, distColors[l].darker().darker())); + } + } else { + maxY = Math.max(2d, densityFunc.getMaxY()*1.5); + double length = dist.getSupportUpperBound() - dist.getSupportLowerBound(); + int bins = 100; + double binWidth = length / bins; + EvenlyDiscretizedFunc hist = new EvenlyDiscretizedFunc(dist.getSupportLowerBound()+0.5*binWidth, bins, binWidth); + for (SimpleValuedNode node : nodes) + hist.add(hist.getClosestXIndex(node.getValue()), 1d); + + hist.scale(1d/(samples*binWidth)); + + funcs.add(hist); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, distColors[l])); + + funcs.add(densityFunc); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 1f, Color.BLACK)); + } + + PlotSpec plot = new PlotSpec(funcs, chars, sm.getName(), level.getName(), "PDF Density"); + + Range yRange = new Range(0d, maxY); + + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + gp.drawGraphPanel(plot, false, false, xRange, yRange); + PlotUtils.setYTick(gp, 0.5); + + PlotUtils.writePrintPlots(outputDir, samplePrefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH*0.5, 3d, dpi, true, true, false); + } else { + List nodes = level.getNodes(); + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + List anns = new ArrayList<>(); + + int maxCount = 0; + + Font nameFont = new Font(Font.SANS_SERIF, Font.BOLD, 12); + Font countFont = new Font(Font.SANS_SERIF, Font.BOLD, 12); + Font subNameFont = new Font(Font.SANS_SERIF, Font.BOLD, 10); + Font subCountFont = new Font(Font.SANS_SERIF, Font.BOLD, 10); + + double offset = samples*0.01; + + for (int i=0; i branch : tree) + if (branch.getValue(l).equals(node)) + count++; + maxCount = Integer.max(count, maxCount); + EvenlyDiscretizedFunc hist = new EvenlyDiscretizedFunc(0.5, nodes.size(), 1d); + hist.set(i, (double)count); + + funcs.add(hist); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, nodeColors.get(node))); + + XYTextAnnotation ann = new XYTextAnnotation(node.getShortName(), hist.getX(i), count+offset); + ann.setFont(nameFont); + ann.setTextAnchor(TextAnchor.BASELINE_CENTER); + anns.add(ann); + + ann = new XYTextAnnotation(count+"", hist.getX(i), offset); + ann.setFont(countFont); + ann.setTextAnchor(TextAnchor.BASELINE_CENTER); + anns.add(ann); + } + + PlotSpec plot = new PlotSpec(funcs, chars, sm.getName(), level.getName(), "Sample Count"); + plot.setPlotAnnotations(anns); + + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + double maxY = switch (nodes.size()){ + case 2: + yield 0.65*samples; + case 3: + yield 0.45*samples; + default: + yield maxCount*1.2d; + }; + gp.drawGraphPanel(plot, false, false, new Range(0d, nodes.size()), new Range(0d, maxY)); + PlotUtils.setAxisVisible(gp, false, true); + PlotUtils.setGridLinesVisible(gp, false, true); + + PlotUtils.writePrintPlots(outputDir, samplePrefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH*0.5, 3d, dpi, true, true, false); + + for (int m=0; m oLevel = levels.get(m); + if (l == m || oLevel instanceof ContinuousDistributionSampledLevel) + continue; + + String pairPrefix = level.getFilePrefix()+"_and_"+oLevel.getFilePrefix()+"_samples_"+sm.name(); + + funcs.clear(); + chars.clear(); + anns.clear(); + + List oNodes = levels.get(m).getNodes(); + + for (int i=0; i branch : tree) + if (branch.getValue(l).equals(node) && branch.getValue(m).equals(oNode)) + subCount++; + + int countStart = count; + int countEnd = count+subCount; + EvenlyDiscretizedFunc hist = new EvenlyDiscretizedFunc(0.5, nodes.size(), 1d); + hist.set(i, (double)countEnd); + + funcs.add(hist); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, nodeColors.get(oNode))); + + XYTextAnnotation ann = new XYTextAnnotation(oNode.getShortName(), x, countEnd); + ann.setFont(subNameFont); + ann.setTextAnchor(TextAnchor.TOP_CENTER); + anns.add(ann); + + ann = new XYTextAnnotation(subCount+"", x, countStart+0.5*offset); + ann.setFont(subCountFont); + ann.setTextAnchor(TextAnchor.BASELINE_CENTER); + anns.add(ann); + + count = countEnd; + } + + XYTextAnnotation ann = new XYTextAnnotation(node.getShortName(), x, count+offset); + ann.setFont(nameFont); + ann.setTextAnchor(TextAnchor.BASELINE_CENTER); + anns.add(ann); + } + + plot = new PlotSpec(funcs, chars, sm.getName(), level.getName(), "Sample Count"); + plot.setPlotAnnotations(anns); + + gp.setRenderingOrder(DatasetRenderingOrder.REVERSE); + gp.drawGraphPanel(plot, false, false, new Range(0d, nodes.size()), new Range(0d, maxY)); + PlotUtils.setAxisVisible(gp, false, true); + PlotUtils.setGridLinesVisible(gp, false, true); + + PlotUtils.writePrintPlots(outputDir, pairPrefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH*0.5, 3d, dpi, true, true, false); + } + } + } + + if (samples <= 30) { + // build branch vector plot + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + List anns = new ArrayList<>(); + + BasicStroke outlineStroke = new BasicStroke(1f); +// Font indexOrigFont = new Font(Font.SANS_SERIF, Font.PLAIN, 10); +// Font indexSwappedFont = new Font(Font.SANS_SERIF, Font.BOLD, 10); + + + Font indexOrigFont = null; + Font indexSwappedFont = new Font(Font.SANS_SERIF, Font.PLAIN, 10); + + List origBranchIndexes = null; + if (sm ==SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE) { + LogicTree tree2 = LogicTree.buildSampled(levels, samples, seed, SamplingMethod.LATIN_HYPERCUBE); + List levelFixedWeights = new ArrayList<>(); + for (int l=0; l level = levels.get(l); + if (level instanceof ContinuousDistributionSampledLevel) { + levelFixedWeights.add(null); + } else { + List nodes = level.getNodes(); + double[] weights = new double[nodes.size()]; + for (int n=0; n iter = new LogicTreePairwiseLHSIteration<>( + levels, tree2.getBranches(), levelFixedWeights); + + iter.setTrackSwaps(true); + + iter.iterate(Integer.max(10000, samples*100), new Random(seed), false); + + origBranchIndexes = iter.getOriginalBranchIndexes(); + tree = tree2; + } + + for (int n=0; n branch = tree.getBranch(n); + + double x0 = n-0.4; + double x1 = n+0.4; + + for (int l=0; l level = levels.get(l); + LogicTreeNode node = branch.getValue(l); + + Color color; + if (level instanceof ContinuousDistributionSampledLevel) { + ContinuousDistribution dist = ((ContinuousDistributionSampledLevel)level).getDistribution(); + double value = ((ValuedLogicTreeNode)node).getValue(); + color = distCPTs[l].getColor(dist.cumulativeProbability(value)); + } else { + color = nodeColors.get(node); + } + + double y1 = (levels.size()-l); + double y0 = y1-1; + double y = y0+0.5; +// double y0 = l; +// double y1 = l+1; +// double y = l+0.5; + + anns.add(new XYBoxAnnotation(x0, y0, x1, y1, outlineStroke, Color.BLACK, color)); + + if (origBranchIndexes != null) { + int index = origBranchIndexes.get(n)[l]; + XYTextAnnotation indexAnn = new XYTextAnnotation(index+"", x, y); + indexAnn.setTextAnchor(TextAnchor.CENTER); + if (index == n) { + if (indexOrigFont != null) { + indexAnn.setFont(indexOrigFont); + anns.add(indexAnn); + } + } else { + indexAnn.setFont(indexSwappedFont); + anns.add(indexAnn); + } + } + } + } + + PlotSpec plot = new PlotSpec(funcs, chars, sm.getName(), "Branch Index", " "); + plot.setPlotAnnotations(anns); + + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + gp.drawGraphPanel(plot, false, false, new Range(-0.5d, samples-0.5), new Range(-0.05d, levels.size()+0.05)); + PlotUtils.setAxisVisible(gp, true, false); + PlotUtils.setGridLinesVisible(gp, false, false); + + PlotUtils.writePrintPlots(outputDir, "branches_"+sm.name(), gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH, 3d, dpi, true, true, false); + } + } + } + + private enum DefModelEnum implements LogicTreeNode.FixedWeightNode { + GEOLOGIC("Geologic", 0.5), + GEODETIC("Geodetic", 0.5); + + private String name; + private double weight; + + private DefModelEnum(String name, double weight) { + this.name = name; + this.weight = weight; + } + + @Override + public String getFilePrefix() { + return name(); + } + + @Override + public String getShortName() { + return name; + } + + @Override + public String getName() { + return name; + } + + @Override + public double getNodeWeight() { + return weight; + } + } + + private enum ScaleEnum implements LogicTreeNode.FixedWeightNode { + LOGA_4p1("LogA+4.1", 1d/3d), + LOGA_4p2("LogA+4.2", 1d/3d), + LOGA_4p3("LogA+4.3", 1d/3d); + + private String name; + private double weight; + + private ScaleEnum(String name, double weight) { + this.name = name; + this.weight = weight; + } + + @Override + public String getFilePrefix() { + return name(); + } + + @Override + public String getShortName() { + return name; + } + + @Override + public String getName() { + return name; + } + + @Override + public double getNodeWeight() { + return weight; + } + } + +} diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 866e52f2..15c1a3be 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -756,14 +756,16 @@ public static void main(String[] args) throws IOException { // int numBranchSamples = 2000; int numBranchSamples = 5000; // int numBranchSamples = 10000; +// int numBranchSamples = 20000; // int numBranchSamples = 100000; TectonicRegionType trt = null; parallelBA = true; - boolean deterministicSeed = true; + boolean deterministicSeed = false; -// SamplingMethod samplingMethod = SamplingMethod.MONTE_CARLO; - SamplingMethod samplingMethod = SamplingMethod.LATIN_HYPERCUBE; + SamplingMethod samplingMethod = SamplingMethod.MONTE_CARLO; +// SamplingMethod samplingMethod = SamplingMethod.LATIN_HYPERCUBE; +// SamplingMethod samplingMethod = SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE; if (trt == null) { customTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, numBranchSamples, deterministicSeed, samplingMethod); @@ -780,8 +782,12 @@ public static void main(String[] args) throws IOException { List> levels = new ArrayList<>(customTree.getLevels()); dirName += "-nshm27-"+seisReg.name()+"-"+numBranchSamples+"samples"; - if (samplingMethod == SamplingMethod.LATIN_HYPERCUBE) + if (samplingMethod == SamplingMethod.MONTE_CARLO) + dirName += "-mcs"; + else if (samplingMethod == SamplingMethod.LATIN_HYPERCUBE) dirName += "-lhs"; + else if (samplingMethod == SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE) + dirName += "-lhs_pairwise"; if (!deterministicSeed) dirName += "-unique_seed"; if (trt != null) @@ -797,6 +803,7 @@ public static void main(String[] args) throws IOException { Region mapRegion = NSHM27_MapRegions.valueOf(seisReg.name()).load(); forceHazardReg = new GriddedRegion(mapRegion, 0.1, GriddedRegion.ANCHOR_0_0); +// forceHazardReg = new GriddedRegion(mapRegion, 0.2, GriddedRegion.ANCHOR_0_0); dirName += "-haz0.2deg"; // forceHazardReg = new GriddedRegion(mapRegion, 0.025, GriddedRegion.ANCHOR_0_0); sigmaTrunc = 3d; diff --git a/src/main/java/scratch/kevin/nshm23/NSHM23LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm23/NSHM23LogicTreeFigure.java new file mode 100644 index 00000000..650f9162 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm23/NSHM23LogicTreeFigure.java @@ -0,0 +1,26 @@ +package scratch.kevin.nshm23; + +import java.io.File; +import java.io.IOException; + +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeFigureWriter; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.NSHM23_LogicTreeBranch; + +public class NSHM23LogicTreeFigure { + + public static void main(String[] args) throws IOException { + LogicTree tree = LogicTree.buildExhaustive(NSHM23_LogicTreeBranch.levelsOnFault, true); + LogicTreeFigureWriter treeFig = new LogicTreeFigureWriter(tree, false, true); + treeFig.write(new File("/tmp/"), "nshm23_on_fault", true, false); + + tree = LogicTree.buildExhaustive(NSHM23_LogicTreeBranch.levelsOffFault, true); + treeFig = new LogicTreeFigureWriter(tree, false, true); + treeFig.write(new File("/tmp/"), "nshm23_off_fault", true, false); + + tree = LogicTree.buildExhaustive(NSHM23_LogicTreeBranch.levelsCombined, true); + treeFig = new LogicTreeFigureWriter(tree, false, true); + treeFig.write(new File("/tmp/"), "nshm23_combined", true, false); + } + +} diff --git a/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java b/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java index ad7b1187..a17ab498 100644 --- a/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java +++ b/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java @@ -36,6 +36,7 @@ public static void main(String[] args) throws IOException { // ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(7.6, 0.134, 7.15, 8.05); ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(8, 0.2, 7.45, 8.55); int precisionScale = 1; + int bins = 3; //// ContinuousDistribution dist = UniformContinuousDistribution.of(0d, 1d); //// ContinuousDistribution dist = UniformContinuousDistribution.of(0.5d, 1d); @@ -121,7 +122,7 @@ public static void main(String[] args) throws IOException { chars.add(new PlotCurveCharacterstics(PlotSymbol.FILLED_CIRCLE, 5f, Colors.tab_green)); } - ContinuousDistributionBinnedLevel binned = level.toBinnedLevel(); + ContinuousDistributionBinnedLevel binned = bins > 0 ? level.toBinnedLevel(bins) : level.toBinnedLevel(); List>> binNodes = binned.getNodes(); for (int i=0; i> node = binNodes.get(i); From d24066efb1fad7b3af8894ddae9609668cb5ca84 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 20 Apr 2026 11:27:22 -0700 Subject: [PATCH 25/71] minor --- .../kevin/ltSampling/LHSExampleFigures.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java index 2964743e..494eedab 100644 --- a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java +++ b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java @@ -51,9 +51,9 @@ public class LHSExampleFigures { public static void main(String[] args) throws IOException { -// int samples = 30; + int samples = 30; // int samples = 100; - int samples = 1000; +// int samples = 1000; // int samples = 2000; int dpi = 300; @@ -384,9 +384,9 @@ public static void main(String[] args) throws IOException { // double y1 = l+1; // double y = l+0.5; - anns.add(new XYBoxAnnotation(x0, y0, x1, y1, outlineStroke, Color.BLACK, color)); - - if (origBranchIndexes != null) { + if (origBranchIndexes == null) { + anns.add(new XYBoxAnnotation(x0, y0, x1, y1, outlineStroke, Color.BLACK, color)); + } else { int index = origBranchIndexes.get(n)[l]; XYTextAnnotation indexAnn = new XYTextAnnotation(index+"", x, y); indexAnn.setTextAnchor(TextAnchor.CENTER); @@ -395,11 +395,16 @@ public static void main(String[] args) throws IOException { indexAnn.setFont(indexOrigFont); anns.add(indexAnn); } + anns.add(new XYBoxAnnotation(x0, y0, x1, y1, outlineStroke, Color.BLACK, + new Color(color.getRed(), color.getGreen(), color.getBlue(), 60))); } else { + anns.add(new XYBoxAnnotation(x0, y0, x1, y1, outlineStroke, Color.BLACK, color)); indexAnn.setFont(indexSwappedFont); anns.add(indexAnn); } } + + } } From f5642751c37204ec092e5848565db0e90b9f0c1b Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 24 Apr 2026 10:21:03 -0700 Subject: [PATCH 26/71] inversion slurm submit script reorg --- .../scratch/kevin/HazardMapScriptCreator.java | 2 +- .../scratch/kevin/MPJ_HPC_DebugScriptGen.java | 2 +- .../scratch/kevin/MorganSTREC_ScriptGen.java | 2 +- .../kevin/bbp/MPJ_BBP_RupGenSimScriptGen.java | 2 +- .../scratch/kevin/nshm23/BA_Reprocess.java | 2 +- .../nshm23/BatchInversionScriptWriter.java | 4 +- .../BranchAveragedHazardScriptWriter.java | 2 +- .../nshm23/FaultSlipRateInvestigations.java | 7 +++- .../nshm23/GMM_LogicTreeBranchAttach.java | 2 +- .../nshm23/InvFileDeadlockScriptWriter.java | 2 +- ..._LogicTreeInversionRunnerScriptWriter.java | 26 ++++++------ .../MPJ_WrapperHazardCalcScriptWriter.java | 2 +- ...ourceBranchAveragedHazardScriptWriter.java | 2 +- .../PaperHazardScriptWriter.java | 2 +- .../HazardBranchesPostProcessPBSWriter.java | 8 ++-- .../HazardMapLogicTreeInRegionsGen.java | 2 +- .../kevin/prvi25/BowinFaultAddTest.java | 2 +- .../kevin/prvi25/GMMLogicTreeWriter.java | 4 +- .../kevin/simulators/erf/HazardMapPBSGen.java | 9 +++-- .../TimeDepFSS_ERF_Simulator_ScriptGen.java | 2 +- .../hazard/HazardMapCompareScriptGen.java | 12 +++--- .../UCERF3ComparisonScriptGen.java | 2 +- .../ruptures/MPJ_BBP_CatalogSimScriptGen.java | 2 +- .../ruptures/MPJ_BBP_PartBSimScriptGen.java | 2 +- .../ruptures/MPJ_BBP_RuptureScriptsGen.java | 10 +++-- .../azimuthal/AzimuthalScriptsGen.java | 14 +++---- ...atedRupVariabilityMagDistSimScriptGen.java | 2 +- ...tedRupVariabilityScenarioSimScriptGen.java | 2 +- .../SurfDistCacheTestScriptWriter.java | 4 +- .../kevin/ucerf3/BulkCompoundScriptWrite.java | 11 +++-- .../GriddedSeisImportanceHazardMapCalc.java | 10 ++--- .../MPJ_UCERF3_ShakeMapPrecalcScriptGen.java | 2 +- .../eal/MPJ_UCERF3_EAL_CombinerScriptGen.java | 2 +- .../ucerf3/eal/UCERF3_EAL_ScriptGen.java | 2 +- .../eal/UCERF3_EAL_Validate_ScriptGen.java | 2 +- ..._SpatiallyCorrelatedLossCalcScriptGen.java | 2 +- .../ucerf3/etas/CacheSpeedScriptGen.java | 40 ------------------- .../etas/MPJ_ETAS_HazardMapCalcScriptGen.java | 14 +++---- .../MPJ_ETAS_SimulatorInternScriptGen.java | 2 +- .../etas/MPJ_ETAS_SimulatorScriptGen.java | 20 +++++----- ...J_GK_DesclusteringHazardCalcScriptGen.java | 2 +- .../inversion/InversionEALInputGen.java | 2 +- .../kevin/ucerf3/maps/MapScriptWriter.java | 2 +- .../maps/MultiSolComparisonMapScriptGen.java | 5 ++- 44 files changed, 110 insertions(+), 144 deletions(-) delete mode 100644 src/main/java/scratch/kevin/ucerf3/etas/CacheSpeedScriptGen.java diff --git a/src/main/java/scratch/kevin/HazardMapScriptCreator.java b/src/main/java/scratch/kevin/HazardMapScriptCreator.java index 61547cbc..31b02c07 100644 --- a/src/main/java/scratch/kevin/HazardMapScriptCreator.java +++ b/src/main/java/scratch/kevin/HazardMapScriptCreator.java @@ -153,7 +153,7 @@ public static void main(String[] args) throws IOException { List script = mpj.buildScript(MPJHazardCurveDriver.class.getName(), cliArgs); USC_HPCC_ScriptWriter writer = new USC_HPCC_ScriptWriter(); - script = writer.buildScript(script, mins, nodes, ppn, queue); + script = writer.buildScript(script, mins, nodes, ppn, -1, queue); File pbsFile = new File(localJobDir, jobName+".pbs"); System.out.println("Writing "+pbsFile.getAbsolutePath()); diff --git a/src/main/java/scratch/kevin/MPJ_HPC_DebugScriptGen.java b/src/main/java/scratch/kevin/MPJ_HPC_DebugScriptGen.java index 21756ce4..e6832e62 100644 --- a/src/main/java/scratch/kevin/MPJ_HPC_DebugScriptGen.java +++ b/src/main/java/scratch/kevin/MPJ_HPC_DebugScriptGen.java @@ -69,7 +69,7 @@ public static void main(String[] args) throws IOException { script = fmpjWrite.buildScript(className, myArgs); else script = mpjWrite.buildScript(className, myArgs); - script = pbsWrite.buildScript(script, mins, nodes, ppn, queue); + script = pbsWrite.buildScript(script, mins, nodes, ppn, -1, queue); pbsWrite.writeScript(new File(localDir, prefix+".pbs"), script); } diff --git a/src/main/java/scratch/kevin/MorganSTREC_ScriptGen.java b/src/main/java/scratch/kevin/MorganSTREC_ScriptGen.java index 801a17a5..c27ec4b7 100644 --- a/src/main/java/scratch/kevin/MorganSTREC_ScriptGen.java +++ b/src/main/java/scratch/kevin/MorganSTREC_ScriptGen.java @@ -69,7 +69,7 @@ public static void main(String[] args) throws IOException { runNum = "0"+runNum; File opbsFile = new File(writeDir, "job"+runNum+".pbs"); - pbsWrite.writeScript(opbsFile, script, mins, nodes, ppn, queue); + pbsWrite.writeScript(opbsFile, script, mins, nodes, ppn, -1, queue); } for (int i=0; i script = mpjWrite.buildScript(MPJ_BBP_RupGenSim.class.getName(), argz); - script = pbsWrite.buildScript(script, mins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mins, nodes, threads, -1, queue); pbsWrite.writeScript(new File(localJobDir, "bbp_parallel.pbs"), script); } diff --git a/src/main/java/scratch/kevin/nshm23/BA_Reprocess.java b/src/main/java/scratch/kevin/nshm23/BA_Reprocess.java index 13fc3f75..9dc5f13a 100644 --- a/src/main/java/scratch/kevin/nshm23/BA_Reprocess.java +++ b/src/main/java/scratch/kevin/nshm23/BA_Reprocess.java @@ -64,7 +64,7 @@ public static void main(String[] args) throws IOException { argz += " --annealing-threads 1"; List script = mpjWrite.buildScript(MPJ_LogicTreeInversionRunner.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, "ba_regen.slurm"), script, mins, nodes, remoteToalThreads, queue); + pbsWrite.writeScript(new File(localDir, "ba_regen.slurm"), script, mins, nodes, remoteToalThreads, -1, queue); } } diff --git a/src/main/java/scratch/kevin/nshm23/BatchInversionScriptWriter.java b/src/main/java/scratch/kevin/nshm23/BatchInversionScriptWriter.java index ed8ec0dc..b65a4bf0 100644 --- a/src/main/java/scratch/kevin/nshm23/BatchInversionScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/BatchInversionScriptWriter.java @@ -1742,7 +1742,7 @@ else if (dirName.contains("tapered")) script.add("# open up permissions"); script.add("chmod -R go+rX "+remoteSubDir.getAbsolutePath()); - script = scriptWrite.buildScript(script, mins, 1, remoteToalThreads, queue); + script = scriptWrite.buildScript(script, mins, 1, remoteToalThreads, -1, queue); File localScript = new File(localSubDir, name+".slurm"); System.out.println("Writing "+localScript.getAbsolutePath()); @@ -1799,7 +1799,7 @@ public static void writeMeanJob(int remoteToalThreads, BatchScriptWriter scriptW script.add("# open up permissions"); script.add("chmod -R go+rX "+remoteDir.getAbsolutePath()); - script = scriptWrite.buildScript(script, 60, 1, remoteToalThreads, queue); + script = scriptWrite.buildScript(script, 60, 1, remoteToalThreads, -1, queue); File localScript = new File(localDir, "mean_solution.slurm"); System.out.println("Writing "+localScript.getAbsolutePath()); diff --git a/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java b/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java index 8f4cfa9f..de8c5a63 100644 --- a/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java @@ -336,7 +336,7 @@ else if (!supersampleQuick) System.out.println("Writing "+jobFile.getAbsolutePath()); - pbsWrite.writeScript(jobFile, script, mins, myNodes, remoteTotalThreads, queue); + pbsWrite.writeScript(jobFile, script, mins, myNodes, remoteTotalThreads, -1, queue); } } diff --git a/src/main/java/scratch/kevin/nshm23/FaultSlipRateInvestigations.java b/src/main/java/scratch/kevin/nshm23/FaultSlipRateInvestigations.java index 03961d5e..1a5365a5 100644 --- a/src/main/java/scratch/kevin/nshm23/FaultSlipRateInvestigations.java +++ b/src/main/java/scratch/kevin/nshm23/FaultSlipRateInvestigations.java @@ -18,8 +18,11 @@ public static void main(String[] args) throws IOException { NSHM23_FaultModels fm = NSHM23_FaultModels.WUS_FM_v3; FaultModels u3FM = FaultModels.FM3_1; - int nshm23_id = FaultSectionUtils.findSectionID(fm.getFaultSections(), "Silver", "Creek"); - int u3_id = FaultSectionUtils.findSectionID(u3FM.getFaultSections(), "Silver", "Creek"); +// int nshm23_id = FaultSectionUtils.findSectionID(fm.getFaultSections(), "Silver", "Creek"); +// int u3_id = FaultSectionUtils.findSectionID(u3FM.getFaultSections(), "Silver", "Creek"); + + int nshm23_id = FaultSectionUtils.findSectionID(fm.getFaultSections(), "Rose", "Canyon"); + int u3_id = FaultSectionUtils.findSectionID(u3FM.getFaultSections(), "Rose", "Canyon"); double u3Avg = avgSlipRate(DeformationModels.MEAN_UCERF3.build(u3FM, DeformationModels.MEAN_UCERF3, null), u3_id); NSHM23_DeformationModels[] dms = NSHM23_DeformationModels.values(); diff --git a/src/main/java/scratch/kevin/nshm23/GMM_LogicTreeBranchAttach.java b/src/main/java/scratch/kevin/nshm23/GMM_LogicTreeBranchAttach.java index 77418ac7..65653c47 100644 --- a/src/main/java/scratch/kevin/nshm23/GMM_LogicTreeBranchAttach.java +++ b/src/main/java/scratch/kevin/nshm23/GMM_LogicTreeBranchAttach.java @@ -119,7 +119,7 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) int nodeRounds = (int)Math.ceil((double)finalTree.getLogicTree().size()/(double)(nodes)); int mins = minsEach*nodeRounds + 60; nodes = Integer.min(40, nodes); - pbsWrite.writeScript(new File(destDir, "batch_hazard.slurm"), script, mins, nodes, remoteToalThreads, queue); + pbsWrite.writeScript(new File(destDir, "batch_hazard.slurm"), script, mins, nodes, remoteToalThreads, -1, queue); } } diff --git a/src/main/java/scratch/kevin/nshm23/InvFileDeadlockScriptWriter.java b/src/main/java/scratch/kevin/nshm23/InvFileDeadlockScriptWriter.java index c13dee46..05290cd4 100644 --- a/src/main/java/scratch/kevin/nshm23/InvFileDeadlockScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/InvFileDeadlockScriptWriter.java @@ -159,7 +159,7 @@ public static void main(String[] args) throws IOException { argz += " "+MPJTaskCalculator.argumentBuilder().exactDispatch(remoteInversionsPerBundle).build(); List script = mpjWrite.buildScript(MPJ_LogicTreeInversionRunner.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, localDir.getName()+".slurm"), script, minsEach, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, localDir.getName()+".slurm"), script, minsEach, nodes, remoteTotalThreads, -1, queue); } } diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 15c1a3be..6e8747c6 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -1085,7 +1085,7 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) System.out.println("Total job time: "+mins+" mins = "+(float)((double)mins/60d)+" hours"); // make sure to not exceed 1 week mins = Integer.min(mins, 60*24*7 - 1); - pbsWrite.writeScript(new File(localDir, "batch_inversion.slurm"), script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "batch_inversion.slurm"), script, mins, nodes, remoteTotalThreads, -1, queue); Map baFiles = AbstractAsyncLogicTreeWriter.getBranchAverageSolutionFileMap(new File("results"), logicTree); @@ -1155,7 +1155,7 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) if (queue != null && queue.equals("scec")) // run hazard in the high priority queue queue = "scec_hiprio"; - pbsWrite.writeScript(new File(localDir, "batch_hazard.slurm"), script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "batch_hazard.slurm"), script, mins, nodes, remoteTotalThreads, -1, queue); JavaShellScriptWriter javaWrite = new JavaShellScriptWriter( mpjWrite.getJavaBin(), remoteTotalMemGB*1024, classpath); @@ -1208,7 +1208,7 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) int gridThreads = Integer.max(1, remoteTotalThreads/2); argz += " "+MPJTaskCalculator.argumentBuilder().exactDispatch(1).threads(gridThreads).build(); script = mpjWrite.buildScript(MPJ_GridSeisBranchBuilder.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, "batch_grid_calc.slurm"), script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "batch_grid_calc.slurm"), script, mins, nodes, remoteTotalThreads, -1, queue); String griddedBAName = null; if (baFiles != null && baFiles.size() == 1) @@ -1220,7 +1220,7 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) if (griddedBAName != null) argz += " "+dirPath+"/"+griddedBAName; script = javaWrite.buildScript(TrueMeanSolutionCreator.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, "true_mean_builder.slurm"), script, mins, 1, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "true_mean_builder.slurm"), script, mins, 1, remoteTotalThreads, -1, queue); // now add hazard calc jobs with gridded for (int i=0; i<5; i++) { @@ -1295,7 +1295,7 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) int myMins = mins; if (i == 1) myMins = Integer.min(mins*5, 60*24*7 - 1); - pbsWrite.writeScript(jobFile, script, myMins, myNodes, remoteTotalThreads, queue); + pbsWrite.writeScript(jobFile, script, myMins, myNodes, remoteTotalThreads, -1, queue); } // write out gridded seismicity combiner script @@ -1309,12 +1309,12 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) argz += " "+resultsPath+"_hazard.zip"; script = javaWrite.buildScript(FaultAndGriddedSeparateTreeHazardCombiner.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, "fault_grid_hazard_combine.slurm"), script, mins, 1, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "fault_grid_hazard_combine.slurm"), script, mins, 1, remoteTotalThreads, -1, queue); } else { // true mean without gridded argz = resultsPath+".zip true_mean_solution.zip"; script = javaWrite.buildScript(TrueMeanSolutionCreator.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, "true_mean_builder.slurm"), script, mins, 1, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "true_mean_builder.slurm"), script, mins, 1, remoteTotalThreads, -1, queue); } // site hazard job @@ -1360,7 +1360,7 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) for (AttenRelRef gmpe : gmpes) argz += " --gmpe "+gmpe.name(); script = mpjWrite.buildScript(MPJ_SiteLogicTreeHazardCurveCalc.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, "batch_hazard_sites.slurm"), script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "batch_hazard_sites.slurm"), script, mins, nodes, remoteTotalThreads, -1, queue); if (griddedJob) { Preconditions.checkState(!hazardGridded); @@ -1377,7 +1377,7 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) argz += " --gmpe "+gmpe.name(); argz += " "+MPJTaskCalculator.argumentBuilder().minDispatch(2).maxDispatch(10).threads(remoteTotalThreads).build(); script = mpjWrite.buildScript(MPJ_SiteLogicTreeHazardCurveCalc.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, "batch_hazard_sites_full_gridded.slurm"), script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "batch_hazard_sites_full_gridded.slurm"), script, mins, nodes, remoteTotalThreads, -1, queue); } } } @@ -1441,7 +1441,7 @@ else if (baFiles.size() == 1) argz += " --branch-averaged-file "+dirPath+"/"+baFile.getName(); script = javaWrite.buildScript(LogicTreeBranchAverageWriter.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, "full_node_ba"+baJobSuffixes.get(n)+".slurm"), script, mins, 1, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "full_node_ba"+baJobSuffixes.get(n)+".slurm"), script, mins, 1, remoteTotalThreads, -1, queue); // // write out individual node BA scripts (useful if the tree is enormous // File baIndvLocalDir = new File(localDir, "indv_node_ba_scripts"); @@ -1494,7 +1494,7 @@ else if (baFiles.size() == 1) argz += " "+MPJTaskCalculator.argumentBuilder().exactDispatch(1).threads(remoteTotalThreads).build(); script = mpjWrite.buildScript(MPJ_LogicTreeBranchAverageBuilder.class.getName(), argz); pbsWrite.writeScript(new File(localDir, "batch_node_ba"+baJobSuffixes.get(n)+".slurm"), - script, mins, myNodes, remoteTotalThreads, queue); + script, mins, myNodes, remoteTotalThreads, -1, queue); } } } @@ -1561,7 +1561,7 @@ else if (baFiles.size() == 1) int transNodes = Integer.min(16, nodes); pbsWrite.writeScript(new File(modLocalDir, "batch_strict_branch_translate.slurm"), script, mins, transNodes, - remoteTotalThreads, queue); + remoteTotalThreads, -1, queue); // now write hazard script argz = "--input-file "+modResultsPath+".zip"; @@ -1570,7 +1570,7 @@ else if (baFiles.size() == 1) script = mpjWrite.buildScript(MPJ_LogicTreeHazardCalc.class.getName(), argz); nodes = Integer.min(40, nodes); - pbsWrite.writeScript(new File(modLocalDir, "batch_hazard.slurm"), script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(modLocalDir, "batch_hazard.slurm"), script, mins, nodes, remoteTotalThreads, -1, queue); } } diff --git a/src/main/java/scratch/kevin/nshm23/wrapper/MPJ_WrapperHazardCalcScriptWriter.java b/src/main/java/scratch/kevin/nshm23/wrapper/MPJ_WrapperHazardCalcScriptWriter.java index db2b6d76..978548c3 100644 --- a/src/main/java/scratch/kevin/nshm23/wrapper/MPJ_WrapperHazardCalcScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/wrapper/MPJ_WrapperHazardCalcScriptWriter.java @@ -155,7 +155,7 @@ else if (mpjWrite instanceof FastMPJShellScriptWriter) // make sure to not exceed 1 week mins = Integer.min(mins, 60*24*7 - 1); - pbsWrite.writeScript(new File(localDir, "batch_wrapper_calc.slurm"), script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, "batch_wrapper_calc.slurm"), script, mins, nodes, remoteTotalThreads, -1, queue); } } diff --git a/src/main/java/scratch/kevin/pointSources/PointSourceBranchAveragedHazardScriptWriter.java b/src/main/java/scratch/kevin/pointSources/PointSourceBranchAveragedHazardScriptWriter.java index a2b8d9f7..6cea3bd7 100644 --- a/src/main/java/scratch/kevin/pointSources/PointSourceBranchAveragedHazardScriptWriter.java +++ b/src/main/java/scratch/kevin/pointSources/PointSourceBranchAveragedHazardScriptWriter.java @@ -394,7 +394,7 @@ else if (!supersampleQuick) System.out.println("Writing "+jobFile.getAbsolutePath()); - pbsWrite.writeScript(jobFile, script, mins, myNodes, remoteTotalThreads, queue); + pbsWrite.writeScript(jobFile, script, mins, myNodes, remoteTotalThreads, -1, queue); } } diff --git a/src/main/java/scratch/kevin/pointSources/paperFigs2026/PaperHazardScriptWriter.java b/src/main/java/scratch/kevin/pointSources/paperFigs2026/PaperHazardScriptWriter.java index 954f582a..3f7edb66 100644 --- a/src/main/java/scratch/kevin/pointSources/paperFigs2026/PaperHazardScriptWriter.java +++ b/src/main/java/scratch/kevin/pointSources/paperFigs2026/PaperHazardScriptWriter.java @@ -273,7 +273,7 @@ else if (gridReg.getNodeCount() > 5000) // System.out.println("\t\tWriting "+jobFile.getAbsolutePath()); - pbsWrite.writeScript(jobFile, script, mins, myNodes, remoteTotalThreads, queue); + pbsWrite.writeScript(jobFile, script, mins, myNodes, remoteTotalThreads, -1, queue); } } } diff --git a/src/main/java/scratch/kevin/portfolioLEC/HazardBranchesPostProcessPBSWriter.java b/src/main/java/scratch/kevin/portfolioLEC/HazardBranchesPostProcessPBSWriter.java index ff3fe7f7..4d950fb9 100644 --- a/src/main/java/scratch/kevin/portfolioLEC/HazardBranchesPostProcessPBSWriter.java +++ b/src/main/java/scratch/kevin/portfolioLEC/HazardBranchesPostProcessPBSWriter.java @@ -5,7 +5,7 @@ import java.util.List; import org.opensha.commons.hpc.JavaShellScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; +import org.opensha.commons.hpc.pbs.USC_CARC_ScriptWriter; import com.google.common.collect.Lists; @@ -24,8 +24,8 @@ public static void main(String[] args) throws IOException { List classpath = Lists.newArrayList(); classpath.add(new File("/home/scec-02/kmilner/hazMaps/svn/dist/OpenSHA_complete.jar")); - JavaShellScriptWriter javaWrite = new JavaShellScriptWriter(USC_HPCC_ScriptWriter.JAVA_BIN, 7000, classpath); - USC_HPCC_ScriptWriter pbsWrite = new USC_HPCC_ScriptWriter("dodecacore"); + JavaShellScriptWriter javaWrite = new JavaShellScriptWriter(USC_CARC_ScriptWriter.JAVA_BIN, 7000, classpath); + USC_CARC_ScriptWriter pbsWrite = new USC_CARC_ScriptWriter("dodecacore"); int mins = 60; int nodes = 1; @@ -43,7 +43,7 @@ public static void main(String[] args) throws IOException { List script = javaWrite.buildScript(HazardBranchesPostProcess.class.getName(), cliargs); File pbsFile = new File(outDir, "assemble_"+name+".pbs"); - pbsWrite.writeScript(pbsFile, script, mins, nodes, ppn, queue); + pbsWrite.writeScript(pbsFile, script, mins, nodes, ppn, -1, queue); } } diff --git a/src/main/java/scratch/kevin/portfolioLEC/HazardMapLogicTreeInRegionsGen.java b/src/main/java/scratch/kevin/portfolioLEC/HazardMapLogicTreeInRegionsGen.java index 6f387307..426ec9d1 100644 --- a/src/main/java/scratch/kevin/portfolioLEC/HazardMapLogicTreeInRegionsGen.java +++ b/src/main/java/scratch/kevin/portfolioLEC/HazardMapLogicTreeInRegionsGen.java @@ -256,7 +256,7 @@ public static void main(String[] args) throws DocumentException, IOException { File pbsFile = new File(writeDir, prefix+".pbs"); USC_HPCC_ScriptWriter pbsWriter = new USC_HPCC_ScriptWriter(); - pbsWriter.writeScript(pbsFile, script, mins, nodes, ppn, queue); + pbsWriter.writeScript(pbsFile, script, mins, nodes, ppn, -1, queue); } } diff --git a/src/main/java/scratch/kevin/prvi25/BowinFaultAddTest.java b/src/main/java/scratch/kevin/prvi25/BowinFaultAddTest.java index 73a3b2e0..4baa4fd0 100644 --- a/src/main/java/scratch/kevin/prvi25/BowinFaultAddTest.java +++ b/src/main/java/scratch/kevin/prvi25/BowinFaultAddTest.java @@ -318,7 +318,7 @@ public static void main(String[] args) throws IOException { System.out.println("Writing "+jobFile.getAbsolutePath()); - pbsWrite.writeScript(jobFile, script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(jobFile, script, mins, nodes, remoteTotalThreads, -1, queue); } } diff --git a/src/main/java/scratch/kevin/prvi25/GMMLogicTreeWriter.java b/src/main/java/scratch/kevin/prvi25/GMMLogicTreeWriter.java index f5dabd4d..d6354152 100644 --- a/src/main/java/scratch/kevin/prvi25/GMMLogicTreeWriter.java +++ b/src/main/java/scratch/kevin/prvi25/GMMLogicTreeWriter.java @@ -300,7 +300,7 @@ else if (bgOp == IncludeBackgroundOption.EXCLUDE) } argz += " "+MPJTaskCalculator.argumentBuilder().maxDispatch(100).threads(remoteTotalThreads).build(); List script = mpjWrite.buildScript(MPJ_LogicTreeHazardCalc.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, mapScriptName), script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, mapScriptName), script, mins, nodes, remoteTotalThreads, -1, queue); // now write hazard curve script CSVFile csv = CSVFile.readStream(PRVI25_CrustalFaultModels.class.getResourceAsStream("/data/erf/prvi25/sites/prvi_sites.csv"), true); @@ -338,7 +338,7 @@ else if (bgOp == IncludeBackgroundOption.EXCLUDE) } argz += " "+MPJTaskCalculator.argumentBuilder().minDispatch(1).maxDispatch(10).threads(remoteTotalThreads).build(); script = mpjWrite.buildScript(MPJ_SiteLogicTreeHazardCurveCalc.class.getName(), argz); - pbsWrite.writeScript(new File(localDir, siteScriptName), script, mins, nodes, remoteTotalThreads, queue); + pbsWrite.writeScript(new File(localDir, siteScriptName), script, mins, nodes, remoteTotalThreads, -1, queue); // combTree = LogicTree.read(new File(outputDir, "logic_tree.json")); // diff --git a/src/main/java/scratch/kevin/simulators/erf/HazardMapPBSGen.java b/src/main/java/scratch/kevin/simulators/erf/HazardMapPBSGen.java index 6fe5b425..f162beb4 100644 --- a/src/main/java/scratch/kevin/simulators/erf/HazardMapPBSGen.java +++ b/src/main/java/scratch/kevin/simulators/erf/HazardMapPBSGen.java @@ -20,7 +20,6 @@ import org.opensha.commons.hpc.JavaShellScriptWriter; import org.opensha.commons.hpc.mpj.FastMPJShellScriptWriter; import org.opensha.commons.hpc.pbs.BatchScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; import org.opensha.commons.util.XMLUtils; import org.opensha.sha.calc.hazardMap.components.AsciiFileCurveArchiver; import org.opensha.sha.calc.hazardMap.components.CalculationInputsXMLFile; @@ -58,8 +57,10 @@ public class HazardMapPBSGen { * @throws IOException */ public static void main(String[] args) throws IOException { - RunSites runSite = RunSites.HPCC; - BatchScriptWriter writer = new USC_HPCC_ScriptWriter(); +// RunSites runSite = RunSites.HPCC; +// BatchScriptWriter writer = new USC_HPCC_ScriptWriter(); + RunSites runSite = null; + BatchScriptWriter writer = null; int nodes = 30; int mins = 60 * 5; int heapMB = 9000; @@ -152,7 +153,7 @@ public static void main(String[] args) throws IOException { List script = mpj.buildScript(MPJHazardCurveDriver.class.getName(), cliArgs); - script = writer.buildScript(script, mins, nodes, 0, null); + script = writer.buildScript(script, mins, nodes, 0, -1, null); File pbsFile = new File(localRunDir, pbsName+".pbs"); JavaShellScriptWriter.writeScript(pbsFile, script); diff --git a/src/main/java/scratch/kevin/simulators/erf/TimeDepFSS_ERF_Simulator_ScriptGen.java b/src/main/java/scratch/kevin/simulators/erf/TimeDepFSS_ERF_Simulator_ScriptGen.java index 4bb87005..5c3e2ff8 100644 --- a/src/main/java/scratch/kevin/simulators/erf/TimeDepFSS_ERF_Simulator_ScriptGen.java +++ b/src/main/java/scratch/kevin/simulators/erf/TimeDepFSS_ERF_Simulator_ScriptGen.java @@ -55,7 +55,7 @@ public static void main(String[] args) throws IOException { String scriptArgs = remoteOutputDir.getAbsolutePath()+" "+prefix+" "+trialsPerJob+" "+cov.name()+" "+duration; List script = writer.buildScript(TimeDepFSS_ERF_Simulator_Test.class.getName(), scriptArgs); - pbsWrite.writeScript(pbsFile, script, mins, 1, 8, null); + pbsWrite.writeScript(pbsFile, script, mins, 1, 8, -1, null); } } diff --git a/src/main/java/scratch/kevin/simulators/hazard/HazardMapCompareScriptGen.java b/src/main/java/scratch/kevin/simulators/hazard/HazardMapCompareScriptGen.java index 8f8fd9df..42f94c0b 100644 --- a/src/main/java/scratch/kevin/simulators/hazard/HazardMapCompareScriptGen.java +++ b/src/main/java/scratch/kevin/simulators/hazard/HazardMapCompareScriptGen.java @@ -20,7 +20,7 @@ import org.opensha.commons.hpc.mpj.FastMPJShellScriptWriter.Device; import org.opensha.commons.hpc.mpj.MPJExpressShellScriptWriter; import org.opensha.commons.hpc.pbs.StampedeScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; +import org.opensha.commons.hpc.pbs.USC_CARC_ScriptWriter; import org.opensha.commons.param.Parameter; import org.opensha.commons.util.XMLUtils; import org.opensha.sha.calc.hazardMap.components.BinaryCurveArchiver; @@ -172,12 +172,12 @@ public static void main(String[] args) throws IOException, DocumentException { int nodes = 18; int ppn = 20; String queue = "scec_hiprio"; - File javaBin = USC_HPCC_ScriptWriter.JAVA_BIN; + File javaBin = USC_CARC_ScriptWriter.JAVA_BIN; File remoteMainDir = new File("/home/scec-02/kmilner/simulators/hazard"); JavaShellScriptWriter mpj = new MPJExpressShellScriptWriter(javaBin, 55*1024, null, - USC_HPCC_ScriptWriter.MPJ_HOME); + USC_CARC_ScriptWriter.MPJ_HOME); ((MPJExpressShellScriptWriter)mpj).setUseLaunchWrapper(true); - USC_HPCC_ScriptWriter writer = new USC_HPCC_ScriptWriter(); + USC_CARC_ScriptWriter writer = new USC_CARC_ScriptWriter(); // int mins = 24*60; // int nodes = 10; @@ -375,7 +375,7 @@ public static void main(String[] args) throws IOException, DocumentException { List script = mpj.buildScript(MPJHazardCurveDriver.class.getName(), cliArgs); - script = writer.buildScript(script, mins, nodes, ppn, queue); + script = writer.buildScript(script, mins, nodes, ppn, -1, queue); String jobName = localJobDir.getName(); if (!rsqsim) @@ -435,7 +435,7 @@ public static void main(String[] args) throws IOException, DocumentException { List script = mpj.buildScript(MPJHazardCurveDriver.class.getName(), cliArgs); - script = writer.buildScript(script, mins, nodes, ppn, queue); + script = writer.buildScript(script, mins, nodes, ppn, -1, queue); String jobName = localJobDir.getName()+"_"+getIMTLabel(imt, period); File pbsFile = new File(localJobDir, jobName+".pbs"); diff --git a/src/main/java/scratch/kevin/simulators/momRateVariation/UCERF3ComparisonScriptGen.java b/src/main/java/scratch/kevin/simulators/momRateVariation/UCERF3ComparisonScriptGen.java index 2822ead1..17c5eb33 100644 --- a/src/main/java/scratch/kevin/simulators/momRateVariation/UCERF3ComparisonScriptGen.java +++ b/src/main/java/scratch/kevin/simulators/momRateVariation/UCERF3ComparisonScriptGen.java @@ -62,7 +62,7 @@ public static void main(String[] args) throws IOException { List script = javaWrite.buildScript(UCERF3ComparisonCalc.class.getName(), argsStr); File outputFile = new File(localOutputDir, dirName+".pbs"); - pbsWrite.writeScript(outputFile, script, mins, 1, threadsPerBatch, queue); + pbsWrite.writeScript(outputFile, script, mins, 1, threadsPerBatch, -1, queue); } } diff --git a/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_CatalogSimScriptGen.java b/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_CatalogSimScriptGen.java index 285b8671..ea34af4d 100644 --- a/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_CatalogSimScriptGen.java +++ b/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_CatalogSimScriptGen.java @@ -320,7 +320,7 @@ public static void main(String[] args) throws IOException { if (!addLines.isEmpty()) script.addAll(2, addLines); - script = pbsWrite.buildScript(script, mins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mins, nodes, threads, -1, queue); pbsWrite.writeScript(new File(localJobDir, "cat_bbp_parallel.slurm"), script); } diff --git a/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_PartBSimScriptGen.java b/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_PartBSimScriptGen.java index 23776d56..1122aedf 100644 --- a/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_PartBSimScriptGen.java +++ b/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_PartBSimScriptGen.java @@ -135,7 +135,7 @@ public static void main(String[] args) throws IOException { if (!addLines.isEmpty()) script.addAll(2, addLines); - script = pbsWrite.buildScript(script, mins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mins, nodes, threads, -1, queue); pbsWrite.writeScript(new File(localJobDir, "cat_bbp_partb.slurm"), script); } diff --git a/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_RuptureScriptsGen.java b/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_RuptureScriptsGen.java index 8f1dc4a7..60f1a499 100644 --- a/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_RuptureScriptsGen.java +++ b/src/main/java/scratch/kevin/simulators/ruptures/MPJ_BBP_RuptureScriptsGen.java @@ -14,7 +14,6 @@ import org.opensha.commons.hpc.pbs.BatchScriptWriter; import org.opensha.commons.hpc.pbs.StampedeScriptWriter; import org.opensha.commons.hpc.pbs.USC_CARC_ScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; import org.opensha.sha.simulators.RSQSimEvent; import org.opensha.sha.simulators.srf.RSQSimEventSlipTimeFunc; import org.opensha.sha.simulators.srf.RSQSimSRFGenerator; @@ -160,6 +159,7 @@ public static void main(String[] args) throws IOException { BatchScriptWriter pbsWrite; JavaShellScriptWriter mpjWrite; + int nodeMemBG; if (stampede) { threads = 96; queue = "skx-normal"; @@ -173,6 +173,7 @@ public static void main(String[] args) throws IOException { sharedScratchDir = null; pbsWrite = new StampedeScriptWriter(true); mpjWrite = new FastMPJShellScriptWriter(StampedeScriptWriter.JAVA_BIN, heapSizeMB, null, StampedeScriptWriter.FMPJ_HOME); + nodeMemBG = heapSizeMB / 1024 + 4; ((FastMPJShellScriptWriter)mpjWrite).setUseLaunchWrapper(true); } else { // threads = 20; @@ -208,6 +209,7 @@ public static void main(String[] args) throws IOException { mpjWrite = new FastMPJShellScriptWriter( USC_CARC_ScriptWriter.JAVA_BIN, heapSizeMB, null, USC_CARC_ScriptWriter.FMPJ_HOME); ((FastMPJShellScriptWriter)mpjWrite).setUseLaunchWrapper(true); + nodeMemBG = -1; } String dateStr = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); @@ -312,7 +314,7 @@ else if (cs500Sites) if (!addLines.isEmpty()) script.addAll(2, addLines); - script = pbsWrite.buildScript(script, gpMins, nodes, threads, queue); + script = pbsWrite.buildScript(script, gpMins, nodes, threads, nodeMemBG, queue); pbsWrite.writeScript(new File(localJobDir, "gp_bbp_parallel.slurm"), script); } if (doShakeMap) { @@ -364,7 +366,7 @@ else if (cs500Sites) if (!addLines.isEmpty()) script.addAll(2, addLines); - script = pbsWrite.buildScript(script, mapMins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mapMins, nodes, threads, nodeMemBG, queue); pbsWrite.writeScript(new File(localJobDir, "map_bbp_parallel.slurm"), script); } if (doGPShakeMaps) { @@ -431,7 +433,7 @@ else if (cs500Sites) if (!addLines.isEmpty()) script.addAll(2, addLines); - script = pbsWrite.buildScript(script, mapMins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mapMins, nodes, threads, nodeMemBG, queue); pbsWrite.writeScript(new File(localJobDir, "map_bbp_parallel.slurm"), script); } } diff --git a/src/main/java/scratch/kevin/simulators/ruptures/azimuthal/AzimuthalScriptsGen.java b/src/main/java/scratch/kevin/simulators/ruptures/azimuthal/AzimuthalScriptsGen.java index 282f4935..980251a7 100644 --- a/src/main/java/scratch/kevin/simulators/ruptures/azimuthal/AzimuthalScriptsGen.java +++ b/src/main/java/scratch/kevin/simulators/ruptures/azimuthal/AzimuthalScriptsGen.java @@ -13,7 +13,7 @@ import org.opensha.commons.hpc.mpj.MPJExpressShellScriptWriter; import org.opensha.commons.hpc.pbs.BatchScriptWriter; import org.opensha.commons.hpc.pbs.StampedeScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; +import org.opensha.commons.hpc.pbs.USC_CARC_ScriptWriter; import com.google.common.base.Preconditions; @@ -74,19 +74,19 @@ public static void main(String[] args) throws IOException { String queue = "scec"; int mins = 48*60; int heapSizeMB = 45*1024; - String bbpDataDir = USC_HPCC_ScriptWriter.NODE_TEMP_DIR; + String bbpDataDir = USC_CARC_ScriptWriter.NODE_TEMP_DIR; String nodeScratchDir = null; - String bbpCopyParentDir = USC_HPCC_ScriptWriter.SHARED_SCRATCH_DIR+"/kmilner"; - String nodeGFDir = USC_HPCC_ScriptWriter.NODE_TEMP_DIR+"/gfs"; + String bbpCopyParentDir = USC_CARC_ScriptWriter.SHARED_SCRATCH_DIR+"/kmilner"; + String nodeGFDir = USC_CARC_ScriptWriter.NODE_TEMP_DIR+"/gfs"; File bbpEnvFile = new File("/auto/scec-02/kmilner/bbp/bbp_env.sh"); // String sharedScratchDir = "${SCRATCHDIR}"; String sharedScratchDir = null; File remoteDir = new File("/auto/scec-02/kmilner/bbp/parallel"); - BatchScriptWriter pbsWrite = new USC_HPCC_ScriptWriter(); + BatchScriptWriter pbsWrite = new USC_CARC_ScriptWriter(); List classpath = new ArrayList<>(); classpath.add(new File(remoteDir, "opensha-dev-all.jar")); JavaShellScriptWriter mpjWrite = new MPJExpressShellScriptWriter( - USC_HPCC_ScriptWriter.JAVA_BIN, heapSizeMB, classpath, USC_HPCC_ScriptWriter.MPJ_HOME); + USC_CARC_ScriptWriter.JAVA_BIN, heapSizeMB, classpath, USC_CARC_ScriptWriter.MPJ_HOME); ((MPJExpressShellScriptWriter)mpjWrite).setUseLaunchWrapper(true); // int threads = 48; @@ -189,7 +189,7 @@ public static void main(String[] args) throws IOException { if (!addLines.isEmpty()) script.addAll(2, addLines); - script = pbsWrite.buildScript(script, mins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mins, nodes, threads, -1, queue); String scriptName = gp ? "gp_bbp_azimuthal.slurm" : "cat_bbp_azimuthal.slurm"; pbsWrite.writeScript(new File(localJobDir, scriptName), script); } diff --git a/src/main/java/scratch/kevin/simulators/ruptures/rotation/MPJ_BBP_RotatedRupVariabilityMagDistSimScriptGen.java b/src/main/java/scratch/kevin/simulators/ruptures/rotation/MPJ_BBP_RotatedRupVariabilityMagDistSimScriptGen.java index d1d8c153..52b002a2 100644 --- a/src/main/java/scratch/kevin/simulators/ruptures/rotation/MPJ_BBP_RotatedRupVariabilityMagDistSimScriptGen.java +++ b/src/main/java/scratch/kevin/simulators/ruptures/rotation/MPJ_BBP_RotatedRupVariabilityMagDistSimScriptGen.java @@ -188,7 +188,7 @@ private static void writeScript(String catalogDirName, int skipYears, RuptureTyp if (!addLines.isEmpty()) script.addAll(2, addLines); - script = pbsWrite.buildScript(script, mins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mins, nodes, threads, -1, queue); pbsWrite.writeScript(new File(localJobDir, scriptFileName), script); } diff --git a/src/main/java/scratch/kevin/simulators/ruptures/rotation/MPJ_BBP_RotatedRupVariabilityScenarioSimScriptGen.java b/src/main/java/scratch/kevin/simulators/ruptures/rotation/MPJ_BBP_RotatedRupVariabilityScenarioSimScriptGen.java index e8e83b69..0ffeb346 100644 --- a/src/main/java/scratch/kevin/simulators/ruptures/rotation/MPJ_BBP_RotatedRupVariabilityScenarioSimScriptGen.java +++ b/src/main/java/scratch/kevin/simulators/ruptures/rotation/MPJ_BBP_RotatedRupVariabilityScenarioSimScriptGen.java @@ -218,7 +218,7 @@ public static void main(String[] args) throws IOException { if (!addLines.isEmpty()) script.addAll(2, addLines); - script = pbsWrite.buildScript(script, mins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mins, nodes, threads, -1, queue); String scriptName = gp ? "gp_bbp_rotated.slurm" : "cat_bbp_rotated.slurm"; pbsWrite.writeScript(new File(localJobDir, scriptName), script); } diff --git a/src/main/java/scratch/kevin/surfDistCache/SurfDistCacheTestScriptWriter.java b/src/main/java/scratch/kevin/surfDistCache/SurfDistCacheTestScriptWriter.java index 6e6b55a4..bc4de20d 100644 --- a/src/main/java/scratch/kevin/surfDistCache/SurfDistCacheTestScriptWriter.java +++ b/src/main/java/scratch/kevin/surfDistCache/SurfDistCacheTestScriptWriter.java @@ -69,8 +69,8 @@ public static void main(String[] args) throws IOException { String argz = type.name()+" "+solFile.getAbsolutePath()+" "+threads+" "+numSites; for (int j=0; j script = writer.buildScript(javaWrite.buildScript(className, argz), mins, nodes, ppn, queue); - writer.writeScript(outputFile, script, mins, nodes, ppn, queue); + List script = writer.buildScript(javaWrite.buildScript(className, argz), mins, nodes, ppn, -1, queue); + writer.writeScript(outputFile, script, mins, nodes, ppn, -1, queue); } } } diff --git a/src/main/java/scratch/kevin/ucerf3/BulkCompoundScriptWrite.java b/src/main/java/scratch/kevin/ucerf3/BulkCompoundScriptWrite.java index 67db5655..9693c436 100644 --- a/src/main/java/scratch/kevin/ucerf3/BulkCompoundScriptWrite.java +++ b/src/main/java/scratch/kevin/ucerf3/BulkCompoundScriptWrite.java @@ -8,7 +8,6 @@ import org.opensha.commons.hpc.mpj.FastMPJShellScriptWriter; import org.opensha.commons.hpc.mpj.MPJExpressShellScriptWriter; import org.opensha.commons.hpc.pbs.BatchScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; import com.google.common.collect.Lists; @@ -78,8 +77,8 @@ public static void main(String[] args) throws IOException { if (!writeDir.exists()) writeDir.mkdir(); - RunSites site = RunSites.HPCC; -// RunSites site = RunSites.STAMPEDE; +// RunSites site = RunSites.HPCC; + RunSites site = RunSites.STAMPEDE; int nodes = 30; // int bundleSize = 30; // TODO, must be >0 // int jobMins = 6*60; // TODO @@ -97,8 +96,8 @@ public static void main(String[] args) throws IOException { mpjWrite.setHeadless(true); BatchScriptWriter batchWrite = site.forBranch(null); - if (batchWrite instanceof USC_HPCC_ScriptWriter) - ((USC_HPCC_ScriptWriter)batchWrite).setNodesAddition(null); +// if (batchWrite instanceof USC_HPCC_ScriptWriter) +// ((USC_HPCC_ScriptWriter)batchWrite).setNodesAddition(null); for (U3LogicTreeBranchNode fm : fmBranches) { for (U3LogicTreeBranchNode dm : dmBranches) { @@ -124,7 +123,7 @@ public static void main(String[] args) throws IOException { String scriptName = remoteJobDir.getName()+".pbs"; - batchWrite.writeScript(new File(writeDir, scriptName), script, jobMins, nodes, site.getPPN(null), null); + batchWrite.writeScript(new File(writeDir, scriptName), script, jobMins, nodes, -1, site.getPPN(null), null); } } } diff --git a/src/main/java/scratch/kevin/ucerf3/GriddedSeisImportanceHazardMapCalc.java b/src/main/java/scratch/kevin/ucerf3/GriddedSeisImportanceHazardMapCalc.java index 18f05ef6..aefb1936 100644 --- a/src/main/java/scratch/kevin/ucerf3/GriddedSeisImportanceHazardMapCalc.java +++ b/src/main/java/scratch/kevin/ucerf3/GriddedSeisImportanceHazardMapCalc.java @@ -15,7 +15,7 @@ import org.opensha.commons.geo.Region; import org.opensha.commons.hpc.JavaShellScriptWriter; import org.opensha.commons.hpc.mpj.MPJExpressShellScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; +import org.opensha.commons.hpc.pbs.USC_CARC_ScriptWriter; import org.opensha.commons.util.XMLUtils; import org.opensha.sha.calc.hazardMap.components.BinaryCurveArchiver; import org.opensha.sha.calc.hazardMap.components.CalculationInputsXMLFile; @@ -157,14 +157,14 @@ public static void main(String[] args) throws IOException, DocumentException { xValsMap.put("curves", xValues); CalculationSettings calcSettings = new CalculationSettings(xValues, maxSourceDistance); - File javaBin = USC_HPCC_ScriptWriter.JAVA_BIN; + File javaBin = USC_CARC_ScriptWriter.JAVA_BIN; File jarFile = new File(remoteBaseDir, "opensha-dev-all.jar"); List classpath = Lists.newArrayList(); classpath.add(jarFile); MPJExpressShellScriptWriter mpj = new MPJExpressShellScriptWriter(javaBin, 60000, classpath, - USC_HPCC_ScriptWriter.MPJ_HOME); + USC_CARC_ScriptWriter.MPJ_HOME); mpj.setUseLaunchWrapper(true); List> imrMaps = Lists.newArrayList(); @@ -224,9 +224,9 @@ public static void main(String[] args) throws IOException, DocumentException { String cliArgs = "--max-dispatch 1000 "+remoteInputsFile.getAbsolutePath(); List script = mpj.buildScript(MPJHazardCurveDriver.class.getName(), cliArgs); - USC_HPCC_ScriptWriter writer = new USC_HPCC_ScriptWriter(); + USC_CARC_ScriptWriter writer = new USC_CARC_ScriptWriter(); - script = writer.buildScript(script, mins, nodes, ppn, queue); + script = writer.buildScript(script, mins, nodes, ppn, -1, queue); File pbsFile = new File(localSubDir, subDirName+".slurm"); JavaShellScriptWriter.writeScript(pbsFile, script); diff --git a/src/main/java/scratch/kevin/ucerf3/MPJ_UCERF3_ShakeMapPrecalcScriptGen.java b/src/main/java/scratch/kevin/ucerf3/MPJ_UCERF3_ShakeMapPrecalcScriptGen.java index b7288542..b78ad219 100644 --- a/src/main/java/scratch/kevin/ucerf3/MPJ_UCERF3_ShakeMapPrecalcScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/MPJ_UCERF3_ShakeMapPrecalcScriptGen.java @@ -156,7 +156,7 @@ public static void main(String[] args) throws IOException { List script = mpjWrite.buildScript(MPJ_UCERF3_ShakeMapPrecalc.class.getName(), argz); int mins = hours*60; - script = pbsWrite.buildScript(script, mins, nodes, ppn, queue); + script = pbsWrite.buildScript(script, mins, nodes, ppn, -1, queue); pbsWrite.writeScript(new File(localDir, jobName+".pbs"), script); } diff --git a/src/main/java/scratch/kevin/ucerf3/eal/MPJ_UCERF3_EAL_CombinerScriptGen.java b/src/main/java/scratch/kevin/ucerf3/eal/MPJ_UCERF3_EAL_CombinerScriptGen.java index d9a9a34e..b6227a1b 100644 --- a/src/main/java/scratch/kevin/ucerf3/eal/MPJ_UCERF3_EAL_CombinerScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/eal/MPJ_UCERF3_EAL_CombinerScriptGen.java @@ -134,7 +134,7 @@ public static void main(String[] args) throws IOException { argz += " "+remoteJobDir.getAbsolutePath(); List script = mpjWrite.buildScript(MPJ_UCERF3_EAL_Combiner.class.getName(), argz); - script = pbsWrite.buildScript(script, mins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mins, nodes, threads, -1, queue); pbsWrite.writeScript(new File(localJobDir, "eal_consolidate.slurm"), script); } diff --git a/src/main/java/scratch/kevin/ucerf3/eal/UCERF3_EAL_ScriptGen.java b/src/main/java/scratch/kevin/ucerf3/eal/UCERF3_EAL_ScriptGen.java index 2797a5ff..984fdcd2 100644 --- a/src/main/java/scratch/kevin/ucerf3/eal/UCERF3_EAL_ScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/eal/UCERF3_EAL_ScriptGen.java @@ -190,7 +190,7 @@ public static void main(String[] args) throws IOException { +remoteXML.getAbsolutePath()+" "+remoteOutput.getAbsolutePath(); File jobFile = new File(writeDir, name+".slurm"); - pbsWrite.writeScript(jobFile, javaWrite.buildScript(className, jobArgs), mins, nodes, ppn, queue); + pbsWrite.writeScript(jobFile, javaWrite.buildScript(className, jobArgs), mins, nodes, ppn, -1, queue); } } diff --git a/src/main/java/scratch/kevin/ucerf3/eal/UCERF3_EAL_Validate_ScriptGen.java b/src/main/java/scratch/kevin/ucerf3/eal/UCERF3_EAL_Validate_ScriptGen.java index e2f54800..ef75a674 100644 --- a/src/main/java/scratch/kevin/ucerf3/eal/UCERF3_EAL_Validate_ScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/eal/UCERF3_EAL_Validate_ScriptGen.java @@ -136,7 +136,7 @@ public static void main(String[] args) throws IOException { +remoteXML.getAbsolutePath()+" "+remoteOutput.getAbsolutePath(); File jobFile = new File(writeDir, name+".pbs"); - pbsWrite.writeScript(jobFile, javaWrite.buildScript(className, jobArgs), mins, nodes, ppn, queue); + pbsWrite.writeScript(jobFile, javaWrite.buildScript(className, jobArgs), mins, nodes, ppn, -1, queue); } } } diff --git a/src/main/java/scratch/kevin/ucerf3/eal/spatialCorr/MPJ_SpatiallyCorrelatedLossCalcScriptGen.java b/src/main/java/scratch/kevin/ucerf3/eal/spatialCorr/MPJ_SpatiallyCorrelatedLossCalcScriptGen.java index 29e7fb99..622e329a 100644 --- a/src/main/java/scratch/kevin/ucerf3/eal/spatialCorr/MPJ_SpatiallyCorrelatedLossCalcScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/eal/spatialCorr/MPJ_SpatiallyCorrelatedLossCalcScriptGen.java @@ -89,7 +89,7 @@ public static void main(String[] args) throws IOException { argz += " "+remoteJobDir.getAbsolutePath(); List script = mpjWrite.buildScript(MPJ_SpatiallyCorrelatedLossCalc.class.getName(), argz); - script = pbsWrite.buildScript(script, mins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mins, nodes, threads, -1, queue); pbsWrite.writeScript(new File(localJobDir, "spatial_calc.slurm"), script); } diff --git a/src/main/java/scratch/kevin/ucerf3/etas/CacheSpeedScriptGen.java b/src/main/java/scratch/kevin/ucerf3/etas/CacheSpeedScriptGen.java deleted file mode 100644 index 2e3356f6..00000000 --- a/src/main/java/scratch/kevin/ucerf3/etas/CacheSpeedScriptGen.java +++ /dev/null @@ -1,40 +0,0 @@ -package scratch.kevin.ucerf3.etas; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -import org.opensha.commons.hpc.JavaShellScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; - -import com.google.common.collect.Lists; - -public class CacheSpeedScriptGen { - - public static void main(String[] args) throws IOException { - File localDir = new File("/home/kevin/OpenSHA/UCERF3/etas/cache_tests/soft_10Gjvm"); - File remoteDir = new File("/auto/scec-02/kmilner/ucerf3/etas_sim/cache_test/soft_10Gjvm"); - - double[] sizes = { 0d, 0.5d, 1d, 2d, 4d, 8d, 16d }; - int numRuns = 5; - - List classpath = Lists.newArrayList(); - classpath.add(new File(remoteDir, "OpenSHA_complete.jar")); - classpath.add(new File(remoteDir.getParentFile().getParentFile(), "commons-cli-1.2.jar")); - - JavaShellScriptWriter javaWrite = new JavaShellScriptWriter(USC_HPCC_ScriptWriter.JAVA_BIN, 10*1024, classpath); - USC_HPCC_ScriptWriter pbsWrite = new USC_HPCC_ScriptWriter("dodecacore"); - - for (double size : sizes) { - for (int run=0; run script = javaWrite.buildScript(CacheSpeedTester.class.getName(), - remoteDir.getAbsolutePath()+" "+(float)size+" "+run); - script.add(script.size()-2, "cd "+remoteDir.getParentFile().getAbsolutePath()); - pbsWrite.writeScript(new File(localDir, jobName), script, 90, 1, 24, null); - } - } - } - -} diff --git a/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_HazardMapCalcScriptGen.java b/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_HazardMapCalcScriptGen.java index 6f441f0b..334c1ea9 100644 --- a/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_HazardMapCalcScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_HazardMapCalcScriptGen.java @@ -16,7 +16,7 @@ import org.opensha.commons.hpc.mpj.MPJExpressShellScriptWriter; import org.opensha.commons.hpc.pbs.BatchScriptWriter; import org.opensha.commons.hpc.pbs.StampedeScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; +import org.opensha.commons.hpc.pbs.USC_CARC_ScriptWriter; import org.opensha.sha.imr.AttenRelRef; import org.opensha.sha.imr.AttenuationRelationship; @@ -193,14 +193,14 @@ public static void main(String[] args) throws IOException { boolean fmpj = nodes < 25; fmpj = false; if (fmpj) { - mpjWrite = new FastMPJShellScriptWriter(USC_HPCC_ScriptWriter.JAVA_BIN, memGigs*1024, - null, USC_HPCC_ScriptWriter.FMPJ_HOME); + mpjWrite = new FastMPJShellScriptWriter(USC_CARC_ScriptWriter.JAVA_BIN, memGigs*1024, + null, USC_CARC_ScriptWriter.FMPJ_HOME); ((FastMPJShellScriptWriter)mpjWrite).setUseLaunchWrapper(true); } else { - mpjWrite = new MPJExpressShellScriptWriter(USC_HPCC_ScriptWriter.JAVA_BIN, memGigs*1024, - null, USC_HPCC_ScriptWriter.MPJ_HOME); + mpjWrite = new MPJExpressShellScriptWriter(USC_CARC_ScriptWriter.JAVA_BIN, memGigs*1024, + null, USC_CARC_ScriptWriter.MPJ_HOME); } - pbsWrite = new USC_HPCC_ScriptWriter(); + pbsWrite = new USC_CARC_ScriptWriter(); remoteMainDir = new File("/home/scec-02/kmilner/ucerf3/etas_hazard"); @@ -275,7 +275,7 @@ public static void main(String[] args) throws IOException { List script = mpjWrite.buildScript(MPJ_ETAS_HazardMapCalc.class.getName(), argz); int mins = hours*60; - script = pbsWrite.buildScript(script, mins, nodes, ppn, queue); + script = pbsWrite.buildScript(script, mins, nodes, ppn, -1, queue); String scriptName; if (stampede) { if (knl) diff --git a/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_SimulatorInternScriptGen.java b/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_SimulatorInternScriptGen.java index 51d59c9c..28b5a113 100644 --- a/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_SimulatorInternScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_SimulatorInternScriptGen.java @@ -111,7 +111,7 @@ public static void main(String[] args) throws IOException { List script = mpjWrite.buildScript(MPJ_ETAS_Simulator.class.getName(), argz); - script = pbsWrite.buildScript(script, mins, nodes, ppn, queue); + script = pbsWrite.buildScript(script, mins, nodes, ppn, -1, queue); pbsWrite.writeScript(pbsFile, script); } } diff --git a/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_SimulatorScriptGen.java b/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_SimulatorScriptGen.java index 3b6e5c44..49666cdb 100644 --- a/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_SimulatorScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/etas/MPJ_ETAS_SimulatorScriptGen.java @@ -15,7 +15,7 @@ import org.opensha.commons.hpc.mpj.MPJExpressShellScriptWriter; import org.opensha.commons.hpc.pbs.BatchScriptWriter; import org.opensha.commons.hpc.pbs.StampedeScriptWriter; -import org.opensha.commons.hpc.pbs.USC_HPCC_ScriptWriter; +import org.opensha.commons.hpc.pbs.USC_CARC_ScriptWriter; import scratch.UCERF3.erf.ETAS.ETAS_Simulator.TestScenario; import scratch.UCERF3.erf.ETAS.ETAS_CatalogIO; @@ -281,15 +281,15 @@ public static void main(String[] args) throws IOException { boolean fmpj = nodes < 25; fmpj = false; if (fmpj) { - mpjWrite = new FastMPJShellScriptWriter(USC_HPCC_ScriptWriter.JAVA_BIN, memGigs*1024, - null, USC_HPCC_ScriptWriter.FMPJ_HOME); + mpjWrite = new FastMPJShellScriptWriter(USC_CARC_ScriptWriter.JAVA_BIN, memGigs*1024, + null, USC_CARC_ScriptWriter.FMPJ_HOME); ((FastMPJShellScriptWriter)mpjWrite).setUseLaunchWrapper(true); } else { - mpjWrite = new MPJExpressShellScriptWriter(USC_HPCC_ScriptWriter.JAVA_BIN, memGigs*1024, - null, USC_HPCC_ScriptWriter.MPJ_HOME); + mpjWrite = new MPJExpressShellScriptWriter(USC_CARC_ScriptWriter.JAVA_BIN, memGigs*1024, + null, USC_CARC_ScriptWriter.MPJ_HOME); } - pbsWrite = new USC_HPCC_ScriptWriter(); - ((USC_HPCC_ScriptWriter)pbsWrite).setSkipRootNode(hpcSkipRoot); + pbsWrite = new USC_CARC_ScriptWriter(); + ((USC_CARC_ScriptWriter)pbsWrite).setSkipRootNode(hpcSkipRoot); cacheDir = new File(remoteDir, "cache_fm3p1_ba"); } @@ -517,7 +517,7 @@ public static void main(String[] args) throws IOException { } } - script = pbsWrite.buildScript(script, mins, nodes, ppn, queue); + script = pbsWrite.buildScript(script, mins, nodes, ppn, -1, queue); pbsWrite.writeScript(pbsFile, script); if (writeConsolidate && !bundleConsolidate && stampede) { @@ -530,8 +530,8 @@ public static void main(String[] args) throws IOException { script.add(""); script.addAll(consolidationLines); - pbsWrite.writeScript(new File(localJobDir, "consolidate_dev.pbs"), script, 60, 1, 16, "development"); - pbsWrite.writeScript(new File(localJobDir, "consolidate_norm.pbs"), script, 60, 1, 16, "normal"); + pbsWrite.writeScript(new File(localJobDir, "consolidate_dev.pbs"), script, 60, 1, 16, -1, "development"); + pbsWrite.writeScript(new File(localJobDir, "consolidate_norm.pbs"), script, 60, 1, 16, -1, "normal"); } } } diff --git a/src/main/java/scratch/kevin/ucerf3/etas/MPJ_GK_DesclusteringHazardCalcScriptGen.java b/src/main/java/scratch/kevin/ucerf3/etas/MPJ_GK_DesclusteringHazardCalcScriptGen.java index 719661bb..6fe3e376 100644 --- a/src/main/java/scratch/kevin/ucerf3/etas/MPJ_GK_DesclusteringHazardCalcScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/etas/MPJ_GK_DesclusteringHazardCalcScriptGen.java @@ -56,7 +56,7 @@ public static void main(String[] args) throws IOException { List script = mpjWrite.buildScript(MPJ_GK_DesclusteringHazardCalc.class.getName(), argz); - script = pbsWrite.buildScript(script, mins, nodes, threads, queue); + script = pbsWrite.buildScript(script, mins, nodes, threads, -1, queue); pbsWrite.writeScript(pbsFile, script); } diff --git a/src/main/java/scratch/kevin/ucerf3/inversion/InversionEALInputGen.java b/src/main/java/scratch/kevin/ucerf3/inversion/InversionEALInputGen.java index 96f0799e..d78e2d6e 100644 --- a/src/main/java/scratch/kevin/ucerf3/inversion/InversionEALInputGen.java +++ b/src/main/java/scratch/kevin/ucerf3/inversion/InversionEALInputGen.java @@ -66,7 +66,7 @@ private static void writeRTGMJob(MPJExpressShellScriptWriter writer, File portfo List script = writer.buildScript(MPJ_AssetRTGM_Calc.class.getName(), args); USC_HPCC_ScriptWriter usc = new USC_HPCC_ScriptWriter(); - script = usc.buildScript(script, mins, nodes, 8, queue); + script = usc.buildScript(script, mins, nodes, 8, -1, queue); usc.writeScript(jobFile, script); } diff --git a/src/main/java/scratch/kevin/ucerf3/maps/MapScriptWriter.java b/src/main/java/scratch/kevin/ucerf3/maps/MapScriptWriter.java index e1f2290d..39268712 100644 --- a/src/main/java/scratch/kevin/ucerf3/maps/MapScriptWriter.java +++ b/src/main/java/scratch/kevin/ucerf3/maps/MapScriptWriter.java @@ -129,7 +129,7 @@ public static void main(String[] args) throws ZipException, IOException { scriptName = "maps_"+scriptName+".pbs"; - batchWrite.writeScript(new File(writeDir, scriptName), script, jobMins, nodes, site.getPPN(null), null); + batchWrite.writeScript(new File(writeDir, scriptName), script, jobMins, nodes, site.getPPN(null), -1, null); jobCount += branches.size(); batchCount++; diff --git a/src/main/java/scratch/kevin/ucerf3/maps/MultiSolComparisonMapScriptGen.java b/src/main/java/scratch/kevin/ucerf3/maps/MultiSolComparisonMapScriptGen.java index 3c601f9f..36646794 100644 --- a/src/main/java/scratch/kevin/ucerf3/maps/MultiSolComparisonMapScriptGen.java +++ b/src/main/java/scratch/kevin/ucerf3/maps/MultiSolComparisonMapScriptGen.java @@ -23,7 +23,8 @@ public class MultiSolComparisonMapScriptGen { public static void main(String[] args) throws IOException { File localMainDir = new File("/home/kevin/OpenSHA/UCERF3/biasi_downsample_tests"); - RunSites site = RunSites.HPCC; +// RunSites site = RunSites.HPCC; + RunSites site = null; File remoteMainDir = new File("/home/scec-02/kmilner/ucerf3/maps"); String runName = "biasi-downsample-pga"; @@ -84,7 +85,7 @@ public static void main(String[] args) throws IOException { List script = mpjWrite.buildScript(className, classArgs); - batchWrite.writeScript(pbsFile, script, jobMins, nodes, site.getPPN(null), null); + batchWrite.writeScript(pbsFile, script, jobMins, nodes, site.getPPN(null), -1, null); } } From 979a5c54a7e01149db9ba790e20302d90155e973 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 15 May 2026 12:14:54 -0700 Subject: [PATCH 27/71] bump comm-stat-dist to 1.3 with truncN fixes, remove local temp version --- .../java/scratch/kevin/ltSampling/LHSExampleFigures.java | 4 ++-- .../java/scratch/kevin/nshm27/DistSampleCountTests.java | 8 ++++---- src/main/java/scratch/kevin/nshm27/SamplerTest.java | 3 +-- .../kevin/nshm27/UpdatedRandTreeSerialzationTests.java | 3 +-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java index 494eedab..df937907 100644 --- a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java +++ b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java @@ -14,7 +14,7 @@ import java.util.Random; import org.apache.commons.statistics.distribution.ContinuousDistribution; -import org.apache.commons.statistics.distribution.CorrTruncatedNormalDistribution; +import org.apache.commons.statistics.distribution.TruncatedNormalDistribution; import org.apache.commons.statistics.distribution.UniformContinuousDistribution; import org.jfree.chart.annotations.XYAnnotation; import org.jfree.chart.annotations.XYBoxAnnotation; @@ -70,7 +70,7 @@ public static void main(String[] args) throws IOException { levels.add(new ContinuousDistributionSampledLevel( "GR b-value", "GR b-value", UniformContinuousDistribution.of(0d, 1d), "Sample ", "Sample", "Sample")); levels.add(new ContinuousDistributionSampledLevel( - "Off-fault Mmax", "Off-fault Mmax", CorrTruncatedNormalDistribution.of(7.6, 0.2, 7.15, 8.05), -1, "Sample ", "Sample", "Sample")); + "Off-fault Mmax", "Off-fault Mmax", TruncatedNormalDistribution.of(7.6, 0.2, 7.15, 8.05), -1, "Sample ", "Sample", "Sample")); long seed = 123456789l; diff --git a/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java b/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java index a17ab498..09bdefd1 100644 --- a/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java +++ b/src/main/java/scratch/kevin/nshm27/DistSampleCountTests.java @@ -7,7 +7,7 @@ import java.util.List; import org.apache.commons.statistics.distribution.ContinuousDistribution; -import org.apache.commons.statistics.distribution.CorrTruncatedNormalDistribution; +import org.apache.commons.statistics.distribution.TruncatedNormalDistribution; import org.apache.commons.statistics.distribution.UniformContinuousDistribution; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DefaultXY_DataSet; @@ -33,14 +33,14 @@ public class DistSampleCountTests { public static void main(String[] args) throws IOException { -// ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(7.6, 0.134, 7.15, 8.05); - ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(8, 0.2, 7.45, 8.55); +// ContinuousDistribution dist = TruncatedNormalDistribution.of(7.6, 0.134, 7.15, 8.05); + ContinuousDistribution dist = TruncatedNormalDistribution.of(8, 0.2, 7.45, 8.55); int precisionScale = 1; int bins = 3; //// ContinuousDistribution dist = UniformContinuousDistribution.of(0d, 1d); //// ContinuousDistribution dist = UniformContinuousDistribution.of(0.5d, 1d); -// ContinuousDistribution dist = CorrTruncatedNormalDistribution.of(0.75, 0.5, 0d, 1.5); +// ContinuousDistribution dist = TruncatedNormalDistribution.of(0.75, 0.5, 0d, 1.5); // int precisionScale = 2; // ContinuousDistribution dist = UniformContinuousDistribution.of(1000d, 1500d); diff --git a/src/main/java/scratch/kevin/nshm27/SamplerTest.java b/src/main/java/scratch/kevin/nshm27/SamplerTest.java index f452ba08..fe3ba1c5 100644 --- a/src/main/java/scratch/kevin/nshm27/SamplerTest.java +++ b/src/main/java/scratch/kevin/nshm27/SamplerTest.java @@ -12,7 +12,6 @@ import org.jfree.chart.ui.RectangleAnchor; import org.jfree.data.Range; import org.apache.commons.statistics.distribution.ContinuousDistribution.Sampler; -import org.apache.commons.statistics.distribution.CorrTruncatedNormalDistribution; import org.apache.commons.statistics.distribution.NormalDistribution; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DiscretizedFunc; @@ -81,7 +80,7 @@ public static void main(String[] args) throws IOException { hist1.scale(1d/(samples*hist1.getDelta())); EvenlyDiscretizedFunc hist2 = new EvenlyDiscretizedFunc(hist1.getMinX(), hist1.size(), hist1.getDelta()); - ContinuousDistribution corrDist = CorrTruncatedNormalDistribution.of(mean, sd, lower, upper); + ContinuousDistribution corrDist = TruncatedNormalDistribution.of(mean, sd, lower, upper); Sampler corrSampler = corrDist.createSampler(RandomSource.XO_RO_SHI_RO_128_PP.create(123456l)); for (int i=0; i Date: Wed, 27 May 2026 13:03:14 -0700 Subject: [PATCH 28/71] updated grid seis and other tests --- .../GridSourceGeneralVersionValidations.java | 374 ++++++++++++++++++ .../HardcodedInversionFactoryRunner.java | 22 +- .../nshm27/figures/SlipProjectionFigures.java | 78 +++- 3 files changed, 450 insertions(+), 24 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm23/GridSourceGeneralVersionValidations.java diff --git a/src/main/java/scratch/kevin/nshm23/GridSourceGeneralVersionValidations.java b/src/main/java/scratch/kevin/nshm23/GridSourceGeneralVersionValidations.java new file mode 100644 index 00000000..bd1ec00e --- /dev/null +++ b/src/main/java/scratch/kevin/nshm23/GridSourceGeneralVersionValidations.java @@ -0,0 +1,374 @@ +package scratch.kevin.nshm23; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Supplier; + +import org.apache.commons.math3.util.Precision; +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.util.modules.AverageableModule.AveragingAccumulator; +import org.opensha.commons.util.modules.ModuleContainer; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; +import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; +import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList; +import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupture; +import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceProvider; +import org.opensha.sha.earthquake.faultSysSolution.modules.SolutionLogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.NSHM23_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.NSHM23_LogicTreeBranch; +import org.opensha.sha.magdist.IncrementalMagFreqDist; +import org.opensha.sha.util.TectonicRegionType; + +import com.google.common.base.Preconditions; + +public class GridSourceGeneralVersionValidations { + + public static void main(String[] args) throws IOException { + ModuleContainer.VERBOSE_DEFAULT = false; + + SolutionLogicTree slt = SolutionLogicTree.load(new File("/home/kevin/OpenSHA/nshm23/batch_inversions/" + + "2024_02_02-nshm23_branches-WUS_FM_v3/results.zip")); + LogicTree faultTree = slt.getLogicTree(); + LogicTree gridTree = LogicTree.buildExhaustive(NSHM23_LogicTreeBranch.levelsOffFault, true); + int numTestBranches = 2; + AveragingAccumulator origListAvg = null; + AveragingAccumulator newListAvg = null; + boolean convertToPrecomputed = true; + boolean averageWithPrev = true; + +// final int threads = 1; + final int threads = 16; + ExecutorService exec = threads > 1 ? Executors.newFixedThreadPool(threads) : Executors.newSingleThreadExecutor(); + + NSHM23_InvConfigFactory factory = new NSHM23_InvConfigFactory(); + for (int i=0; i faultBranch = faultTree.getBranch(i); + double faultWeight = faultBranch.getBranchWeight(); + System.out.println("Processing branch "+i+": "+faultBranch); + FaultSystemSolution sol = slt.forBranch(faultBranch); + + factory.preGridBuildHook(sol, faultBranch); + + final int branchIndex = i; + + List> futures = new ArrayList<>(gridTree.size()); + for (int g=0; g gridBranch = gridTree.getBranch(g); + Supplier supplier = () -> { + try { + if (threads < 2) + System.out.println("Building original for "+branchIndex+"-"+gridBranchIndex+": "+gridBranch); + GridSourceList origGridList = factory.buildGridSourceProvider(sol, gridBranch); + if (threads < 2) + System.out.println("Building updated for "+branchIndex+"-"+gridBranchIndex+": "+gridBranch); + GridSourceList modGridList = NSHM23_InvConfigFactory.buildUpdatedGridSourceProv(sol, gridBranch); + System.out.println("Done building for "+branchIndex+"-"+gridBranchIndex+": "+gridBranch); + if (convertToPrecomputed && origGridList instanceof GridSourceList.DynamicallyBuilt) { + // do the conversion + EnumMap>> trtRupLists = new EnumMap<>(TectonicRegionType.class); + for (TectonicRegionType trt : origGridList.getTectonicRegionTypes()) { + List> rupLists = new ArrayList<>(); + trtRupLists.put(trt, rupLists); + for (int gridIndex=0; gridIndex origSubAvg = null; + AveragingAccumulator modSubAvg = null; + + AveragingAccumulator origPrevAvg = null; + AveragingAccumulator modPrevAvg = null; + + for (int b=0; b gridBranch = gridTree.getBranch(b); + double gridWeight = gridBranch.getBranchWeight(); + GridSourceList[] provs = futures.get(b).join(); + futures.set(b, null); + GridSourceList origProv = provs[0]; + GridSourceList modList = provs[1]; + + System.out.println("Built for "+b+"/"+gridTree.size()+" "+gridBranch+", validating..."); + validate(origProv, modList, false); + + if (origSubAvg == null) + origSubAvg = origProv.averagingAccumulator(); + origSubAvg.process(origProv, gridWeight); + if (modSubAvg == null) + modSubAvg = modList.averagingAccumulator(); + modSubAvg.process(modList, gridWeight); + + if (averageWithPrev) { + if (b > 0) { + System.out.println("Averaging with prior and comparing"); + origPrevAvg.process(origProv, gridWeight); + GridSourceList mfdWithPrev = (GridSourceList)origPrevAvg.getAverage(); + modPrevAvg.process(modList, gridWeight); + GridSourceList listWithPrev = (GridSourceList)modPrevAvg.getAverage(); + validate(mfdWithPrev, listWithPrev, false); + } + + if (b < gridTree.size()-1) { + origPrevAvg = origProv.averagingAccumulator(); + origPrevAvg.process(origProv, gridWeight); + modPrevAvg = modList.averagingAccumulator(); + modPrevAvg.process(modList, gridWeight); + } + } + } + + GridSourceList avgOfOrig = (GridSourceList)origSubAvg.getAverage(); + GridSourceList avgOfMod = (GridSourceList)modSubAvg.getAverage(); + System.out.println("Built all for "+faultBranch+", validating averages"); + validate(avgOfOrig, avgOfMod, false); + if (origListAvg == null) + origListAvg = avgOfOrig.averagingAccumulator(); + origListAvg.process(avgOfOrig, faultWeight); + if (newListAvg == null) + newListAvg = avgOfMod.averagingAccumulator(); + newListAvg.process(avgOfMod, faultWeight); + } + + exec.shutdown(); + + System.out.println("Built all, validating averages"); + GridSourceList avgOfOrig = (GridSourceList)origListAvg.getAverage(); + GridSourceList avgOfMod = (GridSourceList)newListAvg.getAverage(); + validate(avgOfOrig, avgOfMod, true); + + System.out.println("DONE"); + System.exit(0); + } + + private static void validate(GridSourceList origList, GridSourceList modList, boolean verbose) { + for (int i=0; i refMFD.size()) + refMFD = mfdSubSeis1; + if (refMFD != null) { + System.out.println("MFDs\tUnAssoc1\tUnAssoc2\tSubSeis1\tSubSeis2\tSumEach1\tSumEach2"); + for (int x=0; x x) + unassoc1 = mfdUnassoc1.getY(x); + double unassoc2 = 0d; + if (mfdUnassoc2 != null && mfdUnassoc2.size() > x) + unassoc2 = mfdUnassoc2.getY(x); + double subSeis1 = 0d; + if (mfdSubSeis1 != null && mfdSubSeis1.size() > x) + subSeis1 = mfdSubSeis1.getY(x); + double subSeis2 = 0d; + if (mfdSubSeis2 != null && mfdSubSeis2.size() > x) + subSeis2 = mfdSubSeis2.getY(x); + + System.out.println((float)refMFD.getX(x)+"\t"+(float)unassoc1+"\t"+(float)unassoc2 + +"\t"+(float)subSeis1+"\t"+(float)subSeis2 + +"\t"+(float)(unassoc1+subSeis1)+"\t"+(float)(unassoc2+subSeis2)); + } + } + System.out.flush(); + e.printStackTrace(); + System.exit(1); + } + + // now verify the ruptures themselves + try { + assertEquals(origList, modList, i); + } catch (Exception e) { + System.out.println("Failed for Grid Node "+i+"/"+modList.getNumLocations()); + System.out.flush(); + e.printStackTrace(); + System.exit(1); + } + } + System.out.println("Validated!"); + } + + private static List getSorted(List rups) { + if (rups == null) + return new ArrayList<>(); + List ret = new ArrayList<>(rups); + ret.sort(gridRupComp); + for (int i=ret.size(); --i>=0;) + if (ret.get(i).properties.magnitude < 2.5d) + ret.remove(i); + return ret; + } + + private static Comparator gridRupComp = new Comparator() { + + @Override + public int compare(GriddedRupture o1, GriddedRupture o2) { + // magnitude first + int cmp = Float.compare((float)o1.properties.magnitude, (float)o2.properties.magnitude); + if (cmp != 0) + return cmp; + // rake + cmp = Float.compare((float)o1.properties.rake, (float)o2.properties.rake); + if (cmp != 0) + return cmp; + return o1.compareTo(o2); + } + }; + + private static boolean mfdEquals(double v1, double v2) { + return equalsWithTol(v1, v2, 1e-3, 0d, 1e-10); + } + + private static boolean rateEquals(double v1, double v2) { + return equalsWithTol(v1, v2, 1e-3, 1e-10, 1e-15); + } + + private static boolean assocEquals(double v1, double v2) { + return equalsWithTol(v1, v2, 1e-3, 1e-6, 1e-10); + } + + private static boolean equalsWithTol(double v1, double v2, double relativeTol, double absTol, + double ignoreBelowThresh) { + if (v1 < ignoreBelowThresh && v2 < ignoreBelowThresh) + return true; + if (relativeTol > 0 && !Precision.equalsWithRelativeTolerance(v1, v2, relativeTol)) + return false; + if (absTol > 0 && !Precision.equals(v1, v2, absTol)) + return false; + return true; + } + + private static void assertEquals(IncrementalMagFreqDist mfd1, IncrementalMagFreqDist mfd2, int gridIndex, boolean assoc) { + if (mfd1 == null || mfd1.calcSumOfY_Vals() == 0d) { + Preconditions.checkState(mfd2 == null || mfd2.calcSumOfY_Vals() == 0d, + "GridIndex=%s, assoc=%s: MFDList is null, SourceList is %s", gridIndex, assoc, mfd2); + } else { + double delta = Math.max(mfd1.getDelta(), mfd2.getDelta()); + + for (int i=0; i= (float)0.5*delta) { + Preconditions.checkState(x1 > x2, "x1=%s, x2=%s, delta=%s", x1, x2, delta); + x2 = x1; + y2 = 0d; + } else { + y2 = mfd2.getY(i2); + } + Preconditions.checkState(mfdEquals(y1, y2) || y1 < 1e-10 && y2 < 1e-10, + "Mismatch at GridIndex=%s, assoc=%s:\tMFDProv[%s]=%s\tSourceList[%s]=%s", + gridIndex, assoc, (float)x1, (float)y1, (float)x2, (float)y2); + } + for (int i=mfd1.size(); i= (float)0.5*mfd2.getDelta()) { + Preconditions.checkState(x1 > x2); + x2 = x1; + y2 = 0d; + } else { + y2 = mfd1.getY(i2); + } + Preconditions.checkState(mfdEquals(y1, y2) || y1 < 1e-10 && y2 < 1e-10, + "Mismatch at GridIndex=%s, assoc=%s:\tMFDProv[%s]=%s\tSourceList[%s]=%s", + gridIndex, assoc, (float)x2, (float)y2, (float)x1, (float)y1); + } + } + } + + private static void assertEquals(GridSourceList gridList1, GridSourceList gridList2, int gridIndex) { + List origRups = getSorted(gridList1.getRuptures(null, gridIndex)); + List modRups = getSorted(gridList2.getRuptures(null, gridIndex)); + + double totRate1 = origRups.stream().mapToDouble(R->R.rate).sum(); + double totRate2 = modRups.stream().mapToDouble(R->R.rate).sum(); + + Preconditions.checkState(origRups.size() == modRups.size(), + "Original list has %s rups (totRate=%s), mod has %s (totRate=%s); gridIndex=%s", + origRups.size(), totRate1, modRups.size(), totRate2, gridIndex); + + for (int i=0; i level = branch.getLevel(l); + if (level instanceof SectionSupraSeisBValues.FixedValueLevel) { + ((SectionSupraSeisBValues.FixedValueLevel)level).setValue(b); + branch.setValue(level.getNodes().get(0)); + } + } plotLevel = PlotLevel.REVIEW; diff --git a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java index f71eef8d..9e079ec6 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java @@ -11,6 +11,7 @@ import org.apache.commons.math3.stat.StatUtils; import org.opensha.commons.geo.Location; import org.opensha.commons.geo.LocationList; +import org.opensha.commons.geo.LocationUtils; import org.opensha.commons.geo.LocationUtils.LocationAverager; import org.opensha.commons.gui.plot.GeographicMapMaker; import org.opensha.commons.gui.plot.PlotCurveCharacterstics; @@ -18,9 +19,11 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.FaultUtils.AngleAverager; import org.opensha.commons.util.cpt.CPT; import org.opensha.sha.earthquake.faultSysSolution.ruptures.util.GeoJSONFaultReader; import org.opensha.sha.faultSurface.FaultSection; +import org.opensha.sha.faultSurface.FaultTrace; import org.opensha.sha.faultSurface.GeoJSONFaultSection; import org.opensha.sha.util.TectonicRegionType; @@ -38,8 +41,10 @@ public static void main(String[] args) throws IOException { File outputDir = new File(FIGURES_DIR, "slip_projection"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); - NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; -// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; +// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; +// double maxSlip = 160; + NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; + double maxSlip = 30d; List sects = fm.buildSubSects(fm); @@ -49,7 +54,49 @@ public static void main(String[] args) throws IOException { NSHM27_InterfaceDeformationModels dm = fm.getDefaultDeformationModel(); - GeographicMapMaker mapMaker = new GeographicMapMaker(sects); + LogicTreeBranch branch = NSHM27_LogicTree.buildDefault(fm.getSeisReg(), TectonicRegionType.SUBDUCTION_INTERFACE, false); + branch.setValue(NSHM27_InterfaceCouplingDepthModels.NONE); + +// double maxSlip = maxSlip(dm.apply(fm, branch, sects)); + CPT slipCPT = GMT_CPT_Files.SEQUENTIAL_BATLOW_UNIFORM.instance().rescale(0d, maxSlip); + + DeformationFront df = dm.getDeformationFront(fm); + double moveOffset = 15d; // km + + LocationList dfTrace = df.trace(); + List regSects = new ArrayList<>(sects); + if (moveOffset > 0d) { + LocationList movedTrace = new LocationList(dfTrace.size()); + for (int i=0; i branch = NSHM27_LogicTree.buildDefault(fm.getSeisReg(), TectonicRegionType.SUBDUCTION_INTERFACE, false); - branch.setValue(NSHM27_InterfaceCouplingDepthModels.NONE); - - double maxSlip = maxSlip(dm.apply(fm, branch, sects)); - CPT slipCPT = GMT_CPT_Files.SEQUENTIAL_BATLOW_UNIFORM.instance().rescale(0d, maxSlip); - - DeformationFront df = dm.getDeformationFront(fm); - for (NSHM27_InterfaceCouplingDepthModels depthCoupling : NSHM27_InterfaceCouplingDepthModels.values()) { branch.setValue(depthCoupling); List dmSects = dm.apply(fm, branch, sects); @@ -79,23 +118,24 @@ public static void main(String[] args) throws IOException { List traces = new ArrayList<>(); List traceChars = new ArrayList<>(); - traces.add(df.trace()); - traceChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 10f, Color.BLACK)); - traces.add(df.trace()); - traceChars.add(new PlotCurveCharacterstics(PlotLineType.DASHED, 10f, Color.LIGHT_GRAY)); + + traces.add(dfTrace); + traceChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 15f, Color.BLACK)); +// traces.add(dfTrace); +// traceChars.add(new PlotCurveCharacterstics(PlotLineType.DASHED, 10f, Color.LIGHT_GRAY)); for (int i=0; i Date: Thu, 4 Jun 2026 10:06:44 -0700 Subject: [PATCH 29/71] minor --- .../HardcodedInversionFactoryRunner.java | 32 ++++++++++++------- .../kevin/nshm27/BathymetryConvert.java | 2 +- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index a682fc4b..633b06fa 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -64,7 +64,9 @@ import com.google.common.base.Preconditions; import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_CrustalAggregatedDeformationModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceMinSubSects; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; @@ -183,21 +185,27 @@ public static void main(String[] args) throws IOException { // branch.setValue(node); // writeGridProv = true; -// LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( -// NSHM26_SeismicityRegions.GNMI, TectonicRegionType.SUBDUCTION_INTERFACE, false); -//// LogicTreeBranch branch = NSHM26_LogicTree.buildDefault( -//// NSHM26_SeismicityRegions.GNMI, TectonicRegionType.ACTIVE_SHALLOW, false); -// dirName += "-gnmi"; +// LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( +// NSHM27_SeismicityRegions.GNMI, TectonicRegionType.SUBDUCTION_INTERFACE, false); LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( - NSHM27_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); - dirName += "-amsam"; + NSHM27_SeismicityRegions.GNMI, TectonicRegionType.ACTIVE_SHALLOW, false); + dirName += "-gnmi"; +// LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( +// NSHM27_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); +// dirName += "-amsam"; - branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.AVERAGE); -// branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.SECTION_SPECIFIC); - branch.setValue(NSHM27_InterfaceMinSubSects.TWO); + if (branch.hasValue(NSHM27_InterfaceFaultModels.class) ) { + branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.AVERAGE); +// branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.SECTION_SPECIFIC); + branch.setValue(NSHM27_InterfaceMinSubSects.TWO); + branch.setValue(NSHM27_InterfaceDeformationModels.PREF_COUPLING); + } else { + branch.setValue(NSHM27_CrustalAggregatedDeformationModels.AVERAGE); + } branch.setValue(NSHM27_SeisRateModelBranch.AVERAGE); - branch.setValue(NSHM27_InterfaceDeformationModels.PREF_COUPLING); - branch.setValue(NSHM27_InterfaceDeformationModels.PREF_COUPLING); + +// writeGridProv = false; + writeGridProv = true; double b = 1d; dirName += "-b"+(float)b; diff --git a/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java b/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java index a8f78e68..d9ba8d4e 100644 --- a/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java +++ b/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java @@ -67,7 +67,7 @@ public static void main(String[] args) throws IOException { e.printStackTrace(); } - GriddedGeoDataSet.writeXYZFile(depths, new File("/tmp/"+seisReg.name()+"_depths.xyz")); + GriddedGeoDataSet.writeXYZFile(depths, new File("/tmp/"+seisReg.name()+"-depths.xyz")); GeographicMapMaker mapMaker = new GeographicMapMaker(gridReg); CPT cpt = GMT_CPT_Files.SEQUENTIAL_NAVIA_UNIFORM.instance().reverse().rescale(0d, 10d); cpt.setNanColor(Colors.tab_orange); From c66bed90216612659a7278f677a9338ff6f92661 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 22 Jun 2026 10:28:50 -0700 Subject: [PATCH 30/71] for upstream --- .../HardcodedInversionFactoryRunner.java | 6 +++--- .../nshm27/figures/SlipProjectionFigures.java | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index 633b06fa..000fda50 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -64,7 +64,7 @@ import com.google.common.base.Preconditions; import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_CrustalAggregatedDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_CrustalDeformationModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceMinSubSects; @@ -198,9 +198,9 @@ public static void main(String[] args) throws IOException { branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.AVERAGE); // branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.SECTION_SPECIFIC); branch.setValue(NSHM27_InterfaceMinSubSects.TWO); - branch.setValue(NSHM27_InterfaceDeformationModels.PREF_COUPLING); + branch.setValue(NSHM27_InterfaceDeformationModels.Aggregated.PREF_COUPLING); } else { - branch.setValue(NSHM27_CrustalAggregatedDeformationModels.AVERAGE); + branch.setValue(NSHM27_CrustalDeformationModels.Aggregated.AVERAGE); } branch.setValue(NSHM27_SeisRateModelBranch.AVERAGE); diff --git a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java index 9e079ec6..167ba1a9 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java @@ -21,7 +21,6 @@ import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.util.FaultUtils.AngleAverager; import org.opensha.commons.util.cpt.CPT; -import org.opensha.sha.earthquake.faultSysSolution.ruptures.util.GeoJSONFaultReader; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.faultSurface.FaultTrace; import org.opensha.sha.faultSurface.GeoJSONFaultSection; @@ -52,7 +51,7 @@ public static void main(String[] args) throws IOException { double maxRatio = 1.5; CPT ratioCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(0d, 2d).trim(1d, 2d).rescale(1d, maxRatio); - NSHM27_InterfaceDeformationModels dm = fm.getDefaultDeformationModel(); + NSHM27_InterfaceDeformationModels.Aggregated dm = fm.getDefaultDeformationModel(); LogicTreeBranch branch = NSHM27_LogicTree.buildDefault(fm.getSeisReg(), TectonicRegionType.SUBDUCTION_INTERFACE, false); branch.setValue(NSHM27_InterfaceCouplingDepthModels.NONE); @@ -60,7 +59,7 @@ public static void main(String[] args) throws IOException { // double maxSlip = maxSlip(dm.apply(fm, branch, sects)); CPT slipCPT = GMT_CPT_Files.SEQUENTIAL_BATLOW_UNIFORM.instance().rescale(0d, maxSlip); - DeformationFront df = dm.getDeformationFront(fm); + DeformationFront df = NSHM27_InterfaceDeformationModels.getDeformationFront(fm); double moveOffset = 15d; // km LocationList dfTrace = df.trace(); @@ -123,33 +122,35 @@ public static void main(String[] args) throws IOException { traceChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 15f, Color.BLACK)); // traces.add(dfTrace); // traceChars.add(new PlotCurveCharacterstics(PlotLineType.DASHED, 10f, Color.LIGHT_GRAY)); - for (int i=0; i Date: Mon, 22 Jun 2026 19:32:36 -0700 Subject: [PATCH 31/71] tests and upstream --- .../java/scratch/kevin/BranchScratch.java | 79 ++++++++++++++++++- .../HardcodedInversionFactoryRunner.java | 17 ++-- .../nshm27/figures/SlipProjectionFigures.java | 11 +-- 3 files changed, 94 insertions(+), 13 deletions(-) diff --git a/src/main/java/scratch/kevin/BranchScratch.java b/src/main/java/scratch/kevin/BranchScratch.java index c4a66a4c..db652a70 100644 --- a/src/main/java/scratch/kevin/BranchScratch.java +++ b/src/main/java/scratch/kevin/BranchScratch.java @@ -1,6 +1,7 @@ package scratch.kevin; import java.awt.Color; +import java.awt.geom.Point2D; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -8,7 +9,9 @@ import org.jfree.data.Range; import org.opensha.commons.data.CSVFile; +import org.opensha.commons.data.function.DiscretizedFunc; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.function.LightFixedXFunc; import org.opensha.commons.geo.Location; import org.opensha.commons.geo.Region; import org.opensha.commons.gui.plot.HeadlessGraphPanel; @@ -20,12 +23,21 @@ import org.opensha.sha.earthquake.ProbEqkSource; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; +import org.opensha.sha.earthquake.faultSysSolution.modules.ModSectMinMags; +import org.opensha.sha.earthquake.faultSysSolution.modules.RupMFDsModule; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; import org.opensha.sha.earthquake.rupForecastImpl.WGCEP_UCERF_2_Final.UCERF2; import org.opensha.sha.earthquake.rupForecastImpl.WGCEP_UCERF_2_Final.MeanUCERF2.MeanUCERF2; +import org.opensha.sha.earthquake.rupForecastImpl.prvi25.erf.NSHM25_PRVI_BranchAveragedERF; +import org.opensha.sha.earthquake.util.GriddedSeismicitySettings; import org.opensha.sha.faultSurface.FaultSection; +import org.opensha.sha.faultSurface.PointSurface; +import org.opensha.sha.faultSurface.RuptureSurface; import org.opensha.sha.magdist.IncrementalMagFreqDist; +import scratch.UCERF3.erf.mean.MeanUCERF3; +import scratch.UCERF3.inversion.InversionFaultSystemRupSet; + public class BranchScratch { private static void test1() throws IOException { @@ -105,13 +117,78 @@ private static void test2() throws IOException { } } + private static void test3() throws IOException { + NSHM25_PRVI_BranchAveragedERF erf = new NSHM25_PRVI_BranchAveragedERF(); +// erf.setGriddedSeismicitySettings(GriddedSeismicitySettings.DEFAULT.forDistanceCorrection(null)); + erf.updateForecast(); + long numRups = 0l; + long numPtRups = 0l; + long numPtRupsWithCorr = 0l; + for (ProbEqkSource source : erf) { + numRups += source.getNumRuptures(); + for (ProbEqkRupture rup : source) { + RuptureSurface surf = rup.getRuptureSurface(); + if (surf instanceof PointSurface) { + numPtRups++; + PointSurface ptSurf = (PointSurface)surf; + if (ptSurf instanceof PointSurface.DistanceCorrectable || ptSurf instanceof PointSurface.DistanceCorrectionAttached) + numPtRupsWithCorr++; + } + } + } + System.out.println("Have "+numRups+" total rups"); + System.out.println("\t"+numPtRups+" are point sources"); + System.out.println("\t"+numPtRupsWithCorr+" are point sources w/ dist corrs"); + } + + private static void test4() throws IOException { + File storeDir = MeanUCERF3.getStoreDir(); + File solFile = MeanUCERF3.checkDownload( + new File(storeDir, "cached_FM3_1_dep100.0_depMean_rakeMean.zip")).join(); + FaultSystemSolution sol = FaultSystemSolution.load(solFile); + FaultSystemRupSet rupSet = sol.getRupSet(); + System.out.println("Sol type: "+sol.getClass()); + System.out.println("Rup set type: "+rupSet.getClass()); + System.out.println("Inv type? "+(rupSet instanceof InversionFaultSystemRupSet)); + ModSectMinMags modMags = rupSet.getModule(ModSectMinMags.class); + if (modMags == null) { + System.out.println("No mod mags"); + } else { + System.out.println("Mod mags type: "+modMags.getClass()+"; name="+modMags.getName()); + } + + RupMFDsModule mfds = rupSet.getModule(RupMFDsModule.class); + System.out.println("Has MFDs? "+(mfds != null)); + for (int s=0; s 0) { + totRate += pt.getY(); + minMag = Math.min(minMag, pt.getX()); + } + } + } +// if (minMag < 5.9d) { + if (minMag < 6d) { + FaultSection sect = rupSet.getFaultSectionData(s); + System.out.println(s+". "+sect.getSectionName()+" (parent="+sect.getParentSectionId()+"):\tminMag="+(float)minMag + +"\trate="+(float)totRate+"\tRI="+(float)(1d/totRate)); + } + } + } + /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { try { - test2(); + test4(); } catch (Throwable t) { t.printStackTrace(); System.exit(1); diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index 000fda50..f39055d9 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -187,22 +187,25 @@ public static void main(String[] args) throws IOException { // LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( // NSHM27_SeismicityRegions.GNMI, TectonicRegionType.SUBDUCTION_INTERFACE, false); +//// LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( +//// NSHM27_SeismicityRegions.GNMI, TectonicRegionType.ACTIVE_SHALLOW, false); +// dirName += "-gnmi"; LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( - NSHM27_SeismicityRegions.GNMI, TectonicRegionType.ACTIVE_SHALLOW, false); - dirName += "-gnmi"; -// LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( -// NSHM27_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); -// dirName += "-amsam"; + NSHM27_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); + dirName += "-amsam"; if (branch.hasValue(NSHM27_InterfaceFaultModels.class) ) { - branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.AVERAGE); +// branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.NONE); +// branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.AVERAGE); // branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.SECTION_SPECIFIC); + branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.EXTRAPOLATE); branch.setValue(NSHM27_InterfaceMinSubSects.TWO); branch.setValue(NSHM27_InterfaceDeformationModels.Aggregated.PREF_COUPLING); } else { branch.setValue(NSHM27_CrustalDeformationModels.Aggregated.AVERAGE); } - branch.setValue(NSHM27_SeisRateModelBranch.AVERAGE); +// branch.setValue(NSHM27_SeisRateModelBranch.AVERAGE); + branch.setValue(NSHM27_SeisRateModelBranch.PREFFERRED); // writeGridProv = false; writeGridProv = true; diff --git a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java index 167ba1a9..f189bce4 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java @@ -37,13 +37,14 @@ public class SlipProjectionFigures { public static void main(String[] args) throws IOException { - File outputDir = new File(FIGURES_DIR, "slip_projection"); +// File outputDir = new File(FIGURES_DIR, "slip_projection"); + File outputDir = new File("/tmp/nshm27_slip_projection"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); -// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; -// double maxSlip = 160; - NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; - double maxSlip = 30d; + NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; + double maxSlip = 160; +// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; +// double maxSlip = 30d; List sects = fm.buildSubSects(fm); From 1f4a8ffb2529b1846350471b44db9882bcabb919 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 23 Jun 2026 15:54:45 -0700 Subject: [PATCH 32/71] for upstream --- .../java/scratch/kevin/BranchScratch.java | 30 +++-- .../HardcodedInversionFactoryRunner.java | 4 +- .../java/scratch/kevin/nshm27/LmaxTests.java | 52 +++++++++ .../nshm27/figures/SlipProjectionFigures.java | 105 +++++++++++++++++- 4 files changed, 175 insertions(+), 16 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm27/LmaxTests.java diff --git a/src/main/java/scratch/kevin/BranchScratch.java b/src/main/java/scratch/kevin/BranchScratch.java index db652a70..9373087b 100644 --- a/src/main/java/scratch/kevin/BranchScratch.java +++ b/src/main/java/scratch/kevin/BranchScratch.java @@ -142,42 +142,52 @@ private static void test3() throws IOException { } private static void test4() throws IOException { - File storeDir = MeanUCERF3.getStoreDir(); - File solFile = MeanUCERF3.checkDownload( - new File(storeDir, "cached_FM3_1_dep100.0_depMean_rakeMean.zip")).join(); +// File storeDir = MeanUCERF3.getStoreDir(); +// File solFile = MeanUCERF3.checkDownload( +// new File(storeDir, "cached_FM3_1_dep100.0_depMean_rakeMean.zip")).join(); + File solFile = new File("/home/kevin/OpenSHA/fss_inversions/2021_11_30-u3_branches-orig_calcs-5h/results_FM3_1_branch_averaged.zip"); FaultSystemSolution sol = FaultSystemSolution.load(solFile); FaultSystemRupSet rupSet = sol.getRupSet(); + RupMFDsModule mfds = rupSet.getModule(RupMFDsModule.class); + ModSectMinMags modMags = rupSet.getModule(ModSectMinMags.class); System.out.println("Sol type: "+sol.getClass()); System.out.println("Rup set type: "+rupSet.getClass()); System.out.println("Inv type? "+(rupSet instanceof InversionFaultSystemRupSet)); - ModSectMinMags modMags = rupSet.getModule(ModSectMinMags.class); if (modMags == null) { System.out.println("No mod mags"); } else { System.out.println("Mod mags type: "+modMags.getClass()+"; name="+modMags.getName()); } - RupMFDsModule mfds = rupSet.getModule(RupMFDsModule.class); System.out.println("Has MFDs? "+(mfds != null)); for (int s=0; s 0) { totRate += pt.getY(); - minMag = Math.min(minMag, pt.getX()); + rupMinMag = Math.min(rupMinMag, pt.getX()); } } + minMag = Math.min(minMag, rupMinMag); + if (modMags == null || !modMags.isRupBelowSectMinMag(rupIndex)) + minIncludedMag = Math.min(minIncludedMag, rupMinMag); } -// if (minMag < 5.9d) { - if (minMag < 6d) { + if (minMag < 5.9d) { +// if (minMag < 6d) { FaultSection sect = rupSet.getFaultSectionData(s); - System.out.println(s+". "+sect.getSectionName()+" (parent="+sect.getParentSectionId()+"):\tminMag="+(float)minMag - +"\trate="+(float)totRate+"\tRI="+(float)(1d/totRate)); + String prefix = s+". "+sect.getSectionName()+" (parent="+sect.getParentSectionId()+"):"; + if (modMags == null) + System.out.println(prefix+"\tminMag="+(float)minMag+"\trate="+(float)totRate+"\tRI="+(float)(1d/totRate)); + else + System.out.println(prefix+"\tminMag="+(float)minMag+"\tminIncludedMag="+(float)minIncludedMag + +"\trate="+(float)totRate+"\tRI="+(float)(1d/totRate)); } } } diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index f39055d9..eb57ff1a 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -195,10 +195,10 @@ public static void main(String[] args) throws IOException { dirName += "-amsam"; if (branch.hasValue(NSHM27_InterfaceFaultModels.class) ) { -// branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.NONE); + branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.NONE); // branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.AVERAGE); // branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.SECTION_SPECIFIC); - branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.EXTRAPOLATE); +// branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.EXTRAPOLATE); branch.setValue(NSHM27_InterfaceMinSubSects.TWO); branch.setValue(NSHM27_InterfaceDeformationModels.Aggregated.PREF_COUPLING); } else { diff --git a/src/main/java/scratch/kevin/nshm27/LmaxTests.java b/src/main/java/scratch/kevin/nshm27/LmaxTests.java new file mode 100644 index 00000000..38de3187 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/LmaxTests.java @@ -0,0 +1,52 @@ +package scratch.kevin.nshm27; + +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.BitSet; + +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; +import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; +import org.opensha.sha.util.TectonicRegionType; + +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; + +public class LmaxTests { + + public static void main(String[] args) throws IOException { + NSHM27_SeismicityRegions reg = NSHM27_SeismicityRegions.AMSAM; +// NSHM27_SeismicityRegions reg = NSHM27_SeismicityRegions.GNMI; + + double[] lMaxs = {150, 175, 200, 250, 300, 400, 500, 600, 700, 800, 900, 950, 1000, 1100, 1200, 1300}; + + PRVI25_SubductionScalingRelationships scale = PRVI25_SubductionScalingRelationships.LOGA_C4p0; + + LogicTreeBranch branch = NSHM27_LogicTree.buildDefault(reg, TectonicRegionType.SUBDUCTION_INTERFACE, false); + branch.setValue(scale); + FaultSystemRupSet rupSet = new NSHM27_InvConfigFactory().buildRuptureSet(branch, 16); + + DecimalFormat magDF = new DecimalFormat("0.00"); + + for (double lMax : lMaxs) { + BitSet rups = new BitSet(rupSet.getNumRuptures()); + for (int r=0; r sects = fm.buildSubSects(fm); @@ -143,6 +150,96 @@ public static void main(String[] args) throws IOException { mapMaker.plot(outputDir, fm.name()+"_"+dm.getFilePrefix()+"_"+depthCoupling.name()+"_slip_deficit_rate", dm.getShortName()+" DM, "+depthCoupling.getShortName()+" Taper"); + + if (depthCoupling == NSHM27_InterfaceCouplingDepthModels.NONE) { + // add length annotations + + FaultSection sect= fm.getFaultSections().get(0); + FaultTrace upper = sect.getFaultTrace(); + FaultTrace lower = sect.getLowerFaultTrace(); + + int numResample = 5000; + + upper = FaultUtils.resampleTrace(upper, numResample); + lower = FaultUtils.resampleTrace(lower, numResample); + + FaultTrace middle = new FaultTrace(); + for (int i=0; i lengthVals = new ArrayList<>(); + + double curLen = 0d; + for (int i=0; i 0) + curLen += LocationUtils.horzDistance(middle.get(i-1), middle.get(i)); + if (curLen >= nextMarker || i == numResample-1) { + Location loc; + double markerLen; + if (i > 0 && i < numResample-1) { + double overshoot = curLen - nextMarker; + double backAz = LocationUtils.azimuthRad(middle.get(i), middle.get(i-1)); + loc = LocationUtils.location(middle.get(i), backAz, overshoot); + markerLen = nextMarker; + } else { + loc = middle.get(i); + markerLen = curLen; + } + lengthLocs.add(loc); + lengthVals.add(markerLen); + + nextMarker += markerDelta; + } + } + + for (int i=0; i Date: Thu, 25 Jun 2026 11:20:34 -0700 Subject: [PATCH 33/71] upstream --- .../nshm23/HardcodedInversionFactoryRunner.java | 15 +++++++++++++++ .../nshm27/InterfaceSubSeisMoReductionTests.java | 2 +- .../kevin/nshm27/InversionMinSubSectMagTests.java | 2 +- .../nshm27/figures/SlipProjectionFigures.java | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index eb57ff1a..d18a6d5c 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -29,6 +29,7 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.InversionTargetMFDs; import org.opensha.sha.earthquake.faultSysSolution.reports.ReportPageGen; import org.opensha.sha.earthquake.faultSysSolution.reports.ReportPageGen.PlotLevel; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.NSHM23_ConstraintBuilder; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.NSHM23_InvConfigFactory; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.data.NSHM23_PaleoDataLoader; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.data.NSHM23_WasatchSegmentationData; @@ -65,6 +66,7 @@ import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_CrustalDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceMinSubSects; @@ -200,7 +202,11 @@ public static void main(String[] args) throws IOException { // branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.SECTION_SPECIFIC); // branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.EXTRAPOLATE); branch.setValue(NSHM27_InterfaceMinSubSects.TWO); +// branch.setValue(NSHM27_InterfaceDeformationModels.Aggregated.LOW_COUPLING); branch.setValue(NSHM27_InterfaceDeformationModels.Aggregated.PREF_COUPLING); +// branch.setValue(NSHM27_InterfaceDeformationModels.Aggregated.HIGH_COUPLING); +// branch.setValue(NSHM27_InterfaceCouplingDepthModels.DOUBLE_TAPER); + branch.setValue(NSHM27_InterfaceCouplingDepthModels.AVERAGE); } else { branch.setValue(NSHM27_CrustalDeformationModels.Aggregated.AVERAGE); } @@ -211,7 +217,16 @@ public static void main(String[] args) throws IOException { writeGridProv = true; double b = 1d; +// double b = 0.5d; +// double b = 0d; dirName += "-b"+(float)b; + +// // hinged b-value tests +// FaultSystemRupSet tempRupSet = factory.buildRuptureSet(branch, threads); +// new NSHM27_InvConfigFactory().getSolutionLogicTreeProcessor().processRupSet(tempRupSet, branch); +// double b = NSHM27_InvConfigFactory.calcInterfaceHingedBValue(tempRupSet, branch); +// dirName += "-hingedB"+(float)b; + for (int l=0; l level = branch.getLevel(l); if (level instanceof SectionSupraSeisBValues.FixedValueLevel) { diff --git a/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java index 9a2c2c0a..1c25ae2e 100644 --- a/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java +++ b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java @@ -48,7 +48,7 @@ public static void main(String[] args) throws IOException { NSHM27_InterfaceFaultModels fm = branch.requireValue(NSHM27_InterfaceFaultModels.class); NSHM27_InterfaceDeformationModels dm = branch.requireValue(NSHM27_InterfaceDeformationModels.class); - NSHM27_SeismicityRegions reg = fm.getSeisReg(); + NSHM27_SeismicityRegions reg = fm.getSeismicityRegion(); File pdfBaseDir = new File("/home/kevin/OpenSHA/nshm26/data/spatial_seis_pdfs/"+reg.name().toLowerCase()+"/2026_03_09-v1_2D/INTERFACE"); System.out.println("Branch: "+branch+"; reg="+reg); diff --git a/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java b/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java index fd1ec97a..190ded00 100644 --- a/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java +++ b/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java @@ -25,7 +25,7 @@ public static void main(String[] args) throws IOException { NSHM27_InterfaceMinSubSects[] minSects = NSHM27_InterfaceMinSubSects.values(); for (NSHM27_InterfaceFaultModels fm : NSHM27_InterfaceFaultModels.values()) { LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( - fm.getSeisReg(), TectonicRegionType.SUBDUCTION_INTERFACE, false); + fm.getSeismicityRegion(), TectonicRegionType.SUBDUCTION_INTERFACE, false); branch.setValue(PRVI25_SubductionScalingRelationships.AVERAGE); FaultSystemRupSet rupSet = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); diff --git a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java index 42dbc3e1..cc86f0b4 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java @@ -61,7 +61,7 @@ public static void main(String[] args) throws IOException { NSHM27_InterfaceDeformationModels.Aggregated dm = fm.getDefaultDeformationModel(); - LogicTreeBranch branch = NSHM27_LogicTree.buildDefault(fm.getSeisReg(), TectonicRegionType.SUBDUCTION_INTERFACE, false); + LogicTreeBranch branch = NSHM27_LogicTree.buildDefault(fm.getSeismicityRegion(), TectonicRegionType.SUBDUCTION_INTERFACE, false); branch.setValue(NSHM27_InterfaceCouplingDepthModels.NONE); // double maxSlip = maxSlip(dm.apply(fm, branch, sects)); From a7935cb59b71033110a89f0e80bca8e50715ca6f Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 30 Jun 2026 07:09:09 -0700 Subject: [PATCH 34/71] beta model updates --- .../kevin/nshm23/GriddedMFDWriter.java | 21 ++++++----- .../HardcodedInversionFactoryRunner.java | 37 ++++++++++--------- .../UpdatedRandTreeSerialzationTests.java | 4 +- .../nshm27/figures/SlipProjectionFigures.java | 8 ++-- 4 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/GriddedMFDWriter.java b/src/main/java/scratch/kevin/nshm23/GriddedMFDWriter.java index dbd7554d..17e01469 100644 --- a/src/main/java/scratch/kevin/nshm23/GriddedMFDWriter.java +++ b/src/main/java/scratch/kevin/nshm23/GriddedMFDWriter.java @@ -53,14 +53,15 @@ public static void main(String[] args) throws IOException { Region reg = NSHM23_RegionLoader.loadFullConterminousWUS(); GriddedRegion gridReg = new GriddedRegion(reg, 0.1, GriddedRegion.ANCHOR_0_0); - EvenlyDiscretizedFunc refMFD = FaultSysTools.initEmptyMFD(5.01, 8.55); +// EvenlyDiscretizedFunc refMFD = FaultSysTools.initEmptyMFD(5.01, 8.55); + EvenlyDiscretizedFunc refMFD = FaultSysTools.initEmptyMFD(4.01, 8.55); File assocFile = null; FaultSystemSolution refSol = FaultSystemSolution.load(new File(solDir, "results_WUS_FM_v3_branch_averaged_gridded.zip")); -// File outputFile = new File("/tmp/nshm23_wus_gridded_mfds.csv"); -// FaultSystemSolution sol = refSol; + File outputFile = new File("/tmp/nshm23_wus_gridded_mfds.csv"); + FaultSystemSolution sol = refSol; // File outputFile = new File("/tmp/nshm23_wus_gridded_mfds_b0.csv"); // FaultSystemSolution sol = FaultSystemSolution.load(new File(baSolDir, "SupraB_SupraB0.0.zip")); @@ -116,12 +117,12 @@ public static void main(String[] args) throws IOException { // File outputFile = new File("/tmp/nshm23_wus_gridded_mfds_smooth_fixed.csv"); // sol.setGridSourceProvider(getAverageGridProv(gridSLT, NSHM23_SeisSmoothingAlgorithms.FIXED)); - File outputFile = new File("/tmp/ucerf3_gridded_mfds.csv"); - refSol = null; - reg = new CaliforniaRegions.RELM_TESTING(); - gridReg = new CaliforniaRegions.RELM_TESTING_GRIDDED(); - FaultSystemSolution sol = FaultSystemSolution.load(new File("/home/kevin/OpenSHA/nshm23/batch_inversions/2021_11_30-u3_branches-orig_calcs-5h/results_FM3_1_branch_averaged.zip")); - assocFile = new File("/tmp/ucerf3_gridded_fault_associations.csv"); +// File outputFile = new File("/tmp/ucerf3_gridded_mfds.csv"); +// refSol = null; +// reg = new CaliforniaRegions.RELM_TESTING(); +// gridReg = new CaliforniaRegions.RELM_TESTING_GRIDDED(); +// FaultSystemSolution sol = FaultSystemSolution.load(new File("/home/kevin/OpenSHA/nshm23/batch_inversions/2021_11_30-u3_branches-orig_calcs-5h/results_FM3_1_branch_averaged.zip")); +// assocFile = new File("/tmp/ucerf3_gridded_fault_associations.csv"); FaultGridAssociations assoc = sol.getRupSet().getModule(FaultGridAssociations.class); if (assoc == null) { @@ -294,7 +295,7 @@ public static CSVFile buildForSolution(FaultSystemSolution refSol, Fault // do gridded for (int s=0; s branch = NSHM27_LogicTree.buildDefault( //// NSHM27_SeismicityRegions.GNMI, TectonicRegionType.ACTIVE_SHALLOW, false); // dirName += "-gnmi"; + NSHM27_LogicTree.INTERFACE_B_HINGED_WEIGHT = 1d; LogicTreeBranch branch = NSHM27_LogicTree.buildDefault( NSHM27_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, false); dirName += "-amsam"; @@ -216,24 +217,24 @@ public static void main(String[] args) throws IOException { // writeGridProv = false; writeGridProv = true; - double b = 1d; -// double b = 0.5d; -// double b = 0d; - dirName += "-b"+(float)b; - -// // hinged b-value tests -// FaultSystemRupSet tempRupSet = factory.buildRuptureSet(branch, threads); -// new NSHM27_InvConfigFactory().getSolutionLogicTreeProcessor().processRupSet(tempRupSet, branch); -// double b = NSHM27_InvConfigFactory.calcInterfaceHingedBValue(tempRupSet, branch); -// dirName += "-hingedB"+(float)b; - - for (int l=0; l level = branch.getLevel(l); - if (level instanceof SectionSupraSeisBValues.FixedValueLevel) { - ((SectionSupraSeisBValues.FixedValueLevel)level).setValue(b); - branch.setValue(level.getNodes().get(0)); - } - } +// double b = 1d; +//// double b = 0.5d; +//// double b = 0d; +// dirName += "-b"+(float)b; +// +//// // hinged b-value tests +//// FaultSystemRupSet tempRupSet = factory.buildRuptureSet(branch, threads); +//// new NSHM27_InvConfigFactory().getSolutionLogicTreeProcessor().processRupSet(tempRupSet, branch); +//// double b = NSHM27_InvConfigFactory.calcInterfaceHingedBValue(tempRupSet, branch); +//// dirName += "-hingedB"+(float)b; +// +// for (int l=0; l level = branch.getLevel(l); +// if (level instanceof SectionSupraSeisBValues.FixedValueLevel) { +// ((SectionSupraSeisBValues.FixedValueLevel)level).setValue(b); +// branch.setValue(level.getNodes().get(0)); +// } +// } plotLevel = PlotLevel.REVIEW; diff --git a/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java b/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java index a2268818..25ae72af 100644 --- a/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java +++ b/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java @@ -118,9 +118,9 @@ public TestValuedLevel() { } @Override - protected void doBuild(long seed, int numNodes, SamplingMethod samplingMethod) { + protected void doBuild(long seed, int numNodes, SamplingMethod samplingMethod, double weightEach) { Random rand = new Random(seed); - super.build(()->rand.nextDouble(), numNodes, 1d/numNodes); + super.build(()->rand.nextDouble(), numNodes, weightEach); } @Override diff --git a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java index cc86f0b4..3b2c79c3 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java @@ -48,10 +48,10 @@ public static void main(String[] args) throws IOException { File outputDir = new File("/tmp/nshm27_slip_projection"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); -// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; -// double maxSlip = 150; - NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; - double maxSlip = 30d; + NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; + double maxSlip = 150; +// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; +// double maxSlip = 30d; List sects = fm.buildSubSects(fm); From 8e6319dacebeb650d8c421929dd2892c5e22a599 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 13 Jul 2026 11:23:40 -0700 Subject: [PATCH 35/71] for upstream --- .../InterfaceSubSeisMoReductionTests.java | 4 +- .../kevin/nshm27/figures/LogicTreeFigure.java | 43 +- .../figures/ObsUncertaintyBoundsFigure.java | 490 +++++++++--------- .../nshm27/figures/SlipProjectionFigures.java | 8 +- .../prvi25/figures/CombinedMFDsPlot.java | 27 +- .../prvi25/figures/IndividualMFDPlots.java | 32 +- .../prvi25/figures/RateEpochComparison.java | 22 +- 7 files changed, 331 insertions(+), 295 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java index 1c25ae2e..9c6f23b4 100644 --- a/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java +++ b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java @@ -33,6 +33,7 @@ import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisClassificationMethod; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelBranch; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisSmoothingAlgorithms; import gov.usgs.earthquake.nshmp.erf.nshm27.util.InterfaceGridAssociations; @@ -105,7 +106,8 @@ public static void main(String[] args) throws IOException { double[] mMins = {6.55, 7.05, 7.55}; for (double mMin : mMins) { - IncrementalMagFreqDist seisMFD = rateModel.build(reg, TectonicRegionType.SUBDUCTION_INTERFACE, refMFD, + IncrementalMagFreqDist seisMFD = rateModel.build(reg, NSHM27_SeisClassificationMethod.PROFACE, + TectonicRegionType.SUBDUCTION_INTERFACE, refMFD, refMFD.getX(refMFD.getClosestXIndex(mMin-0.1))); // System.out.println("Seis MFD for interface Mmin="+mMin+":\n"+seisMFD); double[] impliedMoments = new double[sects.size()]; diff --git a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java index 9e28ee86..2f922bfc 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java @@ -4,13 +4,16 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeFigureWriter; import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.sha.earthquake.faultSysSolution.RupSetFaultModel; import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; @@ -36,6 +39,7 @@ public static void main(String[] args) throws IOException { for (NSHM27_SeismicityRegions seisReg : NSHM27_SeismicityRegions.values()) { for (TectonicRegionType trt : trts) { LogicTree tree = NSHM27_LogicTree.buildLogicTree(seisReg, trt, samples, true, samplingMethod); + tree = stripFaultModels(tree); LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(tree, false, useLevelWeights); ltFig.write(outputDir, seisReg.name()+"_"+trt.name(), true, true); @@ -43,13 +47,16 @@ public static void main(String[] args) throws IOException { boolean doSeparate = trt == TectonicRegionType.SUBDUCTION_INTERFACE || (trt == TectonicRegionType.ACTIVE_SHALLOW && seisReg == NSHM27_SeismicityRegions.GNMI); if (doSeparate) { - List> levels = NSHM27_LogicTree.buildLevels(seisReg, trt, useLevelWeights, true, false); + List> levels = NSHM27_LogicTree.buildLevels(seisReg, trt, useLevelWeights, true, false, false); + levels = stripFaultModels(levels); tree = LogicTree.buildSampled(levels, samples, 123456l, NSHM27_InterfaceFaultModels.regionDefault(seisReg)); ltFig = new LogicTreeFigureWriter(tree, false, useLevelWeights); ltFig.write(outputDir, seisReg.name()+"_"+trt.name()+"_inversion", true, true); - levels = NSHM27_LogicTree.buildLevels(seisReg, trt, useLevelWeights, false, true); + // include common with gridded + levels = NSHM27_LogicTree.buildLevels(seisReg, trt, useLevelWeights, false, true, true); + levels = stripFaultModels(levels); tree = LogicTree.buildSampled(levels, samples, 123456l); ltFig = new LogicTreeFigureWriter(tree, false, useLevelWeights); @@ -58,9 +65,39 @@ public static void main(String[] args) throws IOException { } LogicTree multiTree = NSHM27_LogicTree.buildMultiRegimeTree(seisReg, samples, true, samplingMethod); - LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(LogicTree.unrollTRTs(multiTree), false, useLevelWeights); + LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(stripFaultModels(LogicTree.unrollTRTs(multiTree)), false, useLevelWeights); ltFig.write(outputDir, seisReg.name()+"_combined", true, true); } } + + private static List> stripFaultModels(List> levels) { + List> ret = new ArrayList<>(); + + for (LogicTreeLevel level : levels) { + if (RupSetFaultModel.class.isAssignableFrom(level.getType())) + continue; + ret.add(level); + } + + return ret; + } + + private static LogicTree stripFaultModels(LogicTree tree) { + List> levels = stripFaultModels(tree.getLevels()); + List> branches = new ArrayList<>(tree.size()); + for (LogicTreeBranch branch : tree) { + List values = new ArrayList<>(levels.size()); + for (LogicTreeNode value : branch) { + if (value instanceof RupSetFaultModel) + continue; + values.add(value); + } + Preconditions.checkState(values.size() == levels.size()); + LogicTreeBranch modBranch = new LogicTreeBranch<>(levels, values); + modBranch.setOrigBranchWeight(branch.getOrigBranchWeight()); + branches.add(modBranch); + } + return LogicTree.fromExisting(levels, branches); + } } diff --git a/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java b/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java index 5404bc76..b8943ce4 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java @@ -34,6 +34,7 @@ import com.google.common.base.Preconditions; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisClassificationMethod; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelBranch; import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelSamples; import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader; @@ -85,280 +86,281 @@ public static void main(String[] args) throws IOException { double weightHigh = NSHM27_SeisRateModelBranch.HIGH.getNodeWeight(); for (NSHM27_SeismicityRegions seisReg : seisRegions) { - for (TectonicRegionType trt : trts) { - List funcs = new ArrayList<>(); - List chars = new ArrayList<>(); - - String prefix = seisReg.name()+"_"+trt.name(); - String title = seisReg.getShortName()+" ("+NSHM27_RegionLoader.getNameForTRT(trt)+")"; - - DecimalFormat oDF = new DecimalFormat("0.#"); - - Double m1 = null; - Double mMax = null; - Map typeMagFuncs = new HashMap<>(); - EvenlyDiscretizedFunc overallMean = null; - for (RateType type : types) { - SeismicityRateModel rateModel = NSHM27_SeisRateModelBranch.loadRateModel(seisReg, trt, type); - - RateRecord meanRec = rateModel.getMeanRecord(); - if (m1 == null) - m1 = meanRec.M1; - if (mMax == null && meanRec instanceof PureGR) - mMax = ((PureGR)meanRec).Mmax; + for (NSHM27_SeisClassificationMethod classification : NSHM27_SeisClassificationMethod.values()) { + for (TectonicRegionType trt : trts) { + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); - EvenlyDiscretizedFunc meanMFD; - if (incremental) - meanMFD = SeismicityRateFileLoader.buildIncrementalMFD(meanRec, refMFD, refMFD.getMaxX()); - else - meanMFD = cmlMFD(meanRec, refMFD); - - if (funcs.isEmpty()) { - meanMFD.setName("Mean"); - funcs.add(meanMFD); - chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 4f, Color.BLACK)); - overallMean = meanMFD; - } + String prefix = seisReg.name()+"_"+trt.name()+"_"+classification.name(); + String title = seisReg.getShortName()+" ("+NSHM27_RegionLoader.getNameForTRT(trt)+", "+classification.getShortName()+")"; - Color color = colors[type.ordinal()]; - PlotLineType plt = lineTypes[type.ordinal()]; - RateRecord low = rateModel.getLowerRecord(); - RateRecord high = rateModel.getUpperRecord(); + DecimalFormat oDF = new DecimalFormat("0.#"); - EvenlyDiscretizedFunc lowMFD; - EvenlyDiscretizedFunc highMFD; - if (incremental) { - lowMFD = SeismicityRateFileLoader.buildIncrementalMFD(low, refMFD, refMFD.getMaxX()); - highMFD = SeismicityRateFileLoader.buildIncrementalMFD(high, refMFD, refMFD.getMaxX()); - } else { - lowMFD = cmlMFD(low, refMFD); - highMFD = cmlMFD(high, refMFD); - } - - typeMagFuncs.put(type, new EvenlyDiscretizedFunc[] {lowMFD, highMFD}); - - lowMFD.setName(type.toString().replace("Branches", "branches")); - funcs.add(lowMFD); - chars.add(new PlotCurveCharacterstics(plt, 3f, color)); - highMFD.setName(null); - funcs.add(highMFD); - chars.add(new PlotCurveCharacterstics(plt, 3f, color)); - - if (includeWtMean && type == RateType.M1_TO_MMAX) { - EvenlyDiscretizedFunc weightAvg = new EvenlyDiscretizedFunc(meanMFD.getMinX(), meanMFD.size(), meanMFD.getDelta()); - Preconditions.checkState((float)meanMFD.getMinX() == (float)lowMFD.getMinX()); - Preconditions.checkState((float)meanMFD.getMinX() == (float)highMFD.getMinX()); - for (int i=0; i typeMagFuncs = new HashMap<>(); + EvenlyDiscretizedFunc overallMean = null; + for (RateType type : types) { + SeismicityRateModel rateModel = NSHM27_SeisRateModelBranch.loadRateModel(seisReg, classification, trt, type); - if (!incremental) { - System.out.println(title); - System.out.println("\tM>5: "+(float)weightAvg.getY(weightAvg.getClosestXIndex(5.01))); - System.out.println("\tM>6: "+(float)weightAvg.getY(weightAvg.getClosestXIndex(6.01))); - System.out.println("\tM>6 snapped: "+(float)weightAvg.getX(weightAvg.getClosestXIndex(6.01))); - System.out.println("\tM1="+m1.floatValue()); - System.out.println("\tMmax="+mMax.floatValue()); + RateRecord meanRec = rateModel.getMeanRecord(); + if (m1 == null) + m1 = meanRec.M1; + if (mMax == null && meanRec instanceof PureGR) + mMax = ((PureGR)meanRec).Mmax; + + EvenlyDiscretizedFunc meanMFD; + if (incremental) + meanMFD = SeismicityRateFileLoader.buildIncrementalMFD(meanRec, refMFD, refMFD.getMaxX()); + else + meanMFD = cmlMFD(meanRec, refMFD); + + if (funcs.isEmpty()) { + meanMFD.setName("Mean"); + funcs.add(meanMFD); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 4f, Color.BLACK)); + overallMean = meanMFD; } - weightAvg.setName(type.toString()+" Average"); - funcs.add(weightAvg); - chars.add(new PlotCurveCharacterstics(plt, 3f, Color.DARK_GRAY)); - } - } - - for (XY_DataSet func : funcs) { - if (func.getName() != null && func.getName().contains("M1")) - func.setName(func.getName().replace("M1", "M₁")); - if (func.getName() != null && func.getName().contains("Mmax")) - func.setName(func.getName().replace("Mmax", "Mₘₐₓ")); - } - - Range xRange = new Range(4d, 8d); - Range yRange = incremental ? new Range(1e-4, 1e2) : new Range(1e-3, 1e3); - - List anns = new ArrayList<>(); - Font annFont = new Font(Font.SANS_SERIF, Font.PLAIN, 22); - - DefaultXY_DataSet m1Line = new DefaultXY_DataSet(); - m1Line.set(m1, yRange.getLowerBound()); - m1Line.set(m1, yRange.getUpperBound()); - funcs.add(m1Line); - chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 2f, Color.DARK_GRAY)); - - DefaultXY_DataSet mMaxLine = new DefaultXY_DataSet(); - mMaxLine.set(mMax, yRange.getLowerBound()); - mMaxLine.set(mMax, yRange.getUpperBound()); - funcs.add(mMaxLine); - chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 2f, Color.DARK_GRAY)); - - XYTextAnnotation m1Ann = new XYTextAnnotation(" M₁=5", m1, yRange.getUpperBound()); - m1Ann.setFont(annFont); - m1Ann.setTextAnchor(TextAnchor.TOP_LEFT); - anns.add(m1Ann); - - XYTextAnnotation mMaxAnn = new XYTextAnnotation("Mₘₐₓ="+mMax.floatValue()+" ", mMax, yRange.getLowerBound()); - mMaxAnn.setFont(annFont); - mMaxAnn.setTextAnchor(TextAnchor.BOTTOM_RIGHT); - anns.add(mMaxAnn); - - PlotSpec plot = new PlotSpec(funcs, chars, title, "Magnitude", incremental ? "Incremental Rate (1/yr)" : "Cumulative Rate (1/yr)"); - plot.setLegendInset(true); - plot.setPlotAnnotations(anns); - - HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); - - gp.drawGraphPanel(plot, false, true, xRange, yRange); - - PlotUtils.writePlots(outputDir, prefix, gp, 700, 650, true, true, false); - - if (!incremental) { - List samples = new NSHM27_SeisRateModelSamples(seisReg, trt).loadOrigSamples(); - Collections.shuffle(samples, new Random(samples.size())); - -// int c = 200; -// int a = 127; -// int c = 150; -// int a = 80; - int c = 180; - int a = 60; - PlotCurveCharacterstics indvChar = new PlotCurveCharacterstics(PlotLineType.SOLID, 1f, new Color(c, c, c, a)); - int maxNumRates = 1000; - int numRates = Integer.min(maxNumRates, samples.size()); - GutenbergRichterMagFreqDist[] rateMFDs = new GutenbergRichterMagFreqDist[samples.size()]; - for (int i=0; i5: "+(float)weightAvg.getY(weightAvg.getClosestXIndex(5.01))); + System.out.println("\tM>6: "+(float)weightAvg.getY(weightAvg.getClosestXIndex(6.01))); + System.out.println("\tM>6 snapped: "+(float)weightAvg.getX(weightAvg.getClosestXIndex(6.01))); + System.out.println("\tM1="+m1.floatValue()); + System.out.println("\tMmax="+mMax.floatValue()); } + + weightAvg.setName(type.toString()+" Average"); + funcs.add(weightAvg); + chars.add(new PlotCurveCharacterstics(plt, 3f, Color.DARK_GRAY)); } } - gp.drawGraphPanel(plot, false, true, xRange, yRange); + for (XY_DataSet func : funcs) { + if (func.getName() != null && func.getName().contains("M1")) + func.setName(func.getName().replace("M1", "M₁")); + if (func.getName() != null && func.getName().contains("Mmax")) + func.setName(func.getName().replace("Mmax", "Mₘₐₓ")); + } - PlotUtils.writePlots(outputDir, prefix+"_with_indv", gp, 700, 650, true, true, false); + Range xRange = new Range(4d, 8d); + Range yRange = incremental ? new Range(1e-4, 1e2) : new Range(1e-3, 1e3); - // write histogram - double[] histMags = {5d, 6d, 7d}; + List anns = new ArrayList<>(); + Font annFont = new Font(Font.SANS_SERIF, Font.PLAIN, 22); - for (double histMag : histMags) { - double minRate = Double.POSITIVE_INFINITY; - double maxRate = Double.NEGATIVE_INFINITY; - - double[] typeLowers = new double[types.length]; - double[] typeUppers = new double[types.length]; - - for (int t=0; t samples = new NSHM27_SeisRateModelSamples(seisReg, trt).loadOrigSamples(classification); + Collections.shuffle(samples, new Random(samples.size())); - double[] histValues = new double[samples.size()]; - for (int r=0; r(); - chars = new ArrayList<>(); + // write histogram + double[] histMags = {5d, 6d, 7d}; - linearHist.setName("Sampled Distribution"); - funcs.add(linearHist); - chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, Color.GRAY)); - - - DefaultXY_DataSet meanXY = new DefaultXY_DataSet(); - meanXY.set(meanValue, 0d); - meanXY.set(meanValue, maxY); - meanXY.setName("Mean"); - funcs.add(meanXY); - chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Color.BLACK)); - - for (int t=0; t(); + chars = new ArrayList<>(); + + linearHist.setName("Sampled Distribution"); + funcs.add(linearHist); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, Color.GRAY)); + + + DefaultXY_DataSet meanXY = new DefaultXY_DataSet(); + meanXY.set(meanValue, 0d); + meanXY.set(meanValue, maxY); + meanXY.setName("Mean"); + funcs.add(meanXY); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Color.BLACK)); + + for (int t=0; t"+oDF.format(histMag)+" Rate", "Sample Count"); + plot.setLegendInset(true); + + gp.drawGraphPanel(plot, true, false, new Range(Math.pow(10, logMinRate), Math.pow(10, logMaxRate)), new Range(0d, maxY)); + + PlotUtils.writePlots(outputDir, prefix+"_hist_m"+oDF.format(histMag), gp, 700, 650, true, true, false); } - - plot = new PlotSpec(funcs, chars, " ", "M>"+oDF.format(histMag)+" Rate", "Sample Count"); - plot.setLegendInset(true); - - gp.drawGraphPanel(plot, true, false, new Range(Math.pow(10, logMinRate), Math.pow(10, logMaxRate)), new Range(0d, maxY)); - - PlotUtils.writePlots(outputDir, prefix+"_hist_m"+oDF.format(histMag), gp, 700, 650, true, true, false); } } } - } } diff --git a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java index 3b2c79c3..f0944861 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java @@ -48,10 +48,10 @@ public static void main(String[] args) throws IOException { File outputDir = new File("/tmp/nshm27_slip_projection"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); - NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; - double maxSlip = 150; -// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; -// double maxSlip = 30d; +// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; +// double maxSlip = 120; + NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; + double maxSlip = 20d; List sects = fm.buildSubSects(fm); diff --git a/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java b/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java index 601747b3..d309ec97 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java +++ b/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java @@ -18,6 +18,7 @@ import org.jfree.chart.ui.TextAnchor; import org.jfree.data.Range; import org.opensha.commons.data.CSVFile; +import org.opensha.commons.data.WeightedList; import org.opensha.commons.data.function.DiscretizedFunc; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; import org.opensha.commons.data.uncertainty.UncertainArbDiscFunc; @@ -530,11 +531,10 @@ else if (plot1900) System.out.println(combObsCml); if (useRateModelUncert) { - List incrBounds95funcs = new ArrayList<>(); - List incrBounds68funcs = new ArrayList<>(); - List cmlBounds95funcs = new ArrayList<>(); - List cmlBounds68funcs = new ArrayList<>(); - List epochWeights = new ArrayList<>(); + WeightedList incrBounds95funcs = new WeightedList<>(); + WeightedList incrBounds68funcs = new WeightedList<>(); + WeightedList cmlBounds95funcs = new WeightedList<>(); + WeightedList cmlBounds68funcs = new WeightedList<>(); for (PRVI25_SeismicityRateEpoch epoch : PRVI25_SeismicityRateEpoch.values()) { double weight = epoch.getNodeWeight(null); @@ -602,17 +602,16 @@ else if (plot1900) UncertainArbDiscFunc cmlBounds95 = new UncertainArbDiscFunc(averageCml, cml2p5, cml97p5, UncertaintyBoundType.CONF_95); UncertainArbDiscFunc cmlBounds68 = new UncertainArbDiscFunc(averageCml, cml16, cml84, UncertaintyBoundType.CONF_68); - incrBounds95funcs.add(incrBounds95); - incrBounds68funcs.add(incrBounds68); - cmlBounds95funcs.add(cmlBounds95); - cmlBounds68funcs.add(cmlBounds68); - epochWeights.add(weight); + incrBounds95funcs.add(incrBounds95, weight); + incrBounds68funcs.add(incrBounds68, weight); + cmlBounds95funcs.add(cmlBounds95, weight); + cmlBounds68funcs.add(cmlBounds68, weight); } - UncertainBoundedIncrMagFreqDist incrBounds95 = PRVI25_SeismicityRateEpoch.averageUncert(incrBounds95funcs, epochWeights); - UncertainBoundedIncrMagFreqDist incrBounds68 = PRVI25_SeismicityRateEpoch.averageUncert(incrBounds68funcs, epochWeights); - UncertainArbDiscFunc cmlBounds95 = PRVI25_SeismicityRateEpoch.averageUncertCml(cmlBounds95funcs, epochWeights); - UncertainArbDiscFunc cmlBounds68 = PRVI25_SeismicityRateEpoch.averageUncertCml(cmlBounds68funcs, epochWeights); + UncertainBoundedIncrMagFreqDist incrBounds95 = SeismicityRateModel.averageUncert(incrBounds95funcs); + UncertainBoundedIncrMagFreqDist incrBounds68 = SeismicityRateModel.averageUncert(incrBounds68funcs); + UncertainArbDiscFunc cmlBounds95 = SeismicityRateModel.averageUncertCml(cmlBounds95funcs); + UncertainArbDiscFunc cmlBounds68 = SeismicityRateModel.averageUncertCml(cmlBounds68funcs); incrBounds95.setName("68% and 95% bounds"); myIncrFuncs.add(incrBounds95); diff --git a/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java b/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java index 892b7d62..42ba36c6 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java +++ b/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java @@ -215,10 +215,9 @@ else if (trt == TectonicRegionType.SUBDUCTION_INTERFACE) else if (trt == TectonicRegionType.SUBDUCTION_INTERFACE) onFaultMean = CombinedMFDsPlot.calcFaultMFD(reg, sol, refMFD); - List obsList = new ArrayList<>(); - List obsCmlList = new ArrayList<>(); - List origObsList = r == 0 ? null : new ArrayList<>(); - List obsWeights = new ArrayList<>(); + WeightedList obsList = new WeightedList<>(); + WeightedList obsCmlList = new WeightedList<>(); + WeightedList origObsList = r == 0 ? null : new WeightedList<>(); for (PRVI25_SeismicityRateEpoch epoch : PRVI25_SeismicityRateEpoch.values()) { double weight = epoch.getNodeWeight(null); if (weight == 0d) @@ -227,23 +226,22 @@ else if (trt == TectonicRegionType.SUBDUCTION_INTERFACE) SeismicityRateModel cmlSeisModel = seisModelFunc.apply(epoch, RateType.EXACT); UncertainBoundedIncrMagFreqDist obs = seisModel.getBounded(refMFD, xRange.getUpperBound()+0.1); if (r == 0) { - obsList.add(obs); - obsCmlList.add(cmlSeisModel.getBoundedCml(refMFD, xRange.getUpperBound()+0.1)); + obsList.add(obs, weight); + obsCmlList.add(cmlSeisModel.getBoundedCml(refMFD, xRange.getUpperBound()+0.1), weight); // System.out.println("OBS cml for "+epoch+":\n"+obsCmlList.get(obsCmlList.size()-1)); } else { UncertainBoundedIncrMagFreqDist subsetObs = seisModel.getRemapped(reg, seisReg, PRVI25_DeclusteringAlgorithms.AVERAGE, PRVI25_SeisSmoothingAlgorithms.AVERAGE, refMFD, xRange.getUpperBound()+0.1); subsetObs.setName("Observed (subset), N5="+new DecimalFormat("0.0#").format(obs.getCumRate(obs.getClosestXIndex(5.01)))); - obsList.add(subsetObs); - origObsList.add(obs); + obsList.add(subsetObs, weight); + origObsList.add(obs, weight); obsCmlList.add(new UncertainArbDiscFunc( subsetObs.getCumRateDistWithOffset(), subsetObs.getLower().getCumRateDistWithOffset(), - subsetObs.getUpper().getCumRateDistWithOffset(), subsetObs.getBoundType())); + subsetObs.getUpper().getCumRateDistWithOffset(), subsetObs.getBoundType()), weight); } - obsWeights.add(weight); } - UncertainBoundedIncrMagFreqDist obs = PRVI25_SeismicityRateEpoch.averageUncert(obsList, obsWeights); - UncertainArbDiscFunc obsCml = PRVI25_SeismicityRateEpoch.averageUncertCml(obsCmlList, obsWeights); + UncertainBoundedIncrMagFreqDist obs = SeismicityRateModel.averageUncert(obsList); + UncertainArbDiscFunc obsCml = SeismicityRateModel.averageUncertCml(obsCmlList); IncrementalMagFreqDist gridded; UncertainBoundedIncrMagFreqDist[] griddedDists; if (trt == TectonicRegionType.ACTIVE_SHALLOW || trt == TectonicRegionType.SUBDUCTION_INTERFACE) { @@ -297,7 +295,7 @@ else if (trt == TectonicRegionType.SUBDUCTION_INTERFACE) texFW.write(LaTeXUtils.defineValueCommand(texPrefix+"ObsMFiveRI", LaTeXUtils.numberExpFormatFixedDecimal(1d/obsM5, 1), false)+"\n"); if (r > 0) { - UncertainBoundedIncrMagFreqDist origObs = PRVI25_SeismicityRateEpoch.averageUncert(origObsList, obsWeights); + UncertainBoundedIncrMagFreqDist origObs = SeismicityRateModel.averageUncert(origObsList); double origM5 = origObs.getCumRate(origObs.getClosestXIndex(5.01)); texFW.write(LaTeXUtils.defineValueCommand(texPrefix+"ObsMFivePercent", LaTeXUtils.numberAsPercent(100d*obsM5/origM5, 0), false)+"\n"); @@ -854,8 +852,7 @@ private static IncrementalMagFreqDist sum(IncrementalMagFreqDist mfd1, Increment private static UncertainBoundedIncrMagFreqDist getMmaxAveragedSlab(EvenlyDiscretizedFunc refMFD, PRVI25_SeismicityRegions seisReg, boolean averageRate) throws IOException { - List slabMFDs = new ArrayList<>(); - List slabWeights = new ArrayList<>(); + WeightedList slabMFDs = new WeightedList<>(); for (PRVI25_SeismicityRateEpoch epoch : PRVI25_SeismicityRateEpoch.values()) { double epochWeight = epoch.getNodeWeight(null); if (epochWeight == 0d) @@ -885,11 +882,10 @@ private static UncertainBoundedIncrMagFreqDist getMmaxAveragedSlab(EvenlyDiscret } else { throw new IllegalStateException(); } - slabMFDs.add(siesModel.getBounded(refMFD, slabMmax.getIncrementalMmax())); - slabWeights.add(epochWeight*mMaxWeight); + slabMFDs.add(siesModel.getBounded(refMFD, slabMmax.getIncrementalMmax()), epochWeight*mMaxWeight); } } - return PRVI25_SeismicityRateEpoch.averageUncert(slabMFDs, slabWeights); + return SeismicityRateModel.averageUncert(slabMFDs); } static IncrementalMagFreqDist calcGriddedMFD(Region region, TectonicRegionType trt, diff --git a/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java b/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java index 6c0b76f4..64973ca3 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java +++ b/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java @@ -10,6 +10,7 @@ import org.jfree.chart.ui.RectangleAnchor; import org.jfree.data.Range; import org.opensha.commons.data.CSVFile; +import org.opensha.commons.data.WeightedList; import org.opensha.commons.data.function.DiscretizedFunc; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; import org.opensha.commons.data.uncertainty.UncertainArbDiscFunc; @@ -63,7 +64,7 @@ public static void main(String[] args) throws IOException { double sumNobs1973 = 0d; List avgMFDs = new ArrayList<>(); - List> epochMFDs = new ArrayList<>(); + List> epochMFDs = new ArrayList<>(); PRVI25_SeismicityRegions[] regions = PRVI25_SeismicityRegions.values(); for (PRVI25_SeismicityRegions reg : regions) { @@ -105,9 +106,8 @@ public static void main(String[] args) throws IOException { throw new IllegalStateException("Unknown region: "+reg); } - List epochBounds = new ArrayList<>(); - List epochCmlBounds = new ArrayList<>(); - List epochWeights = new ArrayList<>(); + WeightedList epochBounds = new WeightedList<>(); + WeightedList epochCmlBounds = new WeightedList<>(); for (int e=0; e byEpoch = epochMFDs.get(r); + WeightedList byEpoch = epochMFDs.get(r); System.out.println(regions[r].getName()); for (double mag : regCmlMags) { @@ -312,7 +312,7 @@ public static void main(String[] args) throws IOException { System.out.println("\tM>"+(float)mag+" rate="+(float)rate+", ri="+(float)ri+" years"); if (mag == 5d) { for (int e=0; e branch = NSHM27_LogicTree.buildDefault(seisReg, trt, false); + LogicTreeBranch sampledBranch = NSHM27_LogicTree.buildDefault(seisReg, trt, true); +// int samples = 50; +// int samples = 500; + int samples = 1000; + + for (int l=0; l level = branch.getLevel(l); + System.out.println(l+". "+level.getName()); + System.out.println("\tClass:\t"+level.getClass()); + LogicTreeNode value = branch.getValue(l); + System.out.println("\tValue:\t"+value); + System.out.println("\tValue type:\t"+level.getType()); + System.out.println("\tNum nodes:\t"+level.getNodes().size()); + } + + System.out.println(branch); + + int[] levelIndexes = { + branch.getLevelTypeIndex(NSHM27_InterfaceCouplingDepthModels.class), + branch.getLevelTypeIndex(NSHM27_InterfaceDeformationModels.Aggregated.class), + branch.getLevelTypeIndex(PRVI25_SubductionScalingRelationships.class), + branch.getLevelTypeIndex(SectionSupraSeisBValues.class), + branch.getLevelTypeIndex(NSHM27_InterfaceObsSeisDMAdjustment.class), + branch.getLevelTypeIndex(NSHM27_InterfaceMinSubSects.class), + branch.getLevelTypeIndex(MaxRuptureLengthBranchNode.class), + }; + + WeightedList classificationChoices = new WeightedList<>(); + for (NSHM27_SeisClassificationMethod classification : NSHM27_SeisClassificationMethod.values()) + if (classification.getNodeWeight() > 0d) + classificationChoices.add(classification, classification.getNodeWeight()); + List classificationSamples = classificationChoices.sampleEvenly(samples, new Random(12345l)); + + NSHM27_InvConfigFactory factory = new NSHM27_InvConfigFactory(); + FaultSystemRupSet rupSet = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); + + EvenlyDiscretizedFunc refMFD = FaultSysTools.initEmptyMFD(6.01, 9.99); + + IncrementalMagFreqDist defaultMFD = calculateMFD(factory, rupSet, branch, refMFD); + + CPT tab10CPT = GMT_CPT_Files.CATEGORICAL_TAB10_NOGRAY.instance(); + Color[] tab10 = new Color[tab10CPT.size()]; + for (int i=0; i avgStrings = new ArrayList<>(); + + for (int l : levelIndexes) { + Preconditions.checkState(l >= 0); + LogicTreeLevel level = branch.getLevel(l); + LogicTreeNode defaultValue = branch.getValue(l); + LogicTreeLevel sampledLevel = sampledBranch.getLevel(l); + System.out.println("Processing level "+l+". "+level.getName()); + List incrFuncs = new ArrayList<>(); + List cmlFuncs = new ArrayList<>(); + List chars = new ArrayList<>(); + if (sampledLevel == level) { + System.out.println("\tNormal level"); + SummedMagFreqDist avgMFD = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + double sumWeight = 0d; + int index = 0; + String avgStr = level.getName()+" RIs:"; + for (LogicTreeNode node : level.getNodes()) { + double weight = node.getNodeWeight(branch); + if (weight > 0d) { + branch.setValue(node); + IncrementalMagFreqDist mfd = calculateMFD(factory, rupSet, branch, refMFD); + avgMFD.addIncrementalMagFreqDist(mfd, weight); + sumWeight += weight; + Color color = tab10[index++ % tab10.length]; + mfd.setName(node.getShortName()); + incrFuncs.add(mfd); + EvenlyDiscretizedFunc cml = mfd.getCumRateDistWithOffset(); + cmlFuncs.add(cml); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 4f, color)); + avgStr += "\n\t"+node.getShortName()+":\t"+(float)(1d/cml.getY(0)); + } + } + if ((float)sumWeight != 1f) + avgMFD.scale(1d/sumWeight); + avgMFD.setName("Weighted Average"); + incrFuncs.add(avgMFD); + EvenlyDiscretizedFunc cml = avgMFD.getCumRateDistWithOffset(); + cmlFuncs.add(avgMFD.getCumRateDistWithOffset()); + avgStr += "\n\tAverage:\t"+(float)(1d/cml.getY(0)); + avgStrings.add(avgStr); + chars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 4f, Color.DARK_GRAY)); + + branch.setValue(defaultValue); + } else { +// baselineMFD = defaultMFD.deepClone(); +// baselineMFD.setName(defaultValue.getName()); + System.out.println("\tSampled version: "+sampledLevel.getName()); + List> levels = new ArrayList<>(); + List values = new ArrayList<>(); + for (int i=0; i myBranch = new LogicTreeBranch<>(levels, values); + ((RandomLevel)sampledLevel).build(12345l, samples, SamplingMethod.LATIN_HYPERCUBE); + Preconditions.checkState(sampledLevel.getNodes().size() == samples); + double weightEach = 1d/samples; + SummedMagFreqDist avgMFD = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + List> mfdFutures = new ArrayList<>(samples); + List sampledNodes = sampledLevel.getNodes(); + Preconditions.checkState(sampledNodes.size() == samples); + for (int n=0; n{ + LogicTreeBranch myBranch2 = myBranch.copy(); + myBranch2.setValue(classNode); + myBranch2.setValue(l, node); + try { + return calculateMFD(factory, rupSet, myBranch2, refMFD); + } catch (IOException e) { + e.printStackTrace(); + System.err.flush(); + System.exit(1); + return null; + } + })); + } + + ArbDiscrEmpiricalDistFunc[] incrPDFs = new ArbDiscrEmpiricalDistFunc[refMFD.size()]; + ArbDiscrEmpiricalDistFunc[] cmlPDFs = new ArbDiscrEmpiricalDistFunc[refMFD.size()]; + for (int i=0; i mfdFuture = mfdFutures.get(i); + IncrementalMagFreqDist mfd = mfdFuture.join(); + EvenlyDiscretizedFunc cml = mfd.getCumRateDistWithOffset(); + avgMFD.addIncrementalMagFreqDist(mfd, weightEach); + for (int m=0; m 0 || incrPDFs[m] != null) { + if (incrPDFs[m] == null) { + incrPDFs[m] = new ArbDiscrEmpiricalDistFunc(); + if (i > 0) { + // add weight for prior ones that were zero + incrPDFs[m].set(0d, weightEach*(i-1)); + } + } + incrPDFs[m].set(y, weightEach); + } + double cmlY = cml.getY(m); + if (cmlY > 0 || cmlPDFs[m] != null) { + if (cmlPDFs[m] == null) { + cmlPDFs[m] = new ArbDiscrEmpiricalDistFunc(); + if (i > 0) { + // add weight for prior ones that were zero + cmlPDFs[m].set(0d, weightEach*(i-1)); + } + } + cmlPDFs[m].set(cmlY, weightEach); + } + } + } + double[] fractiles = {0d, 0.025, 0.16, 0.5, 0.84, 0.975, 1d}; + String fractileNames = "p[0, 2.5, 16, 84, 97.5, 100]"; +// Color transColor = new Color(0, 0, 0, 60); + Color transColor = Colors.tab_blue; + transColor = new Color(transColor.getRed(), transColor.getGreen(), transColor.getBlue(), 80); + IncrementalMagFreqDist[] incrFractiles = new IncrementalMagFreqDist[fractiles.length]; + EvenlyDiscretizedFunc[] cmlFractiles = new EvenlyDiscretizedFunc[fractiles.length]; + for (int f=0; f branch, EvenlyDiscretizedFunc refMFD) throws IOException { + ClusterRuptures cRups = rupSet.requireModule(ClusterRuptures.class); + rupSet = factory.updateRuptureSetForBranch(rupSet, branch); + BinaryRuptureProbabilityCalc exclusionModel = NSHM27_InvConfigFactory.getExclusionModel(rupSet, branch, cRups); + + BitSet includedRups = new BitSet(rupSet.getNumRuptures()); + for (int rupIndex=0; rupIndex Date: Wed, 15 Jul 2026 13:10:23 -0700 Subject: [PATCH 37/71] plots and investigations --- .../nshm27/BranchHalfBiasInvestigation.java | 105 ++++++++++++++++++ .../InterfaceLogicTreeMFDExploration.java | 17 ++- 2 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm27/BranchHalfBiasInvestigation.java diff --git a/src/main/java/scratch/kevin/nshm27/BranchHalfBiasInvestigation.java b/src/main/java/scratch/kevin/nshm27/BranchHalfBiasInvestigation.java new file mode 100644 index 00000000..79ce5fb7 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/BranchHalfBiasInvestigation.java @@ -0,0 +1,105 @@ +package scratch.kevin.nshm27; + +import java.io.File; +import java.io.IOException; + +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeLevel; +import org.opensha.commons.logicTree.LogicTreeNode; + +import gov.usgs.earthquake.nshmp.erf.logicTree.TectonicRegionBranchTreeNode; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceHingedBValue.CombinedSampledType; + +public class BranchHalfBiasInvestigation { + + public static void main(String[] args) throws IOException { +// File treeFile = new File("/home/kevin/OpenSHA/fss_inversions/2026_06_27-nshm27-AMSAM-3000samples-lhs_pairwise/logic_tree.json"); + File treeFile = new File("/home/kevin/OpenSHA/fss_inversions/2026_07_13-nshm27-AMSAM-5000samples-lhs_pairwise/logic_tree.json"); +// File treeFile = new File("/home/kevin/OpenSHA/fss_inversions/2026_07_11-nshm27-AMSAM-2000samples-lhs_pairwise/logic_tree.json"); + + LogicTree tree = LogicTree.read(treeFile); + LogicTree interfaceTree = null; + for (int l=0; l level = tree.getLevels().get(l); + if (level instanceof TectonicRegionBranchTreeNode.Level) { + interfaceTree = ((TectonicRegionBranchTreeNode.Level)level).getTree(); + break; + } + } + + int total = tree.size(); + int halfIndex = tree.size()/2; + int numHinged1 = 0; + int numHinged2 = 0; + double sumB1 = 0d; + int numB1 = 0; + double sumB2 = 0d; + int numB2 = 0; + + int numExtraploate1 = 0; + int numExtraploate2 = 0; + + int numTaperDouble1 = 0; + int numTaperNone1 = 0; + int numTaperDouble2 = 0; + int numTaperNone2 = 0; + + for (int i=0; i branch = interfaceTree.getBranch(i); + CombinedSampledType node = branch.requireValue(CombinedSampledType.class); + boolean first = i < halfIndex; + if (node.isHinged()) { + if (first) + numHinged1++; + else + numHinged2++; + } else { + double b = node.getB(null, null); + if (first) { + sumB1 += b; + numB1++; + } else { + sumB2 += b; + numB2++; + } + } + if (branch.hasValue(NSHM27_InterfaceObsSeisDMAdjustment.EXTRAPOLATE)) { + if (first) + numExtraploate1++; + else + numExtraploate2++; + } + if (branch.hasValue(NSHM27_InterfaceCouplingDepthModels.DOUBLE_TAPER)) { + if (first) + numTaperDouble1++; + else + numTaperDouble2++; + } + if (branch.hasValue(NSHM27_InterfaceCouplingDepthModels.NONE)) { + if (first) + numTaperNone1++; + else + numTaperNone2++; + } + } + + double avgB1 = sumB1 / (double)numB1; + double avgB2 = sumB2 / (double)numB2; + System.out.println("First half:"); + System.out.println("\t"+numHinged1+" hinged"); + System.out.println("\t"+avgB1+" average b"); + System.out.println("\t"+numExtraploate1+" extrapolate"); + System.out.println("\t"+numTaperDouble1+" taper-double"); + System.out.println("\t"+numTaperNone1+" taper-none"); + System.out.println("Second half:"); + System.out.println("\t"+numHinged2+" hinged"); + System.out.println("\t"+avgB2+" average b"); + System.out.println("\t"+numExtraploate2+" extrapolate"); + System.out.println("\t"+numTaperDouble2+" taper-double"); + System.out.println("\t"+numTaperNone2+" taper-none"); + } + +} diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java index b5a0ef56..96d99771 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java @@ -239,8 +239,7 @@ public static void main(String[] args) throws IOException { double[] fractiles = {0d, 0.025, 0.16, 0.5, 0.84, 0.975, 1d}; String fractileNames = "p[0, 2.5, 16, 84, 97.5, 100]"; // Color transColor = new Color(0, 0, 0, 60); - Color transColor = Colors.tab_blue; - transColor = new Color(transColor.getRed(), transColor.getGreen(), transColor.getBlue(), 80); + Color base = Colors.tab_blue; IncrementalMagFreqDist[] incrFractiles = new IncrementalMagFreqDist[fractiles.length]; EvenlyDiscretizedFunc[] cmlFractiles = new EvenlyDiscretizedFunc[fractiles.length]; for (int f=0; f Date: Wed, 15 Jul 2026 14:43:28 -0700 Subject: [PATCH 38/71] persistent output dir --- .../nshm27/figures/InterfaceLogicTreeMFDExploration.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java index 96d99771..aebd5186 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java @@ -64,10 +64,14 @@ public class InterfaceLogicTreeMFDExploration { public static void main(String[] args) throws IOException { - File outputDir = new File("/tmp/interface_mfd_exploration"); + File outputDir = new File(NSHM27_PaperPaths.FIGURES_DIR, "interface_mfd_exploration"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); ModuleContainer.VERBOSE_DEFAULT = false; NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.AMSAM; + + outputDir = new File(outputDir, seisReg.name()); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); + TectonicRegionType trt = TectonicRegionType.SUBDUCTION_INTERFACE; LogicTreeBranch branch = NSHM27_LogicTree.buildDefault(seisReg, trt, false); From 4d3c4b545cdb9905819c66940a545156f43ad2da Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 21 Jul 2026 19:15:40 -0700 Subject: [PATCH 39/71] lots of new plots and updates for upstream --- .../kevin/nshm27/figures/BValDistFigure.java | 250 +++++++++ .../nshm27/figures/CombinedMFDsFigure.java | 493 ++++++++++++++++++ .../CrustalNucleationAroundFaultZoom.java | 3 +- .../nshm27/figures/DMLowerLimitTests.java | 136 +++++ .../InterfaceLogicTreeMFDExploration.java | 179 ++++++- .../figures/InterfaceObsSeisAdjFigures.java | 89 ++++ .../InterfaceParticipationRateFigures.java | 255 +++++++++ .../nshm27/figures/NSHM27_PaperPaths.java | 100 ++++ .../nshm27/figures/SlipProjectionFigures.java | 10 +- 9 files changed, 1495 insertions(+), 20 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java create mode 100644 src/main/java/scratch/kevin/nshm27/figures/CombinedMFDsFigure.java create mode 100644 src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java create mode 100644 src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java create mode 100644 src/main/java/scratch/kevin/nshm27/figures/InterfaceParticipationRateFigures.java diff --git a/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java b/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java new file mode 100644 index 00000000..6c7e779f --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java @@ -0,0 +1,250 @@ +package scratch.kevin.nshm27.figures; + +import static scratch.kevin.nshm27.figures.NSHM27_PaperPaths.*; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.commons.statistics.distribution.ContinuousDistribution; +import org.apache.commons.statistics.distribution.UniformContinuousDistribution; +import org.jfree.chart.plot.DatasetRenderingOrder; +import org.jfree.chart.ui.RectangleAnchor; +import org.jfree.data.Range; +import org.opensha.commons.data.function.DefaultXY_DataSet; +import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.function.HistogramFunction; +import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeFigureWriter; +import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.util.modules.ModuleContainer; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; +import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.SectionSupraSeisBValues; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.SectionSupraSeisBValues.DistributionSamplingLevel; +import org.opensha.sha.util.TectonicRegionType; + +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceHingedBValue; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisClassificationMethod; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModel; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; +import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.PureGR; +import net.mahdilamb.colormap.Colors; + +public class BValDistFigure { + + public static void main(String[] args) throws IOException { + System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", FaultSysTools.defaultNumThreads()+""); +// int numSamples = 100; +// int numSamples = 1000; +// int numSamples = 2000; +// int numSamples = 5000; + int numSamples = 10000; +// int numSamples = 50000; +// double binWidth = 0.025; + ModuleContainer.VERBOSE_DEFAULT = false; + double binWidth = 0.05; + Range bRange = new Range(-0.6, 1.6); + Range yRange = new Range(0, 1.4); + + Color hingedColor = Colors.tab_blue; + hingedColor = new Color(hingedColor.getRed(), hingedColor.getGreen(), hingedColor.getBlue(), 200); + Color hingedBelowOverlayColor = new Color(255, 255, 255, 160); + Color extrapColor = Colors.tab_green; + extrapColor = new Color(extrapColor.getRed(), extrapColor.getGreen(), extrapColor.getBlue(), 200); + Color combColor = Colors.tab_lightred; + + double extrapolateWeight = NSHM27_InterfaceObsSeisDMAdjustment.EXTRAPOLATE.getNodeWeight(); + double otherWeight = 1d-extrapolateWeight; + double hingeWeight = NSHM27_LogicTree.INTERFACE_B_HINGED_WEIGHT; + double distWeight = 1d - hingeWeight; + hingeWeight *= otherWeight; + distWeight *= otherWeight; + + NSHM27_LogicTree.INTERFACE_B_HINGED_WEIGHT = 1d; + + EvenlyDiscretizedFunc bValDiscr = HistogramFunction.getEncompassingHistogram(-1, 2, binWidth); + + NSHM27_InvConfigFactory factory = new NSHM27_InvConfigFactory(); + + for (NSHM27_SeismicityRegions seisReg : NSHM27_SeismicityRegions.values()) { + LogicTree tree = NSHM27_LogicTree.buildLogicTree(seisReg, + TectonicRegionType.SUBDUCTION_INTERFACE, numSamples, true, + SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE); + tree.write(new File("/tmp/test_tree_"+seisReg.name()+".json")); + ContinuousDistribution dist = NSHM27_LogicTree.getInterfaceBDist(seisReg); + DistributionSamplingLevel distLevel = new DistributionSamplingLevel("Dist", "Dist", dist); + String distLabel = LogicTreeFigureWriter.getDistString(distLevel); + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + FaultSystemRupSet genericRS = factory.buildGenericRupSet(tree.getBranch(0), FaultSysTools.defaultNumThreads()); + + List> hingedBranches = new ArrayList<>(); + List> extrapolatedBranches = new ArrayList<>(); + for (LogicTreeBranch branch : tree) { + if (branch.hasValue(NSHM27_InterfaceObsSeisDMAdjustment.EXTRAPOLATE)) + extrapolatedBranches.add(branch); + else + hingedBranches.add(branch); + } + + // hinge samples + List> bFutures = new ArrayList<>(numSamples); + for (LogicTreeBranch branch : hingedBranches) { + bFutures.add(CompletableFuture.supplyAsync(()->{ + FaultSystemRupSet rs; + try { + rs = factory.updateRuptureSetForBranch(genericRS, branch); + } catch (IOException e) { + throw ExceptionUtils.asRuntimeException(e); + } + return NSHM27_InterfaceHingedBValue.calcRawInterfaceHingedBValue(rs, branch); + })); + } + + for (int i=0; i branch = hingedBranches.get(i); + try { + bFutures.get(i).get(); + } catch (Exception e) { + System.err.println("Failed on "+branch); + e.printStackTrace(); + System.err.flush(); + System.exit(1); + } + } + + EvenlyDiscretizedFunc hingedHist = new EvenlyDiscretizedFunc( + bValDiscr.getMinX(), bValDiscr.getMaxX(), bValDiscr.size()); + + double densityEach = hingeWeight/(bFutures.size()*hingedHist.getDelta()); + for (CompletableFuture future : bFutures) { + double b = future.join(); + int index = hingedHist.getClosestXIndex(b); + hingedHist.add(index, densityEach); + } + + for (LogicTreeBranch branch : hingedBranches) { + bFutures.add(CompletableFuture.supplyAsync(()->{ + FaultSystemRupSet rs; + try { + rs = factory.updateRuptureSetForBranch(genericRS, branch); + } catch (IOException e) { + throw ExceptionUtils.asRuntimeException(e); + } + return NSHM27_InterfaceHingedBValue.calcRawInterfaceHingedBValue(rs, branch); + })); + } + + EvenlyDiscretizedFunc extrapHist = new EvenlyDiscretizedFunc( + bValDiscr.getMinX(), bValDiscr.getMaxX(), bValDiscr.size()); + + densityEach = extrapolateWeight/(extrapolatedBranches.size()*hingedHist.getDelta()); + for (LogicTreeBranch branch : extrapolatedBranches) { + double b = ((PureGR)branch.requireValue(NSHM27_SeisRateModel.class).getRateRecord( + seisReg, branch.requireValue(NSHM27_SeisClassificationMethod.class), TectonicRegionType.SUBDUCTION_INTERFACE)).b; + int index = extrapHist.getClosestXIndex(b); + extrapHist.add(index, densityEach); + } + + EvenlyDiscretizedFunc totalHist = hingedHist.deepClone(); + + // The hinge calculation is truncated at b = 0. + int zeroBin = totalHist.getClosestXIndex(0d); + for (int i=0; i csvRateHeader = new ArrayList<>(); + List csvRIHeader = new ArrayList<>(); + csvRateHeader.add("Model Component"); + csvRIHeader.add("Model Component"); + for (double mag : csvMags) { + csvRateHeader.add("M>"+oDF.format(mag)+" rate"); + csvRIHeader.add("M>"+oDF.format(mag)+" RI"); + } + + for (NSHM27_SeismicityRegions seisReg : NSHM27_SeismicityRegions.values()) { + FaultSystemSolution sol = getSolution(seisReg); + GridSourceList gridList = sol.requireModule(GridSourceList.class); + Region reg = seisReg.load(); + + for (boolean interfaceOnly : new boolean[] {false, true}) { + CSVFile rateCSV = null; + CSVFile riCSV = null; + if (!interfaceOnly) { + rateCSV = new CSVFile<>(true); + rateCSV.addLine(csvRateHeader); + riCSV = new CSVFile<>(true); + riCSV.addLine(csvRIHeader); + } + TectonicRegionType targetTRT = interfaceOnly ? TectonicRegionType.SUBDUCTION_INTERFACE : null; + List indvIncrFuncs = new ArrayList<>(); + List indvChars = new ArrayList<>(); + + SummedMagFreqDist gridSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + SummedMagFreqDist faultSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + + for (TectonicRegionType trt : TRTs) { + if (interfaceOnly && trt != TectonicRegionType.SUBDUCTION_INTERFACE) + continue; + Color gridColor = getColor(trt, IncludeBackgroundOption.ONLY); + Color faultColor = getColor(trt, IncludeBackgroundOption.EXCLUDE); + Color sumColor = getColor(trt, IncludeBackgroundOption.INCLUDE); + String trtName = NSHM27_RegionLoader.getNameForTRT(trt); + + IncrementalMagFreqDist gridMFD = loadGridded(gridList, trt, refMFD); + IncrementalMagFreqDist faultMFD = loadFault(sol, trt, refMFD, reg); + + processCSVs(faultMFD, trtName+" (on-fault)", csvMags, rateCSV, riCSV); + processCSVs(gridMFD, trtName+" (gridded)", csvMags, rateCSV, riCSV); + + if (faultMFD != null) { + if (!interfaceOnly) { + SummedMagFreqDist sum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + sum.addIncrementalMagFreqDist(gridMFD); + sum.addIncrementalMagFreqDist(faultMFD); + + sum.setName(trtName+" (combined)"); + indvIncrFuncs.add(sum); + indvChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 2f, sumColor)); + + processCSVs(sum, trtName+" (combined)", csvMags, rateCSV, riCSV); + } + + faultMFD.setName(trtName+" (on-fault)"); + indvIncrFuncs.add(faultMFD); + indvChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, faultColor)); + faultSum.addIncrementalMagFreqDist(faultMFD); + } + + gridMFD.setName(trtName+" (gridded)"); + indvIncrFuncs.add(gridMFD); + indvChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, gridColor)); + gridSum.addIncrementalMagFreqDist(gridMFD); + } + + List incrFuncs = new ArrayList<>(); + List cmlFuncs = new ArrayList<>(); + List chars = new ArrayList<>(); + + SummedMagFreqDist mfdSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + mfdSum.addIncrementalMagFreqDist(gridSum); + mfdSum.addIncrementalMagFreqDist(faultSum); + if (interfaceOnly) + mfdSum.setName("Total interface"); + else + mfdSum.setName("Total"); + incrFuncs.add(mfdSum); + cmlFuncs.add(mfdSum.getCumRateDistWithOffset()); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Color.BLACK)); + + processCSVs(mfdSum, "Total", csvMags, rateCSV, riCSV); + + // uncertainty for legend + IncrementalMagFreqDist emptyFunc = new IncrementalMagFreqDist(refMFD.getMinX(), refMFD.size(), refMFD.getDelta()); + UncertainBoundedIncrMagFreqDist emptyUnceratain = new UncertainBoundedIncrMagFreqDist(emptyFunc, emptyFunc, emptyFunc, null); + emptyUnceratain.setName(fractileLabel); + incrFuncs.add(emptyUnceratain); + cmlFuncs.add(emptyUnceratain); + chars.add(bounds68Char); + + // individual components + for (int i=0; i samples = new ArrayList<>(); + samples.addAll(NSHM27_SeisRateModelSamples.loadOrigSamples(seisReg, NSHM27_SeisClassificationMethod.PROFACE, targetTRT)); + int numProface = samples.size(); + samples.addAll(NSHM27_SeisRateModelSamples.loadOrigSamples(seisReg, NSHM27_SeisClassificationMethod.PROSLAB, targetTRT)); + int numProslab = samples.size() - numProface; + double weightProface = NSHM27_SeisClassificationMethod.PROFACE.getNodeWeight(); + double weightProslab = NSHM27_SeisClassificationMethod.PROSLAB.getNodeWeight(); + if ((float)(weightProface+weightProslab) != 1f) { + double sum = weightProface + weightProslab; + weightProface /= sum; + weightProslab /= sum; + } + double[] weights = new double[samples.size()]; + double weightProfaceEach = weightProface/(double)numProface; + double weightProslabEach = weightProslab/(double)numProslab; + for (int i=0; i= 0); + IncrementalMagFreqDist[] incrFractiles = regMFDs.calcRegionalIncrementalFractiles(MFDType.SUM, regionIndex, fractiles); + UncertainBoundedIncrMagFreqDist incrExtrema = new UncertainBoundedIncrMagFreqDist(incrFractiles[3], incrFractiles[0], incrFractiles[6], null); + UncertainBoundedIncrMagFreqDist incr95 = new UncertainBoundedIncrMagFreqDist(incrFractiles[3], incrFractiles[1], incrFractiles[5], null); + UncertainBoundedIncrMagFreqDist incr68 = new UncertainBoundedIncrMagFreqDist(incrFractiles[3], incrFractiles[2], incrFractiles[4], null); + EvenlyDiscretizedFunc[] cmlFractiles = regMFDs.calcRegionalCumulativeFractiles(MFDType.SUM, regionIndex, fractiles); + UncertainArbDiscFunc cmlExtrema = new UncertainArbDiscFunc(cmlFractiles[3], cmlFractiles[0], cmlFractiles[6]); + UncertainArbDiscFunc cml95 = new UncertainArbDiscFunc(cmlFractiles[3], cmlFractiles[1], cmlFractiles[5]); + UncertainArbDiscFunc cml68 = new UncertainArbDiscFunc(cmlFractiles[3], cmlFractiles[2], cmlFractiles[4]); + + processCSVsWithCml(cmlFractiles[0], "Total (minimum)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[1], "Total (2.5 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[2], "Total (16 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[5], "Total (50 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[4], "Total (84 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[5], "Total (97.5 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[6], "Total (maximum)", csvMags, rateCSV, riCSV); + + processCSVsWithCml(obsCmlMean, "Observed", csvMags, rateCSV, riCSV); + processCSVsWithCml(obsCmlLow, "Observed (2.5 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(obsCmlHigh, "Observed (97.5 %-ile)", csvMags, rateCSV, riCSV); + + incrExtrema.setName(null); + incrFuncs.add(incrExtrema); + cmlExtrema.setName(null); + cmlFuncs.add(cmlExtrema); + chars.add(extremaChar); + + incr95.setName(null); + incrFuncs.add(incr95); + cml95.setName(null); + cmlFuncs.add(cml95); + chars.add(bounds95Char); + + incr68.setName(null); + incrFuncs.add(incr68); + cml68.setName(null); + cmlFuncs.add(cml68); + chars.add(bounds68Char); + + RectangleAnchor anchor = RectangleAnchor.TOP_RIGHT; +// RectangleAnchor anchor = RectangleAnchor.BOTTOM_LEFT; + + String title = seisReg.getTitleCaseAcronym(); + if (interfaceOnly) + title += " (interface)"; +// else +// title += " overall"; + + PlotSpec incrPlot = new PlotSpec(incrFuncs, chars, title, "Magnitude", "Incremental rate (1/yr)"); + incrPlot.setLegendInset(anchor); + + PlotSpec cmlPlot = new PlotSpec(cmlFuncs, chars, title, "Magnitude", "Cumulative rate (1/yr)"); + cmlPlot.setLegendInset(anchor); + + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + + gp.setRenderingOrder(DatasetRenderingOrder.REVERSE); + + String prefix = seisReg.name(); + if (interfaceOnly) + prefix += "_interface"; + + gp.drawGraphPanel(incrPlot, false, true, xRange, yRange); + +// PlotUtils.writePrintPlots(outputDir, prefix+"_incr_half", gp, halfWidth, halfHeight, 150, true, true, false); + PlotUtils.writePrintPlots(outputDir, prefix+"_incr", gp, fullWidth, fullHeight, 150, true, true, false); + + gp.drawGraphPanel(cmlPlot, false, true, xRange, yRange); + +// PlotUtils.writePrintPlots(outputDir, prefix+"_cml_half", gp, halfWidth, halfHeight, 150, true, true, false); + PlotUtils.writePrintPlots(outputDir, prefix+"_cml", gp, fullWidth, fullHeight, 150, true, true, false); + + if (!interfaceOnly) { + rateCSV.writeToFile(new File(outputDir, prefix+"_cml_rates.csv")); + riCSV.writeToFile(new File(outputDir, prefix+"_cml_ris.csv")); + } + } + } + } + + private static IncrementalMagFreqDist loadGridded(GridSourceList gridList, + TectonicRegionType trt, EvenlyDiscretizedFunc refMFD) { + SummedMagFreqDist mfdSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + for (int l=0; l 0d) + return mfdSum; + return null; + } + + private static void processCSVs(IncrementalMagFreqDist mfd, String name, double[] mags, + CSVFile rateCSV, CSVFile riCSV) { + if (mfd == null || rateCSV == null) + return; + EvenlyDiscretizedFunc cml = mfd.getCumRateDistWithOffset(); + processCSVsWithCml(cml, name, mags, rateCSV, riCSV); + } + + private static void processCSVsWithCml(EvenlyDiscretizedFunc cmlMFD, String name, double[] mags, + CSVFile rateCSV, CSVFile riCSV) { + if (cmlMFD == null || rateCSV == null) + return; + List rateLine = new ArrayList<>(); + List riLine = new ArrayList<>(); + rateLine.add(name); + riLine.add(name); + for (double mag : mags) { + int index = cmlMFD.getClosestXIndex(mag); + double rate = cmlMFD.getY(index); + rateLine.add((float)rate+""); + double ri = 1d/rate; + if (ri > 10d) + riLine.add((int)Math.round(ri)+""); + else if (ri > 1d) + riLine.add(oDF.format(ri)); + else if (ri > 0.1) + riLine.add(twoDF.format(ri)); + else + riLine.add((float)ri+""); + } + rateCSV.addLine(rateLine); + riCSV.addLine(riLine); + } +} diff --git a/src/main/java/scratch/kevin/nshm27/figures/CrustalNucleationAroundFaultZoom.java b/src/main/java/scratch/kevin/nshm27/figures/CrustalNucleationAroundFaultZoom.java index 4b643b4b..5dd610cd 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/CrustalNucleationAroundFaultZoom.java +++ b/src/main/java/scratch/kevin/nshm27/figures/CrustalNucleationAroundFaultZoom.java @@ -25,7 +25,8 @@ public class CrustalNucleationAroundFaultZoom { public static void main(String[] args) throws IOException { Region reg = new Region(new Location(13, 144), new Location(16, 146)); FaultSystemSolution sol = FaultSystemSolution.load(new File( - "/data/kevin/nshm23/batch_inversions/2026_03_27-nshm26-GNMI-2000samples-gridded/" +// "/data/kevin/nshm23/batch_inversions/2026_03_27-nshm26-GNMI-2000samples-gridded/" + "/data/kevin/nshm23/batch_inversions/2026_07_13-nshm27-GNMI-5000samples-lhs_pairwise/" + "results_GNMI_V1_ACTIVE_SHALLOW_branch_averaged.zip")); File outputDir = new File("/tmp"); GridSourceList gridList = sol.requireModule(GridSourceList.class); diff --git a/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java b/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java new file mode 100644 index 00000000..2714cf67 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java @@ -0,0 +1,136 @@ +package scratch.kevin.nshm27.figures; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; +import org.opensha.commons.util.modules.ModuleContainer; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; +import org.opensha.sha.earthquake.faultSysSolution.inversion.Inversions; +import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.FixedFractileSampler; +import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; +import org.opensha.sha.earthquake.faultSysSolution.modules.SectSlipRates; +import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.faultSurface.FaultSection; +import org.opensha.sha.util.TectonicRegionType; + +import com.google.common.base.Preconditions; + +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceHingedBValue; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; + +public class DMLowerLimitTests { + + public static void main(String[] args) throws IOException { + ModuleContainer.VERBOSE_DEFAULT = false; + NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.GNMI; + int numSamples = 50000; + NSHM27_LogicTree.INTERFACE_B_HINGED_WEIGHT = 1d; + LogicTree tree = NSHM27_LogicTree.buildLogicTree(seisReg, + TectonicRegionType.SUBDUCTION_INTERFACE, numSamples, true, + SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE); + int fixedIndex = 27551; + double searchThreshold = 0d; + + NSHM27_InvConfigFactory factory = new NSHM27_InvConfigFactory(); + FaultSystemRupSet rs = factory.buildGenericRupSet(tree.getBranch(0), 16); + SectSlipRates slips1 = rs.requireModule(SectSlipRates.class); + FaultSystemRupSet genericRS = rs; + + double minDM = Double.POSITIVE_INFINITY; + LogicTreeBranch minDMBranch = null; + if (fixedIndex >= 0) { + LogicTreeBranch branch = tree.getBranch(fixedIndex); + minDM = ((FixedFractileSampler)branch.requireValue(NSHM27_InterfaceDeformationModels.class).getValue()).getFixedFractile(); + minDMBranch = branch; + } else { + for (LogicTreeBranch branch : tree) { + double fract = ((FixedFractileSampler)branch.requireValue(NSHM27_InterfaceDeformationModels.class).getValue()).getFixedFractile(); + if (fract < minDM) { + minDM = fract; + minDMBranch = branch; + } + } + } + System.out.println("Min DM fractile: "+minDM); + System.out.println("Branch: "+minDMBranch); + rs = factory.updateRuptureSetForBranch(rs, minDMBranch); + Preconditions.checkState(rs != genericRS); + SectSlipRates slips2 = rs.requireModule(SectSlipRates.class); + Preconditions.checkState(slips1 != slips2); + for (int s=0; s 0d) { + List> lowBranches = new ArrayList<>(); + for (LogicTreeBranch branch : tree) { + double fract = ((FixedFractileSampler)branch.requireValue(NSHM27_InterfaceDeformationModels.class).getValue()).getFixedFractile(); + if (fract < searchThreshold) + lowBranches.add(branch); + } + System.out.println("Now trying tree for "+lowBranches.size()+" low branches"); + List> bFutures = new ArrayList<>(lowBranches.size()); + for (LogicTreeBranch branch : lowBranches) { + bFutures.add(CompletableFuture.supplyAsync(()->{ + FaultSystemRupSet branchRS; + try { + branchRS = factory.updateRuptureSetForBranch(genericRS, branch); + } catch (IOException e) { + throw ExceptionUtils.asRuntimeException(e); + } + return NSHM27_InterfaceHingedBValue.calcRawInterfaceHingedBValue(branchRS, branch); + })); + } + + for (int i=0; i branch = lowBranches.get(i); + try { + bFutures.get(i).get(); + } catch (Exception e) { + System.err.println("Failed on "+branch); + e.printStackTrace(); + System.err.flush(); + System.exit(1); + } + } + System.out.println("All "+lowBranches.size()+" succeeded for searchThreshold="+(float)searchThreshold); + System.exit(0); + } + } + +} diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java index aebd5186..f9360083 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java @@ -1,19 +1,25 @@ package scratch.kevin.nshm27.figures; +import static scratch.kevin.nshm27.figures.NSHM27_PaperPaths.*; + import java.awt.Color; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.BitSet; +import java.util.Collections; import java.util.List; import java.util.Random; import java.util.concurrent.CompletableFuture; +import org.apache.commons.statistics.distribution.ContinuousDistribution; import org.jfree.data.Range; import org.opensha.commons.data.WeightedList; import org.opensha.commons.data.function.ArbDiscrEmpiricalDistFunc; +import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DiscretizedFunc; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.function.LightFixedXFunc; import org.opensha.commons.data.uncertainty.UncertainArbDiscFunc; import org.opensha.commons.data.uncertainty.UncertainBoundedIncrMagFreqDist; import org.opensha.commons.gui.plot.HeadlessGraphPanel; @@ -32,6 +38,7 @@ import org.opensha.commons.util.modules.ModuleContainer; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.modules.ClusterRuptures; +import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; import org.opensha.sha.earthquake.faultSysSolution.modules.SectSlipRates; import org.opensha.sha.earthquake.faultSysSolution.ruptures.plausibility.impl.prob.RuptureProbabilityCalc.BinaryRuptureProbabilityCalc; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; @@ -74,12 +81,18 @@ public static void main(String[] args) throws IOException { TectonicRegionType trt = TectonicRegionType.SUBDUCTION_INTERFACE; + boolean includeObs = true; + boolean includeTotalObs = true; + LogicTreeBranch branch = NSHM27_LogicTree.buildDefault(seisReg, trt, false); LogicTreeBranch sampledBranch = NSHM27_LogicTree.buildDefault(seisReg, trt, true); // int samples = 50; // int samples = 500; int samples = 1000; +// boolean skipSampled = true; + boolean skipSampled = false; + for (int l=0; l level = branch.getLevel(l); System.out.println(l+". "+level.getName()); @@ -111,9 +124,16 @@ public static void main(String[] args) throws IOException { NSHM27_InvConfigFactory factory = new NSHM27_InvConfigFactory(); FaultSystemRupSet rupSet = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); - EvenlyDiscretizedFunc refMFD = FaultSysTools.initEmptyMFD(6.01, 9.99); + EvenlyDiscretizedFunc refMFD = FaultSysTools.initEmptyMFD(5.01, 9.99); + + FaultGridAssociations assoc = rupSet.requireModule(FaultGridAssociations.class); - IncrementalMagFreqDist defaultMFD = calculateMFD(factory, rupSet, branch, refMFD); + IncrementalMagFreqDist defaultMFD = calculateMFD(factory, rupSet, branch, refMFD, assoc); + + double defaultMmax = 0d; + for (int m=0; m 0) + defaultMmax = defaultMFD.getX(m); CPT tab10CPT = GMT_CPT_Files.CATEGORICAL_TAB10_NOGRAY.instance(); Color[] tab10 = new Color[tab10CPT.size()]; @@ -124,6 +144,31 @@ public static void main(String[] args) throws IOException { Range rateRange = new Range(1e-5, 1e0); List avgStrings = new ArrayList<>(); + + IncrementalMagFreqDist obsMFD = null; + EvenlyDiscretizedFunc obsCmlMFD = null; + if (includeObs) { + NSHM27_SeisRateModel rateModel = branch.requireValue(NSHM27_SeisRateModel.class); + obsMFD = rateModel.build(seisReg, branch.requireValue(NSHM27_SeisClassificationMethod.class), trt, refMFD, defaultMmax); + obsMFD.setName("Observed (interface)"); + System.out.println("Observed rate M>5: "+obsMFD.getCumRate(obsMFD.getClosestXIndex(5.01))); + System.out.println("Observed rate M>6: "+obsMFD.getCumRate(obsMFD.getClosestXIndex(6.01))); + obsCmlMFD = obsMFD.getCumRateDistWithOffset(); + // this could be used to make it appear flat to Mmax, but it's not realistic and won't match the extrap branch +// IncrementalMagFreqDist obsTmp = obsMFD.deepClone(); +// obsTmp.scaleToIncrRate(0, obsCmlMFD.getY(0)); +// obsCmlMFD = obsTmp; + } + IncrementalMagFreqDist obsTotalMFD = null; + EvenlyDiscretizedFunc obsTotalCmlMFD = null; + if (includeTotalObs) { + NSHM27_SeisRateModel rateModel = branch.requireValue(NSHM27_SeisRateModel.class); + obsTotalMFD = rateModel.build(seisReg, branch.requireValue(NSHM27_SeisClassificationMethod.class), null, refMFD, defaultMmax); + obsTotalMFD.setName("Observed (total)"); + System.out.println("Observed total rate M>5: "+obsTotalMFD.getCumRate(obsTotalMFD.getClosestXIndex(5.01))); + System.out.println("Observed total rate M>6: "+obsTotalMFD.getCumRate(obsTotalMFD.getClosestXIndex(6.01))); + obsTotalCmlMFD = obsTotalMFD.getCumRateDistWithOffset(); + } for (int l : levelIndexes) { Preconditions.checkState(l >= 0); @@ -134,6 +179,19 @@ public static void main(String[] args) throws IOException { List incrFuncs = new ArrayList<>(); List cmlFuncs = new ArrayList<>(); List chars = new ArrayList<>(); + + if (includeTotalObs) { + incrFuncs.add(obsTotalMFD); + cmlFuncs.add(obsTotalCmlMFD); + chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 3f, Color.GRAY)); + } + + if (includeObs) { + incrFuncs.add(obsMFD); + cmlFuncs.add(obsCmlMFD); + chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 3f, OBS_RATE_COLOR)); + } + if (sampledLevel == level) { System.out.println("\tNormal level"); SummedMagFreqDist avgMFD = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); @@ -144,7 +202,7 @@ public static void main(String[] args) throws IOException { double weight = node.getNodeWeight(branch); if (weight > 0d) { branch.setValue(node); - IncrementalMagFreqDist mfd = calculateMFD(factory, rupSet, branch, refMFD); + IncrementalMagFreqDist mfd = calculateMFD(factory, rupSet, branch, refMFD, assoc); avgMFD.addIncrementalMagFreqDist(mfd, weight); sumWeight += weight; Color color = tab10[index++ % tab10.length]; @@ -171,6 +229,10 @@ public static void main(String[] args) throws IOException { // baselineMFD = defaultMFD.deepClone(); // baselineMFD.setName(defaultValue.getName()); System.out.println("\tSampled version: "+sampledLevel.getName()); + if (skipSampled) { + System.out.println("Skipping sampling this time"); + continue; + } List> levels = new ArrayList<>(); List values = new ArrayList<>(); for (int i=0; i origIncrs = new ArrayList<>(); + List nodes = level.getNodes(); + for (int i=0; i addFuncs = new ArrayList<>(); + List addChars = new ArrayList<>(); + CPT tab10light = GMT_CPT_Files.CATEGORICAL_TAB10_LIGHT_NOGRAY.instance(); + for (int i=0; i 0) + break; + for (int m=faultMminIndex+1; m branch, EvenlyDiscretizedFunc refMFD) throws IOException { + LogicTreeBranch branch, EvenlyDiscretizedFunc refMFD, FaultGridAssociations assoc) throws IOException { ClusterRuptures cRups = rupSet.requireModule(ClusterRuptures.class); rupSet = factory.updateRuptureSetForBranch(rupSet, branch); BinaryRuptureProbabilityCalc exclusionModel = NSHM27_InvConfigFactory.getExclusionModel(rupSet, branch, cRups); @@ -399,9 +549,12 @@ private static IncrementalMagFreqDist calculateMFD(NSHM27_InvConfigFactory facto SummedMagFreqDist mfd = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); for (int s=0; s 0d) { + GutenbergRichterMagFreqDist gr = new GutenbergRichterMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + gr.setAllButTotCumRate(mMin, mMax, moRate, b); + mfd.addIncrementalMagFreqDist(gr); + } } return mfd; diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java new file mode 100644 index 00000000..9b95c9fd --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java @@ -0,0 +1,89 @@ +package scratch.kevin.nshm27.figures; + +import static scratch.kevin.nshm27.figures.NSHM27_PaperPaths.*; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.math3.stat.StatUtils; +import org.opensha.commons.data.CSVFile; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.DataUtils; +import org.opensha.commons.util.cpt.CPT; +import org.opensha.commons.util.modules.ModuleContainer; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; +import org.opensha.sha.earthquake.faultSysSolution.modules.SectSlipRates; +import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.util.TectonicRegionType; + +import com.google.common.base.Preconditions; + +import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; + +public class InterfaceObsSeisAdjFigures { + + public static void main(String[] args) throws IOException { + ModuleContainer.VERBOSE_DEFAULT = false; + File outputDir = new File(FIGURES_DIR, "interface_obs_seis_adj"); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); + + NSHM27_InvConfigFactory factory = new NSHM27_InvConfigFactory(); + + CPT redCPT = GMT_CPT_Files.SEQUENTIAL_LAJOLLA_UNIFORM.instance().reverse().rescale(0d, 1d); + + for (NSHM27_SeismicityRegions seisReg : NSHM27_SeismicityRegions.values()) { + LogicTreeBranch branch = NSHM27_LogicTree.buildDefault(seisReg, TectonicRegionType.SUBDUCTION_INTERFACE, false); + System.out.println("Default branch: "+branch); + + CSVFile csv = new CSVFile<>(true); + csv.addLine("Adjustment", "Overall Moment Reduction Factor", "Section-Averaged Reduction Factor", + "Maximum Reduction Factor", "Median Reduction Factor"); + + branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.NONE); + + FaultSystemRupSet rs = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); + SectSlipRates fullSlips = rs.requireModule(SectSlipRates.class); + + GeographicMapMaker mapMaker = new GeographicMapMaker(rs.getFaultSectionDataList()); + + double fullMoment = fullSlips.calcTotalMomentRate(); + + for (NSHM27_InterfaceObsSeisDMAdjustment adj : NSHM27_InterfaceObsSeisDMAdjustment.values()) { + if (adj == NSHM27_InterfaceObsSeisDMAdjustment.NONE) + continue; + branch.setValue(adj); + rs = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); + SectSlipRates slips = rs.requireModule(SectSlipRates.class); + + double branchMoment = slips.calcTotalMomentRate(); + + double[] factors = new double[slips.size()]; + for (int s=0; s 0) { + magLabels[m] = "On-fault M>"+oDF.format(minMags[m]); + magPrefixes[m] = "m"+oDF.format(minMags[m]); + } else { + magLabels[m] = "On-fault"; + magPrefixes[m] = "supra"; + } + } + + double[] sltMinMags = {0d}; + String[] sltMagLabels = new String[minMags.length]; + String[] sltMagPrefixes = new String[minMags.length]; + for (int m=0; m 0) { + sltMagLabels[m] = "On-fault M>"+oDF.format(sltMinMags[m]); + sltMagPrefixes[m] = "m"+oDF.format(sltMinMags[m]); + } else { + sltMagLabels[m] = "On-fault"; + sltMagPrefixes[m] = "supra"; + } + } + + List fixedBatchNodes = List.of( + NSHM27_InterfaceDeformationModels.Aggregated.HIGH_COUPLING, + NSHM27_InterfaceDeformationModels.Aggregated.LOW_COUPLING, + NSHM27_InterfaceHingedBValue.HINGED_SINGLE_NODE, + NSHM27_InterfaceObsSeisDMAdjustment.EXTRAPOLATE, + NSHM27_InterfaceCouplingDepthModels.DEEP_TAPER, + NSHM27_InterfaceCouplingDepthModels.DOUBLE_TAPER, + NSHM27_InterfaceCouplingDepthModels.NONE); + List>> fixedBatchLevelClasses = List.of( + BinnedUniformSamplingLevel.class + ); + + for (NSHM27_SeismicityRegions seisReg : NSHM27_SeismicityRegions.values()) { + CPT cpt = GMT_CPT_Files.RAINBOW_UNIFORM.instance(); + if (seisReg == NSHM27_SeismicityRegions.AMSAM) + cpt = cpt.rescale(-4, -1); + else + cpt = cpt.rescale(-5, -2); + cpt.setLog10(true); + File dir = getSolDir(seisReg); + + File solFile = getSolFile(seisReg); + FaultSystemSolution baSol = FaultSystemSolution.load(solFile); + + List interfaceSects = new ArrayList<>(); + List interfaceIndexes = new ArrayList<>(); + for (FaultSection sect : baSol.getRupSet().getFaultSectionDataList()) { + if (sect.getTectonicRegionType() == TectonicRegionType.SUBDUCTION_INTERFACE) { + interfaceSects.add(sect); + interfaceIndexes.add(sect.getSectionId()); + } + } + int[] interfaceRemaps = interfaceIndexes.size() == baSol.getRupSet().getNumSections() ? null : Ints.toArray(interfaceIndexes); + + GeographicMapMaker mapMaker = new GeographicMapMaker(interfaceSects); + + String baPrefix = seisReg.name()+"_ba_"; + + for (int m=0; m analysisTree = getAnalysisLogicTree(seisReg); + + File sltFile = new File(dir, "results_nogrid.zip"); + SolutionLogicTree slt = SolutionLogicTree.load(sltFile); + LogicTree tree = slt.getLogicTree(); + Preconditions.checkState(tree.size() == analysisTree.size()); + + List batchNodesList = new ArrayList<>(); + List> batchNodesLevels = new ArrayList<>(); + for (LogicTreeNode node : fixedBatchNodes) { + LogicTreeLevel match = null; + for (LogicTreeLevel level : tree.getLevels()) { + if (level.isMember(node)) { + match = level; + break; + } + } + if (match == null) { + // check analysis tree + for (LogicTreeLevel level : analysisTree.getLevels()) { + if (level.isMember(node)) { + match = level; + break; + } + } + } + if (match != null) { + batchNodesList.add(node); + batchNodesLevels.add(match); + } + } + for (LogicTree theTree : List.of(tree, analysisTree)) { + for (LogicTreeLevel level : theTree.getLevels()) { + for (Class> clazz : fixedBatchLevelClasses) { + if (clazz.isAssignableFrom(level.getClass())) { + for (LogicTreeNode node : level.getNodes()) { + if (!batchNodesList.contains(node)) { + batchNodesList.add(node); + batchNodesLevels.add(level); + } + } + } + } + } + } + + LogicTreeNode[] batchNodes = new LogicTreeNode[batchNodesList.size()]; + for (int n=0; n level = batchNodesLevels.get(n); + System.out.println("Will average for node: "+level.getShortName()+" "+node.getFilePrefix()); + batchNodes[n] = node; + } + + double[][][] batchValues = new double[batchNodes.length][][]; + double[] batchWeightSums = new double[batchNodes.length]; + int[] batchCounts = new int[batchNodes.length]; + + CompletableFuture processFuture = null; + for (int b=0; b branch = tree.getBranch(b); + LogicTreeBranch analysisBranch = analysisTree.getBranch(b); + + System.out.println("Branch "+b+":\t"+analysisBranch); + + List matches = new ArrayList<>(); + for (LogicTreeNode node : batchNodes) + if (branch.hasValue(node) || analysisBranch.hasValue(node)) + matches.add(node.getFilePrefix()); + if (matches.isEmpty()) { + System.out.println("\tNo matches, skipping"); + continue; + } + System.out.println("\tMatches:\t"+matches); + + FaultSystemSolution sol = slt.forBranch(branch); + + if (processFuture != null) + processFuture.join(); + + double weight = tree.getBranchWeight(b); + + processFuture = CompletableFuture.runAsync(() -> { + int numSects = interfaceRemaps == null ? sol.getRupSet().getNumSections() : interfaceRemaps.length; + + double[][] magRates = new double[sltMinMags.length][]; + for (int m=0; m getLogicTree(NSHM27_SeismicityRegions seisReg) throws IOException { + File ltFile = new File(getSolDir(seisReg), "logic_tree.json"); + return LogicTree.read(ltFile); + } + + public static LogicTree getAnalysisLogicTree(NSHM27_SeismicityRegions seisReg) throws IOException { + File ltFile = new File(getSolDir(seisReg), "logic_tree_analysis.json"); + return LogicTree.read(ltFile); + } + + public static TectonicRegionType[] TRTs = { + TectonicRegionType.SUBDUCTION_INTERFACE, + TectonicRegionType.SUBDUCTION_SLAB, + TectonicRegionType.ACTIVE_SHALLOW, + }; + + public static Color getColor(TectonicRegionType trt, IncludeBackgroundOption bgType) { + return switch (trt) { + case ACTIVE_SHALLOW: + if (bgType == IncludeBackgroundOption.ONLY) + yield Colors.tab_lightblue; + else if (bgType == IncludeBackgroundOption.INCLUDE) + yield darker(Colors.tab_blue); + else + yield Colors.tab_blue; + case SUBDUCTION_INTERFACE: + if (bgType == IncludeBackgroundOption.ONLY) + yield Colors.tab_lightorange; + else if (bgType == IncludeBackgroundOption.INCLUDE) + yield darker(Colors.tab_orange); + else + yield Colors.tab_orange; + case SUBDUCTION_SLAB: + if (bgType == IncludeBackgroundOption.ONLY) + yield Colors.tab_lightgreen; + else if (bgType == IncludeBackgroundOption.INCLUDE) + yield darker(Colors.tab_green); + else + yield Colors.tab_green; + default: + throw new IllegalArgumentException("Unexpected value: " + trt); + }; + } + + public static Color OBS_RATE_COLOR = Colors.tab_brown.darker(); + + public static Color darker(Color color) { + return color.darker(); + } + + public static DecimalFormat oneDF = new DecimalFormat("0.0"); + public static DecimalFormat twoDF = new DecimalFormat("0.00"); + public static DecimalFormat oDF = new DecimalFormat("0.#"); } diff --git a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java index f0944861..78bb37e5 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java @@ -48,10 +48,10 @@ public static void main(String[] args) throws IOException { File outputDir = new File("/tmp/nshm27_slip_projection"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); -// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; -// double maxSlip = 120; - NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; - double maxSlip = 20d; + NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.AMSAM_V1; + double maxSlip = 120; +// NSHM27_InterfaceFaultModels fm = NSHM27_InterfaceFaultModels.GNMI_V1; +// double maxSlip = 20d; List sects = fm.buildSubSects(fm); @@ -249,8 +249,6 @@ public static void main(String[] args) throws IOException { branch.setValue(NSHM27_InterfaceCouplingDepthModels.AVERAGE); for (NSHM27_InterfaceDeformationModels.Aggregated odm : NSHM27_InterfaceDeformationModels.Aggregated.values()) { - if (odm.getNodeWeight() == 0d) - continue; branch.setValue(odm); List dmSects = odm.apply(fm, branch, sects); From 8e5f12337ac774122d12fe3d2be6b7af35edeed5 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 24 Jul 2026 09:46:07 -0700 Subject: [PATCH 40/71] figure updates --- .../BranchAveragedHazardScriptWriter.java | 123 +-- .../nshm27/InterfaceSlipRatePercentiles.java | 86 +++ .../kevin/nshm27/figures/BValDistFigure.java | 4 +- .../nshm27/figures/CombinedMFDsFigure.java | 720 ++++++++++-------- .../InterfaceLogicTreeMFDExploration.java | 18 + .../figures/InterfaceObsSeisAdjFigures.java | 22 +- .../figures/ObsUncertaintyBoundsFigure.java | 150 +++- 7 files changed, 741 insertions(+), 382 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java diff --git a/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java b/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java index de8c5a63..66e2bd97 100644 --- a/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java @@ -28,6 +28,9 @@ import com.google.common.base.Preconditions; import edu.usc.kmilner.mpj.taskDispatch.MPJTaskCalculator; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_MapRegions; +import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; public class BranchAveragedHazardScriptWriter { @@ -95,59 +98,83 @@ public static void main(String[] args) throws IOException { /* * PRVI */ +//// region = PRVI25_RegionLoader.loadPRVI_ModelBroad(); +// region = PRVI25_RegionLoader.loadPRVI_MapExtents(); +// gridSpacing = 0.01; +// +// gmms = new AttenRelRef[] { AttenRelRef.USGS_PRVI_ACTIVE, AttenRelRef.USGS_PRVI_INTERFACE, AttenRelRef.USGS_PRVI_SLAB }; +// periods = new double[] { 0d, 0.2d, 1d, 5d }; +// supersample = true; +// sigmaTrunc = 3d; +// +//// String date = "2025_01_17"; +// String date = "2025_09_12"; +// +//// String baseDirName = date+"-prvi25_crustal_subduction_combined_branches"; +//// String suffix = "ba_only"; +//// String solFileName = "combined_branch_averaged_solution.zip"; +// +//// String baseDirName = date+"-prvi25_crustal_branches-dmSample10x"; +//// String suffix = "ba_only"; +//// String solFileName = "results_PRVI_CRUSTAL_FM_V1p1_branch_averaged_gridded.zip"; +// +// String baseDirName = date+"-prvi25_subduction_branches"; +// // slab (gridded only) +//// String suffix = "ba_only-SLAB_only"; +//// String solFileName = "results_PRVI_SLAB_ONLY_branch_averaged_gridded.zip"; +//// bgOps = new IncludeBackgroundOption[] { IncludeBackgroundOption.ONLY }; +// // interface (will do fault + gridded) +//// String suffix = "ba_only-INTERFACE_only"; +//// String solFileName = "results_PRVI_INTERFACE_ONLY_branch_averaged_gridded.zip"; +// // both +// String suffix = "ba_only-both_fms"; +// String solFileName = "results_PRVI_SUB_FMs_combined_branch_averaged_gridded.zip"; +// +// +// // one off tests below +//// String baseDirName = date+"-prvi25_crustal_subduction_combined_branches"; +//// String suffix = "ba_only-quick"; +//// quickGridded = true; +//// supersampleQuick = true; +//// String solFileName = "combined_branch_averaged_solution.zip"; +// +//// String baseDirName = date+"-prvi25_crustal_subduction_combined_branches"; +//// String suffix = "ba_only-no_sigma_trunc"; +//// sigmaTrunc = null; +//// String solFileName = "combined_branch_averaged_solution.zip"; +// +//// region = PRVI25_RegionLoader.loadPRVI_IntermediateModelMapExtents(); +//// gridSpacing = 0.02; +//// periods = new double[] { 0d, 1d }; +//// String baseDirName = date+"-prvi25_crustal_subduction_combined_branches"; +//// String suffix = "ba_only-wider_region"; +//// String solFileName = "combined_branch_averaged_solution.zip"; +// +//// suffix += "-updatedGMMs"; +// +// vs30 = 760d; suffix += "-vs760"; +//// vs30 = 260d; suffix += "-vs260"; + + /* + * NSHM27 + */ + NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.AMSAM; + String baseDirName = "2026_07_13-nshm27-AMSAM-5000samples-lhs_pairwise"; + String solFileName = "results_branch_averaged.zip"; + +// NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.GNMI; +// String baseDirName = "2026_07_13-nshm27-GNMI-5000samples-lhs_pairwise"; +// String solFileName = "results_branch_averaged.zip"; + // region = PRVI25_RegionLoader.loadPRVI_ModelBroad(); - region = PRVI25_RegionLoader.loadPRVI_MapExtents(); - gridSpacing = 0.01; + region = NSHM27_MapRegions.valueOf(seisReg.name()).load(); + gridSpacing = 0.05; gmms = new AttenRelRef[] { AttenRelRef.USGS_PRVI_ACTIVE, AttenRelRef.USGS_PRVI_INTERFACE, AttenRelRef.USGS_PRVI_SLAB }; periods = new double[] { 0d, 0.2d, 1d, 5d }; supersample = true; - sigmaTrunc = 3d; - -// String date = "2025_01_17"; - String date = "2025_09_12"; -// String baseDirName = date+"-prvi25_crustal_subduction_combined_branches"; -// String suffix = "ba_only"; -// String solFileName = "combined_branch_averaged_solution.zip"; - -// String baseDirName = date+"-prvi25_crustal_branches-dmSample10x"; -// String suffix = "ba_only"; -// String solFileName = "results_PRVI_CRUSTAL_FM_V1p1_branch_averaged_gridded.zip"; - - String baseDirName = date+"-prvi25_subduction_branches"; - // slab (gridded only) -// String suffix = "ba_only-SLAB_only"; -// String solFileName = "results_PRVI_SLAB_ONLY_branch_averaged_gridded.zip"; -// bgOps = new IncludeBackgroundOption[] { IncludeBackgroundOption.ONLY }; - // interface (will do fault + gridded) -// String suffix = "ba_only-INTERFACE_only"; -// String solFileName = "results_PRVI_INTERFACE_ONLY_branch_averaged_gridded.zip"; - // both - String suffix = "ba_only-both_fms"; - String solFileName = "results_PRVI_SUB_FMs_combined_branch_averaged_gridded.zip"; - - - // one off tests below -// String baseDirName = date+"-prvi25_crustal_subduction_combined_branches"; -// String suffix = "ba_only-quick"; -// quickGridded = true; -// supersampleQuick = true; -// String solFileName = "combined_branch_averaged_solution.zip"; - -// String baseDirName = date+"-prvi25_crustal_subduction_combined_branches"; -// String suffix = "ba_only-no_sigma_trunc"; -// sigmaTrunc = null; -// String solFileName = "combined_branch_averaged_solution.zip"; - -// region = PRVI25_RegionLoader.loadPRVI_IntermediateModelMapExtents(); -// gridSpacing = 0.02; -// periods = new double[] { 0d, 1d }; -// String baseDirName = date+"-prvi25_crustal_subduction_combined_branches"; -// String suffix = "ba_only-wider_region"; -// String solFileName = "combined_branch_averaged_solution.zip"; - -// suffix += "-updatedGMMs"; + String suffix = "ba_only"; vs30 = 760d; suffix += "-vs760"; // vs30 = 260d; suffix += "-vs260"; @@ -228,7 +255,7 @@ public static void main(String[] args) throws IOException { String dirPath = "$DIR"; List classpath = new ArrayList<>(); - classpath.add(new File(dirPath+"/opensha-dev-all.jar")); + classpath.add(new File(dirPath+"/opensha-all.jar")); parallelMPJWrite.setClasspath(classpath); List singleClasspath = new ArrayList<>(classpath); diff --git a/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java b/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java new file mode 100644 index 00000000..3c867db4 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java @@ -0,0 +1,86 @@ +package scratch.kevin.nshm27; + +import java.io.IOException; +import java.text.DecimalFormat; + +import org.apache.commons.math3.stat.StatUtils; +import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.AverageSampler; +import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.FixedFractileSampler; +import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.FixedSampler; + +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels.DeformationFront; +import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; + +public class InterfaceSlipRatePercentiles { + + public static void main(String[] args) throws IOException { + double[] fractiles = { + 0.00000001, + 0.0000001, + 0.000001, + 0.00001, + 0.0001, + 0.001, + 0.01, + 0.025, + 0.16, + 0.5, + 0.84, + 0.975, + 0.99, + 0.999, + 0.9999, + 0.99999, + 0.999999, + 0.9999999, + 0.99999999, + 1d, + 2d + }; + + DecimalFormat pDF = new DecimalFormat("0.#########%"); + DecimalFormat slipDF = new DecimalFormat("0.###"); + DecimalFormat groupedDF = new DecimalFormat("0"); + groupedDF.setGroupingSize(3); + groupedDF.setGroupingUsed(true); + + for (NSHM27_InterfaceFaultModels fm : NSHM27_InterfaceFaultModels.values()) { + DeformationFront df = NSHM27_InterfaceDeformationModels.getDeformationFront(fm); + System.out.println(fm.getName()); + + String[] labels = new String[fractiles.length]; + String[] results = new String[fractiles.length]; + int longestLabel = 0; + for (int f=0; f < fractiles.length; f++) { + double fractile = fractiles[f]; + String label; + FixedSampler sampler; + if (fractile == 2d) { + label = "Distribution-average"; + sampler = new AverageSampler(); + } else { + double rarity = Math.min(1d-fractile, fractile); + + label = pDF.format(fractile); + if (rarity < 0.1) + label += " (1 in "+groupedDF.format(1d/rarity)+")"; + sampler = new FixedFractileSampler(fractile); + } + + double[] slipRates = NSHM27_InterfaceDeformationModels.getCoupledSlipRates(df, sampler); + + longestLabel = Integer.max(longestLabel, label.length()); + labels[f] = label+":"; + results[f] = "mean="+slipDF.format(StatUtils.mean(slipRates)) + +"\trange=["+slipDF.format(StatUtils.min(slipRates))+", "+slipDF.format(StatUtils.max(slipRates))+"]"; + } + for (int f=0; f rateCSV = null; - CSVFile riCSV = null; - if (!interfaceOnly) { - rateCSV = new CSVFile<>(true); - rateCSV.addLine(csvRateHeader); - riCSV = new CSVFile<>(true); - riCSV.addLine(csvRIHeader); - } - TectonicRegionType targetTRT = interfaceOnly ? TectonicRegionType.SUBDUCTION_INTERFACE : null; - List indvIncrFuncs = new ArrayList<>(); - List indvChars = new ArrayList<>(); + for (boolean mapRegion : new boolean[] {false,true}) { + Region reg; + if (mapRegion) + reg = NSHM27_MapRegions.valueOf(seisReg.name()).load(); + else + reg = seisReg.load(); - SummedMagFreqDist gridSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); - SummedMagFreqDist faultSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + IncrementalMagFreqDist fullObsMean = null; + EvenlyDiscretizedFunc fullObsMeanCml = null; - for (TectonicRegionType trt : TRTs) { - if (interfaceOnly && trt != TectonicRegionType.SUBDUCTION_INTERFACE) - continue; - Color gridColor = getColor(trt, IncludeBackgroundOption.ONLY); - Color faultColor = getColor(trt, IncludeBackgroundOption.EXCLUDE); - Color sumColor = getColor(trt, IncludeBackgroundOption.INCLUDE); - String trtName = NSHM27_RegionLoader.getNameForTRT(trt); - - IncrementalMagFreqDist gridMFD = loadGridded(gridList, trt, refMFD); - IncrementalMagFreqDist faultMFD = loadFault(sol, trt, refMFD, reg); - - processCSVs(faultMFD, trtName+" (on-fault)", csvMags, rateCSV, riCSV); - processCSVs(gridMFD, trtName+" (gridded)", csvMags, rateCSV, riCSV); - - if (faultMFD != null) { - if (!interfaceOnly) { - SummedMagFreqDist sum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); - sum.addIncrementalMagFreqDist(gridMFD); - sum.addIncrementalMagFreqDist(faultMFD); - - sum.setName(trtName+" (combined)"); - indvIncrFuncs.add(sum); - indvChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 2f, sumColor)); + for (boolean interfaceOnly : new boolean[] {false, true}) { + CSVFile rateCSV = null; + CSVFile riCSV = null; + if (!interfaceOnly) { + rateCSV = new CSVFile<>(true); + rateCSV.addLine(csvRateHeader); + riCSV = new CSVFile<>(true); + riCSV.addLine(csvRIHeader); + } + TectonicRegionType targetTRT = interfaceOnly ? TectonicRegionType.SUBDUCTION_INTERFACE : null; + List indvIncrFuncs = new ArrayList<>(); + List indvChars = new ArrayList<>(); + + SummedMagFreqDist gridSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + SummedMagFreqDist faultSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + + for (TectonicRegionType trt : TRTs) { + if (interfaceOnly && trt != TectonicRegionType.SUBDUCTION_INTERFACE) + continue; + Color gridColor = getColor(trt, IncludeBackgroundOption.ONLY); + Color faultColor = getColor(trt, IncludeBackgroundOption.EXCLUDE); + Color sumColor = getColor(trt, IncludeBackgroundOption.INCLUDE); + String trtName = NSHM27_RegionLoader.getNameForTRT(trt); + + IncrementalMagFreqDist gridMFD = loadGridded(gridList, trt, refMFD, reg); + IncrementalMagFreqDist faultMFD = loadFault(sol, trt, refMFD, reg); + + processCSVs(faultMFD, trtName+" (on-fault)", csvMags, rateCSV, riCSV); + processCSVs(gridMFD, trtName+" (gridded)", csvMags, rateCSV, riCSV); + + if (faultMFD != null) { + if (!interfaceOnly) { + SummedMagFreqDist sum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + sum.addIncrementalMagFreqDist(gridMFD); + sum.addIncrementalMagFreqDist(faultMFD); + + sum.setName(trtName+" (combined)"); + indvIncrFuncs.add(sum); + indvChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 2f, sumColor)); + + processCSVs(sum, trtName+" (combined)", csvMags, rateCSV, riCSV); + } - processCSVs(sum, trtName+" (combined)", csvMags, rateCSV, riCSV); + faultMFD.setName(trtName+" (on-fault)"); + indvIncrFuncs.add(faultMFD); + indvChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, faultColor)); + faultSum.addIncrementalMagFreqDist(faultMFD); } - faultMFD.setName(trtName+" (on-fault)"); - indvIncrFuncs.add(faultMFD); - indvChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, faultColor)); - faultSum.addIncrementalMagFreqDist(faultMFD); + gridMFD.setName(trtName+" (gridded)"); + indvIncrFuncs.add(gridMFD); + indvChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, gridColor)); + gridSum.addIncrementalMagFreqDist(gridMFD); } - gridMFD.setName(trtName+" (gridded)"); - indvIncrFuncs.add(gridMFD); - indvChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, gridColor)); - gridSum.addIncrementalMagFreqDist(gridMFD); - } - - List incrFuncs = new ArrayList<>(); - List cmlFuncs = new ArrayList<>(); - List chars = new ArrayList<>(); - - SummedMagFreqDist mfdSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); - mfdSum.addIncrementalMagFreqDist(gridSum); - mfdSum.addIncrementalMagFreqDist(faultSum); - if (interfaceOnly) - mfdSum.setName("Total interface"); - else - mfdSum.setName("Total"); - incrFuncs.add(mfdSum); - cmlFuncs.add(mfdSum.getCumRateDistWithOffset()); - chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Color.BLACK)); - - processCSVs(mfdSum, "Total", csvMags, rateCSV, riCSV); - - // uncertainty for legend - IncrementalMagFreqDist emptyFunc = new IncrementalMagFreqDist(refMFD.getMinX(), refMFD.size(), refMFD.getDelta()); - UncertainBoundedIncrMagFreqDist emptyUnceratain = new UncertainBoundedIncrMagFreqDist(emptyFunc, emptyFunc, emptyFunc, null); - emptyUnceratain.setName(fractileLabel); - incrFuncs.add(emptyUnceratain); - cmlFuncs.add(emptyUnceratain); - chars.add(bounds68Char); - - // individual components - for (int i=0; i samples = new ArrayList<>(); - samples.addAll(NSHM27_SeisRateModelSamples.loadOrigSamples(seisReg, NSHM27_SeisClassificationMethod.PROFACE, targetTRT)); - int numProface = samples.size(); - samples.addAll(NSHM27_SeisRateModelSamples.loadOrigSamples(seisReg, NSHM27_SeisClassificationMethod.PROSLAB, targetTRT)); - int numProslab = samples.size() - numProface; - double weightProface = NSHM27_SeisClassificationMethod.PROFACE.getNodeWeight(); - double weightProslab = NSHM27_SeisClassificationMethod.PROSLAB.getNodeWeight(); - if ((float)(weightProface+weightProslab) != 1f) { - double sum = weightProface + weightProslab; - weightProface /= sum; - weightProslab /= sum; - } - double[] weights = new double[samples.size()]; - double weightProfaceEach = weightProface/(double)numProface; - double weightProslabEach = weightProslab/(double)numProslab; - for (int i=0; i incrFuncs = new ArrayList<>(); + List cmlFuncs = new ArrayList<>(); + List chars = new ArrayList<>(); + + SummedMagFreqDist mfdSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + mfdSum.addIncrementalMagFreqDist(gridSum); + mfdSum.addIncrementalMagFreqDist(faultSum); + if (interfaceOnly) + mfdSum.setName("Total interface"); else - obsProslabB += sample.b * weights[s]; + mfdSum.setName("Total"); + incrFuncs.add(mfdSum); + cmlFuncs.add(mfdSum.getCumRateDistWithOffset()); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Color.BLACK)); - for (int m=0; m samples = new ArrayList<>(); + samples.addAll(NSHM27_SeisRateModelSamples.loadOrigSamples(seisReg, NSHM27_SeisClassificationMethod.PROFACE, targetTRT)); + int numProface = samples.size(); + samples.addAll(NSHM27_SeisRateModelSamples.loadOrigSamples(seisReg, NSHM27_SeisClassificationMethod.PROSLAB, targetTRT)); + int numProslab = samples.size() - numProface; + double weightProface = NSHM27_SeisClassificationMethod.PROFACE.getNodeWeight(); + double weightProslab = NSHM27_SeisClassificationMethod.PROSLAB.getNodeWeight(); + if ((float)(weightProface+weightProslab) != 1f) { + double sum = weightProface + weightProslab; + weightProface /= sum; + weightProslab /= sum; } - } - Preconditions.checkState(regionIndex >= 0); - IncrementalMagFreqDist[] incrFractiles = regMFDs.calcRegionalIncrementalFractiles(MFDType.SUM, regionIndex, fractiles); - UncertainBoundedIncrMagFreqDist incrExtrema = new UncertainBoundedIncrMagFreqDist(incrFractiles[3], incrFractiles[0], incrFractiles[6], null); - UncertainBoundedIncrMagFreqDist incr95 = new UncertainBoundedIncrMagFreqDist(incrFractiles[3], incrFractiles[1], incrFractiles[5], null); - UncertainBoundedIncrMagFreqDist incr68 = new UncertainBoundedIncrMagFreqDist(incrFractiles[3], incrFractiles[2], incrFractiles[4], null); - EvenlyDiscretizedFunc[] cmlFractiles = regMFDs.calcRegionalCumulativeFractiles(MFDType.SUM, regionIndex, fractiles); - UncertainArbDiscFunc cmlExtrema = new UncertainArbDiscFunc(cmlFractiles[3], cmlFractiles[0], cmlFractiles[6]); - UncertainArbDiscFunc cml95 = new UncertainArbDiscFunc(cmlFractiles[3], cmlFractiles[1], cmlFractiles[5]); - UncertainArbDiscFunc cml68 = new UncertainArbDiscFunc(cmlFractiles[3], cmlFractiles[2], cmlFractiles[4]); - - processCSVsWithCml(cmlFractiles[0], "Total (minimum)", csvMags, rateCSV, riCSV); - processCSVsWithCml(cmlFractiles[1], "Total (2.5 %-ile)", csvMags, rateCSV, riCSV); - processCSVsWithCml(cmlFractiles[2], "Total (16 %-ile)", csvMags, rateCSV, riCSV); - processCSVsWithCml(cmlFractiles[5], "Total (50 %-ile)", csvMags, rateCSV, riCSV); - processCSVsWithCml(cmlFractiles[4], "Total (84 %-ile)", csvMags, rateCSV, riCSV); - processCSVsWithCml(cmlFractiles[5], "Total (97.5 %-ile)", csvMags, rateCSV, riCSV); - processCSVsWithCml(cmlFractiles[6], "Total (maximum)", csvMags, rateCSV, riCSV); - - processCSVsWithCml(obsCmlMean, "Observed", csvMags, rateCSV, riCSV); - processCSVsWithCml(obsCmlLow, "Observed (2.5 %-ile)", csvMags, rateCSV, riCSV); - processCSVsWithCml(obsCmlHigh, "Observed (97.5 %-ile)", csvMags, rateCSV, riCSV); + double[] weights = new double[samples.size()]; + double weightProfaceEach = weightProface/(double)numProface; + double weightProslabEach = weightProslab/(double)numProslab; + for (int i=0; i= 0); + IncrementalMagFreqDist[] incrFractiles = regMFDs.calcRegionalIncrementalFractiles(MFDType.SUM, regionIndex, fractiles); + UncertainBoundedIncrMagFreqDist incrExtrema = new UncertainBoundedIncrMagFreqDist(incrFractiles[3], incrFractiles[0], incrFractiles[6], null); + UncertainBoundedIncrMagFreqDist incr95 = new UncertainBoundedIncrMagFreqDist(incrFractiles[3], incrFractiles[1], incrFractiles[5], null); + UncertainBoundedIncrMagFreqDist incr68 = new UncertainBoundedIncrMagFreqDist(incrFractiles[3], incrFractiles[2], incrFractiles[4], null); + EvenlyDiscretizedFunc[] cmlFractiles = regMFDs.calcRegionalCumulativeFractiles(MFDType.SUM, regionIndex, fractiles); + UncertainArbDiscFunc cmlExtrema = new UncertainArbDiscFunc(cmlFractiles[3], cmlFractiles[0], cmlFractiles[6]); + UncertainArbDiscFunc cml95 = new UncertainArbDiscFunc(cmlFractiles[3], cmlFractiles[1], cmlFractiles[5]); + UncertainArbDiscFunc cml68 = new UncertainArbDiscFunc(cmlFractiles[3], cmlFractiles[2], cmlFractiles[4]); + + processCSVsWithCml(cmlFractiles[0], "Total (minimum)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[1], "Total (2.5 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[2], "Total (16 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[5], "Total (50 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[4], "Total (84 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[5], "Total (97.5 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(cmlFractiles[6], "Total (maximum)", csvMags, rateCSV, riCSV); + + processCSVsWithCml(obsCmlMean, "Observed", csvMags, rateCSV, riCSV); + processCSVsWithCml(obsCmlLow, "Observed (2.5 %-ile)", csvMags, rateCSV, riCSV); + processCSVsWithCml(obsCmlHigh, "Observed (97.5 %-ile)", csvMags, rateCSV, riCSV); - incrExtrema.setName(null); - incrFuncs.add(incrExtrema); - cmlExtrema.setName(null); - cmlFuncs.add(cmlExtrema); - chars.add(extremaChar); + incrExtrema.setName(null); + incrFuncs.add(incrExtrema); + cmlExtrema.setName(null); + cmlFuncs.add(cmlExtrema); + chars.add(extremaChar); - incr95.setName(null); - incrFuncs.add(incr95); - cml95.setName(null); - cmlFuncs.add(cml95); - chars.add(bounds95Char); + incr95.setName(null); + incrFuncs.add(incr95); + cml95.setName(null); + cmlFuncs.add(cml95); + chars.add(bounds95Char); - incr68.setName(null); - incrFuncs.add(incr68); - cml68.setName(null); - cmlFuncs.add(cml68); - chars.add(bounds68Char); - - RectangleAnchor anchor = RectangleAnchor.TOP_RIGHT; -// RectangleAnchor anchor = RectangleAnchor.BOTTOM_LEFT; - - String title = seisReg.getTitleCaseAcronym(); - if (interfaceOnly) - title += " (interface)"; -// else -// title += " overall"; - - PlotSpec incrPlot = new PlotSpec(incrFuncs, chars, title, "Magnitude", "Incremental rate (1/yr)"); - incrPlot.setLegendInset(anchor); - - PlotSpec cmlPlot = new PlotSpec(cmlFuncs, chars, title, "Magnitude", "Cumulative rate (1/yr)"); - cmlPlot.setLegendInset(anchor); - - HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); - - gp.setRenderingOrder(DatasetRenderingOrder.REVERSE); - - String prefix = seisReg.name(); - if (interfaceOnly) - prefix += "_interface"; - - gp.drawGraphPanel(incrPlot, false, true, xRange, yRange); - -// PlotUtils.writePrintPlots(outputDir, prefix+"_incr_half", gp, halfWidth, halfHeight, 150, true, true, false); - PlotUtils.writePrintPlots(outputDir, prefix+"_incr", gp, fullWidth, fullHeight, 150, true, true, false); - - gp.drawGraphPanel(cmlPlot, false, true, xRange, yRange); - -// PlotUtils.writePrintPlots(outputDir, prefix+"_cml_half", gp, halfWidth, halfHeight, 150, true, true, false); - PlotUtils.writePrintPlots(outputDir, prefix+"_cml", gp, fullWidth, fullHeight, 150, true, true, false); - - if (!interfaceOnly) { - rateCSV.writeToFile(new File(outputDir, prefix+"_cml_rates.csv")); - riCSV.writeToFile(new File(outputDir, prefix+"_cml_ris.csv")); + incr68.setName(null); + incrFuncs.add(incr68); + cml68.setName(null); + cmlFuncs.add(cml68); + chars.add(bounds68Char); + + RectangleAnchor anchor = RectangleAnchor.TOP_RIGHT; +// RectangleAnchor anchor = RectangleAnchor.BOTTOM_LEFT; + + String title = seisReg.getTitleCaseAcronym(); + if (mapRegion) + title += " Map Region"; + if (interfaceOnly) + title += " (interface)"; +// else +// title += " overall"; + + PlotSpec incrPlot = new PlotSpec(incrFuncs, chars, title, "Magnitude", "Incremental rate (1/yr)"); + incrPlot.setLegendInset(anchor); + + PlotSpec cmlPlot = new PlotSpec(cmlFuncs, chars, title, "Magnitude", "Cumulative rate (1/yr)"); + cmlPlot.setLegendInset(anchor); + + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + + gp.setRenderingOrder(DatasetRenderingOrder.REVERSE); + + String prefix = seisReg.name(); + if (mapRegion) + prefix += "_map_region"; + if (interfaceOnly) + prefix += "_interface"; + + gp.drawGraphPanel(incrPlot, false, true, xRange, yRange); + +// PlotUtils.writePrintPlots(outputDir, prefix+"_incr_half", gp, halfWidth, halfHeight, 150, true, true, false); + PlotUtils.writePrintPlots(outputDir, prefix+"_incr", gp, fullWidth, fullHeight, 150, true, true, false); + + gp.drawGraphPanel(cmlPlot, false, true, xRange, yRange); + +// PlotUtils.writePrintPlots(outputDir, prefix+"_cml_half", gp, halfWidth, halfHeight, 150, true, true, false); + PlotUtils.writePrintPlots(outputDir, prefix+"_cml", gp, fullWidth, fullHeight, 150, true, true, false); + + if (!interfaceOnly) { + rateCSV.writeToFile(new File(outputDir, prefix+"_cml_rates.csv")); + riCSV.writeToFile(new File(outputDir, prefix+"_cml_ris.csv")); + } } } } } private static IncrementalMagFreqDist loadGridded(GridSourceList gridList, - TectonicRegionType trt, EvenlyDiscretizedFunc refMFD) { + TectonicRegionType trt, EvenlyDiscretizedFunc refMFD, Region reg) { SummedMagFreqDist mfdSum = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); + boolean regCheck = reg != null && !gridList.getGriddedRegion().equalsRegion(reg); for (int l=0; l myBranch2 = myBranch.copy(); + myBranch2.setValue(l, new NSHM27_InterfaceDeformationModels("Lower", "Lower", "Lower", 0d, fixedMin)); + incrFractiles[0] = calculateMFD(factory, rupSet, myBranch2, refMFD, assoc); + cmlFractiles[0] = incrFractiles[0].getCumRateDistWithOffset(); + + FixedFractileSampler fixedMax = new FixedFractileSampler(1d); + myBranch2.setValue(l, new NSHM27_InterfaceDeformationModels("Upper", "Upper", "Upper", 0d, fixedMax)); + incrFractiles[6] = calculateMFD(factory, rupSet, myBranch2, refMFD, assoc); + cmlFractiles[6] = incrFractiles[6].getCumRateDistWithOffset(); + } + UncertainBoundedIncrMagFreqDist incrExtrema = new UncertainBoundedIncrMagFreqDist( incrMedian, incrFractiles[0], incrFractiles[6], null); UncertainArbDiscFunc cmlExtrema = new UncertainArbDiscFunc(cmlMedian, cmlFractiles[0], cmlFractiles[6]); @@ -494,6 +509,9 @@ public static void main(String[] args) throws IOException { Collections.reverse(addChars); incrFuncs.addAll(indexOffset, addFuncs); chars.addAll(indexOffset, addChars); + // remove average + incrFuncs.remove(incrFuncs.size()-1); + chars.remove(chars.size()-1); incrPlot = new PlotSpec(incrFuncs, chars, level.getName(), "Magnitude", "Incremental Rate (1/yr)"); incrPlot.setLegendInset(true); gp.drawGraphPanel(incrPlot, false, true, magRange, rateRange); diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java index 9b95c9fd..9dbe03f1 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java @@ -12,6 +12,7 @@ import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.util.DataUtils; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.commons.util.cpt.CPT; import org.opensha.commons.util.modules.ModuleContainer; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; @@ -43,7 +44,7 @@ public static void main(String[] args) throws IOException { CSVFile csv = new CSVFile<>(true); csv.addLine("Adjustment", "Overall Moment Reduction Factor", "Section-Averaged Reduction Factor", - "Maximum Reduction Factor", "Median Reduction Factor"); + "Maximum Reduction Factor", "Median Reduction Factor", "Average Slip Rate (mm/yr)", "Maximum Slip Rate (mm/yr)"); branch.setValue(NSHM27_InterfaceObsSeisDMAdjustment.NONE); @@ -55,11 +56,15 @@ public static void main(String[] args) throws IOException { double fullMoment = fullSlips.calcTotalMomentRate(); for (NSHM27_InterfaceObsSeisDMAdjustment adj : NSHM27_InterfaceObsSeisDMAdjustment.values()) { - if (adj == NSHM27_InterfaceObsSeisDMAdjustment.NONE) - continue; - branch.setValue(adj); - rs = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); - SectSlipRates slips = rs.requireModule(SectSlipRates.class); + SectSlipRates slips; + if (adj == NSHM27_InterfaceObsSeisDMAdjustment.NONE) { + slips = fullSlips; + } else { + branch.setValue(adj); + rs = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); + slips = rs.requireModule(SectSlipRates.class); + } + MinMaxAveTracker slipTrack = new MinMaxAveTracker(); double branchMoment = slips.calcTotalMomentRate(); @@ -68,6 +73,7 @@ public static void main(String[] args) throws IOException { double fullSlip = fullSlips.getSlipRate(s); double redSlip = slips.getSlipRate(s); factors[s] = (fullSlip - redSlip)/fullSlip; + slipTrack.addValue(slips.getSlipRate(s)*1e3); } mapMaker.plotSectScalars(factors, redCPT, "Slip-deficit rate reduction factor"); @@ -79,7 +85,9 @@ public static void main(String[] args) throws IOException { twoDF.format(overall), twoDF.format(StatUtils.mean(factors)), twoDF.format(StatUtils.max(factors)), - twoDF.format(DataUtils.median(factors))); + twoDF.format(DataUtils.median(factors)), + twoDF.format(slipTrack.getAverage()), + twoDF.format(slipTrack.getMax())); } csv.writeToFile(new File(outputDir, seisReg.name()+"_factors.csv")); diff --git a/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java b/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java index b8943ce4..08f5fb0d 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java @@ -13,8 +13,11 @@ import java.util.Map; import java.util.Random; +import org.apache.commons.math3.stat.StatUtils; import org.apache.commons.math3.util.Precision; import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.ui.RectangleAnchor; +import org.jfree.chart.ui.RectangleInsets; import org.jfree.chart.ui.TextAnchor; import org.jfree.data.Range; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; @@ -23,11 +26,17 @@ import org.opensha.commons.data.function.EvenlyDiscretizedFunc; import org.opensha.commons.data.function.HistogramFunction; import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.data.xyz.EvenlyDiscrXYZ_DataSet; import org.opensha.commons.gui.plot.HeadlessGraphPanel; import org.opensha.commons.gui.plot.PlotCurveCharacterstics; import org.opensha.commons.gui.plot.PlotLineType; import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotSymbol; import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.gui.plot.jfreechart.xyzPlot.XYZPlotSpec; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; +import org.opensha.commons.util.cpt.CPT; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; import org.opensha.sha.magdist.GutenbergRichterMagFreqDist; import org.opensha.sha.util.TectonicRegionType; @@ -70,6 +79,12 @@ public static void main(String[] args) throws IOException { PlotLineType.DOTTED }; + PlotSymbol[] symbolTypes = { + PlotSymbol.FILLED_SQUARE, + PlotSymbol.FILLED_CIRCLE, + PlotSymbol.FILLED_INV_TRIANGLE + }; + RateType[] types = { RateType.M1, RateType.M1_TO_MMAX, @@ -100,8 +115,12 @@ public static void main(String[] args) throws IOException { Double mMax = null; Map typeMagFuncs = new HashMap<>(); EvenlyDiscretizedFunc overallMean = null; - for (RateType type : types) { - SeismicityRateModel rateModel = NSHM27_SeisRateModelBranch.loadRateModel(seisReg, classification, trt, type); + SeismicityRateModel[] rateModels = new SeismicityRateModel[types.length]; + for (int t=0; t"+oDF.format(m1)+" Rate", "Fraction of "+samples.size()+" samples"); + xyzPlot.setLegendInset(RectangleAnchor.TOP_LEFT); + xyzPlot.setIncludeZlabelInLegend(false); + + double ratePlotMax = Math.min(rateVsB.getMaxY()-0.5*rateDelta, StatUtils.percentile(rates, 99.99)); + double ratePlotMin = Math.max(rateVsB.getMinY()+0.5*rateDelta, StatUtils.percentile(rates, 0.01)); + double bPlotMax = Math.min(rateVsB.getMaxX()-0.5*bDelta, StatUtils.percentile(bValues, 99.99)); + double bPlotMin = Math.max(rateVsB.getMinX()+0.5*bDelta, StatUtils.percentile(bValues, 0.01)); + + gp.drawGraphPanel(xyzPlot, false, false, new Range(bPlotMin, bPlotMax), new Range(ratePlotMin, ratePlotMax)); +// new Range(rateVsB.getMinX()-0.5*rateVsB.getGridSpacingX(), rateVsB.getMaxX()+0.5*rateVsB.getGridSpacingX()), +// new Range(rateVsB.getMinY()-0.5*rateVsB.getGridSpacingY(), rateVsB.getMaxY()+0.5*rateVsB.getGridSpacingY())); + + PlotUtils.writePrintPlots(outputDir, prefix+"_rate_vs_b", gp, + PlotUtils.DEFAULT_USABLE_PAGE_WIDTH*2d/3d, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH*2d/3d, + 150, true, true, false); } } } } } + private static String typeName(RateType type) { + String name = type.toString(); + return name.replace("Branches", "branches"); + } + private static EvenlyDiscretizedFunc cmlMFD(RateRecord record, EvenlyDiscretizedFunc refMFD) { if (record.type == RateType.EXACT) return ((Exact)record).cumulativeDist; From 231f66d413ae44b8f6d3a92d78a33dbf3f6ff989 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 27 Jul 2026 08:57:28 -0700 Subject: [PATCH 41/71] fixes for rate model sampling on b-value plot --- .../InterfaceLogicTreeMFDExploration.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java index f7dfa0ec..2211522a 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java @@ -89,7 +89,8 @@ public static void main(String[] args) throws IOException { LogicTreeBranch sampledBranch = NSHM27_LogicTree.buildDefault(seisReg, trt, true); // int samples = 50; // int samples = 500; - int samples = 1000; +// int samples = 1000; + int samples = 10000; // boolean skipSampled = true; boolean skipSampled = false; @@ -121,6 +122,9 @@ public static void main(String[] args) throws IOException { if (classification.getNodeWeight() > 0d) classificationChoices.add(classification, classification.getNodeWeight()); List classificationSamples = classificationChoices.sampleEvenly(samples, new Random(12345l)); + LogicTreeLevel rateLevel = sampledBranch.getLevel(sampledBranch.getLevelTypeIndex(NSHM27_SeisRateModel.class)); + ((RandomLevel)rateLevel).build(12345l, samples, SamplingMethod.LATIN_HYPERCUBE); + List rateModelSamples = rateLevel.getNodes(); NSHM27_InvConfigFactory factory = new NSHM27_InvConfigFactory(); FaultSystemRupSet rupSet = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); @@ -234,17 +238,22 @@ public static void main(String[] args) throws IOException { System.out.println("Skipping sampling this time"); continue; } + boolean doRateSamples = SectionSupraSeisBValues.class.isAssignableFrom(sampledLevel.getType()); List> levels = new ArrayList<>(); List values = new ArrayList<>(); for (int i=0; i myBranch = new LogicTreeBranch<>(levels, values); ((RandomLevel)sampledLevel).build(12345l, samples, SamplingMethod.LATIN_HYPERCUBE); Preconditions.checkState(sampledLevel.getNodes().size() == samples); @@ -256,10 +265,14 @@ public static void main(String[] args) throws IOException { for (int n=0; n{ LogicTreeBranch myBranch2 = myBranch.copy(); myBranch2.setValue(classNode); myBranch2.setValue(l, node); + if (doRateSamples) + myBranch2.setValue(rateNode); try { return calculateMFD(factory, rupSet, myBranch2, refMFD, assoc); } catch (IOException e) { @@ -526,6 +539,7 @@ public static void main(String[] args) throws IOException { private static IncrementalMagFreqDist calculateMFD(NSHM27_InvConfigFactory factory, FaultSystemRupSet rupSet, LogicTreeBranch branch, EvenlyDiscretizedFunc refMFD, FaultGridAssociations assoc) throws IOException { + System.out.println("Calculating MFD for: "+branch); ClusterRuptures cRups = rupSet.requireModule(ClusterRuptures.class); rupSet = factory.updateRuptureSetForBranch(rupSet, branch); BinaryRuptureProbabilityCalc exclusionModel = NSHM27_InvConfigFactory.getExclusionModel(rupSet, branch, cRups); From a568180b8f040e19b30b962379bce423bdd85298 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 27 Jul 2026 16:01:33 -0700 Subject: [PATCH 42/71] comp/diagnostics --- .../ComparisonCalcScriptWriter.java | 97 +++ .../hazardValidation/ComparisonPageGen.java | 634 ++++++++++++++++++ .../GriddedParticipationComparison.java | 109 +++ .../hazardValidation/SiteDataDiagnostics.java | 152 +++++ 4 files changed, 992 insertions(+) create mode 100644 src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java create mode 100644 src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java create mode 100644 src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java create mode 100644 src/main/java/scratch/kevin/nshm23/hazardValidation/SiteDataDiagnostics.java diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java new file mode 100644 index 00000000..b87e53d4 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java @@ -0,0 +1,97 @@ +package scratch.kevin.nshm23.hazardValidation; + +import java.io.File; +import java.io.IOException; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +import org.opensha.commons.data.siteData.CONUS_Versions; +import org.opensha.commons.data.siteData.SiteDataValueListList; +import org.opensha.commons.data.siteData.impl.CONUS_SiteDataProvider; +import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.Region; +import org.opensha.commons.param.Parameter; +import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc; +import org.opensha.sha.earthquake.param.IncludeBackgroundOption; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; +import org.opensha.sha.faultSurface.utils.ptSrcCorr.PointSourceDistanceCorrections; +import org.opensha.sha.imr.AttenRelRef; +import org.opensha.sha.util.TectonicRegionType; + +import gov.usgs.earthquake.nshmp.erf.mpj.HPCConfig; +import gov.usgs.earthquake.nshmp.erf.mpj.HPCConfig.HPCSite; +import gov.usgs.earthquake.nshmp.erf.mpj.HazardConfig; +import gov.usgs.earthquake.nshmp.erf.mpj.MPJ_BranchAveragedHazardScriptWriter; +import gov.usgs.earthquake.nshmp.erf.mpj.MPJ_BranchAveragedHazardScriptWriter.SupersamplingMode; +import gov.usgs.earthquake.nshmp.erf.mpj.RunConfig; + +public class ComparisonCalcScriptWriter { + + public static void main(String[] args) throws IOException { + // start with WUS-only + String regToken = "WUS"; + Region reg = NSHM23_RegionLoader.loadFullConterminousWUS(); + double spacing = 0.1; + String linkFromDir = "2024_02_02-nshm23_branches-WUS_FM_v3"; + String solFileName = "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"; + + File localMainDir = new File("/home/kevin/OpenSHA/fss_inversions"); + + GriddedRegion gridReg = new GriddedRegion(reg, spacing, GriddedRegion.ANCHOR_0_0); + // add site data + SiteDataValueListList siteData = new SiteDataValueListList(); + CONUS_SiteDataProvider data10 = new CONUS_SiteDataProvider( + CONUS_SiteDataProvider.TYPE_DEPTH_TO_1_0, CONUS_Versions.NSHM23); + CONUS_SiteDataProvider data25 = new CONUS_SiteDataProvider( + CONUS_SiteDataProvider.TYPE_DEPTH_TO_2_5, CONUS_Versions.NSHM23); + siteData.add(data10.getAnnotatedValues(gridReg.getNodeList())); + siteData.add(data25.getAnnotatedValues(gridReg.getNodeList())); + gridReg.setSiteData(siteData); + + // TODO add stable continental when ready + String gmpeToken = "active_only"; + Map gmpes = new EnumMap<>(TectonicRegionType.class); + gmpes.put(TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_ACTIVE); + + SolHazardMapCalc.loadSites(gridReg, gmpes); + + HPCSite hpcSite = HPCSite.USC_CARC_FMPJ; + File remoteMainDir = new File("/project2/scec_608/kmilner/fss_inversions"); + + HPCConfig hpc = HPCConfig.builder(hpcSite) + .localMainDir(localMainDir) + .remoteMainDir(remoteMainDir) + .build(); + + HazardConfig hazard = HazardConfig.builder() + .region(gridReg) + .sigmaTruncation(3d) + .gmpes(gmpes.values()) + .vs30(760d) + .build(); + + + RunConfig run = RunConfig.builder() + .baseName("nshm23") + .addNameToken("hazard_validation") + .addNameToken(regToken) + .addNameToken(gmpeToken) + .build(); + + MPJ_BranchAveragedHazardScriptWriter.Request request = MPJ_BranchAveragedHazardScriptWriter.Request.builder() + .distanceCorrection(PointSourceDistanceCorrections.NSHM_2013) + .backgroundOptions(IncludeBackgroundOption.values()) + .run(run) + .linkFromDirectoryName(linkFromDir) + .solutionFileName(solFileName) + .noMFDs(true) + .supersamplingMode(SupersamplingMode.FULL) + .hazard(hazard) + .hpc(hpc) + .build(); + + new MPJ_BranchAveragedHazardScriptWriter().writeScripts(request); + } + +} diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java new file mode 100644 index 00000000..316417fe --- /dev/null +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java @@ -0,0 +1,634 @@ +package scratch.kevin.nshm23.hazardValidation; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; + +import org.apache.commons.math3.stat.StatUtils; +import org.jfree.data.Range; +import org.opensha.commons.data.CSVFile; +import org.opensha.commons.data.function.DiscretizedFunc; +import org.opensha.commons.data.function.LightFixedXFunc; +import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.data.siteData.SiteDataValue; +import org.opensha.commons.data.siteData.SiteDataValueListList; +import org.opensha.commons.data.xyz.GriddedGeoDataSet; +import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.Region; +import org.opensha.commons.geo.json.Feature; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.MarkdownUtils; +import org.opensha.commons.util.MarkdownUtils.TableBuilder; +import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; +import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc; +import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc.ReturnPeriods; +import org.opensha.sha.earthquake.param.IncludeBackgroundOption; +import org.opensha.sha.util.TectonicRegionType; + +import com.google.common.base.Preconditions; +import com.google.common.primitives.Doubles; + +import net.mahdilamb.colormap.Colors; + +public class ComparisonPageGen { + + private static enum CompType { + TOTAL, + CRUSTAL_FAULTS, + CRUSTAL_GRIDDED, + CRUSTAL, + INTERFACE, + SLAB + }; + + public static void main(String[] args) throws IOException { +// String imtName = "PGA"; +// String imtDir = "PGA"; +// double period = 0d; + + String imtName = "1s SA"; + String imtDir = "SA1P0"; + double period = 1d; + +// ReturnPeriods[] rps = ReturnPeriods.values(); + ReturnPeriods[] rps = { ReturnPeriods.TWO_IN_50, ReturnPeriods.TEN_IN_50 }; + + EnumSet trts = EnumSet.of( + TectonicRegionType.ACTIVE_SHALLOW + , TectonicRegionType.STABLE_SHALLOW +// , TectonicRegionType.SUBDUCTION_INTERFACE +// , TectonicRegionType.SUBDUCTION_SLAB + ); + + int vs30 = 760; + + String nameMine = "OpenSHA"; + String nameTheirs = "NSHMP-Haz"; + String suffixMine = "opensha"; + String suffixTheirs = "ext"; + + File inputDir = new File("/home/kevin/OpenSHA/fss_inversions/2026_07_27-nshm23-hazard_validation-WUS-active_only"); + EnumSet bgOps = EnumSet.allOf(IncludeBackgroundOption.class); + File inputSolFile = new File("/home/kevin/OpenSHA/fss_inversions/2024_02_02-nshm23_branches-WUS_FM_v3/" + + "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"); + + File compDirActiveSub = new File("/home/kevin/OpenSHA/nshm23/nshmp-haz-models/ext_hazard_calcs/" + + "conus_2023.R2-no_gmm_region-by_source-active_subduction-vs760-0p1-20260515-95ae7e82fbb85d"); + File compDirStable = new File("/home/kevin/OpenSHA/nshm23/nshmp-haz-models/ext_hazard_calcs/" + + "conus_2023.R2-no_gmm_region-by_source-stable-vs760-0p1-20260515-ea28700aef6c6f"); + File outputDir = new File(inputDir, "nshmp_haz_comparisons_"+imtDir); + double sourceSpacing = 0.1; + + File sourcesDirActiveSub = new File(compDirActiveSub, "vs30-"+vs30+"/"+imtDir+"/source"); + File sourcesDirStable = new File(compDirStable, "vs30-"+vs30+"/"+imtDir+"/source"); + boolean convertToProb = true; + + System.out.println("Output dir: "+outputDir.getAbsolutePath()); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); + File resourcesDir = new File(outputDir, "resources"); + Preconditions.checkState(resourcesDir.exists() || resourcesDir.mkdir()); + + GriddedRegion mapReg = GriddedRegion.fromFeature(Feature.read(new File(inputDir, "gridded_region.geojson"))); + SiteDataValueListList siteData = mapReg.getSiteData(); + + boolean plotTraces = false; + Region plotReg = mapReg; + +// plotReg = new Region(new Location(37.5, -122.5), new Location(38.5, -121.5)); + + plotReg = new Region(new Location(40, -122), new Location(41, -120)); + plotTraces = true; + + Map myCurvesMap = new EnumMap<>(IncludeBackgroundOption.class); + for (IncludeBackgroundOption bgOp : bgOps) + myCurvesMap.put(bgOp, loadRegularCurves(inputDir, bgOp, mapReg, period)); + + Map extCurvesMap = new EnumMap<>(IncludeBackgroundOption.class); + boolean loadFault = bgOps.contains(IncludeBackgroundOption.INCLUDE) || bgOps.contains(IncludeBackgroundOption.EXCLUDE); + boolean loadGrid = bgOps.contains(IncludeBackgroundOption.INCLUDE) || bgOps.contains(IncludeBackgroundOption.ONLY); + + for (TectonicRegionType trt : trts) { + File sourceDir = trt == TectonicRegionType.STABLE_SHALLOW ? sourcesDirStable : sourcesDirActiveSub; + if (trt == TectonicRegionType.ACTIVE_SHALLOW || trt == TectonicRegionType.STABLE_SHALLOW) { + if (loadFault) { + DiscretizedFunc[] curves = loadExtCurves(new File(sourceDir, "FAULT/curves.csv"), mapReg); + addTo(extCurvesMap, curves, IncludeBackgroundOption.INCLUDE, IncludeBackgroundOption.EXCLUDE); + if (trt == TectonicRegionType.STABLE_SHALLOW) { + // "fault cluster" is interface in the active_subduction dir, but crustal for stable + curves = loadExtCurves(new File(sourceDir, "FAULT_CLUSTER/curves.csv"), mapReg); + addTo(extCurvesMap, curves, IncludeBackgroundOption.INCLUDE, IncludeBackgroundOption.EXCLUDE); + } + curves = loadExtCurves(new File(sourceDir, "FAULT_SYSTEM/curves.csv"), mapReg); + addTo(extCurvesMap, curves, IncludeBackgroundOption.INCLUDE, IncludeBackgroundOption.EXCLUDE); + } + if (loadGrid) { + DiscretizedFunc[] curves = loadExtCurves(new File(sourceDir, "GRID/curves.csv"), mapReg); + addTo(extCurvesMap, curves, IncludeBackgroundOption.INCLUDE, IncludeBackgroundOption.ONLY); + // TODO: is zone grid or fault? + curves = loadExtCurves(new File(sourceDir, "ZONE/curves.csv"), mapReg); + addTo(extCurvesMap, curves, IncludeBackgroundOption.INCLUDE, IncludeBackgroundOption.ONLY); + } + } else if (trt == TectonicRegionType.SUBDUCTION_INTERFACE) { + if (loadFault) { + DiscretizedFunc[] curves = loadExtCurves(new File(sourceDir, "INTERFACE/curves.csv"), mapReg); + addTo(extCurvesMap, curves, IncludeBackgroundOption.INCLUDE, IncludeBackgroundOption.EXCLUDE); + // "fault cluster" is interface in the active_subduction dir, but crustal for stable + curves = loadExtCurves(new File(sourceDir, "FAULT_CLUSTER/curves.csv"), mapReg); + addTo(extCurvesMap, curves, IncludeBackgroundOption.INCLUDE, IncludeBackgroundOption.EXCLUDE); + } + } else if (trt == TectonicRegionType.SUBDUCTION_SLAB) { + if (loadGrid) { + DiscretizedFunc[] curves = loadExtCurves(new File(sourceDir, "SLAB/curves.csv"), mapReg); + addTo(extCurvesMap, curves, IncludeBackgroundOption.INCLUDE, IncludeBackgroundOption.ONLY); + } + } + } + + // convert to probabilities + if (convertToProb) { + for (IncludeBackgroundOption bgOp : List.copyOf(extCurvesMap.keySet())) + extCurvesMap.put(bgOp, ratesToProbs(extCurvesMap.get(bgOp))); + } + + GeographicMapMaker mapMaker = new GeographicMapMaker(plotReg); + if (plotTraces) { + mapMaker.setFaultSections(FaultSystemRupSet.load(inputSolFile).getFaultSectionDataList()); + mapMaker.setSectOutlineChar(null); + } +// mapMaker.setDefaultPlotWidth(1000); + + Color transparent = new Color(255, 255, 255, 0); + + CPT hazCPT = GMT_CPT_Files.RAINBOW_UNIFORM.instance().rescale(-3, 1); + hazCPT.setLog10(true); + hazCPT.setNanColor(transparent); + +// CPT pDiffCPT = MethodsAndIngredientsHazChangeFigures.getCenterMaskedCPT(GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance(), 10d, 50d); + CPT pDiffCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-10d, 10d); + pDiffCPT.setNanColor(transparent); + + double diffScale; + if (period == 0d) + diffScale = 0.1; + else + diffScale = 0.05; + CPT diffCPT = GMT_CPT_Files.DIVERGING_BAM_UNIFORM.instance().reverse().rescale(-diffScale, diffScale); + diffCPT.setNanColor(transparent); + + List lines = new ArrayList<>(); + + lines.add("# Hazard Comparisons, "+nameMine+" vs "+nameTheirs); + lines.add(""); + + lines.add("This page compares "+nameMine+" and "+nameTheirs+" hazard maps."); + lines.add(""); + + IncludeBackgroundOption[] bgOrder = { + IncludeBackgroundOption.INCLUDE, + IncludeBackgroundOption.EXCLUDE, + IncludeBackgroundOption.ONLY + }; + + int tocIndex = lines.size(); + String topLink = "*[(top)](#table-of-contents)*"; + + for (IncludeBackgroundOption bgOp : bgOrder) { + if (!bgOps.contains(bgOp)) + continue; + DiscretizedFunc[] myCurves = myCurvesMap.get(bgOp); + DiscretizedFunc[] extCurves = extCurvesMap.get(bgOp); + + String mapLabelAdd; + switch (bgOp) { + case INCLUDE: + lines.add("## Total hazard (fault+gridded)"); + mapLabelAdd = ""; + break; + case EXCLUDE: + lines.add("## On-fault hazard"); + mapLabelAdd = "On-fault "; + break; + case ONLY: + lines.add("## Gridded hazard"); + mapLabelAdd = "Gridded "; + break; + default: + throw new IllegalArgumentException("Unexpected value: " + bgOp); + } + lines.add(topLink); lines.add(""); + + for (ReturnPeriods rp : rps) { + GriddedGeoDataSet myMap = curvestoMap(myCurves, mapReg, rp); + GriddedGeoDataSet extMap = curvestoMap(extCurves, mapReg, rp); + + lines.add("### "+rp.label); + lines.add(topLink); lines.add(""); + + String hazLabel = imtName+", "+rp.label; + String prefix = bgOp.name()+"_"+rp.name(); + + TableBuilder table = MarkdownUtils.tableBuilder(); + + table.addLine(nameMine, nameTheirs); + + table.initNewLine(); + + mapMaker.plotXYZData(myMap, hazCPT, mapLabelAdd+nameMine+", "+hazLabel+" (g)"); + mapMaker.plot(resourcesDir, prefix+"_"+suffixMine, " "); + table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_"+suffixMine+".png)"); + mapMaker.plotXYZData(extMap, hazCPT, mapLabelAdd+nameTheirs+", "+hazLabel+" (g)"); + mapMaker.plot(resourcesDir, prefix+"_"+suffixTheirs, " "); + table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_"+suffixTheirs+".png)"); + + table.finalizeLine(); + + table.addLine(MarkdownUtils.boldCentered("Ratio"), MarkdownUtils.boldCentered("Difference")); + + GriddedGeoDataSet pDiff = mapPDiff(myMap, extMap); + GriddedGeoDataSet diff = mapDiff(myMap, extMap); + + table.initNewLine(); + + mapMaker.plotXYZData(pDiff, pDiffCPT, mapLabelAdd+nameMine+" vs "+nameTheirs+", % Change, "+hazLabel); + mapMaker.plot(resourcesDir, prefix+"_pDiff", " "); + table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_pDiff.png)"); + mapMaker.plotXYZData(diff, diffCPT, mapLabelAdd+nameMine+" - "+nameTheirs+", "+hazLabel+" (g)"); + mapMaker.plot(resourcesDir, prefix+"_diff", " "); + table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_diff.png)"); + + table.finalizeLine(); + table.addLine(diffStr(pDiff, true), diffStr(diff, false)); + + lines.addAll(table.build()); + lines.add(""); + + double maxDiff = Double.NEGATIVE_INFINITY; + double minDiff = Double.POSITIVE_INFINITY; + int maxDiffIndex = -1; + int minDiffIndex = -1; + for (int i=0; i maxDiff) { + maxDiff = v; + maxDiffIndex = i; + } + if (v < minDiff) { + minDiff = v; + minDiffIndex = i; + } + } + } + + table = MarkdownUtils.tableBuilder(); + + table.addLine("Min difference", "Max difference"); + + table.initNewLine(); + for (boolean min : new boolean[] {true,false}) { + int index = min ? minDiffIndex : maxDiffIndex; + Preconditions.checkState(index >= 0); + DiscretizedFunc myCurve = myCurves[index]; + DiscretizedFunc extCurve = extCurves[index]; + Location loc = mapReg.getLocation(index); + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + myCurve.setName(nameMine); + extCurve.setName(nameTheirs); + + funcs.add(extCurve); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Colors.tab_orange)); + + funcs.add(myCurve); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Colors.tab_blue)); + + PlotSpec plot = new PlotSpec(funcs, chars, (float)loc.lat+", "+(float)loc.lon, hazLabel, "Annual Probability of Exceedance"); + plot.setLegendInset(true); + + HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); + + gp.drawGraphPanel(plot, true, true, new Range(1e-3, 1e1), new Range(1e-6, 1e0)); + + String curvePrefix = min ? prefix+"_curve_min" : prefix+"_curve_max"; + + PlotUtils.writePlots(resourcesDir, curvePrefix, gp, 800, 800, true, true, false); + + table.addColumn("![Curve]("+resourcesDir.getName()+"/"+curvePrefix+".png)"); + } + table.finalizeLine().initNewLine(); + for (boolean min : new boolean[] {true,false}) { + int index = min ? minDiffIndex : maxDiffIndex; + Location loc = mapReg.getLocation(index); + String str = "Site: "+(float)loc.getLatitude()+", "+(float)loc.getLongitude(); + if (siteData != null) { + for (SiteDataValue data : siteData.getDataList(index)) { + str += "

"+data.getDataType()+": "; + if (data.getValue() != null && data.getValue() instanceof Number) + str += ((Number)data.getValue()).floatValue(); + else + str += data.getValue(); + } + } + table.addColumn(str); + } + table.finalizeLine(); + + lines.addAll(table.build()); + lines.add(""); + } + } + + // add TOC + lines.addAll(tocIndex, MarkdownUtils.buildTOC(lines, 2)); + lines.add(tocIndex, "## Table Of Contents"); + + // write markdown + MarkdownUtils.writeReadmeAndHTML(lines, outputDir); + } + + private static File getHazardDir(File runDir, IncludeBackgroundOption bgOp, + GriddedRegion gridReg) { + String hazardPrefix = "hazard_"+(float)gridReg.getSpacing()+"deg"; + hazardPrefix += "_grid_seis_"; + hazardPrefix += bgOp.name(); + File resultsDir = new File(runDir, "results"); + return new File(resultsDir, hazardPrefix); + } + + private static DiscretizedFunc[] loadRegularCurves(File runDir, IncludeBackgroundOption bgOp, + GriddedRegion gridReg, double period) throws IOException { + File subDir = getHazardDir(runDir, bgOp, gridReg); + Preconditions.checkState(subDir.exists(), "Doesn't exist: %s", subDir.getAbsolutePath()); + + File curvesFile = new File(subDir, SolHazardMapCalc.getCSV_FileName("curves", period)); + if (!curvesFile.exists()) + curvesFile = new File(curvesFile.getAbsolutePath()+".gz"); + Preconditions.checkState(curvesFile.exists(), "Doesn't exist: %s", curvesFile.getAbsolutePath()); + + return SolHazardMapCalc.loadCurvesCSV(CSVFile.readFile(curvesFile, true), gridReg); + } + + private static DiscretizedFunc[] loadExtCurves(File csvFile, GriddedRegion gridReg) throws IOException { + System.out.println("Loading external curves from "+csvFile.getAbsolutePath()); + CSVFile csv = CSVFile.readFile(csvFile, true); + + double[] xVals = new double[csv.getNumCols()-2]; + for (int i=0; i curve.getMaxX()) + interpY[i] = 0d; + else + interpY[i] = curve.getInterpolatedY_inLogXDomain(x); + } + ret[n] = new LightFixedXFunc(xVals, interpY); + } + return ret; + } + + private static void addTo(Map map, DiscretizedFunc[] curves, + IncludeBackgroundOption... bgOps) { + for (IncludeBackgroundOption bgOp : bgOps) + map.put(bgOp, addTo(map.get(bgOp), curves)); + } + + private static DiscretizedFunc[] addTo(DiscretizedFunc[] current, DiscretizedFunc[]... allCurves) { +// System.out.println("addTo; current: "+(current == null ? "null" : "non-null")); +// System.out.println("allCurves.length: "+allCurves.length); +// for (int i=0; i 1) { + DiscretizedFunc[] comb = add(allCurves); + return add(current, comb); + } else { + Preconditions.checkState(allCurves.length == 1); + return add(current, allCurves[0]); + } + } + + private static DiscretizedFunc[] add(DiscretizedFunc[]... allCurves) { + DiscretizedFunc[] ret = new DiscretizedFunc[allCurves[0].length]; + + double[] xVals = new double[allCurves[0][0].size()]; + for (int i=0; i curve.getMaxY()) + val = 0d; + else if (rp.oneYearProb < curve.getMinY()) + // saturated + val = curve.getMaxX(); + else + val = curve.getFirstInterpolatedX_inLogXLogYDomain(rp.oneYearProb); + ret.set(i, val); + } + + return ret; + } + + private static GriddedGeoDataSet zerosToNaNs(GriddedGeoDataSet xyz) { + xyz = xyz.copy(); + for (int i=0; i allConsidered = new ArrayList<>(); + + for (int i=0; iavg="+df.format(avg)+"; avgAbs="+df.format(avgAbs)+"; median="+df.format(median)+"; "+numNan+" NaN"; + } + +} diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java new file mode 100644 index 00000000..0c7dc3a6 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java @@ -0,0 +1,109 @@ +package scratch.kevin.nshm23.hazardValidation; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.BitSet; + +import org.opensha.commons.data.xyz.GriddedGeoDataSet; +import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.Region; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; +import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; +import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; +import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList; +import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupture; +import org.opensha.sha.earthquake.param.IncludeBackgroundOption; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; +import org.opensha.sha.faultSurface.FaultSection; +import org.opensha.sha.util.TectonicRegionType; + +import gov.usgs.earthquake.nshmp.model.HazardModel; +import gov.usgs.earthquake.nshmp.model.SourceTree; + +public class GriddedParticipationComparison { + + public static void main(String[] args) throws IOException { + File inputSolFile = new File("/home/kevin/OpenSHA/fss_inversions/2024_02_02-nshm23_branches-WUS_FM_v3/" + + "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"); + File modelDir = new File("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.1.3"); + Region reg = NSHM23_RegionLoader.loadFullConterminousWUS(); + + TectonicRegionType trt = TectonicRegionType.ACTIVE_SHALLOW; + IncludeBackgroundOption bgOp = IncludeBackgroundOption.EXCLUDE; + double[] minMags = {0d, 6d, 7d}; + + File outputDir = new File("/data/kevin/nshm23/nshmp-haz-models/gridded_partic_debug"); + + GriddedRegion gridReg = new GriddedRegion(reg, 0.1, GriddedRegion.ANCHOR_0_0); + + FaultSystemSolution sol = FaultSystemSolution.load(inputSolFile); + // we want direct mappings + sol.getRupSet().removeModuleInstances(FaultGridAssociations.class); + + HazardModel model = HazardModel.load(modelDir.toPath()); + + GriddedGeoDataSet[] fssXYZs = new GriddedGeoDataSet[minMags.length]; + GriddedGeoDataSet[] nhXYZs = new GriddedGeoDataSet[minMags.length]; + for (int m=0; m= 0) + sectBitSets[s].set(node); + } + } + + for (int r=0; r= (float)minMags[m]) + for (int i = rupBits.nextSetBit(0); i >= 0; i = rupBits.nextSetBit(i + 1)) + fssXYZs[m].add(i, rate); + } + } + if (bgOp == IncludeBackgroundOption.INCLUDE || bgOp == IncludeBackgroundOption.ONLY) { + GridSourceList gridList = sol.requireModule(GridSourceList.class); + + for (int l=0; l= 0) { + for (GriddedRupture rup : gridList.getRuptures(trt, l)) { + for (int m=0; m= (float)minMags[m]) + fssXYZs[m].add(locIndex, rup.rate); + } + } + } + } + } + + // do NSHMP-haz + for (SourceTree tree : model) { + // TODO + } + } + + + +} diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/SiteDataDiagnostics.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/SiteDataDiagnostics.java new file mode 100644 index 00000000..bd08f95d --- /dev/null +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/SiteDataDiagnostics.java @@ -0,0 +1,152 @@ +package scratch.kevin.nshm23.hazardValidation; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.OptionalDouble; + +import org.apache.commons.math3.util.Precision; +import org.opensha.commons.data.siteData.CONUS_Downloader; +import org.opensha.commons.data.siteData.CONUS_Versions; +import org.opensha.commons.data.siteData.SiteData; +import org.opensha.commons.data.siteData.impl.CONUS_SiteDataProvider; +import org.opensha.commons.data.xyz.GriddedGeoDataSet; +import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.Region; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader.AnalysisRegions; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader.LocalRegions; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader.NSHM23_BaseRegion; + +import com.google.common.base.Preconditions; + +import gov.usgs.earthquake.nshmp.model.HazardModel; +import gov.usgs.earthquake.nshmp.model.SiteData.Values; + +public class SiteDataDiagnostics { + + public static void main(String[] args) throws IOException { + String[] types = { + SiteData.TYPE_DEPTH_TO_1_0, + SiteData.TYPE_DEPTH_TO_2_5, + SiteData.TYPE_SEDIMENT_THICKNESS + }; + String[] typePrefixes = { + "z10", + "z25", + "zSed" + }; + double[] cptMaxs = { + 1d, + 5d, + 10d + }; + + NSHM23_BaseRegion[] regions = { + AnalysisRegions.CONUS_EAST, + AnalysisRegions.CONUS_IMW, + AnalysisRegions.CONUS_U3_RELM, + LocalRegions.CONUS_LA_BASIN, + LocalRegions.CONUS_SF_BAY + + }; + + File outputDir = new File("/home/kevin/OpenSHA/nshm23/nshmp-haz-models/site_data_debug"); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); + + HazardModel model = HazardModel.load(Path.of("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.2.0")); + gov.usgs.earthquake.nshmp.model.SiteData modelSiteData = model.siteData(); + + for (int t=0; t plotRegList = new ArrayList<>(); + List outlineChars = new ArrayList<>(); + for (Region plotReg : data.getRegions()) { + plotRegList.add(plotReg); + outlineChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, Color.BLACK)); + } + for (Region plotReg : data.getRegions()) { + plotRegList.add(plotReg); + outlineChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 2f, Color.WHITE)); + } + mapMaker.plotInsetRegions(plotRegList, outlineChars, null, 0d); + + GriddedRegion dataReg = new GriddedRegion(reg, 0.1, GriddedRegion.ANCHOR_0_0); + GriddedGeoDataSet xyz = new GriddedGeoDataSet(dataReg); + ArrayList values = data.getValues(dataReg.getNodeList()); + boolean anyGood = false; + for (int i=0; i 0d; + xyz.set(i, value); + } + } + if (!anyGood) + continue; + + mapMaker.plotXYZData(xyz, cpt, type); + + mapMaker.plot(outputDir, typePrefix+"_"+analReg.name()+"_opensha", "OpenSHA"); + + // load NSHMP-haz + GriddedGeoDataSet modelXYZ = new GriddedGeoDataSet(dataReg); + for (int i=0; i Date: Tue, 28 Jul 2026 09:15:27 -0700 Subject: [PATCH 43/71] comparison updates --- .../nshm23/RevisedGridProvUpdate2026.java | 44 +- .../hazardValidation/ComparisonPageGen.java | 459 +++++++++++++++++- .../GriddedParticipationComparison.java | 215 +++++++- 3 files changed, 679 insertions(+), 39 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java b/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java index d14d987c..4c1ce54b 100644 --- a/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java +++ b/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java @@ -10,10 +10,13 @@ import java.util.Map; import java.util.Set; +import org.opensha.commons.util.DataUtils; +import org.opensha.commons.util.modules.OpenSHA_Module; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList; import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceProvider; +import org.opensha.sha.earthquake.faultSysSolution.modules.RupMFDsModule; import org.opensha.sha.earthquake.faultSysSolution.modules.RupSetTectonicRegimes; import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupture; import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRuptureProperties; @@ -42,19 +45,42 @@ public static void main(String[] args) throws IOException { if (rupSet.hasModule(RupSetTectonicRegimes.class)) rupSet.addModule(RupSetTectonicRegimes.constant(rupSet, TectonicRegionType.ACTIVE_SHALLOW)); - if (sol.hasModule(GridSourceProvider.class)) { - GridSourceList origGridList = sol.requireModule(GridSourceList.class); - sol.setGridSourceProvider(updateGridList(origGridList)); - } + // update rakes to match Peter's rounding, which unfortunately matters because it pushes ruptures across GMM + // fault style bins, e.g., -135 is normal but -135.4 is SS. (although Peter's bins are also wrong, it should be + // 150 for most NGA-W2's). + // also apply minor rounding to mags via the build(true) call below + double[] rakes = new double[rupSet.getNumRuptures()]; + for (int i=0; i prevSolModules = sol.getModules(true); + sol = new FaultSystemSolution(rupSet, sol.getRateForAllRups()); + for (OpenSHA_Module module : prevSolModules) + sol.addModule(module); + + // remove rup MFDs (not used by Peter) + sol.removeModuleInstances(RupMFDsModule.class); + + // now update the grid list + GridSourceList origGridList = sol.requireModule(GridSourceList.class); + System.out.println("Orig grid list Mmin="+(float)minMag(origGridList)); + sol.setGridSourceProvider(updateGridList(origGridList)); sol.write(outFile); } - private static GridSourceList updateGridList(GridSourceList origGridList) { - double ACTIVE_FRACT = 2d/3d; - double STABLE_FRACT = 1d/3d; - - + private static double minMag(GridSourceList gridList) { + double minMag = Double.POSITIVE_INFINITY; + for (int l=0; l>> trtRuptureLists = new EnumMap<>(TectonicRegionType.class); List> activeList = new ArrayList<>(); trtRuptureLists.put(TectonicRegionType.ACTIVE_SHALLOW, activeList); diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java index 316417fe..b119fd73 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java @@ -7,13 +7,21 @@ import java.util.ArrayList; import java.util.EnumMap; import java.util.EnumSet; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.BiFunction; +import java.util.stream.Collectors; import org.apache.commons.math3.stat.StatUtils; +import org.jfree.chart.ui.RectangleAnchor; import org.jfree.data.Range; import org.opensha.commons.data.CSVFile; +import org.opensha.commons.data.Site; +import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DiscretizedFunc; +import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.function.HistogramFunction; import org.opensha.commons.data.function.LightFixedXFunc; import org.opensha.commons.data.function.XY_DataSet; import org.opensha.commons.data.siteData.SiteDataValue; @@ -30,19 +38,42 @@ import org.opensha.commons.gui.plot.PlotSpec; import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.param.Parameter; import org.opensha.commons.util.MarkdownUtils; import org.opensha.commons.util.MarkdownUtils.TableBuilder; import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.calc.HazardCurveCalculator; +import org.opensha.sha.calc.sourceFilters.SourceFilterManager; +import org.opensha.sha.calc.sourceFilters.SourceFilters; +import org.opensha.sha.earthquake.AbstractERF; +import org.opensha.sha.earthquake.ProbEqkRupture; +import org.opensha.sha.earthquake.ProbEqkSource; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; +import org.opensha.sha.earthquake.faultSysSolution.erf.BaseFaultSystemSolutionERF; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc.ReturnPeriods; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; +import org.opensha.sha.earthquake.param.IncludeBackgroundParam; +import org.opensha.sha.earthquake.param.UseRupMFDsParam; +import org.opensha.sha.earthquake.util.GridCellSupersamplingSettings; +import org.opensha.sha.earthquake.util.GriddedSeismicitySettings; +import org.opensha.sha.faultSurface.RuptureSurface; +import org.opensha.sha.imr.AttenRelRef; +import org.opensha.sha.imr.ScalarIMR; +import org.opensha.sha.imr.attenRelImpl.nshmp.NSHMP_GMM_Wrapper; +import org.opensha.sha.imr.param.IntensityMeasureParams.PGA_Param; +import org.opensha.sha.imr.param.IntensityMeasureParams.SA_Param; +import org.opensha.sha.imr.param.OtherParams.SigmaTruncLevelParam; +import org.opensha.sha.imr.param.OtherParams.SigmaTruncTypeParam; +import org.opensha.sha.util.SiteTranslator; import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; import com.google.common.primitives.Doubles; +import gov.usgs.earthquake.nshmp.model.HazardModel; +import gov.usgs.earthquake.nshmp.model.NshmErf; import net.mahdilamb.colormap.Colors; public class ComparisonPageGen { @@ -86,13 +117,36 @@ public static void main(String[] args) throws IOException { EnumSet bgOps = EnumSet.allOf(IncludeBackgroundOption.class); File inputSolFile = new File("/home/kevin/OpenSHA/fss_inversions/2024_02_02-nshm23_branches-WUS_FM_v3/" + "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"); + boolean rupMFDs = false; File compDirActiveSub = new File("/home/kevin/OpenSHA/nshm23/nshmp-haz-models/ext_hazard_calcs/" + "conus_2023.R2-no_gmm_region-by_source-active_subduction-vs760-0p1-20260515-95ae7e82fbb85d"); File compDirStable = new File("/home/kevin/OpenSHA/nshm23/nshmp-haz-models/ext_hazard_calcs/" + "conus_2023.R2-no_gmm_region-by_source-stable-vs760-0p1-20260515-ea28700aef6c6f"); File outputDir = new File(inputDir, "nshmp_haz_comparisons_"+imtDir); - double sourceSpacing = 0.1; + + File modelDir = new File("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.1.3"); +// File modelDir = new File("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.2.0"); + + boolean doWrapperCalc = true; + + Map gmmRefs = Map.of( + TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_ACTIVE); +// TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.NGAWest_2014_AVG_NOIDRISS); + Map gmms = new HashMap<>(); + for (TectonicRegionType trt : gmmRefs.keySet()) { + ScalarIMR gmm = gmmRefs.get(trt).get(); + gmm.setParamDefaults(); + gmm.getParameter(SigmaTruncTypeParam.NAME).setValue(SigmaTruncTypeParam.SIGMA_TRUNC_TYPE_1SIDED); + gmm.getParameter(SigmaTruncLevelParam.NAME).setValue(3d); + if (period == 0d) { + gmm.setIntensityMeasure(PGA_Param.NAME); + } else { + gmm.setIntensityMeasure(SA_Param.NAME); + SA_Param.setPeriodInSA_Param(gmm.getIntensityMeasure(), period); + } + gmms.put(trt, gmm); + } File sourcesDirActiveSub = new File(compDirActiveSub, "vs30-"+vs30+"/"+imtDir+"/source"); File sourcesDirStable = new File(compDirStable, "vs30-"+vs30+"/"+imtDir+"/source"); @@ -104,7 +158,7 @@ public static void main(String[] args) throws IOException { Preconditions.checkState(resourcesDir.exists() || resourcesDir.mkdir()); GriddedRegion mapReg = GriddedRegion.fromFeature(Feature.read(new File(inputDir, "gridded_region.geojson"))); - SiteDataValueListList siteData = mapReg.getSiteData(); + List sites = SolHazardMapCalc.loadSites(mapReg, gmmRefs); boolean plotTraces = false; Region plotReg = mapReg; @@ -165,13 +219,25 @@ public static void main(String[] args) throws IOException { extCurvesMap.put(bgOp, ratesToProbs(extCurvesMap.get(bgOp))); } + FaultSystemSolution sol = null; + if (plotTraces || doWrapperCalc) + sol = FaultSystemSolution.load(inputSolFile); GeographicMapMaker mapMaker = new GeographicMapMaker(plotReg); if (plotTraces) { - mapMaker.setFaultSections(FaultSystemRupSet.load(inputSolFile).getFaultSectionDataList()); + mapMaker.setFaultSections(sol.getRupSet().getFaultSectionDataList()); mapMaker.setSectOutlineChar(null); } // mapMaker.setDefaultPlotWidth(1000); + BaseFaultSystemSolutionERF solERF = null; + if (doWrapperCalc) { + solERF = new BaseFaultSystemSolutionERF(); + solERF.setSolution(sol); + solERF.setGriddedSeismicitySettings(solERF.getGriddedSeismicitySettings().forSupersamplingSettings(GridCellSupersamplingSettings.QUICK)); + solERF.setParameter(UseRupMFDsParam.NAME, rupMFDs); + solERF.getTimeSpan().setDuration(1d); + } + Color transparent = new Color(255, 255, 255, 0); CPT hazCPT = GMT_CPT_Files.RAINBOW_UNIFORM.instance().rescale(-3, 1); @@ -182,6 +248,10 @@ public static void main(String[] args) throws IOException { CPT pDiffCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-10d, 10d); pDiffCPT.setNanColor(transparent); + HazardModel model = null; + if (doWrapperCalc) + model = HazardModel.load(modelDir.toPath()); + double diffScale; if (period == 0d) diffScale = 0.1; @@ -213,6 +283,16 @@ public static void main(String[] args) throws IOException { DiscretizedFunc[] myCurves = myCurvesMap.get(bgOp); DiscretizedFunc[] extCurves = extCurvesMap.get(bgOp); + NshmErf wrapperERF = null; + if (doWrapperCalc) { + wrapperERF = new NshmErf(model, trts, bgOp); + wrapperERF.getTimeSpan().setDuration(1d); + wrapperERF.updateForecast(); + + solERF.setParameter(IncludeBackgroundParam.NAME, bgOp); + solERF.updateForecast(); + } + String mapLabelAdd; switch (bgOp) { case INCLUDE: @@ -236,6 +316,8 @@ public static void main(String[] args) throws IOException { GriddedGeoDataSet myMap = curvestoMap(myCurves, mapReg, rp); GriddedGeoDataSet extMap = curvestoMap(extCurves, mapReg, rp); + System.out.println("Doing "+bgOp+", "+rp); + lines.add("### "+rp.label); lines.add(topLink); lines.add(""); @@ -272,7 +354,7 @@ public static void main(String[] args) throws IOException { table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_diff.png)"); table.finalizeLine(); - table.addLine(diffStr(pDiff, true), diffStr(diff, false)); + table.addLine(diffStr(pDiff, true, plotReg), diffStr(diff, false, plotReg)); lines.addAll(table.build()); lines.add(""); @@ -282,6 +364,8 @@ public static void main(String[] args) throws IOException { int maxDiffIndex = -1; int minDiffIndex = -1; for (int i=0; i maxDiff) { @@ -300,6 +384,9 @@ public static void main(String[] args) throws IOException { table.addLine("Min difference", "Max difference"); table.initNewLine(); + Site minSite = sites.get(minDiffIndex); + Site maxSite = sites.get(maxDiffIndex); + HazardCurveCalculator calc = new HazardCurveCalculator(new SourceFilterManager(SourceFilters.TRT_DIST_CUTOFFS)); for (boolean min : new boolean[] {true,false}) { int index = min ? minDiffIndex : maxDiffIndex; Preconditions.checkState(index >= 0); @@ -316,9 +403,47 @@ public static void main(String[] args) throws IOException { funcs.add(extCurve); chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Colors.tab_orange)); + Site site = min ? minSite : maxSite; + + if (doWrapperCalc) { + DiscretizedFunc wrappedCurve = extCurve.deepClone(); + DiscretizedFunc logCurve = new ArbitrarilyDiscretizedFunc(); + for (int i=0; i data : siteData.getDataList(index)) { - str += "

"+data.getDataType()+": "; - if (data.getValue() != null && data.getValue() instanceof Number) - str += ((Number)data.getValue()).floatValue(); + Site site = min ? minSite : maxSite; + for (Parameter param : site) + str += "

"+param.getName()+": "+param.getValue(); + table.addColumn(str); + } + table.finalizeLine(); + + if (doWrapperCalc && bgOp == IncludeBackgroundOption.EXCLUDE) { + // add distance hists + double maxDist = 50d; + double maxQuickDist = 60d; + int bins = 50; + + List minWrapperSources = getSourcesWithinCutoff(wrapperERF, mapReg.getLocation(minDiffIndex), maxQuickDist); + List maxWrapperSources = getSourcesWithinCutoff(wrapperERF, mapReg.getLocation(maxDiffIndex), maxQuickDist); + List minFSSSources = getSourcesWithinCutoff(solERF, mapReg.getLocation(minDiffIndex), maxQuickDist); + List maxFSSSources = getSourcesWithinCutoff(solERF, mapReg.getLocation(maxDiffIndex), maxQuickDist); + + System.out.println("Max rate source within "+(float)maxDist+" km"); + table.initNewLine(); + for (boolean min : new boolean[] {true,false}) { + if (min) + System.out.println("Min site"); + else + System.out.println("Max site"); + Site site = min ? minSite : maxSite; + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + ProbEqkRupture fssRup = null; + for (boolean fss : new boolean[] {true,false}) { + List sources; + if (fss) { + System.out.print("FSS ERF:\t"); + sources = min ? minFSSSources : maxFSSSources; + } else { + System.out.print("Wrapped ERF:\t"); + sources = min ? minWrapperSources : maxWrapperSources; + } + double maxProb = 0d; + double maxRate = 0d; + ProbEqkSource maxSource = null; + ProbEqkRupture maxRup = null; + for (ProbEqkSource source : sources) { + for (ProbEqkRupture rup : source) { + double prob = rup.getProbability(); + double rate = rup.getMeanAnnualRate(1d); + if (prob > maxProb) { + maxProb = prob; + maxRate = rate; + maxSource = source; + maxRup = rup; + } + } + } + String maxName = "M"+(float)maxRup.getMag()+", rake="+(float)maxRup.getAveRake() + +", P="+(float)maxProb+" rate="+(float)maxRate; + System.out.println("maxProb="+(float)maxProb+", maxRate="+(float)maxRate+", "+maxName+"; "+maxSource.getName()); + if (fss) + fssRup = maxRup; + + int index = min ? minDiffIndex : maxDiffIndex; + DiscretizedFunc curve = fss ? myCurves[index] : extCurves[index]; + + DiscretizedFunc logIMs = new ArbitrarilyDiscretizedFunc(); + for (int i=0; i= 0); + Location loc = mapReg.getLocation(index); + List wrapperSources = min ? minWrapperSources : maxWrapperSources; + List fssSources = min ? minFSSSources : maxFSSSources; + + EvenlyDiscretizedFunc rakeHistFSS = new EvenlyDiscretizedFunc(-180d, 180d, 181); + EvenlyDiscretizedFunc rakeHistWrapper = new EvenlyDiscretizedFunc(-180d, 180d, 181); + + for (ProbEqkSource source : fssSources) + for (ProbEqkRupture rup : source) + rakeHistFSS.add(rakeHistFSS.getClosestXIndex(rup.getAveRake()), rup.getMeanAnnualRate(1d)); + for (ProbEqkSource source : wrapperSources) + for (ProbEqkRupture rup : source) + rakeHistWrapper.add(rakeHistWrapper.getClosestXIndex(rup.getAveRake()), rup.getMeanAnnualRate(1d)); + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + rakeHistWrapper.setName("Wrapper"); + funcs.add(rakeHistWrapper); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_green, 127))); + + rakeHistFSS.setName(nameMine); + funcs.add(rakeHistFSS); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_blue, 127))); + + PlotSpec plot = new PlotSpec(funcs, chars, " ", "Nearby rupture rake (degrees)", "Rate"); + plot.setLegendInset(RectangleAnchor.TOP_LEFT); + + HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); + + gp.drawGraphPanel(plot, false, false, new Range(-180, 180d), null); + + String histPrefix = prefix+"_hist_rake"; + if (min) + histPrefix += "_min"; + else + histPrefix += "_max"; + + PlotUtils.writePlots(resourcesDir, histPrefix, gp, 800, 800, true, true, false); + + table.addColumn("![Rake hist]("+resourcesDir.getName()+"/"+histPrefix+".png)"); + } + table.finalizeLine(); + + for (int d=0; d<3; d++) { + String distName; + HistogramFunction histFSS; + BiFunction distFunc; + if (d == 0) { + distName = "Rrup"; + histFSS = new HistogramFunction(0d, maxDist, bins); + distFunc = (S,L) -> S.getDistanceRup(L); + } else if (d == 1) { + distName = "Rjb"; + histFSS = new HistogramFunction(0d, maxDist, bins); + distFunc = (S,L) -> S.getDistanceJB(L); + } else { + distName = "RX"; + histFSS = new HistogramFunction(-maxDist, maxDist, bins); + distFunc = (S,L) -> S.getDistanceX(L); + } + + EvenlyDiscretizedFunc histWrapper = histFSS.deepClone(); + + table.initNewLine(); + for (boolean min : new boolean[] {true,false}) { + int index = min ? minDiffIndex : maxDiffIndex; + Preconditions.checkState(index >= 0); + Location loc = mapReg.getLocation(index); + List wrapperSources = min ? minWrapperSources : maxWrapperSources; + List fssSources = min ? minFSSSources : maxFSSSources; + + histFSS.scale(0d); + histWrapper.scale(0d); + + fillDistanceHist(fssSources, distFunc, histFSS, loc); + fillDistanceHist(wrapperSources, distFunc, histWrapper, loc); + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + histWrapper.setName(null); + funcs.add(histWrapper); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_green, 127))); + + histFSS.setName(null); + funcs.add(histFSS); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_blue, 127))); + + EvenlyDiscretizedFunc cmlFSS = new EvenlyDiscretizedFunc(histFSS.getMinX()-0.5*histFSS.getDelta(), histFSS.size(), histFSS.getDelta()); + double sum = 0d; + for (int i=0; i allConsidered = new ArrayList<>(); for (int i=0; iavg="+df.format(avg)+"; avgAbs="+df.format(avgAbs)+"; median="+df.format(median)+"; "+numNan+" NaN"; + +"

avg="+df.format(avg)+"; avgAbs="+df.format(avgAbs)+"; median="+df.format(median) + +"

"+numNan+" NaN; "+numInf+" inf"; + } + + private static List getSourcesWithinCutoff(AbstractERF erf, Location loc, double cutoff) { + Site site = new Site(loc); + return erf.getSourceList().parallelStream().filter(S->(float)S.getMinDistance(site) <= (float)cutoff).collect(Collectors.toList()); + } + + private static void fillDistanceHist(List sources, BiFunction distFunc, + EvenlyDiscretizedFunc hist, Location loc) { + float min = (float)(hist.getMinX() < 0 ? hist.getMinX() - 0.5*hist.getDelta() : 0d); + float max = (float)(hist.getMaxX() + 0.5*hist.getDelta()); + sources.parallelStream().forEach((source)->{ + for (ProbEqkRupture rup : source) { + double dist = distFunc.apply(rup.getRuptureSurface(), loc); + if ((float)dist >= min && (float)dist <= max) { + int index = hist.getClosestXIndex(dist); + synchronized (hist) { + hist.add(index, rup.getMeanAnnualRate(1d)); + } + } + } + }); + } + + private static Color trans(Color c, int a) { + return new Color(c.getRed(), c.getGreen(), c.getBlue(), a); } } diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java index 0c7dc3a6..de13664d 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java @@ -1,14 +1,19 @@ package scratch.kevin.nshm23.hazardValidation; +import java.awt.Color; import java.io.File; import java.io.IOException; -import java.nio.file.Path; import java.util.BitSet; +import java.util.Set; +import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.xyz.GriddedGeoDataSet; import org.opensha.commons.geo.GriddedRegion; import org.opensha.commons.geo.Location; import org.opensha.commons.geo.Region; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.cpt.CPT; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; @@ -16,11 +21,18 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupture; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; +import org.opensha.sha.earthquake.ProbEqkRupture; +import org.opensha.sha.earthquake.ProbEqkSource; import org.opensha.sha.faultSurface.FaultSection; +import org.opensha.sha.faultSurface.RuptureSurface; import org.opensha.sha.util.TectonicRegionType; +import com.google.common.base.Preconditions; + +import gov.usgs.earthquake.nshmp.model.GridSource; import gov.usgs.earthquake.nshmp.model.HazardModel; -import gov.usgs.earthquake.nshmp.model.SourceTree; +import gov.usgs.earthquake.nshmp.model.NshmErf; +import gov.usgs.earthquake.nshmp.model.NshmSource; public class GriddedParticipationComparison { @@ -28,31 +40,35 @@ public static void main(String[] args) throws IOException { File inputSolFile = new File("/home/kevin/OpenSHA/fss_inversions/2024_02_02-nshm23_branches-WUS_FM_v3/" + "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"); File modelDir = new File("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.1.3"); +// File modelDir = new File("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.2.0"); Region reg = NSHM23_RegionLoader.loadFullConterminousWUS(); - + TectonicRegionType trt = TectonicRegionType.ACTIVE_SHALLOW; IncludeBackgroundOption bgOp = IncludeBackgroundOption.EXCLUDE; double[] minMags = {0d, 6d, 7d}; - + File outputDir = new File("/data/kevin/nshm23/nshmp-haz-models/gridded_partic_debug"); - + Preconditions.checkState(outputDir.exists() || outputDir.mkdirs(), + "Could not create output directory: %s", outputDir.getAbsolutePath()); + GriddedRegion gridReg = new GriddedRegion(reg, 0.1, GriddedRegion.ANCHOR_0_0); - + FaultSystemSolution sol = FaultSystemSolution.load(inputSolFile); // we want direct mappings sol.getRupSet().removeModuleInstances(FaultGridAssociations.class); - + HazardModel model = HazardModel.load(modelDir.toPath()); - + GriddedGeoDataSet[] fssXYZs = new GriddedGeoDataSet[minMags.length]; GriddedGeoDataSet[] nhXYZs = new GriddedGeoDataSet[minMags.length]; for (int m=0; m= (float)minMags[m]) { + if (gridLike) { + if (gridSourceIndex >= 0) + nhXYZs[m].add(gridSourceIndex, rate); + } else { + addFiniteRupRate(nhXYZs[m], rup.getRuptureSurface(), rate); + } + } + } + } + } + + System.out.println("NSHMP-Haz had "+numNSHMPSources+" matching sources with "+numNSHMPRups+" total ruptures"); + + System.out.println("Building maps"); + + GeographicMapMaker mapMaker = new GeographicMapMaker(reg); + mapMaker.setFaultSections(sol.getRupSet().getFaultSectionDataList()); + mapMaker.setSectOutlineChar(null); + Color transparent = new Color(255, 255, 255, 0); + + for (int m=0; m 0d) { + double logMax = Math.ceil(Math.log10(maxRate)); + CPT rateCPT = GMT_CPT_Files.RAINBOW_UNIFORM.instance().rescale(logMax - 6d, logMax); + rateCPT.setNanColor(transparent); + + mapMaker.plotXYZData(asLog10(fssXYZs[m]), rateCPT, "OpenSHA Rate, "+magLabel); + mapMaker.plot(outputDir, prefix+"_opensha", " "); + mapMaker.plotXYZData(asLog10(nhXYZs[m]), rateCPT, "NSHMP-Haz Rate, "+magLabel); + mapMaker.plot(outputDir, prefix+"_nshmp_haz", " "); + } + + double maxAbsDiff = maxAbs(diff); + if (maxAbsDiff > 0d) { + CPT diffCPT = GMT_CPT_Files.DIVERGING_BAM_UNIFORM.instance().reverse().rescale(-maxAbsDiff, maxAbsDiff); + diffCPT.setNanColor(transparent); + mapMaker.plotXYZData(diff, diffCPT, "OpenSHA - NSHMP-Haz Rate, "+magLabel); + mapMaker.plot(outputDir, prefix+"_diff", " "); + } + + CPT pDiffCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-100d, 100d); + pDiffCPT.setNanColor(transparent); + mapMaker.plotXYZData(pDiff, pDiffCPT, "OpenSHA vs NSHMP-Haz, % Change, "+magLabel); + mapMaker.plot(outputDir, prefix+"_pDiff", " "); } } - - + + private static boolean includeForBackgroundOption(boolean gridLike, IncludeBackgroundOption bgOp) { + switch (bgOp) { + case INCLUDE: + return true; + case ONLY: + return gridLike; + case EXCLUDE: + return !gridLike; + default: + throw new IllegalStateException("Unhandled background option: "+bgOp); + } + } + + private static Location toOpenSHALocation(gov.usgs.earthquake.nshmp.geo.Location loc) { + return new Location(loc.latitude, loc.longitude, loc.depth); + } + + private static void addFiniteRupRate(GriddedGeoDataSet xyz, RuptureSurface surface, double rate) { + GriddedRegion gridReg = xyz.getRegion(); + BitSet bits = new BitSet(gridReg.getNodeCount()); + for (Location loc : surface.getEvenlyDiscritizedListOfLocsOnSurface()) { + int node = gridReg.indexForLocation(loc); + if (node >= 0) + bits.set(node); + } + for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i + 1)) + xyz.add(i, rate); + } + + private static String magLabel(double minMag) { + return minMag == 0d ? "m0" : "m"+(float)minMag; + } + + private static GriddedGeoDataSet diff(GriddedGeoDataSet xyz1, GriddedGeoDataSet xyz2) { + GriddedGeoDataSet ret = new GriddedGeoDataSet(xyz1.getRegion()); + for (int i=0; i 0d ? Math.log10(xyz.get(i)) : Double.NaN); + return xyz; + } + + private static double max(GriddedGeoDataSet xyz) { + double max = 0d; + for (int i=0; i csv = new CSVFile<>(true); + csv.addLine("Latitude", "Longitude", "OpenSHA Rate", "NSHMP-Haz Rate", "Difference", "Percent Difference"); + GriddedRegion gridReg = fssXYZ.getRegion(); + for (int i=0; i Date: Tue, 28 Jul 2026 10:36:30 -0700 Subject: [PATCH 44/71] rake rounding --- .../nshm23/RevisedGridProvUpdate2026.java | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java b/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java index 4c1ce54b..6d070654 100644 --- a/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java +++ b/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java @@ -37,7 +37,11 @@ public static void main(String[] args) throws IOException { // File inFile = new File(dir, "results_WUS_FM_v3_branch_averaged_gridded.zip"); File inFile = new File(dir, "results_WUS_FM_v3_branch_averaged_gridded_simplified.zip"); - File outFile = new File(dir, inFile.getName().substring(0, inFile.getName().indexOf(".zip"))+"_revised2026.zip"); +// boolean updateRakes = true; +// File outFile = new File(dir, inFile.getName().substring(0, inFile.getName().indexOf(".zip"))+"_revised2026.zip"); + + boolean updateRakes = false; + File outFile = new File(dir, inFile.getName().substring(0, inFile.getName().indexOf(".zip"))+"_revised2026_origRakes.zip"); FaultSystemSolution sol = FaultSystemSolution.load(inFile); FaultSystemRupSet rupSet = sol.getRupSet(); @@ -45,26 +49,30 @@ public static void main(String[] args) throws IOException { if (rupSet.hasModule(RupSetTectonicRegimes.class)) rupSet.addModule(RupSetTectonicRegimes.constant(rupSet, TectonicRegionType.ACTIVE_SHALLOW)); - // update rakes to match Peter's rounding, which unfortunately matters because it pushes ruptures across GMM - // fault style bins, e.g., -135 is normal but -135.4 is SS. (although Peter's bins are also wrong, it should be - // 150 for most NGA-W2's). - // also apply minor rounding to mags via the build(true) call below - double[] rakes = new double[rupSet.getNumRuptures()]; - for (int i=0; i prevSolModules = sol.getModules(true); - sol = new FaultSystemSolution(rupSet, sol.getRateForAllRups()); - for (OpenSHA_Module module : prevSolModules) - sol.addModule(module); + if (updateRakes) { + // update rakes to match Peter's rounding, which unfortunately matters because it pushes ruptures across GMM + // fault style bins, e.g., -135 is normal but -135.4 is SS. (although Peter's bins are also wrong, it should be + // 150 for most NGA-W2's). + // also apply minor rounding to mags via the build(true) call below + double[] rakes = new double[rupSet.getNumRuptures()]; + for (int i=0; i prevSolModules = sol.getModules(true); + sol = new FaultSystemSolution(rupSet, sol.getRateForAllRups()); + for (OpenSHA_Module module : prevSolModules) + sol.addModule(module); + } // remove rup MFDs (not used by Peter) sol.removeModuleInstances(RupMFDsModule.class); // now update the grid list - GridSourceList origGridList = sol.requireModule(GridSourceList.class); - System.out.println("Orig grid list Mmin="+(float)minMag(origGridList)); - sol.setGridSourceProvider(updateGridList(origGridList)); + if (sol.getGridSourceProvider() != null) { + GridSourceList origGridList = sol.requireModule(GridSourceList.class); + System.out.println("Orig grid list Mmin="+(float)minMag(origGridList)); + sol.setGridSourceProvider(updateGridList(origGridList)); + } sol.write(outFile); } From e84224fdc3a95c4acdc4aeed6f042b8971964ebd Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 28 Jul 2026 10:36:38 -0700 Subject: [PATCH 45/71] comparison updates --- .../ComparisonCalcScriptWriter.java | 41 +++++++++++++++---- .../hazardValidation/ComparisonPageGen.java | 31 +++++++------- 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java index b87e53d4..d8fcfa36 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java @@ -7,9 +7,12 @@ import java.util.Map; import org.opensha.commons.data.siteData.CONUS_Versions; +import org.opensha.commons.data.siteData.SiteData; +import org.opensha.commons.data.siteData.SiteDataValueList; import org.opensha.commons.data.siteData.SiteDataValueListList; import org.opensha.commons.data.siteData.impl.CONUS_SiteDataProvider; import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.LocationList; import org.opensha.commons.geo.Region; import org.opensha.commons.param.Parameter; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc; @@ -34,25 +37,31 @@ public static void main(String[] args) throws IOException { Region reg = NSHM23_RegionLoader.loadFullConterminousWUS(); double spacing = 0.1; String linkFromDir = "2024_02_02-nshm23_branches-WUS_FM_v3"; - String solFileName = "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"; +// String solFileName = "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"; +// String extraToken = null; + String solFileName = "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026_origRakes.zip"; + String extraToken = "origRakes"; File localMainDir = new File("/home/kevin/OpenSHA/fss_inversions"); GriddedRegion gridReg = new GriddedRegion(reg, spacing, GriddedRegion.ANCHOR_0_0); // add site data SiteDataValueListList siteData = new SiteDataValueListList(); - CONUS_SiteDataProvider data10 = new CONUS_SiteDataProvider( - CONUS_SiteDataProvider.TYPE_DEPTH_TO_1_0, CONUS_Versions.NSHM23); - CONUS_SiteDataProvider data25 = new CONUS_SiteDataProvider( - CONUS_SiteDataProvider.TYPE_DEPTH_TO_2_5, CONUS_Versions.NSHM23); - siteData.add(data10.getAnnotatedValues(gridReg.getNodeList())); - siteData.add(data25.getAnnotatedValues(gridReg.getNodeList())); + String[] dataTypes = { + CONUS_SiteDataProvider.TYPE_DEPTH_TO_1_0, + CONUS_SiteDataProvider.TYPE_DEPTH_TO_2_5, + CONUS_SiteDataProvider.TYPE_SEDIMENT_THICKNESS + }; + for (String type : dataTypes) { + CONUS_SiteDataProvider prov = new CONUS_SiteDataProvider(type, CONUS_Versions.NSHM23); + addDataIfAny(siteData, prov, gridReg.getNodeList()); + } gridReg.setSiteData(siteData); - // TODO add stable continental when ready - String gmpeToken = "active_only"; + String gmpeToken = null; Map gmpes = new EnumMap<>(TectonicRegionType.class); gmpes.put(TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_ACTIVE); + gmpes.put(TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_STABLE); SolHazardMapCalc.loadSites(gridReg, gmpes); @@ -77,6 +86,7 @@ public static void main(String[] args) throws IOException { .addNameToken("hazard_validation") .addNameToken(regToken) .addNameToken(gmpeToken) + .addNameToken(extraToken) .build(); MPJ_BranchAveragedHazardScriptWriter.Request request = MPJ_BranchAveragedHazardScriptWriter.Request.builder() @@ -93,5 +103,18 @@ public static void main(String[] args) throws IOException { new MPJ_BranchAveragedHazardScriptWriter().writeScripts(request); } + + private static void addDataIfAny(SiteDataValueListList siteData, SiteData prov, LocationList locs) throws IOException { + SiteDataValueList data = prov.getAnnotatedValues(locs); + int count = 0; + for (int i=0; i 0) + siteData.add(data); + } } diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java index b119fd73..ab1a6d65 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java @@ -128,7 +128,16 @@ public static void main(String[] args) throws IOException { File modelDir = new File("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.1.3"); // File modelDir = new File("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.2.0"); - boolean doWrapperCalc = true; + boolean doWrapperCalc = false; + + GriddedRegion mapReg = GriddedRegion.fromFeature(Feature.read(new File(inputDir, "gridded_region.geojson"))); + boolean plotTraces = false; + Region plotReg = mapReg; + +// plotReg = new Region(new Location(37.5, -122.5), new Location(38.5, -121.5)); + +// plotReg = new Region(new Location(40, -122), new Location(41, -120)); +// plotTraces = true; Map gmmRefs = Map.of( TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_ACTIVE); @@ -156,18 +165,8 @@ public static void main(String[] args) throws IOException { Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); File resourcesDir = new File(outputDir, "resources"); Preconditions.checkState(resourcesDir.exists() || resourcesDir.mkdir()); - - GriddedRegion mapReg = GriddedRegion.fromFeature(Feature.read(new File(inputDir, "gridded_region.geojson"))); List sites = SolHazardMapCalc.loadSites(mapReg, gmmRefs); - boolean plotTraces = false; - Region plotReg = mapReg; - -// plotReg = new Region(new Location(37.5, -122.5), new Location(38.5, -121.5)); - - plotReg = new Region(new Location(40, -122), new Location(41, -120)); - plotTraces = true; - Map myCurvesMap = new EnumMap<>(IncludeBackgroundOption.class); for (IncludeBackgroundOption bgOp : bgOps) myCurvesMap.put(bgOp, loadRegularCurves(inputDir, bgOp, mapReg, period)); @@ -996,8 +995,9 @@ private static String diffStr(GriddedGeoDataSet diff, boolean isPDiff, Region pl diff = diff.copy(); diff.scale(0.01); } - + List allConsidered = new ArrayList<>(); + List allConsideredAbs = new ArrayList<>(); for (int i=0; iavg="+df.format(avg)+"; avgAbs="+df.format(avgAbs)+"; median="+df.format(median) + +"

avg="+df.format(avg)+"; avgAbs="+df.format(avgAbs) + +"

median="+df.format(median)+"; medianAbs="+df.format(medianAbs) +"

"+numNan+" NaN; "+numInf+" inf"; } From e98ce4028911bbb8fbc08746895cbe69e3e5df28 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 31 Jul 2026 14:02:29 -0700 Subject: [PATCH 46/71] now works with point source optimizations --- .../earthquake/nshmp/model/NshmRupture.java | 32 +++++----- .../earthquake/nshmp/model/NshmSource.java | 13 ++-- .../earthquake/nshmp/model/NshmSurface.java | 60 +++++++++++++++++++ 3 files changed, 81 insertions(+), 24 deletions(-) diff --git a/src/main/java/gov/usgs/earthquake/nshmp/model/NshmRupture.java b/src/main/java/gov/usgs/earthquake/nshmp/model/NshmRupture.java index 5c01ef44..84537f87 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/model/NshmRupture.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/model/NshmRupture.java @@ -7,23 +7,23 @@ class NshmRupture extends ProbEqkRupture { - final double rate; - final double weight; + final double rate; + final double weight; - NshmRupture( - double mag, - double rake, - double rate, - double weight, - double duration, - RuptureSurface surface) { + NshmRupture( + double mag, + double rake, + double rate, + double weight, + double duration, + RuptureSurface surface) { - super( - mag, rake, - Maths.rateToProbability(rate * weight, duration), - surface, null); + super( + mag, rake, + Maths.rateToProbability(rate * weight, duration), + surface, null); - this.rate = rate; - this.weight = weight; - } + this.rate = rate; + this.weight = weight; + } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/model/NshmSource.java b/src/main/java/gov/usgs/earthquake/nshmp/model/NshmSource.java index de1e570e..b10369b7 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/model/NshmSource.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/model/NshmSource.java @@ -49,11 +49,7 @@ public RuptureSurface getSourceSurface() { throw new UnsupportedOperationException(); } - public Object getDelegate() { - return delegate; - } - - static class Fault extends NshmSource { + public static class Fault extends NshmSource { private final List ruptures; @@ -99,7 +95,7 @@ public void setDuration(double duration) { } } - static class Point extends NshmSource { + public static class Point extends NshmSource { final double weight; double duration; @@ -133,7 +129,8 @@ public ProbEqkRupture getRupture(int index) { rupture.rate(), weight, duration, - new NshmSurface(rupture.surface())); + NshmSurface.buildPointSurface(rupture.surface())); +// new NshmSurface(rupture.surface())); } @Override @@ -142,7 +139,7 @@ public void setDuration(double duration) { } } - static class System extends NshmSource { + public static class System extends NshmSource { final List surfaces; final NshmRupture rupture; diff --git a/src/main/java/gov/usgs/earthquake/nshmp/model/NshmSurface.java b/src/main/java/gov/usgs/earthquake/nshmp/model/NshmSurface.java index 96e1e201..567f0adc 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/model/NshmSurface.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/model/NshmSurface.java @@ -11,6 +11,8 @@ import org.opensha.sha.faultSurface.RuptureSurface; import org.opensha.sha.faultSurface.cache.CacheEnabledSurface; import org.opensha.sha.faultSurface.cache.SurfaceDistances; +import org.opensha.sha.faultSurface.utils.ptSrcCorr.PointSourceDistanceCorrection; +import org.opensha.sha.util.TectonicRegionType; import gov.usgs.earthquake.nshmp.fault.surface.DefaultGriddedSurface; import gov.usgs.earthquake.nshmp.fault.surface.GriddedSurface; @@ -36,6 +38,64 @@ public class NshmSurface implements CacheEnabledSurface { public NshmSurface(gov.usgs.earthquake.nshmp.fault.surface.RuptureSurface delegate) { this.delegate = delegate; } + + /** + * This creates a point surface that will work with existing OpenSHA point-source optimizations + * @param delegate + * @return + */ + public static org.opensha.sha.faultSurface.PointSurface buildPointSurface( + gov.usgs.earthquake.nshmp.fault.surface.RuptureSurface delegate) { + // this is the point surface + double len = 0d; + try { + len = delegate.length(); + } catch (Exception e) {} + org.opensha.sha.faultSurface.PointSurface surf = new org.opensha.sha.faultSurface.PointSurface( + NshmUtil.toOpenShaLocation(delegate.centroid()), delegate.dip(), delegate.depth(), + delegate.depth() + delegate.width()*Math.sin(Math.toRadians(delegate.dip())), len); + return new org.opensha.sha.faultSurface.PointSurface.DistanceCorrecting( + surf, new DelegatePointSourceCorrection(delegate), null, Double.NaN); + } + + /** + * Delegate point source correction that passes through to NSHMP-haz. This is required for point source + * optimizations to work with wrapped point sources. As part of that, equals/hashCode have to be constant + * for all delegate corrections. + */ + private static class DelegatePointSourceCorrection implements PointSourceDistanceCorrection.Single { + + private gov.usgs.earthquake.nshmp.fault.surface.RuptureSurface delegate; + + private DelegatePointSourceCorrection(gov.usgs.earthquake.nshmp.fault.surface.RuptureSurface delegate) { + this.delegate = delegate; + } + + @Override + public SurfaceDistances getCorrectedDistance(Location location, org.opensha.sha.faultSurface.PointSurface surf, + TectonicRegionType trt, double mag, double horzDist) { + Distance distance = delegate.distanceTo(NshmUtil.fromOpenShaLocation(location)); + return new SurfaceDistances.Precomputed(location, distance.rRup, distance.rJB, distance.rX); + } + + private static final int hashCode = DelegatePointSourceCorrection.class.hashCode(); + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object obj) { +// return obj instanceof DelegatePointSourceCorrection; + if (!(obj instanceof DelegatePointSourceCorrection)) + return false; + DelegatePointSourceCorrection other = (DelegatePointSourceCorrection)obj; +// System.out.println("Delegate classes:\t"+delegate.getClass()+"\t"+other.delegate.getClass()); + return other.delegate.getClass().equals(delegate.getClass()); + } + + } // return nshmp-haz rupture centroid as OpenSHA location for // use in computing min distance to a fault system subsection From 0941d442a27d9065597fa29895585f1805dbf174 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 31 Jul 2026 14:02:46 -0700 Subject: [PATCH 47/71] new tests and plots --- .../miscFigures/CompoundAveDipTests.java | 86 ++ .../nshm23/RevisedGridProvUpdate2026.java | 83 +- .../ComparisonCalcScriptWriter.java | 32 +- .../hazardValidation/ComparisonPageGen.java | 1032 ++++++++++------- .../nshm23/hazardValidation/CorrRJBPlot.java | 62 + .../nshm23/hazardValidation/DipCalcTests.java | 80 ++ .../GridPropInvestigation.java | 196 ++++ .../WrapperRupSetRupMapper.java | 113 ++ .../kevin/prvi25/GmmInputCacheBenchmark.java | 3 +- 9 files changed, 1230 insertions(+), 457 deletions(-) create mode 100644 src/main/java/scratch/kevin/miscFigures/CompoundAveDipTests.java create mode 100644 src/main/java/scratch/kevin/nshm23/hazardValidation/CorrRJBPlot.java create mode 100644 src/main/java/scratch/kevin/nshm23/hazardValidation/DipCalcTests.java create mode 100644 src/main/java/scratch/kevin/nshm23/hazardValidation/GridPropInvestigation.java create mode 100644 src/main/java/scratch/kevin/nshm23/hazardValidation/WrapperRupSetRupMapper.java diff --git a/src/main/java/scratch/kevin/miscFigures/CompoundAveDipTests.java b/src/main/java/scratch/kevin/miscFigures/CompoundAveDipTests.java new file mode 100644 index 00000000..9e7776f1 --- /dev/null +++ b/src/main/java/scratch/kevin/miscFigures/CompoundAveDipTests.java @@ -0,0 +1,86 @@ +package scratch.kevin.miscFigures; + +import java.io.File; +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.LocationUtils; +import org.opensha.sha.earthquake.faultSysSolution.ruptures.ClusterRupture; +import org.opensha.sha.earthquake.faultSysSolution.ruptures.FaultSubsectionCluster; +import org.opensha.sha.earthquake.faultSysSolution.ruptures.Jump; +import org.opensha.sha.earthquake.faultSysSolution.ruptures.util.RupCartoonGenerator; +import org.opensha.sha.faultSurface.CompoundSurface; +import org.opensha.sha.faultSurface.FaultSection; +import org.opensha.sha.faultSurface.FaultTrace; +import org.opensha.sha.faultSurface.GeoJSONFaultSection; +import org.opensha.sha.faultSurface.RuptureSurface; + +public class CompoundAveDipTests { + + public static void main(String[] args) throws IOException { + List sects = new ArrayList<>(); + HashMap flips = new HashMap<>(); + sects.add(new GeoJSONFaultSection.Builder(sects.size(), "Fault 1", + FaultTrace.of(new Location(0d, 0.48d), new Location(0d, 0d))) + .dip(60).lowerDepth(10).upperDepth(0).rake(0) + .build()); + flips.put(sects.get(sects.size()-1).getSectionId(), true); + sects.add(new GeoJSONFaultSection.Builder(sects.size(), "Fault 2", + FaultTrace.of(new Location(0d, 0.52d), new Location(0d, 1d))) + .dip(45).lowerDepth(10).upperDepth(0).rake(0) + .build()); + + List surfs = new ArrayList<>(); + for (GeoJSONFaultSection sect : sects) + surfs.add(sect.getFaultSurface(1d)); + + CompoundSurface.Simple surf = new CompoundSurface.Simple(surfs, sects); + + ClusterRupture cRup = null; + int subSectIndex = 0; + for (GeoJSONFaultSection sect : sects) { + double ddw = sect.getOrigDownDipWidth(); + List subSects = sect.getSubSectionsList(ddw/2d, subSectIndex); + if (flips.containsKey(sect.getSectionId())) { + subSects = new ArrayList<>(subSects); + Collections.reverse(subSects); + } + subSectIndex += subSects.size(); + if (cRup == null) { + cRup = new ClusterRupture(new FaultSubsectionCluster(subSects)); + } else { + FaultSubsectionCluster prev = cRup.clusters[cRup.clusters.length-1]; + FaultSection from = null; + FaultSection to = null; + double minDist = Double.POSITIVE_INFINITY; + for (FaultSection testFrom : prev.subSects) { + for (FaultSection testTo : subSects) { + double dist = Double.POSITIVE_INFINITY; + for (Location l1 : testFrom.getFaultTrace()) + for (Location l2 : testTo.getFaultTrace()) + dist = Math.min(dist, LocationUtils.horzDistanceFast(l2, l1)); + if (dist < minDist) { + minDist = dist; + from = testFrom; + to = testTo; + } + } + } + cRup = cRup.take(new Jump(from, prev, to, new FaultSubsectionCluster(subSects), 0)); + } + } + + DecimalFormat dipDF = new DecimalFormat("0"); + String title = "Oriented dip: "+dipDF.format(surf.getAveOrientedDip())+"; Average dip: "+dipDF.format(surf.getAveDip()); + + RupCartoonGenerator.plotRupture(new File("/tmp"), "compound_dip_example", cRup, title, false, false); + + + } + +} diff --git a/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java b/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java index 6d070654..a81048ab 100644 --- a/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java +++ b/src/main/java/scratch/kevin/nshm23/RevisedGridProvUpdate2026.java @@ -18,10 +18,16 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceProvider; import org.opensha.sha.earthquake.faultSysSolution.modules.RupMFDsModule; import org.opensha.sha.earthquake.faultSysSolution.modules.RupSetTectonicRegimes; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.gridded.NSHM23_SingleRegionGridSourceProvider.NSHM23_WUS_FiniteRuptureConverter; import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupture; import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRuptureProperties; +import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupturePropertiesBuilder; +import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupturePropertiesCache; +import org.opensha.sha.util.FocalMech; import org.opensha.sha.util.TectonicRegionType; +import com.google.common.base.Preconditions; + public class RevisedGridProvUpdate2026 { public static void main(String[] args) throws IOException { @@ -36,12 +42,16 @@ public static void main(String[] args) throws IOException { // File inFile = new File(dir, "results_WUS_FM_v3_branch_averaged.zip"); // File inFile = new File(dir, "results_WUS_FM_v3_branch_averaged_gridded.zip"); File inFile = new File(dir, "results_WUS_FM_v3_branch_averaged_gridded_simplified.zip"); + + double stableToActiveFract = 2d/3d; + double stableStaysStableFract = 1d/3d; + boolean updateRakes = true; + boolean applyStablePropsToOverlapActive = true; -// boolean updateRakes = true; -// File outFile = new File(dir, inFile.getName().substring(0, inFile.getName().indexOf(".zip"))+"_revised2026.zip"); + File outFile = new File(dir, inFile.getName().substring(0, inFile.getName().indexOf(".zip"))+"_revised2026.zip"); - boolean updateRakes = false; - File outFile = new File(dir, inFile.getName().substring(0, inFile.getName().indexOf(".zip"))+"_revised2026_origRakes.zip"); +// updateRakes = false; +// File outFile = new File(dir, inFile.getName().substring(0, inFile.getName().indexOf(".zip"))+"_revised2026_origRakes.zip"); FaultSystemSolution sol = FaultSystemSolution.load(inFile); FaultSystemRupSet rupSet = sol.getRupSet(); @@ -71,7 +81,7 @@ public static void main(String[] args) throws IOException { if (sol.getGridSourceProvider() != null) { GridSourceList origGridList = sol.requireModule(GridSourceList.class); System.out.println("Orig grid list Mmin="+(float)minMag(origGridList)); - sol.setGridSourceProvider(updateGridList(origGridList)); + sol.setGridSourceProvider(updateGridList(origGridList, stableToActiveFract, stableStaysStableFract, applyStablePropsToOverlapActive)); } sol.write(outFile); @@ -85,41 +95,60 @@ private static double minMag(GridSourceList gridList) { return minMag; } - private static final double ACTIVE_FRACT = 2d/3d; - private static final double STABLE_FRACT = 1d/3d; - - public static GridSourceList updateGridList(GridSourceList origGridList) { + public static GridSourceList updateGridList(GridSourceList origGridList, double stabletoActiveFract, + double stableStaysStableFract, boolean applyStablePropsToOverlapActive) { EnumMap>> trtRuptureLists = new EnumMap<>(TectonicRegionType.class); List> activeList = new ArrayList<>(); trtRuptureLists.put(TectonicRegionType.ACTIVE_SHALLOW, activeList); List> stableList = new ArrayList<>(); trtRuptureLists.put(TectonicRegionType.STABLE_SHALLOW, stableList); - Map activePropsCache = new HashMap<>(); + NSHM23_WUS_FiniteRuptureConverter converter = new NSHM23_WUS_FiniteRuptureConverter(); + GriddedRupturePropertiesCache cache = new GriddedRupturePropertiesCache(); + + FocalMech mech = FocalMech.STRIKE_SLIP; for (int l=0; lR.rate).sum(); List activeRups = origGridList.getRuptures(TectonicRegionType.ACTIVE_SHALLOW, l); List stableRups = origGridList.getRuptures(TectonicRegionType.STABLE_SHALLOW, l); - if (stableRups != null) { - activeRups = new ArrayList<>(activeRups); + if (!stableRups.isEmpty()) { + double sumStable = stableRups.stream().mapToDouble(R->R.rate).sum(); + double sumActive = activeRups.stream().mapToDouble(R->R.rate).sum(); + Preconditions.checkState(activeRups.isEmpty(), "Already has both active and stable?" + + "\n\tStable:\t%s rups\trate=%s\n\tActive:\t%s rups\trate=%s", + stableRups.size(), (float)sumStable, activeRups.size(), (float)sumActive); + activeRups = new ArrayList<>(stableRups.size()); List modStableRups = new ArrayList<>(stableRups.size()); for (GriddedRupture rup : stableRups) { - GriddedRuptureProperties props = rup.properties; - GriddedRuptureProperties activeProps = new GriddedRuptureProperties( - props.magnitude, props.rake, props.dip, props.strike, props.strikeRange, - props.upperDepth, props.lowerDepth, props.length, props.hypocentralDepth, - props.hypocentralDAS, TectonicRegionType.ACTIVE_SHALLOW); - if (activePropsCache.containsKey(activeProps)) - activeProps = activePropsCache.get(activeProps); - else - activePropsCache.put(activeProps, activeProps); - - activeRups.add(new GriddedRupture(l, rup.location, activeProps, - rup.rate*ACTIVE_FRACT, rup.associatedSections, rup.associatedSectionFracts)); - modStableRups.add(new GriddedRupture(l, rup.location, props, - rup.rate*STABLE_FRACT, rup.associatedSections, rup.associatedSectionFracts)); + Preconditions.checkState((float)mech.rake() == (float)rup.properties.rake); + Preconditions.checkState((float)mech.dip() == (float)rup.properties.dip); + if (stabletoActiveFract > 0d) { + if (applyStablePropsToOverlapActive) { + // NSHMP-haz treats the "active" sources in the overlap zone as a GMM-override only, i.e., + // it continues to use the stable grid properties with Ztor=5 for all magnitudes + + // build it as stable first + GriddedRupture tempRup = converter.buildFiniteRupture(l, rup.location, rup.properties.magnitude, rup.rate*stabletoActiveFract, + mech, TectonicRegionType.STABLE_SHALLOW, rup.associatedSections, rup.associatedSectionFracts, cache); + + // now convert to active + GriddedRuptureProperties props = new GriddedRupturePropertiesBuilder(tempRup.properties) + .tectonicRegionType(TectonicRegionType.ACTIVE_SHALLOW).build(); + props = cache.getCached(props); + activeRups.add(new GriddedRupture(l, tempRup.location, props, tempRup.rate, tempRup.associatedSections, tempRup.associatedSectionFracts)); + } else { + // this is probably the right way, but not how Peter does it + activeRups.add(converter.buildFiniteRupture(l, rup.location, rup.properties.magnitude, rup.rate*stabletoActiveFract, + mech, TectonicRegionType.ACTIVE_SHALLOW, rup.associatedSections, rup.associatedSectionFracts, cache)); + } + } + // this will also correct the zTOR for nshmp-haz that puts everything at 5km (even M>6.5) + if (stableStaysStableFract > 0d) + modStableRups.add(converter.buildFiniteRupture(l, rup.location, rup.properties.magnitude, rup.rate*stableStaysStableFract, + mech, TectonicRegionType.STABLE_SHALLOW, rup.associatedSections, rup.associatedSectionFracts, cache)); } stableRups = modStableRups; @@ -127,6 +156,8 @@ public static GridSourceList updateGridList(GridSourceList origGridList) { activeList.add(activeRups); stableList.add(stableRups); + double newSumRate = activeRups.stream().mapToDouble(R->R.rate).sum() + stableRups.stream().mapToDouble(R->R.rate).sum(); + Preconditions.checkState((float)newSumRate == (float)origSumRate); } return new GridSourceList.Precomputed(origGridList.getGriddedRegion(), trtRuptureLists); diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java index d8fcfa36..6d4176c4 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import java.util.Map; @@ -32,15 +33,16 @@ public class ComparisonCalcScriptWriter { public static void main(String[] args) throws IOException { + List extraTokens = new ArrayList<>(); // start with WUS-only String regToken = "WUS"; Region reg = NSHM23_RegionLoader.loadFullConterminousWUS(); double spacing = 0.1; String linkFromDir = "2024_02_02-nshm23_branches-WUS_FM_v3"; -// String solFileName = "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"; -// String extraToken = null; - String solFileName = "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026_origRakes.zip"; - String extraToken = "origRakes"; + String solFileName = "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"; + +// String solFileName = "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026_origRakes.zip"; +// extraTokens.add("origRakes"); File localMainDir = new File("/home/kevin/OpenSHA/fss_inversions"); @@ -58,10 +60,22 @@ public static void main(String[] args) throws IOException { } gridReg.setSiteData(siteData); - String gmpeToken = null; Map gmpes = new EnumMap<>(TectonicRegionType.class); gmpes.put(TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_ACTIVE); - gmpes.put(TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_STABLE); + gmpes.put(TectonicRegionType.STABLE_SHALLOW, AttenRelRef.USGS_NSHM23_STABLE); + + Double maxDist = null; // use TRT defaults + boolean nshmpIMLs = false; + boolean disablePointOptimize = false; + + extraTokens.add("maxDist300"); + maxDist = 300d; + +// disablePointOptimize = true; +// extraTokens.add("noPointOptimize"); + + nshmpIMLs = true; + extraTokens.add("nshmpIMLs"); SolHazardMapCalc.loadSites(gridReg, gmpes); @@ -78,6 +92,9 @@ public static void main(String[] args) throws IOException { .sigmaTruncation(3d) .gmpes(gmpes.values()) .vs30(760d) + .maxDistance(maxDist) + .disablePointOptimizations(disablePointOptimize) + .setUseNSHMP_IMLs(nshmpIMLs) .build(); @@ -85,8 +102,7 @@ public static void main(String[] args) throws IOException { .baseName("nshm23") .addNameToken("hazard_validation") .addNameToken(regToken) - .addNameToken(gmpeToken) - .addNameToken(extraToken) + .addNameTokens(extraTokens) .build(); MPJ_BranchAveragedHazardScriptWriter.Request request = MPJ_BranchAveragedHazardScriptWriter.Request.builder() diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java index ab1a6d65..d2f67c12 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java @@ -5,6 +5,8 @@ import java.io.IOException; import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; @@ -14,11 +16,13 @@ import java.util.stream.Collectors; import org.apache.commons.math3.stat.StatUtils; +import org.apache.commons.math3.util.Precision; import org.jfree.chart.ui.RectangleAnchor; import org.jfree.data.Range; import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.Site; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; +import org.opensha.commons.data.function.DefaultXY_DataSet; import org.opensha.commons.data.function.DiscretizedFunc; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; import org.opensha.commons.data.function.HistogramFunction; @@ -29,6 +33,8 @@ import org.opensha.commons.data.xyz.GriddedGeoDataSet; import org.opensha.commons.geo.GriddedRegion; import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.LocationList; +import org.opensha.commons.geo.LocationUtils; import org.opensha.commons.geo.Region; import org.opensha.commons.geo.json.Feature; import org.opensha.commons.gui.plot.GeographicMapMaker; @@ -39,10 +45,12 @@ import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.param.Parameter; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.commons.util.MarkdownUtils; import org.opensha.commons.util.MarkdownUtils.TableBuilder; import org.opensha.commons.util.cpt.CPT; import org.opensha.sha.calc.HazardCurveCalculator; +import org.opensha.sha.calc.sourceFilters.FixedDistanceCutoffFilter; import org.opensha.sha.calc.sourceFilters.SourceFilterManager; import org.opensha.sha.calc.sourceFilters.SourceFilters; import org.opensha.sha.earthquake.AbstractERF; @@ -51,11 +59,16 @@ import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; import org.opensha.sha.earthquake.faultSysSolution.erf.BaseFaultSystemSolutionERF; +import org.opensha.sha.earthquake.faultSysSolution.modules.ClusterRuptures; +import org.opensha.sha.earthquake.faultSysSolution.modules.RupMFDsModule; +import org.opensha.sha.earthquake.faultSysSolution.ruptures.ClusterRupture; +import org.opensha.sha.earthquake.faultSysSolution.ruptures.util.RupCartoonGenerator; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc.ReturnPeriods; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; import org.opensha.sha.earthquake.param.IncludeBackgroundParam; import org.opensha.sha.earthquake.param.UseRupMFDsParam; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; import org.opensha.sha.earthquake.util.GridCellSupersamplingSettings; import org.opensha.sha.earthquake.util.GriddedSeismicitySettings; import org.opensha.sha.faultSurface.RuptureSurface; @@ -72,21 +85,15 @@ import com.google.common.base.Preconditions; import com.google.common.primitives.Doubles; +import gov.usgs.earthquake.nshmp.gmm.Gmm; +import gov.usgs.earthquake.nshmp.gmm.GmmInput; import gov.usgs.earthquake.nshmp.model.HazardModel; import gov.usgs.earthquake.nshmp.model.NshmErf; import net.mahdilamb.colormap.Colors; +import scratch.kevin.nshm23.hazardValidation.WrapperRupSetRupMapper.WrapperMatch; public class ComparisonPageGen { - private static enum CompType { - TOTAL, - CRUSTAL_FAULTS, - CRUSTAL_GRIDDED, - CRUSTAL, - INTERFACE, - SLAB - }; - public static void main(String[] args) throws IOException { // String imtName = "PGA"; // String imtDir = "PGA"; @@ -96,6 +103,12 @@ public static void main(String[] args) throws IOException { String imtDir = "SA1P0"; double period = 1d; + double closestDist = Double.POSITIVE_INFINITY; + for (Location loc : NSHM23_RegionLoader.GridSystemRegions.CEUS_STABLE.load().getBorder()) + if (loc.lat < 49d) + closestDist = Math.min(closestDist, LocationUtils.horzDistanceFast(loc, new Location(loc.lat, -115))); + System.out.println("Closest CEUS grid node to the -115 boundary: "+(int)closestDist+" km"); + // ReturnPeriods[] rps = ReturnPeriods.values(); ReturnPeriods[] rps = { ReturnPeriods.TWO_IN_50, ReturnPeriods.TEN_IN_50 }; @@ -113,14 +126,21 @@ public static void main(String[] args) throws IOException { String suffixMine = "opensha"; String suffixTheirs = "ext"; - File inputDir = new File("/home/kevin/OpenSHA/fss_inversions/2026_07_27-nshm23-hazard_validation-WUS-active_only"); + File fssDir = new File("/home/kevin/OpenSHA/fss_inversions"); + File nshm23Dir = new File(fssDir, "2024_02_02-nshm23_branches-WUS_FM_v3/"); + EnumSet bgOps = EnumSet.allOf(IncludeBackgroundOption.class); - File inputSolFile = new File("/home/kevin/OpenSHA/fss_inversions/2024_02_02-nshm23_branches-WUS_FM_v3/" - + "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"); +// EnumSet bgOps = EnumSet.of(IncludeBackgroundOption.EXCLUDE); +// EnumSet bgOps = EnumSet.of(IncludeBackgroundOption.ONLY); +// File inputDir = new File(fssDir, "2026_07_30-nshm23-hazard_validation-WUS"); +// File inputDir = new File(fssDir, "2026_07_30-nshm23-hazard_validation-WUS-maxDist300"); + File inputDir = new File(fssDir, "2026_07_30-nshm23-hazard_validation-WUS-maxDist300-nshmpIMLs"); + File inputSolFile = new File(nshm23Dir, "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"); boolean rupMFDs = false; - + File compDirActiveSub = new File("/home/kevin/OpenSHA/nshm23/nshmp-haz-models/ext_hazard_calcs/" + "conus_2023.R2-no_gmm_region-by_source-active_subduction-vs760-0p1-20260515-95ae7e82fbb85d"); +// + "conus_2023.R2-no_gmm_region-by_source-all-vs760-0p1-20260515-ad25787f499c13"); // hack for all, not just active File compDirStable = new File("/home/kevin/OpenSHA/nshm23/nshmp-haz-models/ext_hazard_calcs/" + "conus_2023.R2-no_gmm_region-by_source-stable-vs760-0p1-20260515-ea28700aef6c6f"); File outputDir = new File(inputDir, "nshmp_haz_comparisons_"+imtDir); @@ -132,17 +152,46 @@ public static void main(String[] args) throws IOException { GriddedRegion mapReg = GriddedRegion.fromFeature(Feature.read(new File(inputDir, "gridded_region.geojson"))); boolean plotTraces = false; - Region plotReg = mapReg; -// plotReg = new Region(new Location(37.5, -122.5), new Location(38.5, -121.5)); + Region zoomReg = null; + + Range curveXRange = new Range(1e-3, 1e1); + Range curveYRange = new Range(1e-6, 1e-0); +// Range curveXRange = new Range(1e-2, 1e1); +// Range curveYRange = new Range(1e-6, 1e-2); + + // the bay area paleo issue +// zoomReg = new Region(new Location(37.5, -122.5), new Location(38.5, -121.5)); + + // the rake-bin issue in NE CA +// curveXRange = new Range(1e-1, 1e1); +// curveYRange = new Range(1e-5, 2e-3); +// zoomReg = new Region(new Location(40, -122), new Location(41, -120)); + + // the dip issue near Santa Barbara +// curveXRange = new Range(1e-1, 1e1); +// curveYRange = new Range(1e-5, 2e-3); +// zoomReg = new Region(new Location(34, -121), new Location(35, -118)); + + // gridded degugging in Montana +// zoomReg = new Region(new Location(45, -110), new Location(49, -105)); + + // wider gridded degugging in NE corner +// zoomReg = new Region(new Location(40, -115), new Location(49, -105)); + + // Nevada-ish + zoomReg = new Region(new Location(35, -121), new Location(43, -113)); -// plotReg = new Region(new Location(40, -122), new Location(41, -120)); -// plotTraces = true; + SourceFilterManager sourceFilters = new SourceFilterManager(SourceFilters.TRT_DIST_CUTOFFS); +// SourceFilterManager sourceFilters = new SourceFilterManager(SourceFilters.FIXED_DIST_CUTOFF); +// sourceFilters.getFilterInstance(FixedDistanceCutoffFilter.class).setMaxDistance(300d); Map gmmRefs = Map.of( - TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_ACTIVE); + TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_ACTIVE, + TectonicRegionType.STABLE_SHALLOW, AttenRelRef.USGS_NSHM23_STABLE); // TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.NGAWest_2014_AVG_NOIDRISS); Map gmms = new HashMap<>(); + Map wrapperGMMs = gmms; for (TectonicRegionType trt : gmmRefs.keySet()) { ScalarIMR gmm = gmmRefs.get(trt).get(); gmm.setParamDefaults(); @@ -157,6 +206,20 @@ public static void main(String[] args) throws IOException { gmms.put(trt, gmm); } +// NSHMP_GMM_Wrapper mixedForWrapperGMM = new NSHMP_GMM_Wrapper.WeightedCombination( +// Map.of(Gmm.TOTAL_TREE_CONUS_ACTIVE_CRUST_2023, 2d/3d, +// Gmm.TOTAL_TREE_CONUS_STABLE_CRUST_2023, 1d/3d), "Hack Mixed GMM", "HackMixed", false); +// mixedForWrapperGMM.setParamDefaults(); +// mixedForWrapperGMM.getParameter(SigmaTruncLevelParam.NAME).setValue(3d); +// if (period == 0d) { +// mixedForWrapperGMM.setIntensityMeasure(PGA_Param.NAME); +// } else { +// mixedForWrapperGMM.setIntensityMeasure(SA_Param.NAME); +// SA_Param.setPeriodInSA_Param(mixedForWrapperGMM.getIntensityMeasure(), period); +// } +// wrapperGMMs = Map.of(TectonicRegionType.ACTIVE_SHALLOW, gmms.get(TectonicRegionType.ACTIVE_SHALLOW), +// TectonicRegionType.STABLE_SHALLOW, mixedForWrapperGMM); + File sourcesDirActiveSub = new File(compDirActiveSub, "vs30-"+vs30+"/"+imtDir+"/source"); File sourcesDirStable = new File(compDirStable, "vs30-"+vs30+"/"+imtDir+"/source"); boolean convertToProb = true; @@ -219,24 +282,32 @@ public static void main(String[] args) throws IOException { } FaultSystemSolution sol = null; - if (plotTraces || doWrapperCalc) + if (plotTraces || doWrapperCalc || zoomReg != null) sol = FaultSystemSolution.load(inputSolFile); - GeographicMapMaker mapMaker = new GeographicMapMaker(plotReg); + GeographicMapMaker fullMapMaker = new GeographicMapMaker(mapReg); + GeographicMapMaker zoomMapMaker = null; + if (zoomReg != null) { + zoomMapMaker = new GeographicMapMaker(zoomReg); + zoomMapMaker.setFaultSections(sol.getRupSet().getFaultSectionDataList()); + zoomMapMaker.setSectOutlineChar(null); + } if (plotTraces) { - mapMaker.setFaultSections(sol.getRupSet().getFaultSectionDataList()); - mapMaker.setSectOutlineChar(null); + fullMapMaker.setFaultSections(sol.getRupSet().getFaultSectionDataList()); + fullMapMaker.setSectOutlineChar(null); } // mapMaker.setDefaultPlotWidth(1000); - BaseFaultSystemSolutionERF solERF = null; + BaseFaultSystemSolutionERF solERF = new BaseFaultSystemSolutionERF(); if (doWrapperCalc) { - solERF = new BaseFaultSystemSolutionERF(); solERF.setSolution(sol); solERF.setGriddedSeismicitySettings(solERF.getGriddedSeismicitySettings().forSupersamplingSettings(GridCellSupersamplingSettings.QUICK)); - solERF.setParameter(UseRupMFDsParam.NAME, rupMFDs); + if (sol.hasModule(RupMFDsModule.class)) + solERF.setParameter(UseRupMFDsParam.NAME, rupMFDs); solERF.getTimeSpan().setDuration(1d); } + WrapperMatch[] wrapperMappings = null; + Color transparent = new Color(255, 255, 255, 0); CPT hazCPT = GMT_CPT_Files.RAINBOW_UNIFORM.instance().rescale(-3, 1); @@ -320,435 +391,539 @@ public static void main(String[] args) throws IOException { lines.add("### "+rp.label); lines.add(topLink); lines.add(""); - String hazLabel = imtName+", "+rp.label; - String prefix = bgOp.name()+"_"+rp.name(); - - TableBuilder table = MarkdownUtils.tableBuilder(); - - table.addLine(nameMine, nameTheirs); - - table.initNewLine(); - - mapMaker.plotXYZData(myMap, hazCPT, mapLabelAdd+nameMine+", "+hazLabel+" (g)"); - mapMaker.plot(resourcesDir, prefix+"_"+suffixMine, " "); - table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_"+suffixMine+".png)"); - mapMaker.plotXYZData(extMap, hazCPT, mapLabelAdd+nameTheirs+", "+hazLabel+" (g)"); - mapMaker.plot(resourcesDir, prefix+"_"+suffixTheirs, " "); - table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_"+suffixTheirs+".png)"); - - table.finalizeLine(); - - table.addLine(MarkdownUtils.boldCentered("Ratio"), MarkdownUtils.boldCentered("Difference")); - - GriddedGeoDataSet pDiff = mapPDiff(myMap, extMap); - GriddedGeoDataSet diff = mapDiff(myMap, extMap); - - table.initNewLine(); + boolean[] zooms = zoomReg == null ? new boolean[] {false} : new boolean[] {false,true}; - mapMaker.plotXYZData(pDiff, pDiffCPT, mapLabelAdd+nameMine+" vs "+nameTheirs+", % Change, "+hazLabel); - mapMaker.plot(resourcesDir, prefix+"_pDiff", " "); - table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_pDiff.png)"); - mapMaker.plotXYZData(diff, diffCPT, mapLabelAdd+nameMine+" - "+nameTheirs+", "+hazLabel+" (g)"); - mapMaker.plot(resourcesDir, prefix+"_diff", " "); - table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_diff.png)"); - - table.finalizeLine(); - table.addLine(diffStr(pDiff, true, plotReg), diffStr(diff, false, plotReg)); - - lines.addAll(table.build()); - lines.add(""); - - double maxDiff = Double.NEGATIVE_INFINITY; - double minDiff = Double.POSITIVE_INFINITY; - int maxDiffIndex = -1; - int minDiffIndex = -1; - for (int i=0; i maxDiff) { - maxDiff = v; - maxDiffIndex = i; - } - if (v < minDiff) { - minDiff = v; - minDiffIndex = i; - } - } - } - - table = MarkdownUtils.tableBuilder(); - - table.addLine("Min difference", "Max difference"); - - table.initNewLine(); - Site minSite = sites.get(minDiffIndex); - Site maxSite = sites.get(maxDiffIndex); - HazardCurveCalculator calc = new HazardCurveCalculator(new SourceFilterManager(SourceFilters.TRT_DIST_CUTOFFS)); - for (boolean min : new boolean[] {true,false}) { - int index = min ? minDiffIndex : maxDiffIndex; - Preconditions.checkState(index >= 0); - DiscretizedFunc myCurve = myCurves[index]; - DiscretizedFunc extCurve = extCurves[index]; - Location loc = mapReg.getLocation(index); - - List funcs = new ArrayList<>(); - List chars = new ArrayList<>(); - - myCurve.setName(nameMine); - extCurve.setName(nameTheirs); + for (boolean zoom : zooms) { + String hazLabel = imtName+", "+rp.label; + String prefix = bgOp.name()+"_"+rp.name(); - funcs.add(extCurve); - chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Colors.tab_orange)); + boolean curves = zoom || zooms.length == 1; - Site site = min ? minSite : maxSite; - - if (doWrapperCalc) { - DiscretizedFunc wrappedCurve = extCurve.deepClone(); - DiscretizedFunc logCurve = new ArbitrarilyDiscretizedFunc(); - for (int i=0; i param : site) - str += "

"+param.getName()+": "+param.getValue(); - table.addColumn(str); - } - table.finalizeLine(); - - if (doWrapperCalc && bgOp == IncludeBackgroundOption.EXCLUDE) { - // add distance hists - double maxDist = 50d; - double maxQuickDist = 60d; - int bins = 50; + mapMaker.plotXYZData(pDiff, pDiffCPT, mapLabelAdd+nameMine+" vs "+nameTheirs+", % Change, "+hazLabel); + mapMaker.plot(resourcesDir, prefix+"_pDiff", " "); + table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_pDiff.png)"); + mapMaker.plotXYZData(diff, diffCPT, mapLabelAdd+nameMine+" - "+nameTheirs+", "+hazLabel+" (g)"); + mapMaker.plot(resourcesDir, prefix+"_diff", " "); + table.addColumn("![Map]("+resourcesDir.getName()+"/"+prefix+"_diff.png)"); - List minWrapperSources = getSourcesWithinCutoff(wrapperERF, mapReg.getLocation(minDiffIndex), maxQuickDist); - List maxWrapperSources = getSourcesWithinCutoff(wrapperERF, mapReg.getLocation(maxDiffIndex), maxQuickDist); - List minFSSSources = getSourcesWithinCutoff(solERF, mapReg.getLocation(minDiffIndex), maxQuickDist); - List maxFSSSources = getSourcesWithinCutoff(solERF, mapReg.getLocation(maxDiffIndex), maxQuickDist); + table.finalizeLine(); + table.addLine(diffStr(pDiff, true, plotReg), diffStr(diff, false, plotReg)); - System.out.println("Max rate source within "+(float)maxDist+" km"); - table.initNewLine(); - for (boolean min : new boolean[] {true,false}) { - if (min) - System.out.println("Min site"); - else - System.out.println("Max site"); - Site site = min ? minSite : maxSite; - - List funcs = new ArrayList<>(); - List chars = new ArrayList<>(); - ProbEqkRupture fssRup = null; - for (boolean fss : new boolean[] {true,false}) { - List sources; - if (fss) { - System.out.print("FSS ERF:\t"); - sources = min ? minFSSSources : maxFSSSources; - } else { - System.out.print("Wrapped ERF:\t"); - sources = min ? minWrapperSources : maxWrapperSources; - } - double maxProb = 0d; - double maxRate = 0d; - ProbEqkSource maxSource = null; - ProbEqkRupture maxRup = null; - for (ProbEqkSource source : sources) { - for (ProbEqkRupture rup : source) { - double prob = rup.getProbability(); - double rate = rup.getMeanAnnualRate(1d); - if (prob > maxProb) { - maxProb = prob; - maxRate = rate; - maxSource = source; - maxRup = rup; - } + lines.addAll(table.build()); + lines.add(""); + + if (curves) { + double maxDiff = Double.NEGATIVE_INFINITY; + double minDiff = Double.POSITIVE_INFINITY; + int maxDiffIndex = -1; + int minDiffIndex = -1; + for (int i=0; i maxDiff) { + maxDiff = v; + maxDiffIndex = i; + } + if (v < minDiff) { + minDiff = v; + minDiffIndex = i; } } - String maxName = "M"+(float)maxRup.getMag()+", rake="+(float)maxRup.getAveRake() - +", P="+(float)maxProb+" rate="+(float)maxRate; - System.out.println("maxProb="+(float)maxProb+", maxRate="+(float)maxRate+", "+maxName+"; "+maxSource.getName()); - if (fss) - fssRup = maxRup; - + } + + table = MarkdownUtils.tableBuilder(); + + table.addLine("Min difference", "Max difference"); + + table.initNewLine(); + Site minSite = sites.get(minDiffIndex); + Site maxSite = sites.get(maxDiffIndex); + HazardCurveCalculator calc = new HazardCurveCalculator(sourceFilters); + for (boolean min : new boolean[] {true,false}) { int index = min ? minDiffIndex : maxDiffIndex; - DiscretizedFunc curve = fss ? myCurves[index] : extCurves[index]; - - DiscretizedFunc logIMs = new ArbitrarilyDiscretizedFunc(); - for (int i=0; i= 0); + DiscretizedFunc myCurve = myCurves[index]; + DiscretizedFunc extCurve = extCurves[index]; + Location loc = mapReg.getLocation(index); - ScalarIMR gmm = gmms.size() == 1 ? gmms.values().iterator().next() : gmms.get(maxSource.getTectonicRegionType()); - calc.getHazardCurve(logIMs, site, gmm, maxRup); + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); - if (gmm instanceof NSHMP_GMM_Wrapper) - System.out.println("\tGMM input:\t"+((NSHMP_GMM_Wrapper)gmm).getCurrentGmmInput()); + myCurve.setName(nameMine); + extCurve.setName(nameTheirs); - DiscretizedFunc ims = new ArbitrarilyDiscretizedFunc(); - for (int i=0; i= 0); - Location loc = mapReg.getLocation(index); - List wrapperSources = min ? minWrapperSources : maxWrapperSources; - List fssSources = min ? minFSSSources : maxFSSSources; - - EvenlyDiscretizedFunc rakeHistFSS = new EvenlyDiscretizedFunc(-180d, 180d, 181); - EvenlyDiscretizedFunc rakeHistWrapper = new EvenlyDiscretizedFunc(-180d, 180d, 181); - - for (ProbEqkSource source : fssSources) - for (ProbEqkRupture rup : source) - rakeHistFSS.add(rakeHistFSS.getClosestXIndex(rup.getAveRake()), rup.getMeanAnnualRate(1d)); - for (ProbEqkSource source : wrapperSources) - for (ProbEqkRupture rup : source) - rakeHistWrapper.add(rakeHistWrapper.getClosestXIndex(rup.getAveRake()), rup.getMeanAnnualRate(1d)); - - List funcs = new ArrayList<>(); - List chars = new ArrayList<>(); - - rakeHistWrapper.setName("Wrapper"); - funcs.add(rakeHistWrapper); - chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_green, 127))); - - rakeHistFSS.setName(nameMine); - funcs.add(rakeHistFSS); - chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_blue, 127))); - - PlotSpec plot = new PlotSpec(funcs, chars, " ", "Nearby rupture rake (degrees)", "Rate"); - plot.setLegendInset(RectangleAnchor.TOP_LEFT); - - HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); - - gp.drawGraphPanel(plot, false, false, new Range(-180, 180d), null); - - String histPrefix = prefix+"_hist_rake"; - if (min) - histPrefix += "_min"; - else - histPrefix += "_max"; - - PlotUtils.writePlots(resourcesDir, histPrefix, gp, 800, 800, true, true, false); - - table.addColumn("![Rake hist]("+resourcesDir.getName()+"/"+histPrefix+".png)"); - } - table.finalizeLine(); - - for (int d=0; d<3; d++) { - String distName; - HistogramFunction histFSS; - BiFunction distFunc; - if (d == 0) { - distName = "Rrup"; - histFSS = new HistogramFunction(0d, maxDist, bins); - distFunc = (S,L) -> S.getDistanceRup(L); - } else if (d == 1) { - distName = "Rjb"; - histFSS = new HistogramFunction(0d, maxDist, bins); - distFunc = (S,L) -> S.getDistanceJB(L); - } else { - distName = "RX"; - histFSS = new HistogramFunction(-maxDist, maxDist, bins); - distFunc = (S,L) -> S.getDistanceX(L); - } - - EvenlyDiscretizedFunc histWrapper = histFSS.deepClone(); - - table.initNewLine(); - for (boolean min : new boolean[] {true,false}) { - int index = min ? minDiffIndex : maxDiffIndex; - Preconditions.checkState(index >= 0); - Location loc = mapReg.getLocation(index); - List wrapperSources = min ? minWrapperSources : maxWrapperSources; - List fssSources = min ? minFSSSources : maxFSSSources; - histFSS.scale(0d); - histWrapper.scale(0d); + funcs.add(myCurve); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Colors.tab_blue)); - fillDistanceHist(fssSources, distFunc, histFSS, loc); - fillDistanceHist(wrapperSources, distFunc, histWrapper, loc); + if (doWrapperCalc) { + DiscretizedFunc fssCurve = myCurve.deepClone(); + DiscretizedFunc logCurve = new ArbitrarilyDiscretizedFunc(); + for (int i=0; i funcs = new ArrayList<>(); - List chars = new ArrayList<>(); + PlotSpec plot = new PlotSpec(funcs, chars, (float)loc.lat+", "+(float)loc.lon, hazLabel, "Annual Probability of Exceedance"); + plot.setLegendInset(true); - histWrapper.setName(null); - funcs.add(histWrapper); - chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_green, 127))); + HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); - histFSS.setName(null); - funcs.add(histFSS); - chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_blue, 127))); + gp.drawGraphPanel(plot, true, true, curveXRange, curveYRange); - EvenlyDiscretizedFunc cmlFSS = new EvenlyDiscretizedFunc(histFSS.getMinX()-0.5*histFSS.getDelta(), histFSS.size(), histFSS.getDelta()); - double sum = 0d; - for (int i=0; i param : site) + str += "

"+param.getName()+": "+param.getValue(); + table.addColumn(str); + } + table.finalizeLine(); + + if (doWrapperCalc && bgOp == IncludeBackgroundOption.EXCLUDE) { + // add distance hists + double maxDist = 50d; + double maxQuickDist = 60d; + int bins = 50; - PlotSpec plot = new PlotSpec(funcs, chars, " ", distName+" (km)", "Rate"); - plot.setLegendInset(RectangleAnchor.TOP_LEFT); + if (wrapperMappings == null) + wrapperMappings = WrapperRupSetRupMapper.map(sol, wrapperERF); + WrapperMatch[] myWrapperMappings = wrapperMappings; - HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); + List minFSSRups = getRupIndexesWithinCutoff(sol, mapReg.getLocation(minDiffIndex), maxQuickDist); + List minWrapperSources = minFSSRups.stream().map( + rupIndex->myWrapperMappings[rupIndex].wrapperSource()).collect(Collectors.toList()); + List minWrapperRups = minFSSRups.stream().map( + rupIndex->myWrapperMappings[rupIndex].wrapperRup()).collect(Collectors.toList()); + List maxFSSRups = getRupIndexesWithinCutoff(sol, mapReg.getLocation(maxDiffIndex), maxQuickDist); + List maxWrapperSources = maxFSSRups.stream().map( + rupIndex->myWrapperMappings[rupIndex].wrapperSource()).collect(Collectors.toList()); + List maxWrapperRups = maxFSSRups.stream().map( + rupIndex->myWrapperMappings[rupIndex].wrapperRup()).collect(Collectors.toList()); - gp.drawGraphPanel(plot, false, false, new Range(cmlFSS.getMinX(), cmlFSS.getMaxX()+cmlFSS.getDelta()), null); + int minRupIndex = -1; + int maxRupIndex = -1; - String histPrefix = prefix+"_hist_"+distName; - if (min) - histPrefix += "_min"; - else - histPrefix += "_max"; + System.out.println("Max rate source within "+(float)maxDist+" km"); + table.initNewLine(); + for (boolean min : new boolean[] {true,false}) { + Site site = min ? minSite : maxSite; + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + List fssIndexes = min ? minFSSRups : maxFSSRups; + List wrapperRups = min ? minWrapperRups : maxWrapperRups; + Preconditions.checkState(fssIndexes.size() == wrapperRups.size()); + + if (fssIndexes.isEmpty()) { + table.addColumn(""); + continue; + } + + // now find the rupture with the biggest change at our gm + int siteIndex = min ? minDiffIndex : maxDiffIndex; + double targetIM = curveVal(myCurves[siteIndex], rp); + + double maxDiffForRateDiff = 0d; + double maxRateDiff = 0d; + int maxDiffRupIndex = -1; + DiscretizedFunc maxDiffMyIMs = null; + DiscretizedFunc maxDiffTheirIMs = null; + ProbEqkRupture fssRup = null; + + for (int r=0; r maxRateDiff) { + maxRateDiff = rateDiff; + maxDiffMyIMs = myIMs; + maxDiffTheirIMs = theirIMs; + maxDiffRupIndex = rupIndex; + fssRup = myRup; + maxDiffForRateDiff = myDiff; + } + } + + if (min) + minRupIndex = maxDiffRupIndex; + else + maxRupIndex = maxDiffRupIndex; + + ProbEqkRupture wrapperRup = wrapperMappings[maxDiffRupIndex].wrapperRup(); + TectonicRegionType trt = wrapperMappings[maxDiffRupIndex].wrapperSource().getTectonicRegionType(); + ScalarIMR gmm = gmms.size() == 1 ? gmms.values().iterator().next() : gmms.get(trt); + String fssRupName = "M"+(float)fssRup.getMag()+", rake="+(float)fssRup.getAveRake() + +", P="+(float)fssRup.getProbability(); + String wrapperRupName = "M"+(float)wrapperRup.getMag()+", rake="+(float)wrapperRup.getAveRake() + +", P="+(float)wrapperRup.getProbability(); + + NSHMP_GMM_Wrapper wrapGMM = gmm instanceof NSHMP_GMM_Wrapper ? (NSHMP_GMM_Wrapper)gmm : null; + + if (min) + System.out.println("Min change rup for IM="+(float)targetIM+": "+maxDiffRupIndex); + else + System.out.println("Max change rup for IM="+(float)targetIM+": "+maxDiffRupIndex); + System.out.println("\tDiff: "+maxDiffForRateDiff); + System.out.println("\tRate: "+sol.getRateForRup(maxDiffRupIndex)); + System.out.println("\tRate-Diff: "+maxRateDiff); + System.out.println("\tFSS:\t"+fssRupName); + System.out.println("\t\tPOE:\t"+maxDiffMyIMs.getInterpolatedY_inLogXLogYDomain(targetIM)); + if (wrapGMM != null) { + wrapGMM.setEqkRupture(fssRup); + System.out.println("\t\tGmmInput:\t"+wrapGMM.getCurrentGmmInput()); + } + System.out.println("\tWrapper:\t"+wrapperRupName); + System.out.println("\t\tPOE:\t"+maxDiffTheirIMs.getInterpolatedY_inLogXLogYDomain(targetIM)); + if (wrapGMM != null) { + wrapGMM.setEqkRupture(wrapperRup); + System.out.println("\t\tGmmInput:\t"+wrapGMM.getCurrentGmmInput()); + } + + maxDiffMyIMs.setName(nameMine+" "+fssRupName); + funcs.add(maxDiffMyIMs); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Colors.tab_blue)); + + maxDiffTheirIMs.setName(nameTheirs+" "+wrapperRupName); + funcs.add(maxDiffTheirIMs); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Colors.tab_green)); + + if (wrapGMM != null) { + // extra tests + wrapGMM.setEqkRupture(fssRup); + GmmInput fssInput = wrapGMM.getCurrentGmmInput(); + wrapGMM.setEqkRupture(wrapperRup); + GmmInput wrapInput = wrapGMM.getCurrentGmmInput(); + + List updates = new ArrayList<>(); + List updateChars = new ArrayList<>(); + List updateNames = new ArrayList<>(); + + updates.add(GmmInput.builder().fromCopy(fssInput) + .rake(wrapInput.rake).build()); + updateNames.add("wrapper rake"); + updateChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 3f, Colors.tab_orange)); + + updates.add(GmmInput.builder().fromCopy(fssInput) + .rake(wrapInput.rake).dip(wrapInput.dip).build()); + updateNames.add("wrapper rake/dip"); + updateChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 3f, Colors.tab_purple)); + + updates.add(GmmInput.builder().fromCopy(fssInput) + .rake(wrapInput.rake).dip(wrapInput.dip).zHyp(wrapInput.zHyp).build()); + updateNames.add("wrapper rake/dip/zHyp"); + updateChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 3f, Colors.tab_olive)); + + for (int u=0; u= 0 && maxRupIndex >= 0) { + FaultSystemRupSet rupSet = sol.getRupSet(); + ClusterRuptures cRups = rupSet.requireModule(ClusterRuptures.class); + RupCartoonGenerator.plotRupture(resourcesDir, prefix+"_rup_min", cRups.get(minRupIndex), + "Rup "+minRupIndex+" M"+(float)rupSet.getMagForRup(minRupIndex) + +" rake="+(float)rupSet.getAveRakeForRup(minRupIndex) + +" dip="+(float)rupSet.getSurfaceForRupture(minRupIndex, 1d).getAveDip(), false, true); + RupCartoonGenerator.plotRupture(resourcesDir, prefix+"_rup_max", cRups.get(maxRupIndex), + "Rup "+maxRupIndex+" M"+(float)rupSet.getMagForRup(maxRupIndex) + +" rake="+(float)rupSet.getAveRakeForRup(maxRupIndex) + +" dip="+(float)rupSet.getSurfaceForRupture(maxRupIndex, 1d).getAveDip(), false, true); + + table.addLine("![Min rup]("+resourcesDir.getName()+"/"+prefix+"_rup_min.png)", + "![Max rup]("+resourcesDir.getName()+"/"+prefix+"_rup_max.png)"); + } - table.addColumn("!["+distName+" hist]("+resourcesDir.getName()+"/"+histPrefix+".png)"); + // rake hist + table.initNewLine(); + for (boolean min : new boolean[] {true,false}) { + int index = min ? minDiffIndex : maxDiffIndex; + Preconditions.checkState(index >= 0); + Location loc = mapReg.getLocation(index); + List wrapperRups = min ? minWrapperRups : maxWrapperRups; + List fssIndexes = min ? minFSSRups : maxFSSRups; + List fssSources = fssIndexes.stream().map( + I->solERF.getSource(solERF.getSrcIndexForFltSysRup(I))).collect(Collectors.toList()); + + EvenlyDiscretizedFunc rakeHistFSS = new EvenlyDiscretizedFunc(-180d, 180d, 181); + EvenlyDiscretizedFunc rakeHistWrapper = new EvenlyDiscretizedFunc(-180d, 180d, 181); + + for (ProbEqkSource source : fssSources) + for (ProbEqkRupture rup : source) + rakeHistFSS.add(rakeHistFSS.getClosestXIndex(rup.getAveRake()), rup.getMeanAnnualRate(1d)); + for (ProbEqkRupture rup : wrapperRups) + rakeHistWrapper.add(rakeHistWrapper.getClosestXIndex(rup.getAveRake()), rup.getMeanAnnualRate(1d)); + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + rakeHistWrapper.setName("Wrapper"); + funcs.add(rakeHistWrapper); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_green, 127))); + + rakeHistFSS.setName(nameMine); + funcs.add(rakeHistFSS); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_blue, 127))); + + PlotSpec plot = new PlotSpec(funcs, chars, " ", "Nearby rupture rake (degrees)", "Rate"); + plot.setLegendInset(RectangleAnchor.TOP_LEFT); + + HeadlessGraphPanel gp = PlotUtils.initScreenHeadless(); + + gp.drawGraphPanel(plot, false, false, new Range(-180, 180d), null); + + String histPrefix = prefix+"_hist_rake"; + if (min) + histPrefix += "_min"; + else + histPrefix += "_max"; + + PlotUtils.writePlots(resourcesDir, histPrefix, gp, 800, 800, true, true, false); + + table.addColumn("![Rake hist]("+resourcesDir.getName()+"/"+histPrefix+".png)"); + } + table.finalizeLine(); + + for (int d=0; d<3; d++) { + String distName; + HistogramFunction histFSS; + BiFunction distFunc; + if (d == 0) { + distName = "Rrup"; + histFSS = new HistogramFunction(0d, maxDist, bins); + distFunc = (S,L) -> S.getDistanceRup(L); + } else if (d == 1) { + distName = "Rjb"; + histFSS = new HistogramFunction(0d, maxDist, bins); + distFunc = (S,L) -> S.getDistanceJB(L); + } else { + distName = "RX"; + histFSS = new HistogramFunction(-maxDist, maxDist, bins); + distFunc = (S,L) -> S.getDistanceX(L); + } + + EvenlyDiscretizedFunc histWrapper = histFSS.deepClone(); + + table.initNewLine(); + for (boolean min : new boolean[] {true,false}) { + int index = min ? minDiffIndex : maxDiffIndex; + Preconditions.checkState(index >= 0); + Location loc = mapReg.getLocation(index); + List wrapperSources = min ? minWrapperSources : maxWrapperSources; + List fssIndexes = min ? minFSSRups : maxFSSRups; + List fssSources = fssIndexes.stream().map( + I->solERF.getSource(solERF.getSrcIndexForFltSysRup(I))).collect(Collectors.toList()); + + histFSS.scale(0d); + histWrapper.scale(0d); + + fillDistanceHist(fssSources, distFunc, histFSS, loc); + fillDistanceHist(wrapperSources, distFunc, histWrapper, loc); + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + histWrapper.setName(null); + funcs.add(histWrapper); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_green, 127))); + + histFSS.setName(null); + funcs.add(histFSS); + chars.add(new PlotCurveCharacterstics(PlotLineType.HISTOGRAM, 1f, trans(Colors.tab_blue, 127))); + + EvenlyDiscretizedFunc cmlFSS = new EvenlyDiscretizedFunc(histFSS.getMinX()-0.5*histFSS.getDelta(), histFSS.size(), histFSS.getDelta()); + double sum = 0d; + for (int i=0; i curve.getMaxY()) - val = 0d; - else if (rp.oneYearProb < curve.getMinY()) - // saturated - val = curve.getMaxX(); - else - val = curve.getFirstInterpolatedX_inLogXLogYDomain(rp.oneYearProb); - ret.set(i, val); - } + for (int i=0; i getSourcesWithinCutoff(AbstractERF erf, Locat return erf.getSourceList().parallelStream().filter(S->(float)S.getMinDistance(site) <= (float)cutoff).collect(Collectors.toList()); } + private static List getRupIndexesWithinCutoff(FaultSystemSolution sol, Location loc, double cutoff) { + List ret = new ArrayList<>(); + FaultSystemRupSet rupSet = sol.getRupSet(); + for (int rupIndex=0; rupIndex sources, BiFunction distFunc, EvenlyDiscretizedFunc hist, Location loc) { float min = (float)(hist.getMinX() < 0 ? hist.getMinX() - 0.5*hist.getDelta() : 0d); @@ -1064,5 +1240,17 @@ private static void fillDistanceHist(List sources, BiFunction curve.getMaxY()) + return 0d; + if (rp.oneYearProb < curve.getMinY()) + // saturated + return curve.getMaxX(); + return curve.getFirstInterpolatedX_inLogXLogYDomain(rp.oneYearProb); +// return curve.getFirstInterpolatedX_inLogYDomain(rp.oneYearProb); + } } diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/CorrRJBPlot.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/CorrRJBPlot.java new file mode 100644 index 00000000..c686b8cc --- /dev/null +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/CorrRJBPlot.java @@ -0,0 +1,62 @@ +package scratch.kevin.nshm23.hazardValidation; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.jfree.chart.title.PaintScaleLegend; +import org.jfree.chart.ui.RectangleEdge; +import org.opensha.commons.data.function.DiscretizedFunc; +import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.gui.plot.GraphPanel; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.rupForecastImpl.PointSourceNshm.DistanceCorrection2013; +import org.opensha.sha.util.TectonicRegionType; + +public class CorrRJBPlot { + + public static void main(String[] args) throws IOException { + File outputDir = new File("/tmp"); + + CPT magCPT = GMT_CPT_Files.SEQUENTIAL_BATLOW_UNIFORM.instance().rescale(6d, 8d); + + EvenlyDiscretizedFunc magRange = new EvenlyDiscretizedFunc(6.05, 19, 0.1); + EvenlyDiscretizedFunc distRange = new EvenlyDiscretizedFunc(0d, 100, 1d); + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + DistanceCorrection2013 corr = new DistanceCorrection2013(); + TectonicRegionType trt = TectonicRegionType.ACTIVE_SHALLOW; + + for (int m=0; m myRups = gridList.getRuptures(trt, gridIndex); + ProbEqkSource mySource = gridList.getSource(trt, gridIndex, 1d, null, gridSettings); + Preconditions.checkState(myRups.size() == mySource.getNumRuptures()); + Site fakeSite = new Site(testLoc); + ProbEqkSource match = null; + for (ProbEqkSource source : wrapper) { + if (source.getTectonicRegionType() != trt) + continue; + if (source.getMinDistance(fakeSite) < 0.001) { + Preconditions.checkState(match == null, "Multiple matches"); + match = source; + } + } + + Preconditions.checkNotNull(match); + + System.out.println("We have "+myRups.size()+" ruptures"); + System.out.println("Wrapper has "+match.getNumRuptures()+" ruptures"); + + List unmapped = new ArrayList<>(match.getNumRuptures()); + for (int i=0; i matches = new ArrayList<>(); + GriddedRupture rup = myRups.get(g); + ProbEqkRupture myProbRup = mySource.getRupture(g); + double mag = rup.properties.magnitude; + double rake = rup.properties.rake; + for (int i=unmapped.size(); --i>=0;) { + int index = unmapped.get(i); + ProbEqkRupture probRup = match.getRupture(index); + if (Precision.equals(mag, probRup.getMag(), 0.001) && Precision.equals(rake, probRup.getAveRake(), 1)) { + matches.add(index); + unmapped.remove(i); + } + } + Collections.reverse(matches); + + PointSurface.DistanceCorrectable surf = (PointSurface.DistanceCorrectable) myProbRup.getRuptureSurface(); + + double rateSum = 0d; + System.out.println("Ours:\t"+rupStr(rup)); + for (int l=0; l<2; l++) { + Location loc = l == 0 ? testLoc : refLoc; + String locStr = l == 0 ? "Colocated" : (int)refDist+" km away"; + WeightedList dists = surf.getCorrectedDistances(loc); + for (int d=0; d rups = new ArrayList<>(); + for (int sourceID=0; sourceID bgOps = EnumSet.of(IncludeBackgroundOption.ONLY); // File inputDir = new File(fssDir, "2026_07_30-nshm23-hazard_validation-WUS"); // File inputDir = new File(fssDir, "2026_07_30-nshm23-hazard_validation-WUS-maxDist300"); - File inputDir = new File(fssDir, "2026_07_30-nshm23-hazard_validation-WUS-maxDist300-nshmpIMLs"); +// File inputDir = new File(fssDir, "2026_07_30-nshm23-hazard_validation-WUS-maxDist300-nshmpIMLs"); +// File inputDir = new File(fssDir, "2026_07_31-nshm23-hazard_validation-WUS-origRakes-maxDist300-nshmpIMLs"); +// File inputDir = new File(fssDir, "2026_08_01-nshm23-hazard_validation-WUS-origNGAW2-maxDist300-nshmpIMLs"); + File inputDir = new File(fssDir, "2026_08_01-nshm23-hazard_validation-WUS-origRakes-origNGAW2-maxDist300-nshmpIMLs"); File inputSolFile = new File(nshm23Dir, "results_WUS_FM_v3_branch_averaged_gridded_simplified_revised2026.zip"); boolean rupMFDs = false; From 93a3b9498b8e432159b311b377cc3976687fa4a3 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Wed, 5 Aug 2026 11:01:38 -0700 Subject: [PATCH 49/71] Refactored nshm packages back into opensha namespace Sorry Peter, but these classes use the OpenSHA APIs and should not be in the nshmp-haz namespace. Putting them in gov.usgs.earthquake.nshmp implies that they work with the NSHMP-haz APIs, which they don't. --- .../BranchAveragedHazardScriptWriter.java | 6 ++--- .../HardcodedInversionFactoryRunner.java | 20 +++++++------- ..._LogicTreeInversionRunnerScriptWriter.java | 8 +++--- .../ComparisonCalcScriptWriter.java | 13 +++++----- .../kevin/nshm27/BathymetryConvert.java | 4 +-- .../nshm27/BranchHalfBiasInvestigation.java | 9 +++---- .../nshm27/DownDipRupSetBuildingTests.java | 2 +- .../nshm27/InterfaceSlipRatePercentiles.java | 7 +++-- .../InterfaceSubSeisMoReductionTests.java | 21 +++++++-------- .../nshm27/InversionMinSubSectMagTests.java | 9 +++---- .../java/scratch/kevin/nshm27/LmaxTests.java | 7 +++-- .../scratch/kevin/nshm27/TreeBinCounts.java | 3 +-- .../kevin/nshm27/figures/BValDistFigure.java | 16 ++++++------ .../nshm27/figures/CombinedMFDsFigure.java | 20 +++++++------- .../nshm27/figures/DMLowerLimitTests.java | 11 ++++---- .../InterfaceLogicTreeMFDExploration.java | 26 +++++++++---------- .../figures/InterfaceObsSeisAdjFigures.java | 9 +++---- .../InterfaceParticipationRateFigures.java | 11 ++++---- .../kevin/nshm27/figures/LogicTreeFigure.java | 7 +++-- .../nshm27/figures/NSHM27_PaperPaths.java | 2 +- .../figures/ObsUncertaintyBoundsFigure.java | 22 ++++++++-------- .../nshm27/figures/SlipProjectionFigures.java | 10 +++---- .../prvi25/GriddedSeismicityMFDTests.java | 5 ++-- .../kevin/prvi25/RateFileScale1973to1900.java | 5 ++-- .../prvi25/RateModelAvgVsPreferredTest.java | 3 +-- .../prvi25/figures/CombinedMFDsPlot.java | 12 ++++----- .../prvi25/figures/IndividualMFDPlots.java | 4 +-- .../figures/ObsUncertaintyBoundsFigure.java | 10 +++---- .../prvi25/figures/RateEpochComparison.java | 6 ++--- .../prvi25/figures/RateModelComparison.java | 8 +++--- .../scratch/kevin/ucerf3/PureScratch.java | 4 +-- 31 files changed, 143 insertions(+), 157 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java b/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java index 66e2bd97..5aedd693 100644 --- a/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/BranchAveragedHazardScriptWriter.java @@ -21,6 +21,9 @@ import org.opensha.sha.earthquake.param.BackgroundRupType; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_MapRegions; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader; import org.opensha.sha.faultSurface.utils.ptSrcCorr.PointSourceDistanceCorrections; import org.opensha.sha.imr.AttenRelRef; @@ -28,9 +31,6 @@ import com.google.common.base.Preconditions; import edu.usc.kmilner.mpj.taskDispatch.MPJTaskCalculator; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_MapRegions; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; public class BranchAveragedHazardScriptWriter { diff --git a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java index 1e1a6333..55b25ba8 100644 --- a/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java +++ b/src/main/java/scratch/kevin/nshm23/HardcodedInversionFactoryRunner.java @@ -51,6 +51,16 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_DeformationModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_FaultModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_LogicTreeBranch; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.NSHM27_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_CrustalDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceMinSubSects; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisRateModelBranch; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.PRVI25_InvConfigFactory; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalDeformationModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalFaultModels; @@ -64,16 +74,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_CrustalDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceMinSubSects; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelBranch; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import scratch.UCERF3.enumTreeBranches.ScalingRelationships; import scratch.UCERF3.inversion.U3InversionConfigFactory; import scratch.UCERF3.logicTree.U3LogicTreeBranch; diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index 6e8747c6..afcad577 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -84,6 +84,10 @@ import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_FaultModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.prior2018.NSHM18_LogicTreeBranch; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.NSHM27_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_MapRegions; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_LogicTree; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader; @@ -99,10 +103,6 @@ import com.google.common.collect.ImmutableList; import edu.usc.kmilner.mpj.taskDispatch.MPJTaskCalculator; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_MapRegions; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import scratch.UCERF3.enumTreeBranches.DeformationModels; import scratch.UCERF3.enumTreeBranches.FaultModels; import scratch.UCERF3.enumTreeBranches.ScalingRelationships; diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java index 6c0c1367..20da026c 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java @@ -16,6 +16,12 @@ import org.opensha.commons.geo.LocationList; import org.opensha.commons.geo.Region; import org.opensha.commons.param.Parameter; +import org.opensha.sha.earthquake.faultSysSolution.mpj.HPCConfig; +import org.opensha.sha.earthquake.faultSysSolution.mpj.HazardConfig; +import org.opensha.sha.earthquake.faultSysSolution.mpj.MPJ_BranchAveragedHazardScriptWriter; +import org.opensha.sha.earthquake.faultSysSolution.mpj.RunConfig; +import org.opensha.sha.earthquake.faultSysSolution.mpj.HPCConfig.HPCSite; +import org.opensha.sha.earthquake.faultSysSolution.mpj.MPJ_BranchAveragedHazardScriptWriter.SupersamplingMode; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.util.NSHM23_RegionLoader; @@ -23,13 +29,6 @@ import org.opensha.sha.imr.AttenRelRef; import org.opensha.sha.util.TectonicRegionType; -import gov.usgs.earthquake.nshmp.erf.mpj.HPCConfig; -import gov.usgs.earthquake.nshmp.erf.mpj.HPCConfig.HPCSite; -import gov.usgs.earthquake.nshmp.erf.mpj.HazardConfig; -import gov.usgs.earthquake.nshmp.erf.mpj.MPJ_BranchAveragedHazardScriptWriter; -import gov.usgs.earthquake.nshmp.erf.mpj.MPJ_BranchAveragedHazardScriptWriter.SupersamplingMode; -import gov.usgs.earthquake.nshmp.erf.mpj.RunConfig; - public class ComparisonCalcScriptWriter { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java b/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java index d9ba8d4e..629099f1 100644 --- a/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java +++ b/src/main/java/scratch/kevin/nshm27/BathymetryConvert.java @@ -12,11 +12,11 @@ import org.opensha.commons.gui.plot.GeographicMapMaker; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.NSHM27_GridSourceBuilder; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_GridSourceBuilder; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import net.mahdilamb.colormap.Colors; public class BathymetryConvert { diff --git a/src/main/java/scratch/kevin/nshm27/BranchHalfBiasInvestigation.java b/src/main/java/scratch/kevin/nshm27/BranchHalfBiasInvestigation.java index 79ce5fb7..2d751e0d 100644 --- a/src/main/java/scratch/kevin/nshm27/BranchHalfBiasInvestigation.java +++ b/src/main/java/scratch/kevin/nshm27/BranchHalfBiasInvestigation.java @@ -7,11 +7,10 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeNode; - -import gov.usgs.earthquake.nshmp.erf.logicTree.TectonicRegionBranchTreeNode; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceHingedBValue.CombinedSampledType; +import org.opensha.commons.logicTree.TectonicRegionBranchTreeNode; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceHingedBValue.CombinedSampledType; public class BranchHalfBiasInvestigation { diff --git a/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java b/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java index 8b268897..79cf9d16 100644 --- a/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java +++ b/src/main/java/scratch/kevin/nshm27/DownDipRupSetBuildingTests.java @@ -29,6 +29,7 @@ import org.opensha.sha.earthquake.faultSysSolution.ruptures.downDip.RectangularDownDipGrowingStrategy.NeighborOverlaps; import org.opensha.sha.earthquake.faultSysSolution.ruptures.util.GeoJSONFaultReader; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.faultSurface.GeoJSONFaultSection; @@ -36,7 +37,6 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Range; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; import net.mahdilamb.colormap.Colors; public class DownDipRupSetBuildingTests { diff --git a/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java b/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java index 3c867db4..30da9687 100644 --- a/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java +++ b/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java @@ -7,10 +7,9 @@ import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.AverageSampler; import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.FixedFractileSampler; import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.FixedSampler; - -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels.DeformationFront; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels.DeformationFront; public class InterfaceSlipRatePercentiles { diff --git a/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java index 9c6f23b4..4076d5fe 100644 --- a/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java +++ b/src/main/java/scratch/kevin/nshm27/InterfaceSubSeisMoReductionTests.java @@ -23,23 +23,22 @@ import org.opensha.commons.util.cpt.CPT; import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_DeclusteringAlgorithms; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisClassificationMethod; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisRateModelBranch; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisSmoothingAlgorithms; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.InterfaceGridAssociations; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_SeisPDF_Loader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.faultSurface.FaultTrace; import org.opensha.sha.faultSurface.RuptureSurface; import org.opensha.sha.magdist.IncrementalMagFreqDist; import org.opensha.sha.util.TectonicRegionType; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_DeclusteringAlgorithms; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisClassificationMethod; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelBranch; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisSmoothingAlgorithms; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.InterfaceGridAssociations; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_SeisPDF_Loader; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; - public class InterfaceSubSeisMoReductionTests { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java b/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java index 190ded00..52b574e5 100644 --- a/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java +++ b/src/main/java/scratch/kevin/nshm27/InversionMinSubSectMagTests.java @@ -9,14 +9,13 @@ import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.NSHM27_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceMinSubSects; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; import org.opensha.sha.util.TectonicRegionType; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceMinSubSects; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; - public class InversionMinSubSectMagTests { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm27/LmaxTests.java b/src/main/java/scratch/kevin/nshm27/LmaxTests.java index 38de3187..f7a34264 100644 --- a/src/main/java/scratch/kevin/nshm27/LmaxTests.java +++ b/src/main/java/scratch/kevin/nshm27/LmaxTests.java @@ -8,13 +8,12 @@ import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.NSHM27_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; import org.opensha.sha.util.TectonicRegionType; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; - public class LmaxTests { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java b/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java index 2408f497..e6713819 100644 --- a/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java +++ b/src/main/java/scratch/kevin/nshm27/TreeBinCounts.java @@ -10,14 +10,13 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.TectonicRegionBranchTreeNode; import org.opensha.commons.logicTree.LogicTreeLevel.BinnableLevel; import org.opensha.commons.logicTree.LogicTreeLevel.BinnedLevel; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; -import gov.usgs.earthquake.nshmp.erf.logicTree.TectonicRegionBranchTreeNode; - public class TreeBinCounts { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java b/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java index 05f3b671..1584c8c3 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java @@ -33,18 +33,18 @@ import org.opensha.commons.util.modules.ModuleContainer; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.PureGR; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.SectionSupraSeisBValues; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.SectionSupraSeisBValues.DistributionSamplingLevel; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.NSHM27_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceHingedBValue; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisClassificationMethod; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisRateModel; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.util.TectonicRegionType; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceHingedBValue; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisClassificationMethod; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModel; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.PureGR; import net.mahdilamb.colormap.Colors; public class BValDistFigure { diff --git a/src/main/java/scratch/kevin/nshm27/figures/CombinedMFDsFigure.java b/src/main/java/scratch/kevin/nshm27/figures/CombinedMFDsFigure.java index acb9255b..78a1de39 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/CombinedMFDsFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/CombinedMFDsFigure.java @@ -33,7 +33,17 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList; import org.opensha.sha.earthquake.faultSysSolution.modules.RegionsOfInterest; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.PureGR; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_DeclusteringAlgorithms; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisClassificationMethod; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisRateModelBranch; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisRateModelSamples; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisSmoothingAlgorithms; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_SeisPDF_Loader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_MapRegions; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.magdist.GutenbergRichterMagFreqDist; import org.opensha.sha.magdist.IncrementalMagFreqDist; @@ -42,16 +52,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_DeclusteringAlgorithms; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisClassificationMethod; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelBranch; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelSamples; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisSmoothingAlgorithms; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_MapRegions; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_SeisPDF_Loader; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.PureGR; import net.mahdilamb.colormap.Colors; import oracle.net.aso.i; diff --git a/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java b/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java index 2714cf67..42a531b6 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java +++ b/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java @@ -19,17 +19,16 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; import org.opensha.sha.earthquake.faultSysSolution.modules.SectSlipRates; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.NSHM27_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceHingedBValue; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceHingedBValue; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; - public class DMLowerLimitTests { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java index 2211522a..d63e4087 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java @@ -44,7 +44,20 @@ import org.opensha.sha.earthquake.faultSysSolution.ruptures.plausibility.impl.prob.RuptureProbabilityCalc.BinaryRuptureProbabilityCalc; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; import org.opensha.sha.earthquake.faultSysSolution.util.MaxRuptureLengthBranchNode; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.PureGR; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.SectionSupraSeisBValues; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.NSHM27_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceHingedBValue; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceMinSubSects; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisClassificationMethod; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisRateModel; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceHingedBValue.CombinedSampledType; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionScalingRelationships; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.magdist.GutenbergRichterMagFreqDist; @@ -54,19 +67,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceHingedBValue; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceHingedBValue.CombinedSampledType; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceMinSubSects; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisClassificationMethod; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModel; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.PureGR; import net.mahdilamb.colormap.Colors; public class InterfaceLogicTreeMFDExploration { diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java index 9dbe03f1..3b3a65ce 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceObsSeisAdjFigures.java @@ -18,15 +18,14 @@ import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.modules.SectSlipRates; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.NSHM27_InvConfigFactory; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.NSHM27_InvConfigFactory; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; - public class InterfaceObsSeisAdjFigures { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceParticipationRateFigures.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceParticipationRateFigures.java index 4738a06a..d63c170c 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceParticipationRateFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceParticipationRateFigures.java @@ -19,18 +19,17 @@ import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.RupSetDeformationModelDistribution.BinnedUniformSamplingLevel; import org.opensha.sha.earthquake.faultSysSolution.modules.SolutionLogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceHingedBValue; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; import com.google.common.primitives.Ints; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceHingedBValue; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceObsSeisDMAdjustment; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; - class InterfaceParticipationRateFigures { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java index 2f922bfc..60278286 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java @@ -14,14 +14,13 @@ import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.sha.earthquake.faultSysSolution.RupSetFaultModel; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; - public class LogicTreeFigure { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/nshm27/figures/NSHM27_PaperPaths.java b/src/main/java/scratch/kevin/nshm27/figures/NSHM27_PaperPaths.java index 11a5d78b..05ab858a 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/NSHM27_PaperPaths.java +++ b/src/main/java/scratch/kevin/nshm27/figures/NSHM27_PaperPaths.java @@ -9,9 +9,9 @@ import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.util.TectonicRegionType; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import net.mahdilamb.colormap.Colors; public class NSHM27_PaperPaths { diff --git a/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java b/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java index 08f5fb0d..e5c8a038 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/ObsUncertaintyBoundsFigure.java @@ -38,22 +38,22 @@ import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.commons.util.cpt.CPT; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateModel; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.Exact; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.PureGR; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateRecord; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateType; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisClassificationMethod; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisRateModelBranch; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisRateModelSamples; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.magdist.GutenbergRichterMagFreqDist; import org.opensha.sha.util.TectonicRegionType; import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisClassificationMethod; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelBranch; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_SeisRateModelSamples; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader; -import gov.usgs.earthquake.nshmp.erf.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Exact; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.PureGR; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateRecord; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; import net.mahdilamb.colormap.Colors; import static scratch.kevin.nshm27.figures.NSHM27_PaperPaths.*; diff --git a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java index 78bb37e5..fa66f60c 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/SlipProjectionFigures.java @@ -27,6 +27,11 @@ import org.opensha.commons.util.FaultUtils; import org.opensha.commons.util.FaultUtils.AngleAverager; import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels.DeformationFront; import org.opensha.sha.faultSurface.FaultSection; import org.opensha.sha.faultSurface.FaultTrace; import org.opensha.sha.faultSurface.GeoJSONFaultSection; @@ -34,11 +39,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceDeformationModels.DeformationFront; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_InterfaceFaultModels; -import gov.usgs.earthquake.nshmp.erf.nshm27.logicTree.NSHM27_LogicTree; import net.mahdilamb.colormap.Colors; public class SlipProjectionFigures { diff --git a/src/main/java/scratch/kevin/prvi25/GriddedSeismicityMFDTests.java b/src/main/java/scratch/kevin/prvi25/GriddedSeismicityMFDTests.java index 6637da50..f2977c8e 100644 --- a/src/main/java/scratch/kevin/prvi25/GriddedSeismicityMFDTests.java +++ b/src/main/java/scratch/kevin/prvi25/GriddedSeismicityMFDTests.java @@ -17,6 +17,8 @@ import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.Exact; import org.opensha.sha.magdist.GutenbergRichterMagFreqDist; import org.opensha.sha.magdist.IncrementalMagFreqDist; import org.opensha.sha.magdist.SummedMagFreqDist; @@ -24,9 +26,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Exact; - public class GriddedSeismicityMFDTests { private static final double FAKE_MFD_TARGET_TOTAL = 2d; diff --git a/src/main/java/scratch/kevin/prvi25/RateFileScale1973to1900.java b/src/main/java/scratch/kevin/prvi25/RateFileScale1973to1900.java index 953b860d..a7ceed52 100644 --- a/src/main/java/scratch/kevin/prvi25/RateFileScale1973to1900.java +++ b/src/main/java/scratch/kevin/prvi25/RateFileScale1973to1900.java @@ -7,15 +7,14 @@ import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.uncertainty.UncertaintyBoundType; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateModel; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateType; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader.PRVI25_SeismicityRegions; import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; - public class RateFileScale1973to1900 { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/prvi25/RateModelAvgVsPreferredTest.java b/src/main/java/scratch/kevin/prvi25/RateModelAvgVsPreferredTest.java index 3f32205a..3a67c848 100644 --- a/src/main/java/scratch/kevin/prvi25/RateModelAvgVsPreferredTest.java +++ b/src/main/java/scratch/kevin/prvi25/RateModelAvgVsPreferredTest.java @@ -2,6 +2,7 @@ import java.io.IOException; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateModel; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionCaribbeanSeismicityRate; @@ -10,8 +11,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; - public class RateModelAvgVsPreferredTest { public static void main(String[] args) throws IOException { diff --git a/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java b/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java index d309ec97..ca3b4843 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java +++ b/src/main/java/scratch/kevin/prvi25/figures/CombinedMFDsPlot.java @@ -40,6 +40,12 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList; import org.opensha.sha.earthquake.faultSysSolution.modules.GridSourceList.GriddedRupture; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateModel; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.Direct; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.Exact; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateRecord; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateType; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.PRVI25_GridSourceBuilder; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; @@ -52,12 +58,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Direct; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Exact; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateRecord; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import net.mahdilamb.colormap.Colors; import scratch.kevin.latex.LaTeXUtils; diff --git a/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java b/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java index 42ba36c6..0e1a834d 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java +++ b/src/main/java/scratch/kevin/prvi25/figures/IndividualMFDPlots.java @@ -45,6 +45,8 @@ import org.opensha.sha.earthquake.faultSysSolution.modules.RegionsOfInterest; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSectionUtils; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateModel; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateType; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.NSHM23_SegmentationModels; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.gridded.PRVI25_GridSourceBuilder; @@ -66,8 +68,6 @@ import com.google.common.base.Preconditions; import com.google.common.primitives.Ints; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import gov.usgs.earthquake.nshmp.model.NshmErf; import net.mahdilamb.colormap.Colors; import scratch.kevin.latex.LaTeXUtils; diff --git a/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java b/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java index a351236f..1d6f3de9 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java +++ b/src/main/java/scratch/kevin/prvi25/figures/ObsUncertaintyBoundsFigure.java @@ -31,6 +31,11 @@ import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.Exact; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.PureGR; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateRecord; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateType; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionCaribbeanSeismicityRate; @@ -40,11 +45,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Exact; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.PureGR; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateRecord; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import net.mahdilamb.colormap.Colors; import static scratch.kevin.prvi25.figures.PRVI_Paths.*; diff --git a/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java b/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java index 64973ca3..2cc3d1c0 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java +++ b/src/main/java/scratch/kevin/prvi25/figures/RateEpochComparison.java @@ -21,6 +21,9 @@ import org.opensha.commons.gui.plot.PlotSpec; import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateModel; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.Direct; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SubductionCaribbeanSeismicityRate; @@ -30,9 +33,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Direct; import net.mahdilamb.colormap.Colors; public class RateEpochComparison { diff --git a/src/main/java/scratch/kevin/prvi25/figures/RateModelComparison.java b/src/main/java/scratch/kevin/prvi25/figures/RateModelComparison.java index 69872450..ecb859b9 100644 --- a/src/main/java/scratch/kevin/prvi25/figures/RateModelComparison.java +++ b/src/main/java/scratch/kevin/prvi25/figures/RateModelComparison.java @@ -21,6 +21,10 @@ import org.opensha.commons.gui.plot.PlotSpec; import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateModel; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.Direct; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateType; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_CrustalSeismicityRate; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.logicTree.PRVI25_SeismicityRateEpoch; import org.opensha.sha.earthquake.rupForecastImpl.prvi25.util.PRVI25_RegionLoader.PRVI25_SeismicityRegions; @@ -28,10 +32,6 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.Direct; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import net.mahdilamb.colormap.Colors; public class RateModelComparison { diff --git a/src/main/java/scratch/kevin/ucerf3/PureScratch.java b/src/main/java/scratch/kevin/ucerf3/PureScratch.java index bd33c8ad..54f23849 100644 --- a/src/main/java/scratch/kevin/ucerf3/PureScratch.java +++ b/src/main/java/scratch/kevin/ucerf3/PureScratch.java @@ -154,6 +154,8 @@ import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysHazardCalcSettings; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc.ReturnPeriods; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateModel; +import org.opensha.sha.earthquake.nshmp.seismicity.SeismicityRateFileLoader.RateType; import org.opensha.sha.earthquake.faultSysSolution.util.SubSectionBuilder; import org.opensha.sha.earthquake.observedEarthquake.ObsEqkRupList; import org.opensha.sha.earthquake.param.ApplyGardnerKnopoffAftershockFilterParam; @@ -226,8 +228,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateModel; -import gov.usgs.earthquake.nshmp.erf.seismicity.SeismicityRateFileLoader.RateType; import gov.usgs.earthquake.nshmp.gmm.Gmm; import gov.usgs.earthquake.nshmp.gmm.GmmInput; import gov.usgs.earthquake.nshmp.gmm.GroundMotion; From 19b02cc49abf38e309f76bcc8a1522e184a537e0 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Thu, 6 Aug 2026 14:19:20 -0700 Subject: [PATCH 50/71] updates for shaded jar --- .../nshmp/shaded/model/NshmSurface.java | 8 +++--- .../hazardValidation/ComparisonPageGen.java | 28 +++++++++---------- .../nshm23/hazardValidation/DipCalcTests.java | 6 ++-- .../GridPropInvestigation.java | 6 ++-- .../GriddedParticipationComparison.java | 16 +++++------ .../hazardValidation/SiteDataDiagnostics.java | 10 +++---- .../WrapperRupSetRupMapper.java | 10 +++---- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/main/java/org/opensha/nshmp/shaded/model/NshmSurface.java b/src/main/java/org/opensha/nshmp/shaded/model/NshmSurface.java index 31065d81..f8fd2f46 100644 --- a/src/main/java/org/opensha/nshmp/shaded/model/NshmSurface.java +++ b/src/main/java/org/opensha/nshmp/shaded/model/NshmSurface.java @@ -45,7 +45,7 @@ public NshmSurface(org.opensha.nshmp.shaded.fault.surface.NshmpRuptureSurface de * @return */ public static org.opensha.sha.faultSurface.PointSurface buildPointSurface( - gov.usgs.earthquake.nshmp.fault.surface.RuptureSurface delegate) { + org.opensha.nshmp.shaded.fault.surface.NshmpRuptureSurface delegate) { // this is the point surface double len = 0d; try { @@ -65,16 +65,16 @@ public static org.opensha.sha.faultSurface.PointSurface buildPointSurface( */ private static class DelegatePointSourceCorrection implements PointSourceDistanceCorrection.Single { - private gov.usgs.earthquake.nshmp.fault.surface.RuptureSurface delegate; + private org.opensha.nshmp.shaded.fault.surface.NshmpRuptureSurface delegate; - private DelegatePointSourceCorrection(gov.usgs.earthquake.nshmp.fault.surface.RuptureSurface delegate) { + private DelegatePointSourceCorrection(org.opensha.nshmp.shaded.fault.surface.NshmpRuptureSurface delegate) { this.delegate = delegate; } @Override public SurfaceDistances getCorrectedDistance(Location location, org.opensha.sha.faultSurface.PointSurface surf, TectonicRegionType trt, double mag, double horzDist) { - Distance distance = delegate.distanceTo(NshmUtil.fromOpenShaLocation(location)); + NshmpDistance distance = delegate.distanceTo(NshmUtil.fromOpenShaLocation(location)); return new SurfaceDistances.Precomputed(location, distance.rRup, distance.rJB, distance.rX); } diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java index d6edbd21..35182d3d 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java @@ -85,10 +85,10 @@ import com.google.common.base.Preconditions; import com.google.common.primitives.Doubles; -import gov.usgs.earthquake.nshmp.gmm.Gmm; -import gov.usgs.earthquake.nshmp.gmm.GmmInput; -import gov.usgs.earthquake.nshmp.model.HazardModel; -import gov.usgs.earthquake.nshmp.model.NshmErf; +import org.opensha.nshmp.shaded.gmm.NshmpGmm; +import org.opensha.nshmp.shaded.gmm.NshmpGmmInput; +import org.opensha.nshmp.shaded.model.NshmpHazardModel; +import org.opensha.nshmp.shaded.model.NshmErf; import net.mahdilamb.colormap.Colors; import scratch.kevin.nshm23.hazardValidation.WrapperRupSetRupMapper.WrapperMatch; @@ -210,8 +210,8 @@ public static void main(String[] args) throws IOException { } // NSHMP_GMM_Wrapper mixedForWrapperGMM = new NSHMP_GMM_Wrapper.WeightedCombination( -// Map.of(Gmm.TOTAL_TREE_CONUS_ACTIVE_CRUST_2023, 2d/3d, -// Gmm.TOTAL_TREE_CONUS_STABLE_CRUST_2023, 1d/3d), "Hack Mixed GMM", "HackMixed", false); +// Map.of(NshmpGmm.TOTAL_TREE_CONUS_ACTIVE_CRUST_2023, 2d/3d, +// NshmpGmm.TOTAL_TREE_CONUS_STABLE_CRUST_2023, 1d/3d), "Hack Mixed GMM", "HackMixed", false); // mixedForWrapperGMM.setParamDefaults(); // mixedForWrapperGMM.getParameter(SigmaTruncLevelParam.NAME).setValue(3d); // if (period == 0d) { @@ -321,9 +321,9 @@ public static void main(String[] args) throws IOException { CPT pDiffCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-10d, 10d); pDiffCPT.setNanColor(transparent); - HazardModel model = null; + NshmpHazardModel model = null; if (doWrapperCalc) - model = HazardModel.load(modelDir.toPath()); + model = NshmpHazardModel.load(modelDir.toPath()); double diffScale; if (period == 0d) @@ -703,25 +703,25 @@ public static void main(String[] args) throws IOException { if (wrapGMM != null) { // extra tests wrapGMM.setEqkRupture(fssRup); - GmmInput fssInput = wrapGMM.getCurrentGmmInput(); + NshmpGmmInput fssInput = wrapGMM.getCurrentGmmInput(); wrapGMM.setEqkRupture(wrapperRup); - GmmInput wrapInput = wrapGMM.getCurrentGmmInput(); + NshmpGmmInput wrapInput = wrapGMM.getCurrentGmmInput(); - List updates = new ArrayList<>(); + List updates = new ArrayList<>(); List updateChars = new ArrayList<>(); List updateNames = new ArrayList<>(); - updates.add(GmmInput.builder().fromCopy(fssInput) + updates.add(NshmpGmmInput.builder().fromCopy(fssInput) .rake(wrapInput.rake).build()); updateNames.add("wrapper rake"); updateChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 3f, Colors.tab_orange)); - updates.add(GmmInput.builder().fromCopy(fssInput) + updates.add(NshmpGmmInput.builder().fromCopy(fssInput) .rake(wrapInput.rake).dip(wrapInput.dip).build()); updateNames.add("wrapper rake/dip"); updateChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 3f, Colors.tab_purple)); - updates.add(GmmInput.builder().fromCopy(fssInput) + updates.add(NshmpGmmInput.builder().fromCopy(fssInput) .rake(wrapInput.rake).dip(wrapInput.dip).zHyp(wrapInput.zHyp).build()); updateNames.add("wrapper rake/dip/zHyp"); updateChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 3f, Colors.tab_olive)); diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/DipCalcTests.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/DipCalcTests.java index 17738cab..f13d90d2 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/DipCalcTests.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/DipCalcTests.java @@ -13,8 +13,8 @@ import org.opensha.sha.faultSurface.RuptureSurface; import org.opensha.sha.util.TectonicRegionType; -import gov.usgs.earthquake.nshmp.model.HazardModel; -import gov.usgs.earthquake.nshmp.model.NshmErf; +import org.opensha.nshmp.shaded.model.NshmpHazardModel; +import org.opensha.nshmp.shaded.model.NshmErf; import scratch.kevin.nshm23.hazardValidation.WrapperRupSetRupMapper.WrapperMatch; public class DipCalcTests { @@ -28,7 +28,7 @@ public static void main(String[] args) throws IOException { FaultSystemSolution sol = FaultSystemSolution.load(inputSolFile); - HazardModel model = HazardModel.load(modelDir.toPath()); + NshmpHazardModel model = NshmpHazardModel.load(modelDir.toPath()); NshmErf wrapper = new NshmErf(model, Set.of(TectonicRegionType.ACTIVE_SHALLOW), IncludeBackgroundOption.EXCLUDE); wrapper.getTimeSpan().setDuration(1d); diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/GridPropInvestigation.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/GridPropInvestigation.java index de594874..179b487f 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/GridPropInvestigation.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/GridPropInvestigation.java @@ -30,8 +30,8 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.model.HazardModel; -import gov.usgs.earthquake.nshmp.model.NshmErf; +import org.opensha.nshmp.shaded.model.NshmpHazardModel; +import org.opensha.nshmp.shaded.model.NshmErf; public class GridPropInvestigation { @@ -56,7 +56,7 @@ public static void main(String[] args) throws IOException { gmm.setParamDefaults(); - HazardModel model = HazardModel.load(modelDir.toPath()); + NshmpHazardModel model = NshmpHazardModel.load(modelDir.toPath()); NshmErf wrapper = new NshmErf(model, Set.of(trt), IncludeBackgroundOption.ONLY); wrapper.getTimeSpan().setDuration(1d); diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java index de13664d..33130b3b 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/GriddedParticipationComparison.java @@ -29,10 +29,10 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.model.GridSource; -import gov.usgs.earthquake.nshmp.model.HazardModel; -import gov.usgs.earthquake.nshmp.model.NshmErf; -import gov.usgs.earthquake.nshmp.model.NshmSource; +import org.opensha.nshmp.shaded.model.NshmpGridSource; +import org.opensha.nshmp.shaded.model.NshmpHazardModel; +import org.opensha.nshmp.shaded.model.NshmErf; +import org.opensha.nshmp.shaded.model.NshmSource; public class GriddedParticipationComparison { @@ -57,7 +57,7 @@ public static void main(String[] args) throws IOException { // we want direct mappings sol.getRupSet().removeModuleInstances(FaultGridAssociations.class); - HazardModel model = HazardModel.load(modelDir.toPath()); + NshmpHazardModel model = NshmpHazardModel.load(modelDir.toPath()); GriddedGeoDataSet[] fssXYZs = new GriddedGeoDataSet[minMags.length]; GriddedGeoDataSet[] nhXYZs = new GriddedGeoDataSet[minMags.length]; @@ -125,12 +125,12 @@ public static void main(String[] args) throws IOException { for (ProbEqkSource source : erf) { NshmSource nshmSource = (NshmSource)source; Object delegate = nshmSource.delegate(); - boolean gridLike = delegate instanceof GridSource; + boolean gridLike = delegate instanceof NshmpGridSource; if (!includeForBackgroundOption(gridLike, bgOp)) continue; int gridSourceIndex = -1; if (gridLike) - gridSourceIndex = gridReg.indexForLocation(toOpenSHALocation(((GridSource)delegate).location(null))); + gridSourceIndex = gridReg.indexForLocation(toOpenSHALocation(((NshmpGridSource)delegate).location(null))); numNSHMPSources++; for (ProbEqkRupture rup : source) { numNSHMPRups++; @@ -209,7 +209,7 @@ private static boolean includeForBackgroundOption(boolean gridLike, IncludeBackg } } - private static Location toOpenSHALocation(gov.usgs.earthquake.nshmp.geo.Location loc) { + private static Location toOpenSHALocation(org.opensha.nshmp.shaded.geo.NshmpLocation loc) { return new Location(loc.latitude, loc.longitude, loc.depth); } diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/SiteDataDiagnostics.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/SiteDataDiagnostics.java index bd08f95d..2fbf66ad 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/SiteDataDiagnostics.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/SiteDataDiagnostics.java @@ -29,8 +29,8 @@ import com.google.common.base.Preconditions; -import gov.usgs.earthquake.nshmp.model.HazardModel; -import gov.usgs.earthquake.nshmp.model.SiteData.Values; +import org.opensha.nshmp.shaded.model.NshmpHazardModel; +import org.opensha.nshmp.shaded.model.NshmpSiteData.Values; public class SiteDataDiagnostics { @@ -63,8 +63,8 @@ public static void main(String[] args) throws IOException { File outputDir = new File("/home/kevin/OpenSHA/nshm23/nshmp-haz-models/site_data_debug"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); - HazardModel model = HazardModel.load(Path.of("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.2.0")); - gov.usgs.earthquake.nshmp.model.SiteData modelSiteData = model.siteData(); + NshmpHazardModel model = NshmpHazardModel.load(Path.of("/data/kevin/nshm23/nshmp-haz-models/nshm-conus-6.2.0")); + org.opensha.nshmp.shaded.model.NshmpSiteData modelSiteData = model.siteData(); for (int t=0; t Date: Thu, 6 Aug 2026 15:35:48 -0700 Subject: [PATCH 51/71] now detects and handles sources with TRT-specific-GMM overrides --- .../opensha/nshmp/shaded/model/NshmErf.java | 147 +++++++++++++++--- 1 file changed, 126 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/opensha/nshmp/shaded/model/NshmErf.java b/src/main/java/org/opensha/nshmp/shaded/model/NshmErf.java index b1b33244..f9e5656b 100644 --- a/src/main/java/org/opensha/nshmp/shaded/model/NshmErf.java +++ b/src/main/java/org/opensha/nshmp/shaded/model/NshmErf.java @@ -11,22 +11,28 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.EnumMap; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; +import org.apache.commons.numbers.core.Precision; import org.opensha.commons.data.TimeSpan; import org.opensha.sha.earthquake.AbstractERF; import org.opensha.sha.earthquake.ProbEqkSource; import org.opensha.sha.earthquake.param.IncludeBackgroundOption; +import org.opensha.sha.imr.attenRelImpl.nshmp.NSHMP_GMM_Wrapper; import org.opensha.sha.util.TectonicRegionType; +import com.google.common.base.Preconditions; import com.google.common.collect.Multimap; import com.google.common.collect.MultimapBuilder; import org.opensha.nshmp.shaded.data.NshmpIndexing; +import org.opensha.nshmp.shaded.gmm.NshmpGmm; import org.opensha.nshmp.shaded.model.NshmpSystemRuptureSet.SystemRupture; import org.opensha.nshmp.shaded.tree.NshmpBranch; @@ -43,6 +49,7 @@ public class NshmErf extends AbstractERF { private final boolean volcanic; private final boolean grid; private final boolean faults; + private Set trts; public NshmErf(Path path, Set trts, IncludeBackgroundOption gridOption) { @@ -52,6 +59,7 @@ public NshmErf(Path path, Set trts, public NshmErf(NshmpHazardModel model, Set trts, IncludeBackgroundOption gridOption) { this.model = model; + this.trts = trts; allSources = new ArrayList<>(); sourceMap = MultimapBuilder .enumKeys(TectonicRegionType.class) @@ -69,6 +77,8 @@ public NshmErf(NshmpHazardModel model, Set trts, init(); } + + private static final boolean PROCESS_TRT_OVERRIDES = true; private void init() { @@ -79,37 +89,124 @@ private void init() { // nshmp-haz initializers Multimap trees = model.trees(); + if (PROCESS_TRT_OVERRIDES) { + List trtMappedRuptureSets = parseTRTOverrides(trees); + for (NshmpTRTBranch trtBranch : trtMappedRuptureSets) { + if (!trts.isEmpty() && !trts.contains(trtBranch.trt)) + continue; + List sources = initBranch(trtBranch.branch); + sources.forEach(s -> s.setTectonicRegionType(trtBranch.trt)); + allSources.addAll(sources); + sourceMap.putAll(trtBranch.trt, sources); + } + allSources.sort(new Comparator() { + @Override + public int compare(NshmSource o1, NshmSource o2) { + return Integer.compare(o1.getNSHM_ID(), o2.getNSHM_ID()); + } + }); + } else { + for (Entry entry : trees.entries()) { + NshmpTectonicSetting setting = entry.getKey(); + NshmpSourceTree tree = entry.getValue(); + NshmpSourceType type = tree.type(); + + TectonicRegionType trt = NshmUtil.tectonicSettingToType(setting, type); + if (!trts.isEmpty() && !trts.contains(trt)) + continue; + List sources = initTree(tree); + sources.forEach(s -> s.setTectonicRegionType(trt)); + allSources.addAll(sources); + sourceMap.putAll(trt, sources); + } + } + } + + private record NshmpTRTBranch(TectonicRegionType trt, NshmpBranch branch) {} + + /** + * Map each branch to a tectonic region type, also processing any GMM-overrides that Peter might sneak in there + * to change the TRT within a different NshmpTectonicSetting + * @param trees + * @return + */ + private static List parseTRTOverrides( + Multimap trees) { + List ret = new ArrayList<>(); + for (Entry entry : trees.entries()) { - NshmpTectonicSetting setting = entry.getKey(); NshmpSourceTree tree = entry.getValue(); NshmpSourceType type = tree.type(); - - if (setting == NshmpTectonicSetting.SUBDUCTION) { - if ((type == NshmpSourceType.INTERFACE || type == NshmpSourceType.INTERFACE_CLUSTER - || type == NshmpSourceType.INTERFACE_GRID || type == NshmpSourceType.INTERFACE_SYSTEM) && !subInterface) { + TectonicRegionType origTRT = NshmUtil.tectonicSettingToType(setting, type); + + for (NshmpBranch rs : tree) { + if (origTRT == VOLCANIC) { + // copy over as is, no current GMM type for volcanic + ret.add(new NshmpTRTBranch(origTRT, rs)); continue; } - if ((type == NshmpSourceType.SLAB || type == NshmpSourceType.INTRASLAB_GRID) && !subSlab) { - continue; + NshmpGmmTree gmmTree = rs.value().gmmTree(); + double weightOrig = 0d; + double weightOverrideSum = 0d; + Map overrideWeights = new EnumMap<>(TectonicRegionType.class); + for (NshmpBranch gmm : gmmTree.tree()) { + TectonicRegionType gmmTRT = NSHMP_GMM_Wrapper.trtForType(gmm.value().type()); + if (gmmTRT != origTRT) { + // we have a GMM TRT override + weightOverrideSum += gmm.weight(); + if (overrideWeights.containsKey(gmmTRT)) + overrideWeights.put(gmmTRT, overrideWeights.get(gmmTRT)+gmm.weight()); + else + overrideWeights.put(gmmTRT, gmm.weight()); + } else { + weightOrig += gmm.weight(); + } + } + if (weightOverrideSum > 0d) { + // we have overrides to process + Preconditions.checkState(Precision.equals(weightOverrideSum + weightOrig, 1d, 1e-4)); + if (weightOrig > 0d) + ret.add(new NshmpTRTBranch(origTRT, new WeightScaledBranch(rs, weightOrig, origTRT))); + for (TectonicRegionType trt : overrideWeights.keySet()) + ret.add(new NshmpTRTBranch(trt, new WeightScaledBranch(rs, overrideWeights.get(trt), trt))); + } else { + // copy over as is + ret.add(new NshmpTRTBranch(origTRT, rs)); } } - if (setting == NshmpTectonicSetting.STABLE_CRUST && !stableCrust) { - continue; - } - if (setting == NshmpTectonicSetting.ACTIVE_CRUST && !activeCrust) { - continue; - } - if (setting == NshmpTectonicSetting.VOLCANIC && !volcanic) { - continue; - } + } + + return ret; + } + + private static class WeightScaledBranch implements NshmpBranch { + + private NshmpBranch upstream; + private double scale; + private TectonicRegionType trt; + + public WeightScaledBranch(NshmpBranch upstream, double scale, TectonicRegionType trt) { + this.upstream = upstream; + this.scale = scale; + this.trt = trt; + } + + @Override + public String id() { + return upstream.id()+"-"+trt.name(); + } + + @Override + public NshmpRuptureSet value() { + return upstream.value(); + } - TectonicRegionType trt = NshmUtil.tectonicSettingToType(setting, type); - List sources = initTree(tree); - sources.forEach(s -> s.setTectonicRegionType(trt)); - allSources.addAll(sources); - sourceMap.putAll(trt, sources); + @Override + public double weight() { + return upstream.weight()*scale; } + } public List allSources() { @@ -152,6 +249,14 @@ public int compare(NshmSource o1, NshmSource o2) { return sources; } + private List initBranch(NshmpBranch branch) { + List sources = new ArrayList<>(); + double duration = getTimeSpan().getDuration(); + sources.addAll(sourcesFromBranch(branch, duration)); + + return sources; + } + private List sourcesFromBranch( NshmpBranch branch, double duration) { From 3a2fabd7db197d140af690296ba95befc18ee3ff Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 7 Aug 2026 09:46:59 -0700 Subject: [PATCH 52/71] there's already a ton of STDOUT upstream, might as well make it useful --- .../opensha/nshmp/shaded/model/NshmErf.java | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/opensha/nshmp/shaded/model/NshmErf.java b/src/main/java/org/opensha/nshmp/shaded/model/NshmErf.java index f9e5656b..1aa78264 100644 --- a/src/main/java/org/opensha/nshmp/shaded/model/NshmErf.java +++ b/src/main/java/org/opensha/nshmp/shaded/model/NshmErf.java @@ -140,13 +140,17 @@ private static List parseTRTOverrides( NshmpSourceType type = tree.type(); TectonicRegionType origTRT = NshmUtil.tectonicSettingToType(setting, type); - for (NshmpBranch rs : tree) { + System.out.println("Processing tree "+tree.id()+". "+tree.name()+" ("+origTRT.name()+")"); + + for (NshmpBranch branch : tree) { if (origTRT == VOLCANIC) { // copy over as is, no current GMM type for volcanic - ret.add(new NshmpTRTBranch(origTRT, rs)); + ret.add(new NshmpTRTBranch(origTRT, branch)); continue; } - NshmpGmmTree gmmTree = rs.value().gmmTree(); + NshmpRuptureSet rs = branch.value(); + System.out.println("\tProcessing RS "+rs.id()+". "+rs.name()+" ("+origTRT.name()+")"); + NshmpGmmTree gmmTree = rs.gmmTree(); double weightOrig = 0d; double weightOverrideSum = 0d; Map overrideWeights = new EnumMap<>(TectonicRegionType.class); @@ -166,13 +170,19 @@ private static List parseTRTOverrides( if (weightOverrideSum > 0d) { // we have overrides to process Preconditions.checkState(Precision.equals(weightOverrideSum + weightOrig, 1d, 1e-4)); - if (weightOrig > 0d) - ret.add(new NshmpTRTBranch(origTRT, new WeightScaledBranch(rs, weightOrig, origTRT))); - for (TectonicRegionType trt : overrideWeights.keySet()) - ret.add(new NshmpTRTBranch(trt, new WeightScaledBranch(rs, overrideWeights.get(trt), trt))); + System.err.println("Detected a GMM TRT override for source "+rs.id()+". "+rs.name()+" with original TRT="+origTRT.name()); + if (weightOrig > 0d) { + System.err.println("\t"+origTRT.name()+":\t"+weightOrig); + ret.add(new NshmpTRTBranch(origTRT, new WeightScaledBranch(branch, weightOrig, origTRT))); + } + for (TectonicRegionType trt : overrideWeights.keySet()) { + double weight = overrideWeights.get(trt); + System.err.println("\t"+trt.name()+":\t"+weight); + ret.add(new NshmpTRTBranch(trt, new WeightScaledBranch(branch, weight, trt))); + } } else { // copy over as is - ret.add(new NshmpTRTBranch(origTRT, rs)); + ret.add(new NshmpTRTBranch(origTRT, branch)); } } } From 356530f3fb5704c31598892057d681494859512a Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 7 Aug 2026 11:39:47 -0700 Subject: [PATCH 53/71] region tests --- .../kevin/nshm27/RegionBufferTests.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/main/java/scratch/kevin/nshm27/RegionBufferTests.java diff --git a/src/main/java/scratch/kevin/nshm27/RegionBufferTests.java b/src/main/java/scratch/kevin/nshm27/RegionBufferTests.java new file mode 100644 index 00000000..8df883cc --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/RegionBufferTests.java @@ -0,0 +1,100 @@ +package scratch.kevin.nshm27; + +import java.awt.Color; +import java.awt.geom.Point2D; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.LocationList; +import org.opensha.commons.geo.Region; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.mapping.PoliticalBoundariesData; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_MapRegions; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; +import org.opensha.sha.faultSurface.FaultSection; + +import net.mahdilamb.colormap.Colors; +import scratch.kevin.nshm27.figures.NSHM27_PaperPaths; + +public class RegionBufferTests { + + public static void main(String[] args) throws IOException { + Region containsRegion = NSHM27_RegionLoader.NSHM27_MapRegions.AMSAM.load(); +// Region region = containsRegion; + Region region = new Region(new Location(-17, 185), new Location(-11, 193)); + + XY_DataSet[] outlines = PoliticalBoundariesData.loadDefaultOutlines(region); + + double minDist = Double.POSITIVE_INFINITY; + + LocationList border = new LocationList(region.getBorder()); + // close it + border.add(border.first()); + + for (XY_DataSet xy : outlines) { + for (Point2D pt : xy) { + Location loc = new Location(pt.getY(), pt.getX()); + if (containsRegion.contains(loc)) + minDist = Math.min(minDist, border.minDistToLine(loc)); + } + } + System.out.println("Nearest coastline is "+(float)minDist+" km from border"); + + List regions = new ArrayList<>(); + List chars = new ArrayList<>(); + List colors = new ArrayList<>(); + + Color color = Colors.tab_blue; + + regions.add(NSHM27_SeismicityRegions.AMSAM.load()); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, Color.BLACK)); + colors.add(color); + + regions.add(region); + chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 3f, Color.BLACK)); + colors.add(color); + + regions.add(NSHM27_MapRegions.AMSAM.load()); + chars.add(new PlotCurveCharacterstics(PlotLineType.DASHED, 3f, Color.BLACK)); + colors.add(color); + + MinMaxAveTracker latTrack = new MinMaxAveTracker(); + MinMaxAveTracker lonTrack = new MinMaxAveTracker(); + for (Region reg : regions) { + latTrack.addValue(reg.getMinLat()); + latTrack.addValue(reg.getMaxLat()); + lonTrack.addValue(reg.getMinLon()); + lonTrack.addValue(reg.getMaxLon()); + } + List sects = NSHM27_PaperPaths.getInterfaceSolution(NSHM27_SeismicityRegions.AMSAM) + .getRupSet().getFaultSectionDataList(); + for (FaultSection sect : sects) { + for (Location loc : sect.getFaultTrace()) { + latTrack.addValue(loc.lat); + lonTrack.addValue(loc.lon); + } + } + + double minLat = Math.floor(latTrack.getMin()-0.5); + double maxLat = Math.ceil(latTrack.getMax()+0.5); + double minLon = Math.floor(lonTrack.getMin()-0.5); + double maxLon = Math.ceil(lonTrack.getMax()+0.5); + GeographicMapMaker mapMaker = new GeographicMapMaker( + new Region(new Location(minLat, minLon), new Location(maxLat, maxLon))); + + mapMaker.setFaultSections(sects); + + mapMaker.plotInsetRegions(regions, chars, colors, 0.3); + + mapMaker.plot(new File("/tmp"), "amsam_seismicity_regions", " "); + } + +} From 2fbdc403ef52314f8c003dfe57b7637cfd0e5f09 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 7 Aug 2026 16:35:08 -0700 Subject: [PATCH 54/71] for upstream --- .../scratch/kevin/nshm23/InversionDebugForSingleFault.java | 2 +- .../nshm27/figures/InterfaceLogicTreeMFDExploration.java | 2 +- .../scratch/kevin/prvi25/figures/RupSetStatsTexWriter.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/InversionDebugForSingleFault.java b/src/main/java/scratch/kevin/nshm23/InversionDebugForSingleFault.java index 106e5876..4bf40727 100644 --- a/src/main/java/scratch/kevin/nshm23/InversionDebugForSingleFault.java +++ b/src/main/java/scratch/kevin/nshm23/InversionDebugForSingleFault.java @@ -36,7 +36,7 @@ public static void main(String[] args) throws IOException { LogicTreeBranch branch = rupSet.requireModule(LogicTreeBranch.class); ClusterRuptures cRups = rupSet.requireModule(ClusterRuptures.class); - BinaryRuptureProbabilityCalc exclusion = NSHM23_InvConfigFactory.getExclusionModel( + BinaryRuptureProbabilityCalc exclusion = NSHM23_InvConfigFactory.buildExclusionModel( rupSet, branch, cRups); double rateSum = 0d; diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java index d63e4087..7fd0d627 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java @@ -542,7 +542,7 @@ private static IncrementalMagFreqDist calculateMFD(NSHM27_InvConfigFactory facto System.out.println("Calculating MFD for: "+branch); ClusterRuptures cRups = rupSet.requireModule(ClusterRuptures.class); rupSet = factory.updateRuptureSetForBranch(rupSet, branch); - BinaryRuptureProbabilityCalc exclusionModel = NSHM27_InvConfigFactory.getExclusionModel(rupSet, branch, cRups); + BinaryRuptureProbabilityCalc exclusionModel = NSHM27_InvConfigFactory.buildExclusionModel(rupSet, branch, cRups); BitSet includedRups = new BitSet(rupSet.getNumRuptures()); for (int rupIndex=0; rupIndex branch : scaleBranches) { FaultSystemRupSet rupSet = factory.buildRuptureSet(branch, FaultSysTools.defaultNumThreads()); ClusterRuptures cRups = rupSet.requireModule(ClusterRuptures.class); - BinaryRuptureProbabilityCalc exclusion = PRVI25_InvConfigFactory.getExclusionModel( + BinaryRuptureProbabilityCalc exclusion = PRVI25_InvConfigFactory.buildExclusionModel( rupSet, branch, cRups); double mMin, mMax; if (exclusion == null) { From 969ffd64e4129c3737ad71af7b09c8c64c6665b2 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 10 Aug 2026 11:07:48 -0700 Subject: [PATCH 55/71] refactored to generic sect dist sampling api --- .../scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java | 4 +--- .../java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java | 2 +- .../nshm27/figures/InterfaceLogicTreeMFDExploration.java | 2 +- .../nshm27/figures/InterfaceParticipationRateFigures.java | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java b/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java index 30da9687..324de539 100644 --- a/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java +++ b/src/main/java/scratch/kevin/nshm27/InterfaceSlipRatePercentiles.java @@ -4,9 +4,7 @@ import java.text.DecimalFormat; import org.apache.commons.math3.stat.StatUtils; -import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.AverageSampler; -import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.FixedFractileSampler; -import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.FixedSampler; +import org.opensha.sha.earthquake.faultSysSolution.logicTree.sectDistSampling.SectDistributionSampler.*; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels.DeformationFront; diff --git a/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java b/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java index 42a531b6..49077093 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java +++ b/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java @@ -15,7 +15,7 @@ import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; import org.opensha.sha.earthquake.faultSysSolution.inversion.Inversions; -import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.FixedFractileSampler; +import org.opensha.sha.earthquake.faultSysSolution.logicTree.sectDistSampling.SectDistributionSampler.FixedFractileSampler; import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; import org.opensha.sha.earthquake.faultSysSolution.modules.SectSlipRates; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java index 7fd0d627..ab77ad30 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java @@ -37,7 +37,7 @@ import org.opensha.commons.util.cpt.CPT; import org.opensha.commons.util.modules.ModuleContainer; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; -import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.DeformationModelDistSampler.FixedFractileSampler; +import org.opensha.sha.earthquake.faultSysSolution.logicTree.sectDistSampling.SectDistributionSampler.FixedFractileSampler; import org.opensha.sha.earthquake.faultSysSolution.modules.ClusterRuptures; import org.opensha.sha.earthquake.faultSysSolution.modules.FaultGridAssociations; import org.opensha.sha.earthquake.faultSysSolution.modules.SectSlipRates; diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceParticipationRateFigures.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceParticipationRateFigures.java index d63c170c..b5b424d3 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceParticipationRateFigures.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceParticipationRateFigures.java @@ -17,7 +17,7 @@ import org.opensha.commons.util.cpt.CPT; import org.opensha.commons.util.modules.ModuleContainer; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemSolution; -import org.opensha.sha.earthquake.faultSysSolution.logicTree.dmSampling.RupSetDeformationModelDistribution.BinnedUniformSamplingLevel; +import org.opensha.sha.earthquake.faultSysSolution.logicTree.sectDistSampling.SectDistributionSampleLevels.BinnedUniformSamplingLevel; import org.opensha.sha.earthquake.faultSysSolution.modules.SolutionLogicTree; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceCouplingDepthModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceDeformationModels; From cecd4a21efd7ed650618a271e58459acd7cb94ff Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Wed, 19 Aug 2026 13:52:12 -0700 Subject: [PATCH 56/71] sampled tree examples for Ian --- .../nshm27/ExampleLogicTreeSampleCSVs.java | 131 ++++++++++++++++++ .../kevin/nshm27/figures/LogicTreeFigure.java | 46 +++++- 2 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 src/main/java/scratch/kevin/nshm27/ExampleLogicTreeSampleCSVs.java diff --git a/src/main/java/scratch/kevin/nshm27/ExampleLogicTreeSampleCSVs.java b/src/main/java/scratch/kevin/nshm27/ExampleLogicTreeSampleCSVs.java new file mode 100644 index 00000000..7e913bc9 --- /dev/null +++ b/src/main/java/scratch/kevin/nshm27/ExampleLogicTreeSampleCSVs.java @@ -0,0 +1,131 @@ +package scratch.kevin.nshm27; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.opensha.commons.data.CSVFile; +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.LogicTreeFigureWriter; +import org.opensha.commons.logicTree.LogicTreeLevel; +import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.LogicTreeNode.ValuedLogicTreeNode; +import org.opensha.sha.earthquake.faultSysSolution.logicTree.sectDistSampling.SectDistributionSampler.FixedFractileSampler; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.SectionSupraSeisBValues; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceHingedBValue; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceHingedBValue.CombinedSampledType; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_SeisRateModel.ClassificationDependentGR; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; +import org.opensha.sha.util.TectonicRegionType; + +import scratch.kevin.nshm27.figures.LogicTreeFigure; + +public class ExampleLogicTreeSampleCSVs { + + public static void main(String[] args) throws IOException { + File outputDir = new File("/home/kevin/OpenSHA/nshm27/sampling/example_trees"); + NSHM27_SeismicityRegions seisReg = NSHM27_SeismicityRegions.AMSAM; + String prefix = "nshm27_amsam_interface"; + + boolean inversion = true; + boolean gridded = false; + +// boolean inversion = false; +// boolean gridded = true; + +// boolean inversion = true; +// boolean gridded = true; + + int[] sampleCounts = { + 256, + 512, + 1024, + 2048, + 4096, + 8192, + 16384 + }; + long seed = 123456l; + SamplingMethod method = SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE; + + if (inversion && gridded) + prefix += "_full"; + else if (inversion) + prefix += "_inversion_only"; + else if (gridded) + prefix += "_gridded_only"; + else + throw new IllegalStateException(); + + boolean common = gridded; + + List> levels = NSHM27_LogicTree.buildLevels( + seisReg, TectonicRegionType.SUBDUCTION_INTERFACE, + true, inversion, gridded, common); + + for (int s=0; s logicTree = LogicTree.buildSampled(levels, samples, seed, method, + NSHM27_InterfaceFaultModels.regionDefault(seisReg)); + + // remove the unnecessary fault model level (it's fixed) + logicTree = LogicTreeFigure.stripFaultModels(logicTree); + // remove the unnecessary overall model/regime level (it's fixed) + logicTree = LogicTreeFigure.stripModelLevel(logicTree); + + CSVFile csv = new CSVFile<>(true); + List header = new ArrayList<>(); + for (LogicTreeLevel level : logicTree.getLevels()) + header.add(level.getName()); + csv.addLine(header); + + for (LogicTreeBranch branch : logicTree) { + List line = new ArrayList<>(header.size()); + + for (LogicTreeNode node : branch) { + if (node instanceof NSHM27_InterfaceHingedBValue.CombinedSampledType combBSample) { + if (combBSample.isHinged()) + line.add(NSHM27_InterfaceHingedBValue.SHORT_NAME); + else + line.add((float)combBSample.getB(null, null)+""); + } else if (node instanceof ValuedLogicTreeNode valued) { + Object value = valued.getValue(); + if (value instanceof FixedFractileSampler fractiles) { + line.add((float)fractiles.getFixedFractile()+""); + } else if (value instanceof ClassificationDependentGR gr) { + line.add((float)gr.getSampleFractile()+""); + } else { +// if (!(value instanceof Number)) +// System.out.println("UNKNOWN value "+value+" of type "+value.getClass().getName() +// +" with node "+node.getShortName()+" of type "+node.getClass()); + line.add(value.toString()); + } + } else { + line.add(node.getShortName()); + } + } + + csv.addLine(line); + } + + csv.writeToFile(new File(outputDir, samplePrefix+".csv")); + + if (s == 0) { + LogicTreeFigureWriter ltFig = new LogicTreeFigureWriter(logicTree, false, true); + ltFig.write(outputDir, prefix, true, true); + } + System.out.println("========================="); + System.out.println(); + } + } + +} diff --git a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java index 60278286..857dcc9f 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java @@ -5,6 +5,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.opensha.commons.logicTree.LogicTree; @@ -16,6 +17,7 @@ import org.opensha.sha.earthquake.faultSysSolution.RupSetFaultModel; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_ModelRegimeNode; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; import org.opensha.sha.util.TectonicRegionType; @@ -81,16 +83,48 @@ private static List> stripFaultModels(Li return ret; } - private static LogicTree stripFaultModels(LogicTree tree) { + public static LogicTree stripFaultModels(LogicTree tree) { List> levels = stripFaultModels(tree.getLevels()); + return buildStrippedTree(tree, levels); + } + + private static List> stripModelLevel(List> levels) { + List> ret = new ArrayList<>(); + + for (LogicTreeLevel level : levels) { + if (NSHM27_ModelRegimeNode.class.isAssignableFrom(level.getType())) + continue; + ret.add(level); + } + + return ret; + } + + public static LogicTree stripModelLevel(LogicTree tree) { + List> levels = stripModelLevel(tree.getLevels()); + return buildStrippedTree(tree, levels); + } + + private static LogicTree buildStrippedTree(LogicTree tree, List> levels) { List> branches = new ArrayList<>(tree.size()); + int[] levelIndexes = new int[levels.size()]; + Arrays.fill(levelIndexes, -1); + List> origLevels = tree.getLevels(); + for (int i=0; i level = levels.get(i); + for (int l=0; l origLevel = origLevels.get(l); + if (level == origLevel) { + Preconditions.checkState(levelIndexes[i] == -1); + levelIndexes[i] = l; + } + } + Preconditions.checkState(levelIndexes[i] >= 0); + } for (LogicTreeBranch branch : tree) { List values = new ArrayList<>(levels.size()); - for (LogicTreeNode value : branch) { - if (value instanceof RupSetFaultModel) - continue; - values.add(value); - } + for (int i=0; i modBranch = new LogicTreeBranch<>(levels, values); modBranch.setOrigBranchWeight(branch.getOrigBranchWeight()); From d325841c8bad2579f05d792965f67b232e54aea7 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Thu, 27 Aug 2026 16:21:04 -0700 Subject: [PATCH 57/71] upstream refactors and new figures --- .../java/scratch/kevin/BranchScratch.java | 8 +- .../kevin/ltSampling/LHSExampleFigures.java | 4 +- ..._LogicTreeInversionRunnerScriptWriter.java | 5 +- .../RandomDefModSampleLevel.java | 6 +- .../kevin/nshm27/DistSampleCountTests.java | 11 +- .../nshm27/ExampleLogicTreeSampleCSVs.java | 2 +- .../UpdatedRandTreeSerialzationTests.java | 19 +- .../kevin/nshm27/figures/BValDistFigure.java | 2 +- .../nshm27/figures/DMLowerLimitTests.java | 2 +- .../InterfaceLogicTreeMFDExploration.java | 9 +- .../kevin/nshm27/figures/LogicTreeFigure.java | 2 +- .../sampling/HazardConvergenceCalcs.java | 130 ++++ .../kevin/sampling/InitialSamplingTests.java | 207 ++++++ .../scratch/kevin/sampling/PaperPaths.java | 12 + .../kevin/sampling/SamplingScoreFigures.java | 647 ++++++++++++++++++ .../scratch/kevin/ucerf3/PureScratch.java | 2 +- 16 files changed, 1044 insertions(+), 24 deletions(-) create mode 100644 src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java create mode 100644 src/main/java/scratch/kevin/sampling/InitialSamplingTests.java create mode 100644 src/main/java/scratch/kevin/sampling/PaperPaths.java create mode 100644 src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java diff --git a/src/main/java/scratch/kevin/BranchScratch.java b/src/main/java/scratch/kevin/BranchScratch.java index 9373087b..8c1092a5 100644 --- a/src/main/java/scratch/kevin/BranchScratch.java +++ b/src/main/java/scratch/kevin/BranchScratch.java @@ -19,6 +19,7 @@ import org.opensha.commons.gui.plot.PlotLineType; import org.opensha.commons.gui.plot.PlotSpec; import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.logicTree.LogicTree; import org.opensha.sha.earthquake.ProbEqkRupture; import org.opensha.sha.earthquake.ProbEqkSource; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; @@ -192,13 +193,18 @@ private static void test4() throws IOException { } } + private static void test5() throws IOException { + File treeFile = new File("/home/kevin/OpenSHA/fss_inversions/2026_07_17-nshm27-AMSAM-20000samples-mcs/logic_tree_analysis.json"); + LogicTree.read(treeFile); + } + /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { try { - test4(); + test5(); } catch (Throwable t) { t.printStackTrace(); System.exit(1); diff --git a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java index a3c6335c..c5151837 100644 --- a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java +++ b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java @@ -36,11 +36,11 @@ import org.opensha.commons.logicTree.LogicTreeFigureWriter; import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeLevel.ContinuousDistributionSampledLevel; -import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.logicTree.LogicTreeNode.SimpleValuedNode; import org.opensha.commons.logicTree.LogicTreeNode.ValuedLogicTreeNode; import org.opensha.commons.logicTree.lhs.PairwiseLogicTreeNodeSwapIteration; +import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.util.cpt.CPT; @@ -136,7 +136,7 @@ public static void main(String[] args) throws IOException { funcs.add(densityFunc); chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 0.5f, Color.GRAY)); - if (sm.isLHS()) { + if (sm == SamplingMethod.LATIN_HYPERCUBE || sm == SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE) { // draw ticks double tickDelta = maxY*0.05; EvenlyDiscretizedFunc binEdges = new EvenlyDiscretizedFunc( diff --git a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java index afcad577..dc8ece2d 100644 --- a/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/MPJ_LogicTreeInversionRunnerScriptWriter.java @@ -33,8 +33,8 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeLevel.RandomlyGeneratedLevel; -import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; +import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.util.ClassUtils; import org.opensha.sha.earthquake.faultSysSolution.RupSetFaultModel; @@ -886,8 +886,9 @@ else if (forceRequiredNonzeroWeight) List> levelNodes = new ArrayList<>(); for (RandomlyGeneratedLevel level : individualRandomLevels) { - level.build(rand.nextLong(), numBranches); +// level.build(rand.nextLong(), numBranches); levelNodes.add(level.getNodes()); + throw new IllegalStateException("Need to revive if needed"); } List> modBranches = new ArrayList<>(); diff --git a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java index 090bbf30..82bede27 100644 --- a/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java +++ b/src/main/java/scratch/kevin/nshm23/dmCovarianceTests/RandomDefModSampleLevel.java @@ -17,7 +17,11 @@ public RandomDefModSampleLevel(int numSamples) { public RandomDefModSampleLevel(int numSamples, long seed) { super("Random Deformation Model Sample", "DMSample", "Deformation Model Sample ", "DMSample", "DMSample"); - build(seed, numSamples); + double[] samples = new double[numSamples]; + Random r = new Random(seed); + for (int i=0; i node : level.getNodes()) @@ -66,7 +71,7 @@ public static void main(String[] args) throws IOException { for (SimpleValuedNode node : level.getNodes()) hist.add(hist.getClosestXIndex(node.getValue()), 1d); - hist.scale(1d/(samples*hist.getDelta())); + hist.scale(1d/(numSamples*hist.getDelta())); EvenlyDiscretizedFunc pdfDensity = new EvenlyDiscretizedFunc(track.getMin()-0.5*delta, track.getMax()+0.5*delta, 1000); diff --git a/src/main/java/scratch/kevin/nshm27/ExampleLogicTreeSampleCSVs.java b/src/main/java/scratch/kevin/nshm27/ExampleLogicTreeSampleCSVs.java index 7e913bc9..e5b60420 100644 --- a/src/main/java/scratch/kevin/nshm27/ExampleLogicTreeSampleCSVs.java +++ b/src/main/java/scratch/kevin/nshm27/ExampleLogicTreeSampleCSVs.java @@ -10,9 +10,9 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeFigureWriter; import org.opensha.commons.logicTree.LogicTreeLevel; -import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.logicTree.LogicTreeNode.ValuedLogicTreeNode; +import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.sha.earthquake.faultSysSolution.logicTree.sectDistSampling.SectDistributionSampler.FixedFractileSampler; import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.SectionSupraSeisBValues; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; diff --git a/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java b/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java index 25ae72af..bb52a63f 100644 --- a/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java +++ b/src/main/java/scratch/kevin/nshm27/UpdatedRandTreeSerialzationTests.java @@ -17,6 +17,7 @@ import org.opensha.commons.logicTree.LogicTreeNode.RandomlyGeneratedNode; import org.opensha.commons.logicTree.LogicTreeNode.SimpleValuedNode; import org.opensha.commons.logicTree.LogicTreeNode.ValuedLogicTreeNode; +import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import com.google.common.base.Preconditions; @@ -27,9 +28,14 @@ public static void main(String[] args) throws IOException { List> inTrees = new ArrayList<>(); inTrees.add(LogicTree.read(new File("/home/kevin/OpenSHA/nshm23/batch_inversions/2025_01_17-prvi25_crustal_branches-dmSample10x/logic_tree.json"))); + + double[] samples = new double[1000]; + Random r = new Random(12345l); + for (int i=0; i lastTree = inTrees.get(inTrees.size()-1); @@ -118,14 +124,13 @@ public TestValuedLevel() { } @Override - protected void doBuild(long seed, int numNodes, SamplingMethod samplingMethod, double weightEach) { - Random rand = new Random(seed); - super.build(()->rand.nextDouble(), numNodes, weightEach); + public Class getValueType() { + return Double.class; } @Override - public Class getValueType() { - return Double.class; + protected void doBuild(double[] unitSamples, double weightEach) { + super.build(unitSamples, D->D, weightEach); } } diff --git a/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java b/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java index 1584c8c3..dcaee697 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/BValDistFigure.java @@ -28,8 +28,8 @@ import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeFigureWriter; -import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.commons.util.modules.ModuleContainer; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; diff --git a/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java b/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java index 49077093..5a2e8e09 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java +++ b/src/main/java/scratch/kevin/nshm27/figures/DMLowerLimitTests.java @@ -9,7 +9,7 @@ import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeNode; -import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; +import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.commons.util.modules.ModuleContainer; import org.opensha.sha.earthquake.faultSysSolution.FaultSystemRupSet; diff --git a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java index ab77ad30..36500a26 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java +++ b/src/main/java/scratch/kevin/nshm27/figures/InterfaceLogicTreeMFDExploration.java @@ -20,6 +20,7 @@ import org.opensha.commons.data.function.DiscretizedFunc; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; import org.opensha.commons.data.function.LightFixedXFunc; +import org.opensha.commons.data.sampling.generator.LatinHypercubePointSetGenerator; import org.opensha.commons.data.uncertainty.UncertainArbDiscFunc; import org.opensha.commons.data.uncertainty.UncertainBoundedIncrMagFreqDist; import org.opensha.commons.gui.plot.HeadlessGraphPanel; @@ -30,8 +31,8 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeLevel; import org.opensha.commons.logicTree.LogicTreeLevel.RandomLevel; -import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.commons.util.cpt.CPT; @@ -117,13 +118,15 @@ public static void main(String[] args) throws IOException { branch.getLevelTypeIndex(MaxRuptureLengthBranchNode.class), }; + double[] lhSamples = new LatinHypercubePointSetGenerator(new Random(12345l)).generate(1000, 1).getDimensionValues(0); + WeightedList classificationChoices = new WeightedList<>(); for (NSHM27_SeisClassificationMethod classification : NSHM27_SeisClassificationMethod.values()) if (classification.getNodeWeight() > 0d) classificationChoices.add(classification, classification.getNodeWeight()); List classificationSamples = classificationChoices.sampleEvenly(samples, new Random(12345l)); LogicTreeLevel rateLevel = sampledBranch.getLevel(sampledBranch.getLevelTypeIndex(NSHM27_SeisRateModel.class)); - ((RandomLevel)rateLevel).build(12345l, samples, SamplingMethod.LATIN_HYPERCUBE); + ((RandomLevel)rateLevel).build(lhSamples); List rateModelSamples = rateLevel.getNodes(); NSHM27_InvConfigFactory factory = new NSHM27_InvConfigFactory(); @@ -255,7 +258,7 @@ public static void main(String[] args) throws IOException { } Preconditions.checkNotNull(rateLevel); LogicTreeBranch myBranch = new LogicTreeBranch<>(levels, values); - ((RandomLevel)sampledLevel).build(12345l, samples, SamplingMethod.LATIN_HYPERCUBE); + ((RandomLevel)sampledLevel).build(lhSamples); Preconditions.checkState(sampledLevel.getNodes().size() == samples); double weightEach = 1d/samples; SummedMagFreqDist avgMFD = new SummedMagFreqDist(refMFD.getMinX(), refMFD.getMaxX(), refMFD.size()); diff --git a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java index 857dcc9f..d327b9e7 100644 --- a/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java +++ b/src/main/java/scratch/kevin/nshm27/figures/LogicTreeFigure.java @@ -12,8 +12,8 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.LogicTreeFigureWriter; import org.opensha.commons.logicTree.LogicTreeLevel; -import org.opensha.commons.logicTree.LogicTreeLevel.SamplingMethod; import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.sha.earthquake.faultSysSolution.RupSetFaultModel; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_InterfaceFaultModels; import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java new file mode 100644 index 00000000..f81e4a1e --- /dev/null +++ b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java @@ -0,0 +1,130 @@ +package scratch.kevin.sampling; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.List; +import java.util.StringTokenizer; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; + +import org.opensha.commons.data.xyz.GriddedGeoDataSet; +import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.LocationUtils; +import org.opensha.commons.geo.json.Feature; +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.LogicTreeBranch; +import org.opensha.commons.logicTree.sampling.SamplingMethod; +import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc.ReturnPeriods; + +import com.google.common.base.Preconditions; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; + +public class HazardConvergenceCalcs { + + public static void main(String[] args) throws IOException { + String treeFileName = "logic_tree_analysis.json"; + String hazardFileName = "results_hazard.zip"; + + File refMCSDir = new File(PaperPaths.INVS_DIR, "2026_07_17-nshm27-AMSAM-20000samples-mcs"); + LogicTree refMCSTree = LogicTree.read(new File(refMCSDir, treeFileName)); + File refMCSHazardZip = new File(refMCSDir, hazardFileName); + + GriddedRegion gridReg = GriddedRegion.fromFeature(Feature.read(new File(refMCSDir, "gridded_region.geojson"))); + + double period = 0; + String periodName = "PGA"; + String periodPrefix = "pga"; + +// double period = 1; +// String periodName = "1s SA"; +// String periodPrefix = "1s_sa"; + + ReturnPeriods rp = ReturnPeriods.TWO_IN_50; + + System.out.println("Ref has "+refMCSTree.size()+" branches"); + + Table> runDirs = HashBasedTable.create(); + + runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 512, List.of( + new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-512samples-sobol_scrambled"), + new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-512samples-sobol_scrambled-unique_seed") + )); + runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 1024, List.of( + new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-1024samples-sobol_scrambled"), + new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-1024samples-sobol_scrambled-unique_seed") + )); + runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 2048, List.of( + new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-2048samples-sobol_scrambled"), + new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-2048samples-sobol_scrambled-unique_seed") + )); + runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 4096, List.of( + new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-4096samples-sobol_scrambled"), + new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-4096samples-sobol_scrambled-unique_seed") + )); + + ModelHazarMaps refMCSMaps = loadMaps(refMCSHazardZip, refMCSTree, gridReg, period, rp); + } + + private static String mapFilePrefix(double period, ReturnPeriods rp) { + String perStr = period == 0d ? "pga" : (float)period+"s"; + return perStr+"_"+rp.name(); + } + + private static GriddedGeoDataSet readMap(GriddedRegion gridReg, InputStream is) throws IOException { + GriddedGeoDataSet xyz = new GriddedGeoDataSet(gridReg, false); + BufferedReader bRead = new BufferedReader(new InputStreamReader(is)); + String line = bRead.readLine(); + int index = 0; + while (line != null) { + line = line.trim(); + if (!line.startsWith("#")) { + StringTokenizer tok = new StringTokenizer(line); + double lon = Double.parseDouble(tok.nextToken()); + double lat = Double.parseDouble(tok.nextToken()); + double val = Double.parseDouble(tok.nextToken()); + Location loc = new Location(lat, lon); + Preconditions.checkState(LocationUtils.areSimilar(loc, gridReg.getLocation(index))); + xyz.set(index++, val); + } + line = bRead.readLine(); + } + Preconditions.checkState(index == gridReg.getNodeCount()); + bRead.close(); + return xyz; + } + + private static ModelHazarMaps loadMaps(File hazardZip, LogicTree tree, GriddedRegion gridReg, + double period, ReturnPeriods rp) throws ZipException, IOException { + System.out.println("Loading maps from "+hazardZip.getAbsolutePath()); + try (ZipFile zip = new ZipFile(hazardZip)) { + String suffix = mapFilePrefix(period, rp)+".txt"; + String meanEntryName = "mean_map_"+suffix; + ZipEntry meanEntry = zip.getEntry(meanEntryName); + Preconditions.checkNotNull(meanEntry, "Entry doesn't exist in %s: %s", hazardZip.getAbsolutePath(), meanEntryName); + GriddedGeoDataSet meanMap = readMap(gridReg, zip.getInputStream(meanEntry)); + + GriddedGeoDataSet[] individual = new GriddedGeoDataSet[tree.size()]; + for (int i=0; i branch = tree.getBranch(i); + String mapName = branch.buildFileName()+"/map_"+suffix; + ZipEntry mapEntry = zip.getEntry(mapName); + Preconditions.checkNotNull(mapEntry, "Entry doesn't exist in %s: %s", hazardZip.getAbsolutePath(), mapName); + individual[i] = readMap(gridReg, zip.getInputStream(mapEntry)); + } + + System.out.println("\tLoaded mean & "+individual.length+" individual"); + + return new ModelHazarMaps(meanMap, individual); + } + } + + record ModelHazarMaps(GriddedGeoDataSet mean, GriddedGeoDataSet[] individual) {} + +} diff --git a/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java b/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java new file mode 100644 index 00000000..6657d15b --- /dev/null +++ b/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java @@ -0,0 +1,207 @@ +package scratch.kevin.sampling; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.math3.stat.StatUtils; +import org.apache.commons.numbers.core.Precision; +import org.opensha.commons.data.sampling.ArrayPointSet; +import org.opensha.commons.data.sampling.CategoricalSamplingDimension; +import org.opensha.commons.data.sampling.ContinuousSamplingDimension; +import org.opensha.commons.data.sampling.DimensionedPointSet; +import org.opensha.commons.data.sampling.PermutedPointSet; +import org.opensha.commons.data.sampling.PointSet; +import org.opensha.commons.data.sampling.SamplingDimension; +import org.opensha.commons.data.sampling.generator.*; +import org.opensha.commons.data.sampling.optimization.IncrementalPointSetScorer; +import org.opensha.commons.data.sampling.optimization.PointSetHillClimber; +import org.opensha.commons.data.sampling.optimization.PointSetOptimizationResult; +import org.opensha.commons.data.sampling.optimization.QuantizedIncrementalPointSetScorer; +import org.opensha.commons.data.sampling.scoring.ExactPointSetScorer; +import org.opensha.commons.data.sampling.scoring.PointSetScore; +import org.opensha.commons.data.sampling.scoring.PointSetScorer; +import org.opensha.commons.data.sampling.scoring.QuantizedPointSetScorer; + +import com.google.common.base.Preconditions; +import com.google.common.base.Stopwatch; + +public class InitialSamplingTests { + + public static void main(String[] args) { + int numSamples = powerOfTwo(12); +// int numSamples = 5000; +// int numDimensions = 10; + int numDimensions = 30; + int numCategorical = 5; + int maxCategoriesPerDimension = 5; + int numScoringDimensions = 3; + int numIterations = 100000; + + Random r = new Random(123456789l); // repeatable +// Random r = new Random(); // different each time + + List dimensions = buildDimensions(numDimensions, numCategorical, maxCategoriesPerDimension, r); + +// PointSetGenerator generator = new MonteCarloPointSetGenerator(r); +// PointSetGenerator generator = new LatinHypercubePointSetGenerator(r); +// PointSetGenerator generator = new SobolPointSetGenerator(); +// PointSetGenerator generator = new SobolPointSetGenerator(1); + PointSetGenerator generator = new OwenScrambledSobolPointSetGenerator(r); + + System.out.println("\nGenerating "+numSamples+" "+numDimensions+"-D samples with generator: "+generator); + + Stopwatch watch = Stopwatch.createStarted(); + PointSet samples = generator.generate(numSamples, numDimensions); + watch.stop(); + System.out.println("Done in "+timeStr(watch)); + int[] debugPoints = {0, 1, 2, 3, 4, numSamples-1}; + for (int debugPoint : debugPoints) { + System.out.print("Point "+debugPoint+":\t["); + for (int d=0; d 0) + System.out.print(", "); + System.out.print((float)samples.get(debugPoint, d)); + } + System.out.println("]"); + } + + PointSetScorer exactScorer = new ExactPointSetScorer(16); + + System.out.println("\nScoring continuous case to order "+numScoringDimensions); + watch.reset().start(); + PointSetScore score = exactScorer.score(samples, numScoringDimensions); + watch.stop(); + System.out.println("Done in "+timeStr(watch)); + System.out.println("Continuous score:\t"+score); +// System.exit(0); + +// System.out.println("\nRe-scoring continuous case using quantized scorer"); +// PointSetScorer quantizedScorer = new QuantizedPointSetScorer(100); +// watch.reset().start(); +// PointSetScore quantizedScore = quantizedScorer.score(samples, numScoringDimensions); +// watch.stop(); +// System.out.println("Done in "+timeStr(watch)); +// System.out.println("Continuous score:\t"+quantizedScore); + + // now make some categorical + DimensionedPointSet dimensioned = new DimensionedPointSet(samples, dimensions); + System.out.println("\nScoring dimensioned set"); + watch.reset().start(); + PointSetScore dimensionedScore = exactScorer.score(dimensioned, numScoringDimensions); + watch.stop(); + System.out.println("Done in "+timeStr(watch)); + System.out.println("Dimensioned score:\t"+dimensionedScore); + + System.out.println("\nImproving pairwise with "+numIterations+" hill-climbing iterations"); + watch.reset().start(); + PermutedPointSet permuted = PermutedPointSet.independentDimensions(dimensioned); + IncrementalPointSetScorer incrementalScorer = new QuantizedIncrementalPointSetScorer(permuted, 100); + PointSetOptimizationResult result = PointSetHillClimber.optimize(incrementalScorer, numIterations, r); + watch.stop(); + System.out.println("Done in "+timeStr(watch)); + System.out.println("Optimization result:\t"+result); + + System.out.println("\nScoring optimized version"); + watch.reset().start(); + PointSetScore optimizedScore = exactScorer.score(permuted, numScoringDimensions); + watch.stop(); + System.out.println("Done in "+timeStr(watch)); + System.out.println("Optimized score:\t"+optimizedScore); + + // these tests can be uncommented if we need to check JVM or PointSet implementation performance again +// System.out.println("\nConverting optimized version to an ArrayPointSet"); +// watch.reset().start(); +// DimensionedPointSet materialized = new DimensionedPointSet(new ArrayPointSet(permuted), dimensions); +// watch.stop(); +// System.out.println("Done in "+timeStr(watch)); +// System.out.println("Optimized score:\t"+optimizedScore); +// +// System.out.println("\nRe-scoring ArrayPointSet view of optimized version"); +// watch.reset().start(); +// PointSetScore materializedScore = scorer.score(materialized, numScoringDimensions); +// watch.stop(); +// System.out.println("Done in "+timeStr(watch)); +// System.out.println("Optimized score:\t"+materializedScore); +// +// System.out.println("\nRe-scoring the initial continuos case (JVM test)"); +// watch.reset().start(); +// PointSetScore score2 = scorer.score(samples, numScoringDimensions); +// watch.stop(); +// System.out.println("Done in "+timeStr(watch)); +// System.out.println("Continuous re-score:\t"+score2); + } + + static List buildDimensions(int numDimensions, int numCategorical, int maxCategoriesPerDimension, Random r) { + System.out.println("Building categories"); + List dimensions = new ArrayList<>(numDimensions); + Preconditions.checkState(numCategorical <= numDimensions); + Preconditions.checkState(maxCategoriesPerDimension >= 2); + // fill with sequential initially + for (int i=0; i 2 ? 2 + r.nextInt(maxCategoriesPerDimension-2) : 2; + boolean even = r.nextBoolean(); + double[] weights = new double[numCategories]; + if (even) { + Arrays.fill(weights, 1d/numCategories); + } else { + for (int i=0; i 0.04999); + int removeIndex = r.nextInt(numCategories); + if (weights[removeIndex] > 0.0999) { + weights[removeIndex] -= 0.05d; + sum = StatUtils.sum(weights); + remainder = sum - 1d; + } + } + } + } + } + System.out.println("Replacing index "+index+" with categorical weights: "+Arrays.toString(weights)); + dimensions.set(index, CategoricalSamplingDimension.forWeights(weights)); + myNumCategorical++; + } + return dimensions; + } + + private static int powerOfTwo(int n) { + Preconditions.checkState(n <= 30); + return 1 << n; + } + + private static final DecimalFormat timeDF = new DecimalFormat("0.0"); + private static String timeStr(Stopwatch watch) { + double secs = watch.elapsed(TimeUnit.MILLISECONDS)/1000d; + if (secs < 90d) + return timeDF.format(secs)+" s"; + double mins = secs/60d; + if (mins < 90d) + return timeDF.format(mins)+" m"; + double hours = mins / 60d; + return timeDF.format(hours)+" h"; + } + +} \ No newline at end of file diff --git a/src/main/java/scratch/kevin/sampling/PaperPaths.java b/src/main/java/scratch/kevin/sampling/PaperPaths.java new file mode 100644 index 00000000..20e263ef --- /dev/null +++ b/src/main/java/scratch/kevin/sampling/PaperPaths.java @@ -0,0 +1,12 @@ +package scratch.kevin.sampling; + +import java.io.File; + +public class PaperPaths { + + public static final File PAPER_DIR = new File("/home/kevin/Documents/papers/2026_epistemic_sampling/papers-2026-sampled-uncertainties"); + public static final File FIGURES_DIR = new File(PAPER_DIR, "Figures"); + + public static final File INVS_DIR = new File("/home/kevin/OpenSHA/fss_inversions"); + +} diff --git a/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java new file mode 100644 index 00000000..b5835aa0 --- /dev/null +++ b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java @@ -0,0 +1,647 @@ +package scratch.kevin.sampling; + +import java.awt.Color; +import java.awt.Font; +import java.io.File; +import java.io.IOException; +import java.text.DecimalFormat; +import java.text.FieldPosition; +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.IntToDoubleFunction; + +import org.apache.commons.math3.stat.StatUtils; +import org.jfree.chart.LegendItemCollection; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.DatasetRenderingOrder; +import org.jfree.chart.ui.RectangleAnchor; +import org.jfree.chart.ui.RectangleInsets; +import org.jfree.data.Range; +import org.opensha.commons.data.CSVFile; +import org.opensha.commons.data.function.DefaultXY_DataSet; +import org.opensha.commons.data.function.EvenlyDiscretizedFunc; +import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.data.sampling.CategoricalSamplingDimension; +import org.opensha.commons.data.sampling.ContinuousSamplingDimension; +import org.opensha.commons.data.sampling.PointSet; +import org.opensha.commons.data.sampling.SamplingDimension; +import org.opensha.commons.data.sampling.scoring.ExactPointSetScorer; +import org.opensha.commons.data.sampling.scoring.PointSetScore; +import org.opensha.commons.data.sampling.scoring.PointSetScorer; +import org.opensha.commons.data.sampling.scoring.ProjectionScore; +import org.opensha.commons.data.uncertainty.UncertainArbDiscFunc; +import org.opensha.commons.data.xyz.EvenlyDiscrXYZ_DataSet; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.gui.plot.PlotPreferences; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotSymbol; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.gui.plot.jfreechart.xyzPlot.XYZPlotSpec; +import org.opensha.commons.logicTree.LogicTreeLevel; +import org.opensha.commons.logicTree.LogicTreeNode; +import org.opensha.commons.logicTree.sampling.LogicTreePointSetMapper; +import org.opensha.commons.logicTree.sampling.SamplingMethod; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.RandomSeedUtils; +import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.rupForecastImpl.nshm23.logicTree.NSHM23_LogicTreeBranch; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_LogicTree; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.logicTree.NSHM27_ModelRegimeNode; +import org.opensha.sha.earthquake.rupForecastImpl.nshm27.util.NSHM27_RegionLoader.NSHM27_SeismicityRegions; +import org.opensha.sha.util.TectonicRegionType; + +import com.google.common.base.Preconditions; +import com.google.common.base.Stopwatch; + +import net.mahdilamb.colormap.Colors; + +public class SamplingScoreFigures { + + static List getDimsNSHM23() { + List> levels = new ArrayList<>(NSHM23_LogicTreeBranch.levelsCombined); + // remove the first fault model (fixed) level + levels.remove(0); + LogicTreePointSetMapper mapper = new LogicTreePointSetMapper<>(levels); + List dims = mapper.getSamplingDimensions(); + System.out.println("NSHM23 levels:"); + for (int l=0; l getDimsNSHM27_AmSam() { + List> levels = new ArrayList<>(); + levels.addAll(NSHM27_LogicTree.buildLevels(NSHM27_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_INTERFACE, true, true, true, true)); + levels.addAll(NSHM27_LogicTree.buildLevels(NSHM27_SeismicityRegions.AMSAM, TectonicRegionType.SUBDUCTION_SLAB, true, true, true, false)); + levels.addAll(NSHM27_LogicTree.buildLevels(NSHM27_SeismicityRegions.AMSAM, TectonicRegionType.ACTIVE_SHALLOW, true, true, true, false)); + // remove the model/regime (fixed) level + for (int l=levels.size(); --l>=0;) + if (levels.get(l) instanceof NSHM27_ModelRegimeNode.Level) + levels.remove(l); + LogicTreePointSetMapper mapper = new LogicTreePointSetMapper<>(levels); + List dims = mapper.getSamplingDimensions(); + System.out.println("NSHM27 levels:"); + for (int l=0; l combPlotChars = Map.of( + SamplingMethod.MONTE_CARLO, + new PlotCurveCharacterstics(PlotLineType.DOTTED, 1f, Colors.tab_red), + SamplingMethod.LATIN_HYPERCUBE, + new PlotCurveCharacterstics(PlotLineType.DASHED, 1f, Colors.tab_green), + SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, + new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 1f, Colors.tab_orange), + SamplingMethod.OWEN_SCRAMBLED_SOBOL, + new PlotCurveCharacterstics(PlotLineType.SOLID, 1f, Colors.tab_blue)); +// int numPlotTrials = 10; + int numPlotTrials = 0; +// int numAvgTrials = 20; +// int numAvgTrials = 50; + int numAvgTrials = 100; +// int numAvgTrials = 500; + + String treeName = null; + List samplingDimensions = new ArrayList<>(); + for (int i=0; i<10; i++) + samplingDimensions.add(ContinuousSamplingDimension.INSTANCE); + String samplingPrefix = "continuous_"+samplingDimensions.size()+"d"; + +// String treeName = "NSHM23-WUS"; +// List samplingDimensions = getDimsNSHM23(); +// String samplingPrefix = "nshm23_"+samplingDimensions.size()+"d"; + +// String treeName = "NSHM27-AmSam"; +// List samplingDimensions = getDimsNSHM27_AmSam(); +// String samplingPrefix = "nshm27_amsam_"+samplingDimensions.size()+"d"; + + final int dimensions = samplingDimensions.size(); + int numContinuous = 0; + int numCategorical = 0; + for (SamplingDimension dim : samplingDimensions) { + if (dim instanceof CategoricalSamplingDimension) + numCategorical++; + else if (dim instanceof ContinuousSamplingDimension) + numContinuous++; + } + + if (treeName == null) + treeName = ""; + else + treeName += ": "; + treeName += dimensions+"D, "; + + if (numContinuous > 0) { + if (numCategorical > 0) + treeName += numContinuous+" continuous, "; + else + treeName += "all continuous"; + } + if (numCategorical > 0) + treeName += numCategorical+" categorical"; + + System.out.println(treeName); + System.out.println(); + + File outputDir = new File(mainDir, samplingPrefix); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); + + ExactPointSetScorer serialScorer = new ExactPointSetScorer(1); +// ExactPointSetScorer serialScorer = new ExactPointSetScorer(4); + ExactPointSetScorer parallelScorer = new ExactPointSetScorer(16); + + Color[] orderColors = new Color[scoreOrders]; + Color[] oderLightColors = new Color[scoreOrders]; + CPT catCPT = GMT_CPT_Files.CATEGORICAL_TAB10_NOGRAY.instance(); + CPT catLightCPT = GMT_CPT_Files.CATEGORICAL_TAB10_LIGHT_NOGRAY.instance(); + for (int d=0; d1d+(scoreOrders-order)/2d; + + // this results in the following, and lower orders don't change as more are added: + // 1D: 3.375 + // 2D: 2.25 + // 3D: 1.5 + // 4D: 1.0 + // 5D: 0.6666667 + // 6D: 0.44444445 + IntToDoubleFunction orderThicknessFunc = (order)->Math.pow(1.5, 4-order); +// for (int order=1; order<=scoreOrders; order++) +// System.out.println(order+"D:\t"+(float)orderThicknessFunc.applyAsDouble(order)); +// System.exit(0); + + Range dimXRange = new Range(1d, dimensions); + Range logYRange = new Range(1e-4, 2e0); + Range equivYRange = new Range(1e2, sampleCounts[sampleCounts.length-1] > 3000 ? 1e8 : 1e7); + + List>> methodScores = new ArrayList<>(); + for (int m=0; m()); + + Stopwatch totalWatch = Stopwatch.createStarted(); + for (int sampleCount : sampleCounts) { + Stopwatch sampleWatch = Stopwatch.createStarted(); + System.out.println("Doing "+sampleCount+" samples"); + File subDir = new File(outputDir, sampleCount+"_samples"); + Preconditions.checkState(subDir.exists() || subDir.mkdir()); + PointSet[] firstPointSets = new PointSet[methods.length]; + for (int m=0; m> sampleFutures = new LinkedList<>(); + + for (int i=0; imethod.prepare(sampleCount, samplingDimensions, seed))); + } + + // if we only have 1 trial, do that one in parallel + // if we have many, rely on across-trial parallelism instead + PointSetScorer scorer = myTrials == 1 ? parallelScorer : serialScorer; + + List> scoreFutures = new ArrayList<>(); + while (!sampleFutures.isEmpty()) { + CompletableFuture sampleFuture = sampleFutures.removeFirst(); + PointSet sample = sampleFuture.join(); + if (firstPointSets[m] == null) + firstPointSets[m] = sample; + scoreFutures.add(CompletableFuture.supplyAsync(()->scorer.score(sample, scoreOrders))); + } + + List scores = scoreFutures.stream().map(F->F.join()).toList(); + + methodScores.get(m).add(scores); + + if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL) { + // rebuild it to remove the row scrambling + firstPointSets[m] = method.createGenerator(baseRand.nextLong()).generate(sampleCount, dimensions); + } + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + + double[][][] scores2D = new double[dimensions][dimensions][myTrials]; + for (int i=0; i shadedFuncs = new ArrayList<>(); + List shadedChars = new ArrayList<>(); + + for (int order=1; order<=scoreOrders; order++) { + double overallAverage = 0d; + double[][] dimScores = new double[dimensions][scores.size()]; + double[] dimAverages = new double[dimensions]; + + for (int s=0; s= 1); + dimScores[d][s] /= dimCounts[d]; + dimAverages[d] += dimScores[d][s]; + } + if (s < numPlotTrials) { + // plot it + EvenlyDiscretizedFunc dimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + for (int d=0; d 1) { + EvenlyDiscretizedFunc upperDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + EvenlyDiscretizedFunc middleDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + EvenlyDiscretizedFunc lowerDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + for (int d=0; d 20 ? 2d : 1d; + + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + + gp.setRenderingOrder(DatasetRenderingOrder.REVERSE); + + gp.drawGraphPanel(plot, false, true, dimXRange, logYRange); + PlotUtils.setXTick(gp, xTick); + + PlotUtils.writePrintPlots(subDir, "scores_"+prefix, gp, + PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 3d, 300, true, true, false); + + EvenlyDiscrXYZ_DataSet avgXYZ = new EvenlyDiscrXYZ_DataSet(dimensions, dimensions, 1d, 1d, 1d); + EvenlyDiscrXYZ_DataSet avgAbsXYZ = new EvenlyDiscrXYZ_DataSet(dimensions, dimensions, 1d, 1d, 1d); + CPT logRatioCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-1d, 1d); + logRatioCPT.setLog10(true); + CPT logAbsCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-1d, 1d).trim(0d, 1d); +// CPT logAbsCPT = logRatioCPT.trim(0d, 1d); + logAbsCPT.setLog10(true); + for (int i=0; i plots = new ArrayList<>(); + Range range = new Range(0d, 1d); + List xRanges = new ArrayList<>(); + List yRanges = List.of(range); + List subtitles = new ArrayList<>(); + for (int m=0; m funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + PointSet sample = firstPointSets[m]; + DefaultXY_DataSet xy = new DefaultXY_DataSet(); + for (int i=0; i 0) + prefix += "_"+dim1+"_"+dim2; + + PlotUtils.writePrintPlots(subDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH, false, 300, true, true, false); + } + } + sampleWatch.stop(); + System.out.println("DONE with "+sampleCount+" in "+timeStr(sampleWatch)+"\n"); + } + + totalWatch.stop(); + System.out.println("DONE with all calculations in "+timeStr(totalWatch)); + + // now combined plots + List scoreFuncs = new ArrayList<>(); + List scoreChars = new ArrayList<>(); + List equivCountFuncs = new ArrayList<>(); + List equivCountChars = new ArrayList<>(); + CSVFile scoresCSV = new CSVFile<>(true); + List header = new ArrayList<>(); + header.add(""); + for (int order=1; order<=scoreOrders; order++) + for (int s=0; s scoreLine = new ArrayList<>(header.size()); + scoreLine.add(method.getShortName()); + + for (int order=1; order<=scoreOrders; order++) { + EvenlyDiscretizedFunc scoreFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); + EvenlyDiscretizedFunc scoreLowerFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); + EvenlyDiscretizedFunc scoreUpperFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); + EvenlyDiscretizedFunc equivFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); + + for (int s=0; s scores = methodScores.get(m).get(s); + + double sum = 0d; + double min = Double.POSITIVE_INFINITY; + double max = 0d; + for (PointSetScore score : scores) { + double orderScore = score.getOrderMeanScore(order); + sum += orderScore; + min = Math.min(min, orderScore); + max = Math.max(max, orderScore); + } + double avg = sum / scores.size(); + scoreLine.add((float)avg+""); + + scoreFunc.set(s, avg); + scoreLowerFunc.set(s, min); + scoreUpperFunc.set(s, max); + double equivCount = (double)sampleCount / avg; + equivFunc.set(s, equivCount); + } + + if (order == 1) { + scoreFunc.setName(method.getShortName()); + equivFunc.setName(method.getShortName()); + } else if (method == SamplingMethod.MONTE_CARLO) { + // they all overlap, cleaner to just show 1D + continue; + } + + double thickness = orderThicknessFunc.applyAsDouble(order); + scoreFuncs.add(scoreFunc); + scoreChars.add(getForThickness(methodChar, thickness)); + +// UncertainArbDiscFunc rangeFunc = new UncertainArbDiscFunc(scoreFunc, scoreLowerFunc, scoreUpperFunc); +// rangeFunc.setName(null); +// scoreFuncs.add(0, rangeFunc); +// scoreChars.add(0, new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, methodTransColor)); + + equivCountFuncs.add(equivFunc); + equivCountChars.add(getForThickness(methodChar, thickness)); + } + scoresCSV.addLine(scoreLine); + } + List orderTicknessFuncs = new ArrayList<>(); + List orderThicknessChars = new ArrayList<>(); + for (int order=1; order<=scoreOrders; order++) { + double thickness = orderThicknessFunc.applyAsDouble(order); + + XY_DataSet fakeXY = new DefaultXY_DataSet(-100d, 1d); + fakeXY.setName(order+"D"); + PlotCurveCharacterstics orderChar = new PlotCurveCharacterstics(PlotLineType.SOLID, (float)thickness, Color.GRAY); + orderTicknessFuncs.add(fakeXY); + orderThicknessChars.add(orderChar); + } + PlotSpec orderPlot = new PlotSpec(orderTicknessFuncs, orderThicknessChars, null, null, null); + + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + PlotPreferences prefs = gp.getPlotPrefs(); + prefs.setPlotLabelFontSize(10); + prefs.setLegendFontSize(8); + prefs.setLegendLineLength(8d); + prefs.getPlotPadding(); + prefs.setPlotPadding(new RectangleInsets(4, 0, 0, 12)); + + gp.drawGraphPanel(orderPlot, false, false); + LegendItemCollection orderLegendItems = gp.getPlot().getLegendItems(); + +// EvenlyDiscretizedFunc equivLinear = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); +// for (int s=0; s= 0 && index < sampleCounts.length + && Math.abs(value - index) < 1e-6) + buffer.append(sampleCounts[index]); + return buffer; + } + + @Override + public StringBuffer format(long value, StringBuffer buffer, FieldPosition pos) { + return format((double)value, buffer, pos); + } + + @Override + public Number parse(String source, ParsePosition pos) { + pos.setErrorIndex(pos.getIndex()); + return null; + } + }; + + PlotSpec plot = new PlotSpec(scoreFuncs, scoreChars, treeName, "Sample count", "Normalized score"); +// plot.setLegendInset(true); + plot.setLegendVisible(true); + + orderPlot.setLegendInset(RectangleAnchor.BOTTOM_LEFT); + plot.addPlotAnnotation(orderPlot.buildInsetLegend(orderLegendItems, prefs, false, true, categoricalXRange, logYRange)); + + gp.setRenderingOrder(DatasetRenderingOrder.REVERSE); + + gp.drawGraphPanel(plot, false, true, categoricalXRange, logYRange); + PlotUtils.setXTick(gp, 1); + ((NumberAxis)gp.getXAxis()).setNumberFormatOverride(categoryFormat); + + String prefix = "combined_scores"; + PlotUtils.writePrintPlots(outputDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 4, 300, true, true, false); + scoresCSV.writeToFile(new File(outputDir, prefix+".csv")); + + plot = new PlotSpec(equivCountFuncs, equivCountChars, treeName, "Sample count", "Equivalent MCS count"); +// plot.setLegendInset(true); + plot.setLegendVisible(true); + + orderPlot.setLegendInset(RectangleAnchor.TOP_LEFT); + plot.addPlotAnnotation(orderPlot.buildInsetLegend(orderLegendItems, prefs, false, true, categoricalXRange, equivYRange)); + + gp.drawGraphPanel(plot, false, true, categoricalXRange, equivYRange); + PlotUtils.setXTick(gp, 1); + ((NumberAxis)gp.getXAxis()).setNumberFormatOverride(categoryFormat); + + prefix = "combined_equivs"; + PlotUtils.writePrintPlots(outputDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 4, 300, true, true, false); + } + + private static PlotCurveCharacterstics getForThickness(PlotCurveCharacterstics pChar, double thickness) { + PlotCurveCharacterstics copy = (PlotCurveCharacterstics)pChar.clone(); + copy.setLineWidth((float)thickness); + return copy; + } + + private static final DecimalFormat timeDF = new DecimalFormat("0.0"); + private static String timeStr(Stopwatch watch) { + double secs = watch.elapsed(TimeUnit.MILLISECONDS)/1000d; + if (secs < 90d) + return timeDF.format(secs)+" s"; + double mins = secs/60d; + if (mins < 90d) + return timeDF.format(mins)+" m"; + double hours = mins / 60d; + return timeDF.format(hours)+" h"; + } + +} diff --git a/src/main/java/scratch/kevin/ucerf3/PureScratch.java b/src/main/java/scratch/kevin/ucerf3/PureScratch.java index 39efc3cd..622e43b3 100644 --- a/src/main/java/scratch/kevin/ucerf3/PureScratch.java +++ b/src/main/java/scratch/kevin/ucerf3/PureScratch.java @@ -738,7 +738,7 @@ private static void test263() throws IOException { } RandomDefModSampleLevel level = new RandomDefModSampleLevel("Name", "Short name"); - level.build(new Random().nextLong(), 10); +// level.build(new Random().nextLong(), 10); System.out.println("Test level: "+level.getName()); System.out.println("\tAffected: "+level.getAffected()); System.out.println("\tNot affected: "+level.getNotAffected()); From fcdba047363dc625671becbdd41c43bd892efcb9 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Wed, 2 Sep 2026 15:49:41 -0700 Subject: [PATCH 58/71] faster calcs --- .../sampling/HazardConvergenceCalcs.java | 937 +++++++++++++++++- .../sampling/HazardConvergencePlots.java | 371 +++++++ .../kevin/sampling/SamplingScoreFigures.java | 590 +++++------ 3 files changed, 1587 insertions(+), 311 deletions(-) create mode 100644 src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java index f81e4a1e..ba51faff 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java @@ -2,16 +2,31 @@ import java.io.BufferedReader; import java.io.File; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumMap; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.SplittableRandom; import java.util.StringTokenizer; +import java.util.TreeMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.stream.IntStream; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; +import org.apache.commons.math3.stat.StatUtils; +import org.opensha.commons.data.CSVFile; +import org.opensha.commons.data.function.DiscretizedFunc; +import org.opensha.commons.data.function.LightFixedXFunc; import org.opensha.commons.data.xyz.GriddedGeoDataSet; import org.opensha.commons.geo.GriddedRegion; import org.opensha.commons.geo.Location; @@ -20,6 +35,8 @@ import org.opensha.commons.logicTree.LogicTree; import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.sampling.SamplingMethod; +import org.opensha.commons.util.RandomSeedUtils; +import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc.ReturnPeriods; import com.google.common.base.Preconditions; @@ -27,31 +44,30 @@ import com.google.common.collect.Table; public class HazardConvergenceCalcs { + static final String MCS_REFERENCE_NAME = "20k MCS"; + static final String POOLED_SOBOL_REFERENCE_NAME = "Pooled Sobol"; + static final String LOO_SOBOL_REFERENCE_NAME = "Pooled Sobol, leave one out"; + private static final int MAX_RUN_LOAD_THREADS = 4; public static void main(String[] args) throws IOException { + File outputDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence"); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir(), + "Couldn't create output directory: %s", outputDir.getAbsolutePath()); String treeFileName = "logic_tree_analysis.json"; String hazardFileName = "results_hazard.zip"; - + File refMCSDir = new File(PaperPaths.INVS_DIR, "2026_07_17-nshm27-AMSAM-20000samples-mcs"); LogicTree refMCSTree = LogicTree.read(new File(refMCSDir, treeFileName)); File refMCSHazardZip = new File(refMCSDir, hazardFileName); - + GriddedRegion gridReg = GriddedRegion.fromFeature(Feature.read(new File(refMCSDir, "gridded_region.geojson"))); - - double period = 0; - String periodName = "PGA"; - String periodPrefix = "pga"; - -// double period = 1; -// String periodName = "1s SA"; -// String periodPrefix = "1s_sa"; - + ReturnPeriods rp = ReturnPeriods.TWO_IN_50; - + System.out.println("Ref has "+refMCSTree.size()+" branches"); - + Table> runDirs = HashBasedTable.create(); - + runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 512, List.of( new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-512samples-sobol_scrambled"), new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-512samples-sobol_scrambled-unique_seed") @@ -66,17 +82,725 @@ public static void main(String[] args) throws IOException { )); runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 4096, List.of( new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-4096samples-sobol_scrambled"), - new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-4096samples-sobol_scrambled-unique_seed") + new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-4096samples-sobol_scrambled-unique_seed"), + new File(PaperPaths.INVS_DIR, "2026_08_27-nshm27-AMSAM-4096samples-sobol_scrambled-unique_seed-2"), + new File(PaperPaths.INVS_DIR, "2026_08_27-nshm27-AMSAM-4096samples-sobol_scrambled-unique_seed-3") )); - - ModelHazarMaps refMCSMaps = loadMaps(refMCSHazardZip, refMCSTree, gridReg, period, rp); + runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 8192, List.of( + new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-8192samples-sobol_scrambled"), + new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed"), + new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-2"), + new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-3") + )); + runDirs.put(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, 4096, List.of( + new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise"), + new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed") + )); + + List sobolRuns = loadRunSpecs(SamplingMethod.OWEN_SCRAMBLED_SOBOL, + runDirs.row(SamplingMethod.OWEN_SCRAMBLED_SOBOL)); + List pairwiseLHSRuns = loadRunSpecs(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, + runDirs.row(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE)); + File convergenceDir = new File(outputDir, "sobol_convergence"); + Preconditions.checkState(convergenceDir.exists() || convergenceDir.mkdir(), + "Couldn't create output directory: %s", convergenceDir.getAbsolutePath()); + + double[] periods = { 0d, 1d }; + String[] periodNames = { "PGA", "1 s SA" }; + String[] periodPrefixes = { "pga", "1s_sa" }; + for (int p=0; p loadRunSpecs(SamplingMethod method, + Map> runDirs) throws IOException { + List runs = new ArrayList<>(); + for (Map.Entry> entry : new TreeMap<>(runDirs).entrySet()) { + for (File dir : entry.getValue()) { + Preconditions.checkState(dir.isDirectory(), "Run directory doesn't exist: %s", dir.getAbsolutePath()); + LogicTree tree = LogicTree.read(new File(dir, "logic_tree_analysis.json")); + Preconditions.checkState(tree.size() == entry.getKey(), "Expected %s branches in %s, have %s", + entry.getKey(), dir.getName(), tree.size()); + Preconditions.checkState(tree.getSamplingMethod() == method, + "Expected %s tree, have %s: %s", method, tree.getSamplingMethod(), dir.getName()); + runs.add(new RunSpec(dir.getName(), dir, tree, method, + tree.getSamplingRandomSeed(), tree.size())); + } + } + return runs; + } + + private static void runSamplingConvergence(List sobolRuns, List pairwiseLHSRuns, + ModelHazardMaps mcsMaps, + GriddedRegion gridReg, double period, String periodName, ReturnPeriods rp, File outputDir) throws IOException { + List sobolData = loadRunPeriodData(sobolRuns, gridReg, period, rp); + List pairwiseLHSData = loadRunPeriodData(pairwiseLHSRuns, gridReg, period, rp); + + HazardStatistics mcsStatistics = calcHazardStatistics(copyValues(mcsMaps.individual()), + mcsMaps.individual().length, copyValues(mcsMaps.mean())); + ReferenceStatistics mcsReference = new ReferenceStatistics(MCS_REFERENCE_NAME, null, + mcsMaps.individual().length, mcsStatistics); + Map leaveOneOut = new LinkedHashMap<>(); + for (RunPeriodData data : sobolData) + leaveOneOut.put(data.run(), buildPooledSobolReference(sobolData, data.run(), gridReg, rp)); + ReferenceStatistics pooledSobol = buildPooledSobolReference(sobolData, null, gridReg, rp); + + List comparisons = new ArrayList<>(); + for (RunPeriodData data : sobolData) { + ReferenceStatistics sobolReference = leaveOneOut.get(data.run()); + for (Map.Entry entry : data.checkpoints().entrySet()) { + appendComparisons(comparisons, data.run(), entry.getKey(), entry.getValue(), sobolReference, gridReg); + appendComparisons(comparisons, data.run(), entry.getKey(), entry.getValue(), mcsReference, gridReg); + } + } + // Pairwise LHS is optimized as a complete design; its prefixes are not valid smaller LHS designs. + for (RunPeriodData data : pairwiseLHSData) { + HazardStatistics statistics = data.checkpoints().get(data.run().maxSamples()); + appendComparisons(comparisons, data.run(), data.run().maxSamples(), + statistics, pooledSobol, gridReg); + appendComparisons(comparisons, data.run(), data.run().maxSamples(), + statistics, mcsReference, gridReg); + } + writeReferenceComparisons(new File(outputDir, "reference_comparisons.csv"), comparisons); + writeReferenceComparisonSummary(new File(outputDir, "reference_comparison_summary.csv"), comparisons); + + List doublings = new ArrayList<>(); + for (RunPeriodData data : sobolData) { + for (Map.Entry entry : data.checkpoints().entrySet()) { + int lowerCount = entry.getKey(); + HazardStatistics upper = data.checkpoints().get(2*lowerCount); + if (upper == null) + continue; + for (ConvergenceMetric metric : ConvergenceMetric.values()) { + MapComparison comparison = compare(upper.values(metric), entry.getValue().values(metric)); + doublings.add(new DoublingComparison(data.run(), lowerCount, 2*lowerCount, + metric, comparison, gridReg.getLocation(comparison.maximumAbsoluteIndex()))); + } + } + } + writeDoublingComparisons(new File(outputDir, "paired_doubling_comparisons.csv"), doublings); + writeDoublingComparisonSummary(new File(outputDir, "paired_doubling_summary.csv"), doublings); + + List allData = new ArrayList<>(sobolData); + allData.addAll(pairwiseLHSData); + List realizationPairs = buildRealizationPairComparisons(allData, gridReg); + writeRealizationPairComparisons(new File(outputDir, "realization_pair_comparisons.csv"), realizationPairs); + writeRealizationPairComparisonSummary( + new File(outputDir, "realization_pair_summary.csv"), realizationPairs); + + HazardConvergencePlots.plotPeriod(outputDir, periodName); + } + + private static List loadRunPeriodData(List runs, + GriddedRegion gridReg, double period, ReturnPeriods rp) throws IOException { + if (runs.isEmpty()) + return List.of(); + int threads = Math.min(MAX_RUN_LOAD_THREADS, runs.size()); + if (threads == 1) + return List.of(loadRunPeriodData(runs.get(0), gridReg, period, rp)); + + ExecutorService executor = Executors.newFixedThreadPool(threads); + try { + List> futures = new ArrayList<>(runs.size()); + for (RunSpec run : runs) + futures.add(executor.submit(() -> loadRunPeriodData(run, gridReg, period, rp))); + List data = new ArrayList<>(runs.size()); + // Retrieve in input order so downstream CSV and plot ordering remains stable. + for (Future future : futures) { + try { + data.add(future.get()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IOException("Interrupted while loading hazard runs", e); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause instanceof IOException ioException) + throw ioException; + if (cause instanceof RuntimeException runtimeException) + throw runtimeException; + if (cause instanceof Error error) + throw error; + throw new IOException("Exception while loading hazard runs", cause); + } + } + return data; + } finally { + executor.shutdownNow(); + } + } + + private static RunPeriodData loadRunPeriodData(RunSpec run, GriddedRegion gridReg, + double period, ReturnPeriods rp) throws IOException { + System.out.println("\nLoading "+run.method().getShortName()+" run: "+run.id()); + ModelHazardMaps maps = loadMaps(new File(run.directory(), "results_hazard.zip"), + run.tree(), gridReg, period, rp); + double[][] branchMaps = copyValues(maps.individual()); + File hazardResultsDir = new File(run.directory(), "results"); + + double[] curveX = null; + double[][] curveSums = null; + Map checkpoints = new TreeMap<>(); + for (int b=0; b= 512 && Integer.bitCount(count) == 1; + if (fullRun || sobolCheckpoint) { + double[] curveMean = buildCurveMeanMap(curveSums, curveX, count, rp); + checkpoints.put(count, calcHazardStatistics(branchMaps, count, curveMean)); + System.out.println("\tBuilt "+count+"-sample checkpoint"); + } + } + Preconditions.checkState(checkpoints.containsKey(run.maxSamples())); + MapComparison archivedComparison = compare( + checkpoints.get(run.maxSamples()).values(ConvergenceMetric.MEAN_HAZARD), copyValues(maps.mean())); + System.out.println("\tCurve mean versus archived mean: "+archivedComparison); + return new RunPeriodData(run, branchMaps, curveX, curveSums, checkpoints); + } + + private static ReferenceStatistics buildPooledSobolReference(List allRuns, + RunSpec excluded, GriddedRegion gridReg, ReturnPeriods rp) { + int sampleCount = 0; + int curveSize = -1; + double[] curveX = null; + for (RunPeriodData data : allRuns) { + if (data.run().equals(excluded)) + continue; + sampleCount += data.run().maxSamples(); + if (curveX == null) { + curveX = data.curveX(); + curveSize = curveX.length; + } else { + Preconditions.checkState(curveSize == data.curveX().length); + for (int i=0; i 0); + double[][] curveSums = new double[gridReg.getNodeCount()][curveSize]; + double[][] branchMaps = new double[sampleCount][]; + int destBranch = 0; + for (RunPeriodData data : allRuns) { + if (data.run().equals(excluded)) + continue; + for (int n=0; n curve.getMaxY()) + map[n] = 0d; + else if (rp.oneYearProb < curve.getMinY()) + map[n] = curve.getMaxX(); + else + map[n] = curve.getFirstInterpolatedX_inLogXLogYDomain(rp.oneYearProb); + } + return map; + } + + private static HazardStatistics calcHazardStatistics(double[][] branchMaps, int sampleCount, + double[] curveMean) { + Preconditions.checkArgument(sampleCount > 1 && sampleCount <= branchMaps.length); + Preconditions.checkArgument(curveMean.length == branchMaps[0].length); + int numSites = curveMean.length; + double[] standardDeviation = new double[numSites]; + double[] iqr = new double[numSites]; + double[] central68 = new double[numSites]; + double[] central95 = new double[numSites]; + int workers = Math.min(numSites, Runtime.getRuntime().availableProcessors()); + // Partition sites rather than allocating a sample array for every parallel-stream element. + IntStream.range(0, workers).parallel().forEach(worker -> { + double[] values = new double[sampleCount]; + for (int n=worker; n -1e-12*sumSquares) + varianceNumerator = 0d; + Preconditions.checkState(varianceNumerator >= 0d, + "Negative variance numerator at site "+n+": "+varianceNumerator); + standardDeviation[n] = Math.sqrt(varianceNumerator/sampleCount); + Arrays.sort(values); + iqr[n] = empiricalFractile(values, 0.75)-empiricalFractile(values, 0.25); + central68[n] = empiricalFractile(values, 0.84)-empiricalFractile(values, 0.16); + central95[n] = empiricalFractile(values, 0.975)-empiricalFractile(values, 0.025); + } + }); + Map metricValues = new EnumMap<>(ConvergenceMetric.class); + metricValues.put(ConvergenceMetric.MEAN_HAZARD, curveMean); + metricValues.put(ConvergenceMetric.STANDARD_DEVIATION, standardDeviation); + metricValues.put(ConvergenceMetric.IQR, iqr); + metricValues.put(ConvergenceMetric.CENTRAL_68_RANGE, central68); + metricValues.put(ConvergenceMetric.CENTRAL_95_RANGE, central95); + return new HazardStatistics(metricValues); + } + + private static double empiricalFractile(double[] sortedValues, double fractile) { + Preconditions.checkArgument(sortedValues.length > 0 && fractile >= 0d && fractile <= 1d); + double previousValue = sortedValues[0]; + int index = 1; + while (index < sortedValues.length && (float)sortedValues[index] == (float)previousValue) + index++; + double previousCDF = (double)index/sortedValues.length; + if (fractile <= previousCDF) + return previousValue; + while (index < sortedValues.length) { + double value = sortedValues[index++]; + while (index < sortedValues.length && (float)sortedValues[index] == (float)value) + index++; + double cdf = (double)index/sortedValues.length; + if (fractile == cdf) + return value; + if (fractile < cdf) { + double relative = (fractile-previousCDF)/(cdf-previousCDF); + return previousValue + relative*(value-previousValue); + } + previousValue = value; + previousCDF = cdf; + } + return sortedValues[sortedValues.length-1]; + } + + private static void appendComparisons(List comparisons, RunSpec run, + int sampleCount, HazardStatistics statistics, ReferenceStatistics reference, GriddedRegion gridReg) { + for (ConvergenceMetric metric : ConvergenceMetric.values()) { + MapComparison comparison = compare(statistics.values(metric), reference.statistics().values(metric)); + comparisons.add(new ReferenceComparison(run, sampleCount, reference.name(), reference.sampleCount(), + metric, comparison, gridReg.getLocation(comparison.maximumAbsoluteIndex()))); + } + } + + private static void writeReferenceComparisons(File file, List comparisons) + throws IOException { + CSVFile csv = new CSVFile<>(true); + csv.addLine("Run", "Sampling method", "Seed", "Maximum run size", "Sample count", + "Reference", "Reference sample count", + "Metric", "Spatial mean % change", "Spatial mean absolute % change", + "Spatial P95 absolute % change", "Maximum absolute % change", "Minimum % change", + "Maximum % change", "Worst longitude", "Worst latitude"); + for (ReferenceComparison row : comparisons) { + MapComparison comparison = row.comparison(); + csv.addLine(row.run().id(), row.run().method().name(), row.run().seed()+"", + row.run().maxSamples()+"", row.sampleCount()+"", + row.referenceName(), row.referenceSampleCount()+"", row.metric().label, + comparison.meanPercentChange()+"", comparison.meanAbsolutePercentChange()+"", + comparison.p95AbsolutePercentChange()+"", comparison.maximumAbsolutePercentChange()+"", + comparison.minimumPercentChange()+"", comparison.maximumPercentChange()+"", + row.worstLocation().lon+"", row.worstLocation().lat+""); + } + csv.writeToFile(file); + } + + private static void writeReferenceComparisonSummary(File file, List comparisons) + throws IOException { + Map> groups = new LinkedHashMap<>(); + for (ReferenceComparison comparison : comparisons) { + ReferenceComparisonGroup group = new ReferenceComparisonGroup(comparison.run().method(), + comparison.sampleCount(), + comparison.referenceName(), comparison.metric()); + groups.computeIfAbsent(group, key -> new ArrayList<>()).add(comparison); + } + CSVFile csv = new CSVFile<>(true); + csv.addLine("Sampling method", "Sample count", "Reference", "Metric", "Spatial summary", "Realizations", + "Mean", "P2.5", "P16", "P50", "P84", "P97.5"); + for (Map.Entry> entry : groups.entrySet()) { + ReferenceComparisonGroup group = entry.getKey(); + for (ConvergenceSummary summary : ConvergenceSummary.values()) { + double[] values = new double[entry.getValue().size()]; + for (int i=0; i comparisons) + throws IOException { + CSVFile csv = new CSVFile<>(true); + csv.addLine("Run", "Sampling method", "Seed", "Maximum run size", "Lower sample count", + "Upper sample count", "Metric", + "Spatial mean % change", "Spatial mean absolute % change", "Spatial P95 absolute % change", + "Maximum absolute % change", "Minimum % change", "Maximum % change", + "Worst longitude", "Worst latitude"); + for (DoublingComparison row : comparisons) { + MapComparison comparison = row.comparison(); + csv.addLine(row.run().id(), row.run().method().name(), row.run().seed()+"", + row.run().maxSamples()+"", row.lowerCount()+"", + row.upperCount()+"", row.metric().label, comparison.meanPercentChange()+"", + comparison.meanAbsolutePercentChange()+"", comparison.p95AbsolutePercentChange()+"", + comparison.maximumAbsolutePercentChange()+"", comparison.minimumPercentChange()+"", + comparison.maximumPercentChange()+"", row.worstLocation().lon+"", row.worstLocation().lat+""); + } + csv.writeToFile(file); + } + + private static void writeDoublingComparisonSummary(File file, List comparisons) + throws IOException { + Map> groups = new LinkedHashMap<>(); + for (DoublingComparison comparison : comparisons) { + DoublingComparisonGroup group = new DoublingComparisonGroup(comparison.run().method(), comparison.lowerCount(), + comparison.upperCount(), comparison.metric()); + groups.computeIfAbsent(group, key -> new ArrayList<>()).add(comparison); + } + CSVFile csv = new CSVFile<>(true); + csv.addLine("Sampling method", "Lower sample count", "Upper sample count", "Metric", + "Spatial summary", "Realizations", + "Mean", "P2.5", "P16", "P50", "P84", "P97.5"); + for (Map.Entry> entry : groups.entrySet()) { + DoublingComparisonGroup group = entry.getKey(); + for (ConvergenceSummary summary : ConvergenceSummary.values()) { + double[] values = new double[entry.getValue().size()]; + for (int i=0; i buildRealizationPairComparisons( + List allData, GriddedRegion gridReg) { + Map> groups = new LinkedHashMap<>(); + for (RunPeriodData data : allData) + for (int sampleCount : data.checkpoints().keySet()) { + MethodCount group = new MethodCount(data.run().method(), sampleCount); + groups.computeIfAbsent(group, unused -> new ArrayList<>()).add(data); + } + List comparisons = new ArrayList<>(); + for (Map.Entry> entry : groups.entrySet()) { + List data = entry.getValue(); + for (int i=0; i comparisons) throws IOException { + CSVFile csv = new CSVFile<>(true); + csv.addLine("Sampling method", "Sample count", "First run", "First seed", "Second run", "Second seed", + "Metric", "Spatial mean % change", "Spatial mean absolute % change", + "Spatial P95 absolute % change", "Maximum absolute % change", "Minimum % change", + "Maximum % change", "Worst longitude", "Worst latitude"); + for (RealizationPairComparison row : comparisons) { + MapComparison comparison = row.comparison(); + csv.addLine(row.method().name(), row.sampleCount()+"", row.first().id(), row.first().seed()+"", + row.second().id(), row.second().seed()+"", row.metric().label, + comparison.meanPercentChange()+"", comparison.meanAbsolutePercentChange()+"", + comparison.p95AbsolutePercentChange()+"", comparison.maximumAbsolutePercentChange()+"", + comparison.minimumPercentChange()+"", comparison.maximumPercentChange()+"", + row.worstLocation().lon+"", row.worstLocation().lat+""); + } + csv.writeToFile(file); + } + + private static void writeRealizationPairComparisonSummary(File file, + List comparisons) throws IOException { + Map> groups = new LinkedHashMap<>(); + for (RealizationPairComparison comparison : comparisons) { + RealizationPairComparisonGroup group = new RealizationPairComparisonGroup(comparison.method(), + comparison.sampleCount(), comparison.metric()); + groups.computeIfAbsent(group, unused -> new ArrayList<>()).add(comparison); + } + CSVFile csv = new CSVFile<>(true); + csv.addLine("Sampling method", "Sample count", "Metric", "Spatial summary", "Realization pairs", + "Mean", "P2.5", "P16", "P50", "P84", "P97.5"); + for (Map.Entry> entry : groups.entrySet()) { + RealizationPairComparisonGroup group = entry.getKey(); + for (ConvergenceSummary summary : ConvergenceSummary.values()) { + double[] values = new double[entry.getValue().size()]; + for (int i=0; i csv, List prefix, double[] values) { + List line = new ArrayList<>(prefix); + line.add(StatUtils.mean(values)+""); + line.add(percentile(values, 2.5)+""); + line.add(percentile(values, 16d)+""); + line.add(percentile(values, 50d)+""); + line.add(percentile(values, 84d)+""); + line.add(percentile(values, 97.5)+""); + csv.addLine(line); } - + + /** + * Resamples the reference MCS branches with replacement. Smaller resample sizes describe the error expected from + * ordinary MCS at those sample counts; the full-size resample describes uncertainty in the reference itself. + * Results are deterministic for a given seed even though replicates are evaluated in parallel. + */ + static void runBootstrapTests(ModelHazardMaps reference, int[] sampleCounts, int numReplicates, long seed, + File outputDir, String outputPrefix) throws IOException { + Preconditions.checkArgument(numReplicates > 1); + Preconditions.checkArgument(sampleCounts.length > 0); + + double[][] branchValues = copyValues(reference.individual()); + StatisticMaps referenceStats = calcStatistics(branchValues, null, branchValues.length); + MapComparison archivedMeanComparison = compare(referenceStats.mean(), copyValues(reference.mean())); + System.out.println("Branch-map arithmetic mean versus archived curve-derived mean (expected to differ): " + +archivedMeanComparison); + + CSVFile replicateCSV = new CSVFile<>(true); + replicateCSV.addLine("Sample count", "Replicate", "Metric", "Spatial mean % change", + "Spatial mean absolute % change", "Minimum % change", "Maximum % change"); + CSVFile summaryCSV = new CSVFile<>(true); + summaryCSV.addLine("Sample count", "Metric", "Spatial summary", "Mean", "P2.5", "P16", "P50", + "P84", "P97.5"); + CSVFile siteCSV = new CSVFile<>(true); + siteCSV.addLine("Sample count", "Metric", "Longitude", "Latitude", "Reference value", + "Mean % change", "Std. dev. % change", "P2.5", "P16", "P50", "P84", "P97.5"); + + for (int sampleCount : sampleCounts) { + Preconditions.checkArgument(sampleCount > 1); + System.out.println("\nBootstrapping "+sampleCount+" branches x "+numReplicates+" replicates"); + BootstrapReplicate[] replicates = new BootstrapReplicate[numReplicates]; + IntStream.range(0, numReplicates).parallel().forEach(r -> { + long replicateSeed = RandomSeedUtils.uniqueSeedCombination(seed, sampleCount, r); + int[] counts = bootstrapCounts(branchValues.length, sampleCount, replicateSeed); + StatisticMaps statistics = calcStatistics(branchValues, counts, sampleCount); + Map comparisons = new EnumMap<>(HazardMetric.class); + for (HazardMetric metric : HazardMetric.values()) + comparisons.put(metric, compare(metric.values(statistics), metric.values(referenceStats))); + replicates[r] = new BootstrapReplicate(statistics, comparisons); + }); + + appendReplicateCSVs(replicateCSV, summaryCSV, siteCSV, reference.mean(), referenceStats, + sampleCount, replicates); + for (HazardMetric metric : HazardMetric.values()) { + double[] meanAbs = new double[numReplicates]; + for (int r=0; r replicateCSV, CSVFile summaryCSV, + CSVFile siteCSV, GriddedGeoDataSet referenceMap, StatisticMaps referenceStats, + int sampleCount, BootstrapReplicate[] replicates) { + for (HazardMetric metric : HazardMetric.values()) { + for (int r=0; r csv, int sampleCount, String metric, + String quantity, double[] values) { + csv.addLine(sampleCount+"", metric, quantity, StatUtils.mean(values)+"", percentile(values, 2.5)+"", + percentile(values, 16d)+"", percentile(values, 50d)+"", percentile(values, 84d)+"", + percentile(values, 97.5)+""); + } + + private static String formatDistribution(double[] values) { + return "median="+(float)percentile(values, 50d)+", 95%=["+(float)percentile(values, 2.5) + +", "+(float)percentile(values, 97.5)+"]"; + } + + private static double percentile(double[] values, double percentile) { + // StatUtils does not modify its input, which lets us reuse the per-replicate arrays for each percentile. + return StatUtils.percentile(values, percentile); + } + + private static int[] bootstrapCounts(int numBranches, int sampleCount, long seed) { + int[] counts = new int[numBranches]; + SplittableRandom random = new SplittableRandom(seed); + for (int i=0; i 0); + Preconditions.checkArgument(sampleCount > 1); + if (counts != null) + Preconditions.checkArgument(counts.length == branchValues.length); + int numSites = branchValues[0].length; + double[] sums = new double[numSites]; + double[] sumSquares = new double[numSites]; + for (int b=0; b -1e-12*sumSquares[n]) + varianceNumerator = 0d; + Preconditions.checkState(varianceNumerator >= 0d, + "Negative variance numerator at site "+n+": "+varianceNumerator); + double standardDeviation = Math.sqrt(varianceNumerator/sampleCount); + means[n] = mean; + standardDeviations[n] = standardDeviation; + coefficientsOfVariation[n] = standardDeviation/mean; + } + return new StatisticMaps(means, standardDeviations, coefficientsOfVariation); + } + + private static MapComparison compare(double[] testValues, double[] referenceValues) { + Preconditions.checkArgument(testValues.length == referenceValues.length); + double sum = 0d; + double sumAbsolute = 0d; + double min = Double.POSITIVE_INFINITY; + double max = Double.NEGATIVE_INFINITY; + double maxAbsolute = Double.NEGATIVE_INFINITY; + int maxAbsoluteIndex = -1; + double[] absoluteChanges = new double[testValues.length]; + for (int i=0; i maxAbsolute) { + maxAbsolute = absolute; + maxAbsoluteIndex = i; + } + } + Arrays.sort(absoluteChanges); + return new MapComparison(sum/testValues.length, sumAbsolute/testValues.length, + empiricalFractile(absoluteChanges, 0.95), maxAbsolute, maxAbsoluteIndex, min, max); + } + + private static double percentChange(double testValue, double referenceValue) { + Preconditions.checkState(Double.isFinite(testValue)); + Preconditions.checkState(Double.isFinite(referenceValue) && referenceValue > 0d, + "Reference values must be finite and positive: %s", referenceValue); + return 100d*(testValue/referenceValue - 1d); + } + private static String mapFilePrefix(double period, ReturnPeriods rp) { String perStr = period == 0d ? "pga" : (float)period+"s"; return perStr+"_"+rp.name(); } - + private static GriddedGeoDataSet readMap(GriddedRegion gridReg, InputStream is) throws IOException { GriddedGeoDataSet xyz = new GriddedGeoDataSet(gridReg, false); BufferedReader bRead = new BufferedReader(new InputStreamReader(is)); @@ -99,8 +823,8 @@ private static GriddedGeoDataSet readMap(GriddedRegion gridReg, InputStream is) bRead.close(); return xyz; } - - private static ModelHazarMaps loadMaps(File hazardZip, LogicTree tree, GriddedRegion gridReg, + + private static ModelHazardMaps loadMaps(File hazardZip, LogicTree tree, GriddedRegion gridReg, double period, ReturnPeriods rp) throws ZipException, IOException { System.out.println("Loading maps from "+hazardZip.getAbsolutePath()); try (ZipFile zip = new ZipFile(hazardZip)) { @@ -109,7 +833,7 @@ private static ModelHazarMaps loadMaps(File hazardZip, LogicTree tree, Gridde ZipEntry meanEntry = zip.getEntry(meanEntryName); Preconditions.checkNotNull(meanEntry, "Entry doesn't exist in %s: %s", hazardZip.getAbsolutePath(), meanEntryName); GriddedGeoDataSet meanMap = readMap(gridReg, zip.getInputStream(meanEntry)); - + GriddedGeoDataSet[] individual = new GriddedGeoDataSet[tree.size()]; for (int i=0; i branch = tree.getBranch(i); @@ -118,13 +842,170 @@ private static ModelHazarMaps loadMaps(File hazardZip, LogicTree tree, Gridde Preconditions.checkNotNull(mapEntry, "Entry doesn't exist in %s: %s", hazardZip.getAbsolutePath(), mapName); individual[i] = readMap(gridReg, zip.getInputStream(mapEntry)); } - + System.out.println("\tLoaded mean & "+individual.length+" individual"); - - return new ModelHazarMaps(meanMap, individual); + + return new ModelHazardMaps(meanMap, individual); + } + } + + private static DiscretizedFunc[] loadBranchCurves(File hazardResultsDir, LogicTreeBranch branch, + GriddedRegion gridReg, double period) throws IOException { + File runDir = branch.getBranchDirectory(hazardResultsDir, false); + File hazardDir = new File(runDir, "hazard_"+(float)gridReg.getSpacing()+"deg_grid_seis_INCLUDE"); + Preconditions.checkState(hazardDir.exists(), "Hazard directory doesn't exist: %s", hazardDir.getAbsolutePath()); + File hazardFile = new File(hazardDir, SolHazardMapCalc.getCSV_FileName("curves", period)); + if (!hazardFile.exists()) + hazardFile = new File(hazardDir, SolHazardMapCalc.getCSV_FileName("curves", period)+".gz"); + Preconditions.checkState(hazardFile.exists(), "Hazard curves file doesn't exist: %s", hazardFile.getAbsolutePath()); + // this will detect that it's gzipped + CSVFile csv = CSVFile.readFile(hazardFile, true); + return SolHazardMapCalc.loadCurvesCSV(csv, gridReg); + } + + private enum HazardMetric { + MEAN("Mean hazard") { + @Override double[] values(StatisticMaps maps) { return maps.mean(); } + }, + STANDARD_DEVIATION("SD of hazard") { + @Override double[] values(StatisticMaps maps) { return maps.standardDeviation(); } + }, + COEFFICIENT_OF_VARIATION("CV of hazard") { + @Override double[] values(StatisticMaps maps) { return maps.coefficientOfVariation(); } + }; + + final String label; + private HazardMetric(String label) { + this.label = label; + } + abstract double[] values(StatisticMaps maps); + } + + enum ConvergenceMetric { + MEAN_HAZARD("Mean hazard", "Mean"), + STANDARD_DEVIATION("SD of hazard", "SD"), + IQR("Interquartile range", "IQR"), + CENTRAL_68_RANGE("Central 68% range", "68%"), + CENTRAL_95_RANGE("Central 95% range", "95%"); + + final String label; + final String shortLabel; + private ConvergenceMetric(String label, String shortLabel) { + this.label = label; + this.shortLabel = shortLabel; + } + + static ConvergenceMetric fromLabel(String label) { + for (ConvergenceMetric metric : values()) + if (metric.label.equals(label)) + return metric; + throw new IllegalArgumentException("Unknown convergence metric: "+label); + } + } + + enum ConvergenceSummary { + MEAN_SIGNED("Spatial mean % change") { + @Override double value(MapComparison comparison) { return comparison.meanPercentChange(); } + }, + MEAN_ABSOLUTE("Spatial mean absolute % change") { + @Override double value(MapComparison comparison) { return comparison.meanAbsolutePercentChange(); } + }, + P95_ABSOLUTE("Spatial P95 absolute % change") { + @Override double value(MapComparison comparison) { return comparison.p95AbsolutePercentChange(); } + }, + MAXIMUM_ABSOLUTE("Maximum absolute % change") { + @Override double value(MapComparison comparison) { return comparison.maximumAbsolutePercentChange(); } + }; + + final String label; + private ConvergenceSummary(String label) { + this.label = label; + } + + static ConvergenceSummary fromLabel(String label) { + for (ConvergenceSummary summary : values()) + if (summary.label.equals(label)) + return summary; + throw new IllegalArgumentException("Unknown convergence summary: "+label); + } + + abstract double value(MapComparison comparison); + } + + private enum ComparisonQuantity { + MEAN("Spatial mean % change") { + @Override double value(MapComparison comparison) { return comparison.meanPercentChange(); } + }, + MEAN_ABSOLUTE("Spatial mean absolute % change") { + @Override double value(MapComparison comparison) { return comparison.meanAbsolutePercentChange(); } + }, + MINIMUM("Minimum % change") { + @Override double value(MapComparison comparison) { return comparison.minimumPercentChange(); } + }, + MAXIMUM("Maximum % change") { + @Override double value(MapComparison comparison) { return comparison.maximumPercentChange(); } + }; + + final String label; + private ComparisonQuantity(String label) { + this.label = label; + } + abstract double value(MapComparison comparison); + } + + record ModelHazardMaps(GriddedGeoDataSet mean, GriddedGeoDataSet[] individual) {} + + private record StatisticMaps(double[] mean, double[] standardDeviation, double[] coefficientOfVariation) {} + + private record MapComparison(double meanPercentChange, double meanAbsolutePercentChange, + double p95AbsolutePercentChange, double maximumAbsolutePercentChange, int maximumAbsoluteIndex, + double minimumPercentChange, double maximumPercentChange) { + @Override + public String toString() { + return "mean="+(float)meanPercentChange+"%, abs="+(float)meanAbsolutePercentChange + +"%, p95abs="+(float)p95AbsolutePercentChange+"%, maxAbs=" + +(float)maximumAbsolutePercentChange+"%, range=["+(float)minimumPercentChange+"%, " + +(float)maximumPercentChange+"%]"; + } + } + + private record BootstrapReplicate(StatisticMaps statistics, Map comparisons) {} + + private record RunSpec(String id, File directory, LogicTree tree, SamplingMethod method, + long seed, int maxSamples) {} + + private record RunPeriodData(RunSpec run, double[][] branchMaps, double[] curveX, + double[][] curveSums, Map checkpoints) {} + + private record HazardStatistics(Map metricValues) { + double[] values(ConvergenceMetric metric) { + return Preconditions.checkNotNull(metricValues.get(metric)); } } - - record ModelHazarMaps(GriddedGeoDataSet mean, GriddedGeoDataSet[] individual) {} + + private record ReferenceStatistics(String name, String excludedRun, int sampleCount, + HazardStatistics statistics) {} + + private record ReferenceComparison(RunSpec run, int sampleCount, String referenceName, + int referenceSampleCount, ConvergenceMetric metric, MapComparison comparison, + Location worstLocation) {} + + private record ReferenceComparisonGroup(SamplingMethod method, int sampleCount, String referenceName, + ConvergenceMetric metric) {} + + private record DoublingComparison(RunSpec run, int lowerCount, int upperCount, + ConvergenceMetric metric, MapComparison comparison, Location worstLocation) {} + + private record DoublingComparisonGroup(SamplingMethod method, int lowerCount, int upperCount, + ConvergenceMetric metric) {} + + private record MethodCount(SamplingMethod method, int sampleCount) {} + + private record RealizationPairComparison(SamplingMethod method, int sampleCount, + RunSpec first, RunSpec second, ConvergenceMetric metric, MapComparison comparison, + Location worstLocation) {} + + private record RealizationPairComparisonGroup(SamplingMethod method, int sampleCount, + ConvergenceMetric metric) {} } diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java new file mode 100644 index 00000000..b043a648 --- /dev/null +++ b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java @@ -0,0 +1,371 @@ +package scratch.kevin.sampling; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.text.FieldPosition; +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.math3.stat.StatUtils; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.ui.RectangleAnchor; +import org.jfree.data.Range; +import org.opensha.commons.data.CSVFile; +import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; +import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.data.uncertainty.UncertainArbDiscFunc; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotCurveCharacterstics; +import org.opensha.commons.gui.plot.PlotLineType; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotSymbol; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.logicTree.sampling.SamplingMethod; + +import com.google.common.base.Preconditions; + +import net.mahdilamb.colormap.Colors; +import scratch.kevin.sampling.HazardConvergenceCalcs.ConvergenceMetric; +import scratch.kevin.sampling.HazardConvergenceCalcs.ConvergenceSummary; + +/** Builds paper-oriented plots from the compact convergence summary CSV files. */ +public class HazardConvergencePlots { + + private static final Range Y_RANGE = new Range(1e-2, 2e1); + private static final String SOBOL_REFERENCE = HazardConvergenceCalcs.LOO_SOBOL_REFERENCE_NAME; + private static final String POOLED_SOBOL_REFERENCE = HazardConvergenceCalcs.POOLED_SOBOL_REFERENCE_NAME; + private static final String MCS_REFERENCE = HazardConvergenceCalcs.MCS_REFERENCE_NAME; + private static final SamplingMethod SOBOL = SamplingMethod.OWEN_SCRAMBLED_SOBOL; + private static final SamplingMethod PAIRWISE_LHS = SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE; + private static final List COMPARISON_METHODS = List.of(SOBOL, PAIRWISE_LHS); + + private static final Map METRIC_COLORS = Map.of( + ConvergenceMetric.MEAN_HAZARD, Colors.tab_blue, + ConvergenceMetric.STANDARD_DEVIATION, Colors.tab_orange, + ConvergenceMetric.IQR, Colors.tab_green, + ConvergenceMetric.CENTRAL_68_RANGE, Colors.tab_red, + ConvergenceMetric.CENTRAL_95_RANGE, Colors.tab_purple); + + private static final Map METRIC_SYMBOLS = Map.of( + ConvergenceMetric.MEAN_HAZARD, PlotSymbol.FILLED_CIRCLE, + ConvergenceMetric.STANDARD_DEVIATION, PlotSymbol.FILLED_INV_TRIANGLE, + ConvergenceMetric.IQR, PlotSymbol.FILLED_TRIANGLE, + ConvergenceMetric.CENTRAL_68_RANGE, PlotSymbol.FILLED_SQUARE, + ConvergenceMetric.CENTRAL_95_RANGE, PlotSymbol.FILLED_DIAMOND); + + public static void main(String[] args) throws IOException { + File convergenceDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence/sobol_convergence"); + plotPeriod(new File(convergenceDir, "pga_two_in_50"), "PGA"); + plotPeriod(new File(convergenceDir, "1s_sa_two_in_50"), "1 s SA"); + } + + static void plotPeriod(File outputDir, String periodName) throws IOException { + List references = loadReferenceSummaries( + new File(outputDir, "reference_comparisons.csv")); + List doublings = loadDoublingSummaries( + new File(outputDir, "paired_doubling_comparisons.csv")); + List realizationPairs = loadRealizationPairSummaries( + new File(outputDir, "realization_pair_comparisons.csv")); + + plotReference(outputDir, periodName, references, SOBOL_REFERENCE, "sobol_consensus", + ConvergenceSummary.MEAN_ABSOLUTE, "Spatial mean absolute difference (%)"); + plotReference(outputDir, periodName, references, SOBOL_REFERENCE, "sobol_consensus", + ConvergenceSummary.MAXIMUM_ABSOLUTE, "Maximum absolute difference (%)"); + plotReference(outputDir, periodName, references, MCS_REFERENCE, "mcs_reference", + ConvergenceSummary.MEAN_ABSOLUTE, "Spatial mean absolute difference (%)"); + plotReference(outputDir, periodName, references, MCS_REFERENCE, "mcs_reference", + ConvergenceSummary.MAXIMUM_ABSOLUTE, "Maximum absolute difference (%)"); + plotDoubling(outputDir, periodName, doublings, ConvergenceSummary.MEAN_ABSOLUTE, + "Spatial mean absolute difference (%)"); + plotDoubling(outputDir, periodName, doublings, ConvergenceSummary.MAXIMUM_ABSOLUTE, + "Maximum absolute difference (%)"); + plotMethodReference(outputDir, references, false, ConvergenceSummary.MEAN_ABSOLUTE, + "Spatial mean absolute difference (%)"); + plotMethodReference(outputDir, references, false, ConvergenceSummary.MAXIMUM_ABSOLUTE, + "Maximum absolute difference (%)"); + plotMethodReference(outputDir, references, true, ConvergenceSummary.MEAN_ABSOLUTE, + "Spatial mean absolute difference (%)"); + plotMethodReference(outputDir, references, true, ConvergenceSummary.MAXIMUM_ABSOLUTE, + "Maximum absolute difference (%)"); + plotRealizationPairs(outputDir, realizationPairs, ConvergenceSummary.MEAN_ABSOLUTE, + "Spatial mean absolute difference (%)"); + plotRealizationPairs(outputDir, realizationPairs, ConvergenceSummary.MAXIMUM_ABSOLUTE, + "Maximum absolute difference (%)"); + } + + private static void plotReference(File outputDir, String periodName, List rows, + String reference, String referencePrefix, ConvergenceSummary spatialSummary, String yLabel) throws IOException { + List matching = rows.stream().filter(row -> row.method() == SOBOL + && row.reference().equals(reference) + && row.spatialSummary().equals(spatialSummary)).toList(); + Preconditions.checkState(!matching.isEmpty(), "No rows for %s, %s", reference, spatialSummary); + int[] counts = matching.stream().mapToInt(ReferenceSummary::sampleCount).distinct().sorted().toArray(); +// String title = periodName+", "+(reference.equals(SOBOL_REFERENCE) +// ? "pooled Sobol consensus" : MCS_REFERENCE+" reference"); + String title = reference.equals(SOBOL_REFERENCE) ? "Pooled Sobol consensus" : MCS_REFERENCE+" reference"; + String prefix = "convergence_"+referencePrefix+"_"+summaryPrefix(spatialSummary); + writePlot(outputDir, prefix, title, "Sample count", yLabel, counts, + Arrays.stream(counts).mapToObj(Integer::toString).toArray(String[]::new), matching); + } + + private static void plotMethodReference(File outputDir, List rows, + boolean sobolConsensus, ConvergenceSummary spatialSummary, String yLabel) throws IOException { + List matching = new ArrayList<>(); + for (int m=0; m rows, + ConvergenceSummary spatialSummary, String yLabel) throws IOException { + List matching = new ArrayList<>(); + for (int m=0; m rows, + ConvergenceSummary spatialSummary, String yLabel) throws IOException { + List matching = rows.stream() + .filter(row -> row.spatialSummary().equals(spatialSummary)).toList(); + Preconditions.checkState(!matching.isEmpty(), "No doubling rows for %s", spatialSummary); + int[] upperCounts = matching.stream().mapToInt(DoublingSummary::upperCount).distinct().sorted().toArray(); + String[] labels = new String[upperCounts.length]; + for (int i=0; i generic = new ArrayList<>(matching); +// String title = periodName+", paired sample-count increases"; + String title = "Paired sample-count increases"; + writePlot(outputDir, "convergence_paired_doubling_"+summaryPrefix(spatialSummary), + title, "Sample-count increase", yLabel, + upperCounts, labels, generic); + } + + private static void writePlot(File outputDir, String prefix, String title, String xLabel, String yLabel, + int[] counts, String[] countLabels, List rows) throws IOException { + Map> byMetric = new LinkedHashMap<>(); + for (ConvergenceMetric metric : ConvergenceMetric.values()) { + List metricRows = rows.stream().filter(row -> row.metric().equals(metric)).toList(); + if (!metricRows.isEmpty()) + byMetric.put(metric, metricRows); + } + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + List medianFuncs = new ArrayList<>(); + List medianChars = new ArrayList<>(); + for (Map.Entry> entry : byMetric.entrySet()) { + ArbitrarilyDiscretizedFunc median = new ArbitrarilyDiscretizedFunc(); + ArbitrarilyDiscretizedFunc lower = new ArbitrarilyDiscretizedFunc(); + ArbitrarilyDiscretizedFunc upper = new ArbitrarilyDiscretizedFunc(); + for (int i=0; i candidate.count() == count) + .findFirst().orElseThrow(); + median.set((double)i, row.median()); + lower.set((double)i, row.minimum()); + upper.set((double)i, row.maximum()); + } + Color color = METRIC_COLORS.get(entry.getKey()); + UncertainArbDiscFunc uncertainty = new UncertainArbDiscFunc(median, lower, upper); + funcs.add(uncertainty); + chars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, + new Color(color.getRed(), color.getGreen(), color.getBlue(), 70))); + median.setName(entry.getKey().shortLabel); + medianFuncs.add(median); + PlotSymbol sym = METRIC_SYMBOLS.get(entry.getKey()); + medianChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, sym, 5f, color)); + } + // Put every envelope in the dataset first so all median lines render above all shading. + funcs.addAll(medianFuncs); + chars.addAll(medianChars); + + PlotSpec plot = new PlotSpec(funcs, chars, title, xLabel, yLabel); +// plot.setLegendVisible(true); +// plot.setLegendInset(RectangleAnchor.TOP_RIGHT); +// plot.setLegendInset(RectangleAnchor.TOP); +// plot.setLegendInset(RectangleAnchor.TOP, 0.5, 0.975, 0.9, false); + plot.setLegendInset(RectangleAnchor.BOTTOM, 0.5, 0.025, 0.9, false); + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + gp.getPlotPrefs().setPlotLabelFontSize(10); + gp.getPlotPrefs().setLegendFontSize(8); + gp.getPlotPrefs().setLegendLineLength(6d); + Range xRange = new Range(-0.2d, counts.length-0.8d); + gp.drawGraphPanel(plot, false, true, xRange, Y_RANGE); + PlotUtils.setXTick(gp, 1d); + ((NumberAxis)gp.getXAxis()).setNumberFormatOverride(categoryFormat(countLabels)); + PlotUtils.writePrintPlots(outputDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, + 3.4d, 300, true, true, false); + } + + private static NumberFormat categoryFormat(String[] labels) { + return new NumberFormat() { + @Override public StringBuffer format(double value, StringBuffer buffer, FieldPosition pos) { + int index = (int)Math.round(value); + if (index >= 0 && index < labels.length && Math.abs(value-index) < 1e-6) + buffer.append(labels[index]); + return buffer; + } + @Override public StringBuffer format(long value, StringBuffer buffer, FieldPosition pos) { + return format((double)value, buffer, pos); + } + @Override public Number parse(String source, ParsePosition pos) { + pos.setErrorIndex(pos.getIndex()); + return null; + } + }; + } + + private static List loadReferenceSummaries(File file) throws IOException { + CSVFile csv = CSVFile.readFile(file, true); + Map> groups = new LinkedHashMap<>(); + for (int row=1; row rows = new ArrayList<>(); + for (Map.Entry> entry : groups.entrySet()) { + ReferenceGroup group = entry.getKey(); + double[] values = entry.getValue().stream().mapToDouble(Double::doubleValue).toArray(); + rows.add(new ReferenceSummary(group.method(), group.sampleCount(), group.reference(), group.metric(), + group.spatialSummary(), values.length, StatUtils.min(values), + StatUtils.percentile(values, 50d), StatUtils.max(values))); + } + return rows; + } + + private static List loadDoublingSummaries(File file) throws IOException { + CSVFile csv = CSVFile.readFile(file, true); + Map> groups = new LinkedHashMap<>(); + for (int row=1; row rows = new ArrayList<>(); + for (Map.Entry> entry : groups.entrySet()) { + DoublingGroup group = entry.getKey(); + double[] values = entry.getValue().stream().mapToDouble(Double::doubleValue).toArray(); + rows.add(new DoublingSummary(group.method(), group.lowerCount(), group.upperCount(), group.metric(), + group.spatialSummary(), values.length, StatUtils.min(values), + StatUtils.percentile(values, 50d), StatUtils.max(values))); + } + return rows; + } + + private static List loadRealizationPairSummaries(File file) throws IOException { + CSVFile csv = CSVFile.readFile(file, true); + Map> groups = new LinkedHashMap<>(); + for (int row=1; row rows = new ArrayList<>(); + for (Map.Entry> entry : groups.entrySet()) { + RealizationPairGroup group = entry.getKey(); + double[] values = entry.getValue().stream().mapToDouble(Double::doubleValue).toArray(); + rows.add(new RealizationPairSummary(group.method(), group.sampleCount(), group.metric(), + group.spatialSummary(), values.length, StatUtils.min(values), + StatUtils.percentile(values, 50d), StatUtils.max(values))); + } + return rows; + } + + private static void addValue(Map> groups, K key, double value) { + groups.computeIfAbsent(key, unused -> new ArrayList<>()).add(value); + } + + private static String summaryPrefix(ConvergenceSummary summary) { + return summary == ConvergenceSummary.MEAN_ABSOLUTE ? "mean_abs" : "max_abs"; + } + + private interface SummaryRow { + int count(); + ConvergenceMetric metric(); + double minimum(); + double median(); + double maximum(); + } + + private record ReferenceSummary(SamplingMethod method, int sampleCount, String reference, ConvergenceMetric metric, + ConvergenceSummary spatialSummary, + int realizations, double minimum, double median, double maximum) implements SummaryRow { + @Override public int count() { return sampleCount; } + } + + private record DoublingSummary(SamplingMethod method, int lowerCount, int upperCount, ConvergenceMetric metric, + ConvergenceSummary spatialSummary, + int realizations, double minimum, double median, double maximum) implements SummaryRow { + @Override public int count() { return upperCount; } + } + + private record MethodSummary(int methodIndex, ConvergenceMetric metric, + ConvergenceSummary spatialSummary, int realizations, + double minimum, double median, double maximum) implements SummaryRow { + @Override public int count() { return methodIndex; } + } + + private record RealizationPairSummary(SamplingMethod method, int sampleCount, ConvergenceMetric metric, + ConvergenceSummary spatialSummary, int realizationPairs, + double minimum, double median, double maximum) {} + + private record ReferenceGroup(SamplingMethod method, int sampleCount, String reference, + ConvergenceMetric metric, + ConvergenceSummary spatialSummary) {} + + private record DoublingGroup(SamplingMethod method, int lowerCount, int upperCount, + ConvergenceMetric metric, + ConvergenceSummary spatialSummary) {} + + private record RealizationPairGroup(SamplingMethod method, int sampleCount, + ConvergenceMetric metric, ConvergenceSummary spatialSummary) {} +} diff --git a/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java index b5835aa0..190283ea 100644 --- a/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java +++ b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java @@ -100,7 +100,8 @@ public static void main(String[] args) throws IOException { File mainDir = new File(PaperPaths.FIGURES_DIR, "scores"); Preconditions.checkState(mainDir.exists() || mainDir.mkdir()); int scoreOrders = 4; - int[] sampleCounts = {256, 512, 1024, 2048, 4096, 8192}; + int[] sampleCounts = {256, 512, 1024, 2048, 4096, 8192, 16384}; +// int[] sampleCounts = {256, 512, 1024, 2048, 4096, 8192}; // int[] sampleCounts = {256, 512, 1024, 2048, 4096}; // int[] sampleCounts = {256, 512, 1024}; // int[] sampleCounts = {256, 512}; @@ -127,19 +128,22 @@ public static void main(String[] args) throws IOException { int numAvgTrials = 100; // int numAvgTrials = 500; - String treeName = null; - List samplingDimensions = new ArrayList<>(); - for (int i=0; i<10; i++) - samplingDimensions.add(ContinuousSamplingDimension.INSTANCE); - String samplingPrefix = "continuous_"+samplingDimensions.size()+"d"; + boolean replotIndvSamples = false; + boolean replotCombOnly = true; + +// String treeName = null; +// List samplingDimensions = new ArrayList<>(); +// for (int i=0; i<10; i++) +// samplingDimensions.add(ContinuousSamplingDimension.INSTANCE); +// String samplingPrefix = "continuous_"+samplingDimensions.size()+"d"; // String treeName = "NSHM23-WUS"; // List samplingDimensions = getDimsNSHM23(); // String samplingPrefix = "nshm23_"+samplingDimensions.size()+"d"; -// String treeName = "NSHM27-AmSam"; -// List samplingDimensions = getDimsNSHM27_AmSam(); -// String samplingPrefix = "nshm27_amsam_"+samplingDimensions.size()+"d"; + String treeName = "NSHM27-AmSam"; + List samplingDimensions = getDimsNSHM27_AmSam(); + String samplingPrefix = "nshm27_amsam_"+samplingDimensions.size()+"d"; final int dimensions = samplingDimensions.size(); int numContinuous = 0; @@ -155,16 +159,12 @@ else if (dim instanceof ContinuousSamplingDimension) treeName = ""; else treeName += ": "; - treeName += dimensions+"D, "; - - if (numContinuous > 0) { - if (numCategorical > 0) - treeName += numContinuous+" continuous, "; - else - treeName += "all continuous"; - } - if (numCategorical > 0) - treeName += numCategorical+" categorical"; + if (dimensions == numContinuous) + treeName += dimensions+"D, all continuous"; + else if (dimensions == numCategorical) + treeName += dimensions+"D, all categorical"; + else + treeName += numContinuous+" continuous, "+numCategorical+" categorical"; System.out.println(treeName); System.out.println(); @@ -207,312 +207,333 @@ else if (dim instanceof ContinuousSamplingDimension) for (int m=0; m()); - Stopwatch totalWatch = Stopwatch.createStarted(); - for (int sampleCount : sampleCounts) { - Stopwatch sampleWatch = Stopwatch.createStarted(); - System.out.println("Doing "+sampleCount+" samples"); - File subDir = new File(outputDir, sampleCount+"_samples"); - Preconditions.checkState(subDir.exists() || subDir.mkdir()); - PointSet[] firstPointSets = new PointSet[methods.length]; - for (int m=0; m> sampleFutures = new LinkedList<>(); - - for (int i=0; imethod.prepare(sampleCount, samplingDimensions, seed))); - } - - // if we only have 1 trial, do that one in parallel - // if we have many, rely on across-trial parallelism instead - PointSetScorer scorer = myTrials == 1 ? parallelScorer : serialScorer; - - List> scoreFutures = new ArrayList<>(); - while (!sampleFutures.isEmpty()) { - CompletableFuture sampleFuture = sampleFutures.removeFirst(); - PointSet sample = sampleFuture.join(); - if (firstPointSets[m] == null) - firstPointSets[m] = sample; - scoreFutures.add(CompletableFuture.supplyAsync(()->scorer.score(sample, scoreOrders))); - } - - List scores = scoreFutures.stream().map(F->F.join()).toList(); - - methodScores.get(m).add(scores); - - if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL) { - // rebuild it to remove the row scrambling - firstPointSets[m] = method.createGenerator(baseRand.nextLong()).generate(sampleCount, dimensions); - } - - List funcs = new ArrayList<>(); - List chars = new ArrayList<>(); + if (replotCombOnly) { + System.out.println("Replotting combined results only"); + } else { + Stopwatch totalWatch = Stopwatch.createStarted(); + for (int sampleCount : sampleCounts) { + Stopwatch sampleWatch = Stopwatch.createStarted(); + System.out.println("Doing "+sampleCount+" samples"); + File subDir = new File(outputDir, sampleCount+"_samples"); + Preconditions.checkState(subDir.exists() || subDir.mkdir()); + PointSet[] firstPointSets = new PointSet[methods.length]; + for (int m=0; m> sampleFutures = new LinkedList<>(); + + for (int i=0; imethod.prepare(sampleCount, samplingDimensions, seed))); + } + + // if we only have 1 trial, do that one in parallel + // if we have many, rely on across-trial parallelism instead + PointSetScorer scorer = myTrials == 1 ? parallelScorer : serialScorer; + + List> scoreFutures = new ArrayList<>(); + while (!sampleFutures.isEmpty()) { + CompletableFuture sampleFuture = sampleFutures.removeFirst(); + PointSet sample = sampleFuture.join(); + if (firstPointSets[m] == null) + firstPointSets[m] = sample; + scoreFutures.add(CompletableFuture.supplyAsync(()->scorer.score(sample, scoreOrders))); + } + + List scores = scoreFutures.stream().map(F->F.join()).toList(); + + methodScores.get(m).add(scores); + + if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL) { + // rebuild it to remove the row scrambling + firstPointSets[m] = method.createGenerator(baseRand.nextLong()).generate(sampleCount, dimensions); + } + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); - double[][][] scores2D = new double[dimensions][dimensions][myTrials]; - for (int i=0; i shadedFuncs = new ArrayList<>(); - List shadedChars = new ArrayList<>(); - - for (int order=1; order<=scoreOrders; order++) { - double overallAverage = 0d; - double[][] dimScores = new double[dimensions][scores.size()]; - double[] dimAverages = new double[dimensions]; + double[][][] scores2D = new double[dimensions][dimensions][myTrials]; + for (int i=0; i shadedFuncs = new ArrayList<>(); + List shadedChars = new ArrayList<>(); + + for (int order=1; order<=scoreOrders; order++) { + double overallAverage = 0d; + double[][] dimScores = new double[dimensions][scores.size()]; + double[] dimAverages = new double[dimensions]; + + for (int s=0; s= 1); + dimScores[d][s] /= dimCounts[d]; + dimAverages[d] += dimScores[d][s]; + } + if (s < numPlotTrials) { + // plot it + EvenlyDiscretizedFunc dimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + for (int d=0; d= 1); - dimScores[d][s] /= dimCounts[d]; - dimAverages[d] += dimScores[d][s]; - } - if (s < numPlotTrials) { - // plot it - EvenlyDiscretizedFunc dimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); - for (int d=0; d 1) { - EvenlyDiscretizedFunc upperDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); - EvenlyDiscretizedFunc middleDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); - EvenlyDiscretizedFunc lowerDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); - for (int d=0; d 1) { + EvenlyDiscretizedFunc upperDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + EvenlyDiscretizedFunc middleDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + EvenlyDiscretizedFunc lowerDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + for (int d=0; d 20 ? 2d : 1d; - if (order == 2) - avgScore2D = overallAverage; - } - - funcs.addAll(shadedFuncs); - chars.addAll(shadedChars); - - PlotSpec plot = new PlotSpec(funcs, chars, method.getShortName()+" (N="+sampleCount+")", "Dimension #", "Normalized score"); - plot.setLegendVisible(true); - double xTick = dimensions > 20 ? 2d : 1d; - - HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); - - gp.setRenderingOrder(DatasetRenderingOrder.REVERSE); - - gp.drawGraphPanel(plot, false, true, dimXRange, logYRange); - PlotUtils.setXTick(gp, xTick); - - PlotUtils.writePrintPlots(subDir, "scores_"+prefix, gp, - PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 3d, 300, true, true, false); - - EvenlyDiscrXYZ_DataSet avgXYZ = new EvenlyDiscrXYZ_DataSet(dimensions, dimensions, 1d, 1d, 1d); - EvenlyDiscrXYZ_DataSet avgAbsXYZ = new EvenlyDiscrXYZ_DataSet(dimensions, dimensions, 1d, 1d, 1d); - CPT logRatioCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-1d, 1d); - logRatioCPT.setLog10(true); - CPT logAbsCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-1d, 1d).trim(0d, 1d); -// CPT logAbsCPT = logRatioCPT.trim(0d, 1d); - logAbsCPT.setLog10(true); - for (int i=0; i plots = new ArrayList<>(); - Range range = new Range(0d, 1d); - List xRanges = new ArrayList<>(); - List yRanges = List.of(range); - List subtitles = new ArrayList<>(); - for (int m=0; m funcs = new ArrayList<>(); - List chars = new ArrayList<>(); - PointSet sample = firstPointSets[m]; - DefaultXY_DataSet xy = new DefaultXY_DataSet(); - for (int i=0; i 0) - prefix += "_"+dim1+"_"+dim2; + gp.drawGraphPanel(xyzPlot, false, false, xyzRange, xyzRange); - PlotUtils.writePrintPlots(subDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH, false, 300, true, true, false); + if (replotIndvSamples || !new File(subDir, "scores_2D_"+prefix+"_deviation.png").exists()) + PlotUtils.writePrintPlots(subDir, "scores_2D_"+prefix+"_deviation", gp, + PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, false, 300, true, true, false); + methodWatch.stop(); + System.out.println("\tDONE in "+timeStr(methodWatch)); } + + if (sampleCount <= 1024) { + // now plot 2D scatters + int[][] plotDims = { + {0, 1}, + {2, 3}, + {4, 5} + }; + for (int p=0; p plots = new ArrayList<>(); + Range range = new Range(0d, 1d); + List xRanges = new ArrayList<>(); + List yRanges = List.of(range); + List subtitles = new ArrayList<>(); + for (int m=0; m funcs = new ArrayList<>(); + List chars = new ArrayList<>(); + PointSet sample = firstPointSets[m]; + DefaultXY_DataSet xy = new DefaultXY_DataSet(); + for (int i=0; i 0) + prefix += "_"+dim1+"_"+dim2; + + if (replotIndvSamples || !new File(subDir, prefix+".png").exists()) + PlotUtils.writePrintPlots(subDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH, false, 300, true, true, false); + } + } + sampleWatch.stop(); + System.out.println("DONE with "+sampleCount+" in "+timeStr(sampleWatch)+"\n"); } - sampleWatch.stop(); - System.out.println("DONE with "+sampleCount+" in "+timeStr(sampleWatch)+"\n"); + + totalWatch.stop(); + System.out.println("DONE with all calculations in "+timeStr(totalWatch)); } - totalWatch.stop(); - System.out.println("DONE with all calculations in "+timeStr(totalWatch)); - // now combined plots + String prefix = "combined_scores"; + File scoresCSVFile = new File(outputDir, prefix+".csv"); + List scoreFuncs = new ArrayList<>(); List scoreChars = new ArrayList<>(); List equivCountFuncs = new ArrayList<>(); List equivCountChars = new ArrayList<>(); - CSVFile scoresCSV = new CSVFile<>(true); - List header = new ArrayList<>(); - header.add(""); - for (int order=1; order<=scoreOrders; order++) - for (int s=0; s scoresCSV = replotCombOnly ? CSVFile.readFile(scoresCSVFile, true) : new CSVFile<>(true); + if (!replotCombOnly) { + List header = new ArrayList<>(); + header.add(""); + for (int order=1; order<=scoreOrders; order++) + for (int s=0; s scoreLine = new ArrayList<>(header.size()); + List scoreLine = new ArrayList<>(); scoreLine.add(method.getShortName()); + int colIndex = 1; + for (int order=1; order<=scoreOrders; order++) { EvenlyDiscretizedFunc scoreFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); - EvenlyDiscretizedFunc scoreLowerFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); - EvenlyDiscretizedFunc scoreUpperFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); +// EvenlyDiscretizedFunc scoreLowerFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); +// EvenlyDiscretizedFunc scoreUpperFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); EvenlyDiscretizedFunc equivFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); for (int s=0; s scores = methodScores.get(m).get(s); - - double sum = 0d; - double min = Double.POSITIVE_INFINITY; - double max = 0d; - for (PointSetScore score : scores) { - double orderScore = score.getOrderMeanScore(order); - sum += orderScore; - min = Math.min(min, orderScore); - max = Math.max(max, orderScore); + + double avg; + if (replotCombOnly) { + avg = scoresCSV.getDouble(rowIndex, colIndex++); + } else { + List scores = methodScores.get(m).get(s); + double sum = 0d; +// double min = Double.POSITIVE_INFINITY; +// double max = 0d; + for (PointSetScore score : scores) { + double orderScore = score.getOrderMeanScore(order); + sum += orderScore; +// min = Math.min(min, orderScore); +// max = Math.max(max, orderScore); + } + avg = sum / scores.size(); } - double avg = sum / scores.size(); scoreLine.add((float)avg+""); scoreFunc.set(s, avg); - scoreLowerFunc.set(s, min); - scoreUpperFunc.set(s, max); +// scoreLowerFunc.set(s, min); +// scoreUpperFunc.set(s, max); double equivCount = (double)sampleCount / avg; equivFunc.set(s, equivCount); } @@ -537,7 +558,10 @@ else if (dim instanceof ContinuousSamplingDimension) equivCountFuncs.add(equivFunc); equivCountChars.add(getForThickness(methodChar, thickness)); } - scoresCSV.addLine(scoreLine); + if (replotCombOnly) + rowIndex++; + else + scoresCSV.addLine(scoreLine); } List orderTicknessFuncs = new ArrayList<>(); List orderThicknessChars = new ArrayList<>(); @@ -607,9 +631,9 @@ public Number parse(String source, ParsePosition pos) { PlotUtils.setXTick(gp, 1); ((NumberAxis)gp.getXAxis()).setNumberFormatOverride(categoryFormat); - String prefix = "combined_scores"; PlotUtils.writePrintPlots(outputDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 4, 300, true, true, false); - scoresCSV.writeToFile(new File(outputDir, prefix+".csv")); + if (!replotCombOnly) + scoresCSV.writeToFile(scoresCSVFile); plot = new PlotSpec(equivCountFuncs, equivCountChars, treeName, "Sample count", "Equivalent MCS count"); // plot.setLegendInset(true); From 8f5a9f73a2ca44193f237a62c0fbdb39799c031e Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Thu, 3 Sep 2026 13:11:30 -0700 Subject: [PATCH 59/71] new models --- .../kevin/sampling/HazardConvergenceCalcs.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java index ba51faff..069766b7 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java @@ -68,6 +68,9 @@ public static void main(String[] args) throws IOException { Table> runDirs = HashBasedTable.create(); + /* + * Sobol runs + */ runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 512, List.of( new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-512samples-sobol_scrambled"), new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-512samples-sobol_scrambled-unique_seed") @@ -92,9 +95,15 @@ public static void main(String[] args) throws IOException { new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-2"), new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-3") )); + + /* + * Pairwise-LHS runs + */ runDirs.put(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, 4096, List.of( new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise"), - new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed") + new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed"), + new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-2"), + new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-3") )); List sobolRuns = loadRunSpecs(SamplingMethod.OWEN_SCRAMBLED_SOBOL, From 7cc8bd608dc5f08492e10a570c75541977e97f5c Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 8 Sep 2026 13:50:49 -0700 Subject: [PATCH 60/71] plot/calc updates --- .../sampling/HazardConvergenceCalcs.java | 234 ++++++++++++----- .../sampling/HazardConvergencePlots.java | 243 +++++++++--------- .../sampling/HazardConvergenceCalcsTest.java | 91 +++++++ .../sampling/HazardConvergencePlotsTest.java | 42 +++ 4 files changed, 425 insertions(+), 185 deletions(-) create mode 100644 src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java create mode 100644 src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java index 069766b7..456fd688 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java @@ -44,7 +44,8 @@ import com.google.common.collect.Table; public class HazardConvergenceCalcs { - static final String MCS_REFERENCE_NAME = "20k MCS"; + static final String MCS_REFERENCE_NAME = "Pooled MCS"; + static final String LOO_MCS_REFERENCE_NAME = "Pooled MCS, leave span out"; static final String POOLED_SOBOL_REFERENCE_NAME = "Pooled Sobol"; static final String LOO_SOBOL_REFERENCE_NAME = "Pooled Sobol, leave one out"; private static final int MAX_RUN_LOAD_THREADS = 4; @@ -53,21 +54,20 @@ public static void main(String[] args) throws IOException { File outputDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir(), "Couldn't create output directory: %s", outputDir.getAbsolutePath()); - String treeFileName = "logic_tree_analysis.json"; - String hazardFileName = "results_hazard.zip"; - - File refMCSDir = new File(PaperPaths.INVS_DIR, "2026_07_17-nshm27-AMSAM-20000samples-mcs"); - LogicTree refMCSTree = LogicTree.read(new File(refMCSDir, treeFileName)); - File refMCSHazardZip = new File(refMCSDir, hazardFileName); - - GriddedRegion gridReg = GriddedRegion.fromFeature(Feature.read(new File(refMCSDir, "gridded_region.geojson"))); ReturnPeriods rp = ReturnPeriods.TWO_IN_50; - System.out.println("Ref has "+refMCSTree.size()+" branches"); - Table> runDirs = HashBasedTable.create(); + /* + * MCS runs + */ + runDirs.put(SamplingMethod.MONTE_CARLO, 20000, List.of( + new File(PaperPaths.INVS_DIR, "2026_07_17-nshm27-AMSAM-20000samples-mcs"), + new File(PaperPaths.INVS_DIR, "2026_09_03-nshm27-AMSAM-20000samples-mcs-unique_seed"), + new File(PaperPaths.INVS_DIR, "2026_09_05-nshm27-AMSAM-20000samples-mcs-unique_seed-2") + )); + /* * Sobol runs */ @@ -108,22 +108,27 @@ public static void main(String[] args) throws IOException { List sobolRuns = loadRunSpecs(SamplingMethod.OWEN_SCRAMBLED_SOBOL, runDirs.row(SamplingMethod.OWEN_SCRAMBLED_SOBOL)); - List pairwiseLHSRuns = loadRunSpecs(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, - runDirs.row(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE)); - File convergenceDir = new File(outputDir, "sobol_convergence"); - Preconditions.checkState(convergenceDir.exists() || convergenceDir.mkdir(), - "Couldn't create output directory: %s", convergenceDir.getAbsolutePath()); + List fullDesignRuns = new ArrayList<>(); + for (SamplingMethod method : runDirs.rowKeySet().stream().sorted().toList()) + if (method != SamplingMethod.MONTE_CARLO && method != SamplingMethod.OWEN_SCRAMBLED_SOBOL) + fullDesignRuns.addAll(loadRunSpecs(method, runDirs.row(method))); + List mcsRuns = loadRunSpecs(SamplingMethod.MONTE_CARLO, + runDirs.row(SamplingMethod.MONTE_CARLO)); + System.out.println("MCS reference has "+mcsRuns.stream().mapToInt(RunSpec::maxSamples).sum() + +" branches across "+mcsRuns.size()+" runs"); + + GriddedRegion gridReg = GriddedRegion.fromFeature( + Feature.read(new File(mcsRuns.get(0).directory, "gridded_region.geojson"))); double[] periods = { 0d, 1d }; String[] periodNames = { "PGA", "1 s SA" }; String[] periodPrefixes = { "pga", "1s_sa" }; for (int p=0; p loadRunSpecs(SamplingMethod method, return runs; } - private static void runSamplingConvergence(List sobolRuns, List pairwiseLHSRuns, - ModelHazardMaps mcsMaps, + private static List loadRunSpecs(SamplingMethod method, List runDirs) throws IOException { + List runs = new ArrayList<>(); + for (File dir : runDirs) { + Preconditions.checkState(dir.isDirectory(), "Run directory doesn't exist: %s", dir.getAbsolutePath()); + LogicTree tree = LogicTree.read(new File(dir, "logic_tree_analysis.json")); + Preconditions.checkState(tree.getSamplingMethod() == method, + "Expected %s tree, have %s: %s", method, tree.getSamplingMethod(), dir.getName()); + runs.add(new RunSpec(dir.getName(), dir, tree, method, + tree.getSamplingRandomSeed(), tree.size())); + } + return runs; + } + + private static void runSamplingConvergence(List sobolRuns, List fullDesignRuns, + List mcsRuns, GriddedRegion gridReg, double period, String periodName, ReturnPeriods rp, File outputDir) throws IOException { List sobolData = loadRunPeriodData(sobolRuns, gridReg, period, rp); - List pairwiseLHSData = loadRunPeriodData(pairwiseLHSRuns, gridReg, period, rp); + List fullDesignData = loadRunPeriodData(fullDesignRuns, gridReg, period, rp); + int[] sampleCounts = sobolData.stream().flatMap(data -> data.checkpoints().keySet().stream()) + .mapToInt(Integer::intValue).distinct().sorted().toArray(); + List mcsData = loadRunPeriodData(mcsRuns, gridReg, period, rp, sampleCounts); - HazardStatistics mcsStatistics = calcHazardStatistics(copyValues(mcsMaps.individual()), - mcsMaps.individual().length, copyValues(mcsMaps.mean())); - ReferenceStatistics mcsReference = new ReferenceStatistics(MCS_REFERENCE_NAME, null, - mcsMaps.individual().length, mcsStatistics); + ReferenceStatistics mcsReference = buildPooledReference(mcsData, null, gridReg, rp, + MCS_REFERENCE_NAME, MCS_REFERENCE_NAME); Map leaveOneOut = new LinkedHashMap<>(); for (RunPeriodData data : sobolData) - leaveOneOut.put(data.run(), buildPooledSobolReference(sobolData, data.run(), gridReg, rp)); - ReferenceStatistics pooledSobol = buildPooledSobolReference(sobolData, null, gridReg, rp); + leaveOneOut.put(data.run(), buildPooledReference(sobolData, data.run(), gridReg, rp, + POOLED_SOBOL_REFERENCE_NAME, LOO_SOBOL_REFERENCE_NAME)); + ReferenceStatistics pooledSobol = buildPooledReference(sobolData, null, gridReg, rp, + POOLED_SOBOL_REFERENCE_NAME, LOO_SOBOL_REFERENCE_NAME); List comparisons = new ArrayList<>(); for (RunPeriodData data : sobolData) { @@ -169,14 +190,16 @@ private static void runSamplingConvergence(List sobolRuns, List mcsSpans = appendMCSSpanComparisons(comparisons, mcsData, sampleCounts, + pooledSobol, gridReg, rp); writeReferenceComparisons(new File(outputDir, "reference_comparisons.csv"), comparisons); writeReferenceComparisonSummary(new File(outputDir, "reference_comparison_summary.csv"), comparisons); @@ -198,8 +221,12 @@ private static void runSamplingConvergence(List sobolRuns, List allData = new ArrayList<>(sobolData); - allData.addAll(pairwiseLHSData); - List realizationPairs = buildRealizationPairComparisons(allData, gridReg); + allData.addAll(fullDesignData); + allData.addAll(mcsData); + List realizations = new ArrayList<>(mcsSpans); + for (RunPeriodData data : allData) + data.checkpoints().forEach((count, statistics) -> realizations.add(new Realization(data.run(), count, statistics))); + List realizationPairs = buildRealizationPairComparisons(realizations, gridReg); writeRealizationPairComparisons(new File(outputDir, "realization_pair_comparisons.csv"), realizationPairs); writeRealizationPairComparisonSummary( new File(outputDir, "realization_pair_summary.csv"), realizationPairs); @@ -208,18 +235,18 @@ private static void runSamplingConvergence(List sobolRuns, List loadRunPeriodData(List runs, - GriddedRegion gridReg, double period, ReturnPeriods rp) throws IOException { + GriddedRegion gridReg, double period, ReturnPeriods rp, int... spanCounts) throws IOException { if (runs.isEmpty()) return List.of(); int threads = Math.min(MAX_RUN_LOAD_THREADS, runs.size()); if (threads == 1) - return List.of(loadRunPeriodData(runs.get(0), gridReg, period, rp)); + return List.of(loadRunPeriodData(runs.get(0), gridReg, period, rp, spanCounts)); ExecutorService executor = Executors.newFixedThreadPool(threads); try { List> futures = new ArrayList<>(runs.size()); for (RunSpec run : runs) - futures.add(executor.submit(() -> loadRunPeriodData(run, gridReg, period, rp))); + futures.add(executor.submit(() -> loadRunPeriodData(run, gridReg, period, rp, spanCounts))); List data = new ArrayList<>(runs.size()); // Retrieve in input order so downstream CSV and plot ordering remains stable. for (Future future : futures) { @@ -246,7 +273,7 @@ private static List loadRunPeriodData(List runs, } private static RunPeriodData loadRunPeriodData(RunSpec run, GriddedRegion gridReg, - double period, ReturnPeriods rp) throws IOException { + double period, ReturnPeriods rp, int[] spanCounts) throws IOException { System.out.println("\nLoading "+run.method().getShortName()+" run: "+run.id()); ModelHazardMaps maps = loadMaps(new File(run.directory(), "results_hazard.zip"), run.tree(), gridReg, period, rp); @@ -256,6 +283,7 @@ private static RunPeriodData loadRunPeriodData(RunSpec run, GriddedRegion gridRe double[] curveX = null; double[][] curveSums = null; Map checkpoints = new TreeMap<>(); + Map curveBoundaries = new TreeMap<>(); for (int b=0; b= 512 && Integer.bitCount(count) == 1; + if (Arrays.stream(spanCounts).anyMatch(size -> count % size == 0)) + curveBoundaries.put(count, Arrays.stream(curveSums).map(double[]::clone).toArray(double[][]::new)); if (fullRun || sobolCheckpoint) { double[] curveMean = buildCurveMeanMap(curveSums, curveX, count, rp); checkpoints.put(count, calcHazardStatistics(branchMaps, count, curveMean)); @@ -287,11 +317,12 @@ private static RunPeriodData loadRunPeriodData(RunSpec run, GriddedRegion gridRe MapComparison archivedComparison = compare( checkpoints.get(run.maxSamples()).values(ConvergenceMetric.MEAN_HAZARD), copyValues(maps.mean())); System.out.println("\tCurve mean versus archived mean: "+archivedComparison); - return new RunPeriodData(run, branchMaps, curveX, curveSums, checkpoints); + return new RunPeriodData(run, branchMaps, curveX, curveSums, checkpoints, curveBoundaries); } - private static ReferenceStatistics buildPooledSobolReference(List allRuns, - RunSpec excluded, GriddedRegion gridReg, ReturnPeriods rp) { + private static ReferenceStatistics buildPooledReference(List allRuns, + RunSpec excluded, GriddedRegion gridReg, ReturnPeriods rp, + String pooledName, String leaveOneOutName) { int sampleCount = 0; int curveSize = -1; double[] curveX = null; @@ -323,12 +354,74 @@ private static ReferenceStatistics buildPooledSobolReference(List } Preconditions.checkState(destBranch == sampleCount); double[] curveMean = buildCurveMeanMap(curveSums, curveX, sampleCount, rp); - String name = excluded == null ? POOLED_SOBOL_REFERENCE_NAME : LOO_SOBOL_REFERENCE_NAME; + String name = excluded == null ? pooledName : leaveOneOutName; return new ReferenceStatistics(name, excluded == null ? null : excluded.id(), sampleCount, calcHazardStatistics(branchMaps, sampleCount, curveMean)); } - private static double[] buildCurveMeanMap(double[][] curveSums, double[] curveX, + /** Uses disjoint full spans within each run; leftover branches still contribute to every reference. */ + static List appendMCSSpanComparisons(List comparisons, + List runs, int[] sampleCounts, ReferenceStatistics sobolReference, + GriddedRegion gridReg, ReturnPeriods rp) { + List spans = new ArrayList<>(); + double[][] allMaps = runs.stream().flatMap(data -> Arrays.stream(data.branchMaps())) + .toArray(double[][]::new); + double[] curveX = runs.get(0).curveX(); + double[][] totalCurves = new double[gridReg.getNodeCount()][curveX.length]; + for (RunPeriodData data : runs) { + Preconditions.checkState(Arrays.equals(curveX, data.curveX()), "MCS curve grids differ"); + for (int n=0; n 1, "Too few MCS reference samples after exclusion"); + double[][] spanCurves = new double[totalCurves.length][curveX.length]; + double[][] remainingCurves = new double[totalCurves.length][curveX.length]; + double[][] before = start == 0 ? null : data.curveBoundaries().get(start); + double[][] after = data.curveBoundaries().get(end); + for (int n=0; n= 0 && start < end && end <= rows.length); + double[][] remaining = new double[rows.length-(end-start)][]; + System.arraycopy(rows, 0, remaining, 0, start); + System.arraycopy(rows, end, remaining, start, rows.length-end); + return remaining; + } + + static double[] buildCurveMeanMap(double[][] curveSums, double[] curveX, int sampleCount, ReturnPeriods rp) { double[] map = new double[curveSums.length]; double[] meanY = new double[curveX.length]; @@ -346,7 +439,7 @@ else if (rp.oneYearProb < curve.getMinY()) return map; } - private static HazardStatistics calcHazardStatistics(double[][] branchMaps, int sampleCount, + static HazardStatistics calcHazardStatistics(double[][] branchMaps, int sampleCount, double[] curveMean) { Preconditions.checkArgument(sampleCount > 1 && sampleCount <= branchMaps.length); Preconditions.checkArgument(curveMean.length == branchMaps[0].length); @@ -418,10 +511,16 @@ private static double empiricalFractile(double[] sortedValues, double fractile) private static void appendComparisons(List comparisons, RunSpec run, int sampleCount, HazardStatistics statistics, ReferenceStatistics reference, GriddedRegion gridReg) { + appendComparisons(comparisons, run, sampleCount, statistics, reference, gridReg, 0); + } + + private static void appendComparisons(List comparisons, RunSpec run, + int sampleCount, HazardStatistics statistics, ReferenceStatistics reference, GriddedRegion gridReg, + int startIndex) { for (ConvergenceMetric metric : ConvergenceMetric.values()) { MapComparison comparison = compare(statistics.values(metric), reference.statistics().values(metric)); comparisons.add(new ReferenceComparison(run, sampleCount, reference.name(), reference.sampleCount(), - metric, comparison, gridReg.getLocation(comparison.maximumAbsoluteIndex()))); + metric, comparison, gridReg.getLocation(comparison.maximumAbsoluteIndex()), startIndex)); } } @@ -432,7 +531,7 @@ private static void writeReferenceComparisons(File file, List buildRealizationPairComparisons( - List allData, GriddedRegion gridReg) { - Map> groups = new LinkedHashMap<>(); - for (RunPeriodData data : allData) - for (int sampleCount : data.checkpoints().keySet()) { - MethodCount group = new MethodCount(data.run().method(), sampleCount); - groups.computeIfAbsent(group, unused -> new ArrayList<>()).add(data); - } + static List buildRealizationPairComparisons( + List allData, GriddedRegion gridReg) { + Map> groups = new LinkedHashMap<>(); + for (Realization data : allData) { + MethodCount group = new MethodCount(data.run().method(), data.sampleCount()); + groups.computeIfAbsent(group, unused -> new ArrayList<>()).add(data); + } List comparisons = new ArrayList<>(); - for (Map.Entry> entry : groups.entrySet()) { - List data = entry.getValue(); + for (Map.Entry> entry : groups.entrySet()) { + List data = entry.getValue(); for (int i=0; i comparisons) {} - private record RunSpec(String id, File directory, LogicTree tree, SamplingMethod method, + record RunSpec(String id, File directory, LogicTree tree, SamplingMethod method, long seed, int maxSamples) {} - private record RunPeriodData(RunSpec run, double[][] branchMaps, double[] curveX, - double[][] curveSums, Map checkpoints) {} + record RunPeriodData(RunSpec run, double[][] branchMaps, double[] curveX, + double[][] curveSums, Map checkpoints, + Map curveBoundaries) {} - private record HazardStatistics(Map metricValues) { + record HazardStatistics(Map metricValues) { double[] values(ConvergenceMetric metric) { return Preconditions.checkNotNull(metricValues.get(metric)); } } - private record ReferenceStatistics(String name, String excludedRun, int sampleCount, + record ReferenceStatistics(String name, String excludedRun, int sampleCount, HazardStatistics statistics) {} - private record ReferenceComparison(RunSpec run, int sampleCount, String referenceName, + record ReferenceComparison(RunSpec run, int sampleCount, String referenceName, int referenceSampleCount, ConvergenceMetric metric, MapComparison comparison, - Location worstLocation) {} + Location worstLocation, int startIndex) {} private record ReferenceComparisonGroup(SamplingMethod method, int sampleCount, String referenceName, ConvergenceMetric metric) {} @@ -1010,7 +1110,9 @@ private record DoublingComparisonGroup(SamplingMethod method, int lowerCount, in private record MethodCount(SamplingMethod method, int sampleCount) {} - private record RealizationPairComparison(SamplingMethod method, int sampleCount, + record Realization(RunSpec run, int sampleCount, HazardStatistics statistics) {} + + record RealizationPairComparison(SamplingMethod method, int sampleCount, RunSpec first, RunSpec second, ConvergenceMetric metric, MapComparison comparison, Location worstLocation) {} diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java index b043a648..dc6c092c 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java @@ -8,13 +8,16 @@ import java.text.ParsePosition; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.IntStream; import org.apache.commons.math3.stat.StatUtils; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.ui.RectangleAnchor; +import org.jfree.chart.ui.RectangleInsets; import org.jfree.data.Range; import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; @@ -28,8 +31,6 @@ import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.commons.logicTree.sampling.SamplingMethod; -import com.google.common.base.Preconditions; - import net.mahdilamb.colormap.Colors; import scratch.kevin.sampling.HazardConvergenceCalcs.ConvergenceMetric; import scratch.kevin.sampling.HazardConvergenceCalcs.ConvergenceSummary; @@ -41,9 +42,9 @@ public class HazardConvergencePlots { private static final String SOBOL_REFERENCE = HazardConvergenceCalcs.LOO_SOBOL_REFERENCE_NAME; private static final String POOLED_SOBOL_REFERENCE = HazardConvergenceCalcs.POOLED_SOBOL_REFERENCE_NAME; private static final String MCS_REFERENCE = HazardConvergenceCalcs.MCS_REFERENCE_NAME; + private static final SamplingMethod MCS = SamplingMethod.MONTE_CARLO; private static final SamplingMethod SOBOL = SamplingMethod.OWEN_SCRAMBLED_SOBOL; - private static final SamplingMethod PAIRWISE_LHS = SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE; - private static final List COMPARISON_METHODS = List.of(SOBOL, PAIRWISE_LHS); + private static final Map METRIC_COLORS = Map.of( ConvergenceMetric.MEAN_HAZARD, Colors.tab_blue, @@ -58,9 +59,17 @@ public class HazardConvergencePlots { ConvergenceMetric.IQR, PlotSymbol.FILLED_TRIANGLE, ConvergenceMetric.CENTRAL_68_RANGE, PlotSymbol.FILLED_SQUARE, ConvergenceMetric.CENTRAL_95_RANGE, PlotSymbol.FILLED_DIAMOND); + + private static final Map METHOD_FILE_PREFIXES; + static { + Map prefixes = new HashMap<>(); + for (SamplingMethod method : SamplingMethod.values()) + prefixes.put(method, method.getShortName().toLowerCase().replaceAll("-", "_")); + METHOD_FILE_PREFIXES = prefixes; + } public static void main(String[] args) throws IOException { - File convergenceDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence/sobol_convergence"); + File convergenceDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence"); plotPeriod(new File(convergenceDir, "pga_two_in_50"), "PGA"); plotPeriod(new File(convergenceDir, "1s_sa_two_in_50"), "1 s SA"); } @@ -68,123 +77,132 @@ public static void main(String[] args) throws IOException { static void plotPeriod(File outputDir, String periodName) throws IOException { List references = loadReferenceSummaries( new File(outputDir, "reference_comparisons.csv")); - List doublings = loadDoublingSummaries( - new File(outputDir, "paired_doubling_comparisons.csv")); List realizationPairs = loadRealizationPairSummaries( new File(outputDir, "realization_pair_comparisons.csv")); - plotReference(outputDir, periodName, references, SOBOL_REFERENCE, "sobol_consensus", - ConvergenceSummary.MEAN_ABSOLUTE, "Spatial mean absolute difference (%)"); - plotReference(outputDir, periodName, references, SOBOL_REFERENCE, "sobol_consensus", - ConvergenceSummary.MAXIMUM_ABSOLUTE, "Maximum absolute difference (%)"); - plotReference(outputDir, periodName, references, MCS_REFERENCE, "mcs_reference", - ConvergenceSummary.MEAN_ABSOLUTE, "Spatial mean absolute difference (%)"); - plotReference(outputDir, periodName, references, MCS_REFERENCE, "mcs_reference", - ConvergenceSummary.MAXIMUM_ABSOLUTE, "Maximum absolute difference (%)"); - plotDoubling(outputDir, periodName, doublings, ConvergenceSummary.MEAN_ABSOLUTE, - "Spatial mean absolute difference (%)"); - plotDoubling(outputDir, periodName, doublings, ConvergenceSummary.MAXIMUM_ABSOLUTE, - "Maximum absolute difference (%)"); - plotMethodReference(outputDir, references, false, ConvergenceSummary.MEAN_ABSOLUTE, - "Spatial mean absolute difference (%)"); - plotMethodReference(outputDir, references, false, ConvergenceSummary.MAXIMUM_ABSOLUTE, - "Maximum absolute difference (%)"); - plotMethodReference(outputDir, references, true, ConvergenceSummary.MEAN_ABSOLUTE, - "Spatial mean absolute difference (%)"); - plotMethodReference(outputDir, references, true, ConvergenceSummary.MAXIMUM_ABSOLUTE, - "Maximum absolute difference (%)"); + for (SamplingMethod method : references.stream().map(ReferenceSummary::method).distinct().sorted().toList()) { + for (boolean sobolPool : new boolean[] {true, false}) { + plotReference(outputDir, references, method, sobolPool, ConvergenceSummary.MEAN_ABSOLUTE); +// // Retain the original Sobol convergence maximum plots as standalone figures. +// if (method == SOBOL) +// plotReference(outputDir, references, method, sobolPool, ConvergenceSummary.MAXIMUM_ABSOLUTE); + } + } + for (boolean sobolPool : new boolean[] {true, false}) + plotMethodReference(outputDir, references, sobolPool, ConvergenceSummary.MEAN_ABSOLUTE, + "Absolute difference (%)"); plotRealizationPairs(outputDir, realizationPairs, ConvergenceSummary.MEAN_ABSOLUTE, - "Spatial mean absolute difference (%)"); - plotRealizationPairs(outputDir, realizationPairs, ConvergenceSummary.MAXIMUM_ABSOLUTE, - "Maximum absolute difference (%)"); + "Absolute difference (%)"); } - private static void plotReference(File outputDir, String periodName, List rows, - String reference, String referencePrefix, ConvergenceSummary spatialSummary, String yLabel) throws IOException { - List matching = rows.stream().filter(row -> row.method() == SOBOL - && row.reference().equals(reference) - && row.spatialSummary().equals(spatialSummary)).toList(); - Preconditions.checkState(!matching.isEmpty(), "No rows for %s, %s", reference, spatialSummary); + private static String referenceFor(SamplingMethod method, boolean sobolPool) { + return sobolPool ? (method == SOBOL ? SOBOL_REFERENCE : POOLED_SOBOL_REFERENCE) + : (method == MCS ? HazardConvergenceCalcs.LOO_MCS_REFERENCE_NAME : MCS_REFERENCE); + } + + private static boolean includeSummary(ConvergenceSummary actual, ConvergenceSummary requested) { + return actual == requested || requested == ConvergenceSummary.MEAN_ABSOLUTE + && actual == ConvergenceSummary.MAXIMUM_ABSOLUTE; + } + + private static void plotReference(File outputDir, List rows, + SamplingMethod method, boolean sobolPool, ConvergenceSummary summary) throws IOException { + List matching = rows.stream().filter(row -> row.method() == method + && row.reference().equals(referenceFor(method, sobolPool)) + && includeSummary(row.spatialSummary(), summary)).toList(); int[] counts = matching.stream().mapToInt(ReferenceSummary::sampleCount).distinct().sorted().toArray(); -// String title = periodName+", "+(reference.equals(SOBOL_REFERENCE) -// ? "pooled Sobol consensus" : MCS_REFERENCE+" reference"); - String title = reference.equals(SOBOL_REFERENCE) ? "Pooled Sobol consensus" : MCS_REFERENCE+" reference"; - String prefix = "convergence_"+referencePrefix+"_"+summaryPrefix(spatialSummary); - writePlot(outputDir, prefix, title, "Sample count", yLabel, counts, + if (counts.length < 2) + return; + String pool = sobolPool ? "sobol_consensus" : "mcs_reference"; + String prefix = "convergence_"+METHOD_FILE_PREFIXES.get(method)+"_vs_" + +pool+"_"+summaryPrefix(summary); + writePlot(outputDir, prefix, method.getShortName()+" versus "+(sobolPool ? "Sobol pool" : "MCS pool"), + "Sample count", summary == ConvergenceSummary.MEAN_ABSOLUTE ? "Absolute difference (%)" + : "Maximum absolute difference (%)", counts, Arrays.stream(counts).mapToObj(Integer::toString).toArray(String[]::new), matching); } - private static void plotMethodReference(File outputDir, List rows, + static void plotMethodReference(File outputDir, List rows, boolean sobolConsensus, ConvergenceSummary spatialSummary, String yLabel) throws IOException { + int[] counts = rows.stream().mapToInt(ReferenceSummary::sampleCount).distinct().sorted().toArray(); + for (int count : counts) + plotMethodReference(outputDir, rows, sobolConsensus, spatialSummary, yLabel, count); + } + + private static void plotMethodReference(File outputDir, List rows, + boolean sobolConsensus, ConvergenceSummary spatialSummary, String yLabel, int sampleCount) throws IOException { List matching = new ArrayList<>(); - for (int m=0; m labels = new ArrayList<>(); + for (SamplingMethod method : rows.stream().map(row -> row.method()).distinct().sorted().toList()) { + String reference = referenceFor(method, sobolConsensus); + int index = labels.size(); for (ReferenceSummary row : rows) { - if (row.method() == method && row.sampleCount() == 4096 && row.reference().equals(reference) - && row.spatialSummary() == spatialSummary) { - matching.add(new MethodSummary(m, row.metric(), row.spatialSummary(), row.realizations(), + if (row.method() == method && row.sampleCount() == sampleCount + && row.reference().equals(reference) + && includeSummary(row.spatialSummary(), spatialSummary)) { + matching.add(new MethodSummary(index, row.metric(), row.spatialSummary(), row.realizations(), row.minimum(), row.median(), row.maximum())); } } + if (matching.stream().anyMatch(row -> row.count() == index)) + labels.add(method.getShortName()); } - Preconditions.checkState(!matching.isEmpty(), "No 4096-sample method comparisons"); + if (matching.isEmpty()) + return; String referencePrefix = sobolConsensus ? "sobol_consensus" : "mcs_reference"; - String title = "4096 samples versus "+(sobolConsensus ? "pooled Sobol consensus" : MCS_REFERENCE); - writePlot(outputDir, "method_comparison_"+referencePrefix+"_"+summaryPrefix(spatialSummary), - title, "Sampling method", yLabel, new int[] { 0, 1 }, - COMPARISON_METHODS.stream().map(SamplingMethod::getShortName).toArray(String[]::new), matching); + String title = sampleCount+" samples versus " + +(sobolConsensus ? "pooled Sobol consensus" : MCS_REFERENCE); + writePlot(outputDir, "method_comparison_"+sampleCount+"_"+referencePrefix+"_"+summaryPrefix(spatialSummary), + title, "Sampling method", yLabel, + IntStream.range(0, labels.size()).toArray(), labels.toArray(String[]::new), matching); } private static void plotRealizationPairs(File outputDir, List rows, ConvergenceSummary spatialSummary, String yLabel) throws IOException { + int[] counts = rows.stream().mapToInt(RealizationPairSummary::sampleCount).distinct().sorted().toArray(); + for (int count : counts) + plotRealizationPairs(outputDir, rows, spatialSummary, yLabel, count); + } + + private static void plotRealizationPairs(File outputDir, List rows, + ConvergenceSummary spatialSummary, String yLabel, int sampleCount) throws IOException { List matching = new ArrayList<>(); - for (int m=0; m labels = new ArrayList<>(); + for (SamplingMethod method : rows.stream().map(row -> row.method()).distinct().sorted().toList()) { + int index = labels.size(); for (RealizationPairSummary row : rows) { - if (row.method() == method && row.sampleCount() == 4096 - && row.spatialSummary() == spatialSummary) { - matching.add(new MethodSummary(m, row.metric(), row.spatialSummary(), row.realizationPairs(), + if (row.method() == method && row.sampleCount() == sampleCount + && includeSummary(row.spatialSummary(), spatialSummary)) { + matching.add(new MethodSummary(index, row.metric(), row.spatialSummary(), row.realizationPairs(), row.minimum(), row.median(), row.maximum())); } } + if (matching.stream().anyMatch(row -> row.count() == index)) + labels.add(method.getShortName()); } - Preconditions.checkState(!matching.isEmpty(), "No 4096-sample realization-pair comparisons"); - writePlot(outputDir, "method_comparison_realization_pairs_"+summaryPrefix(spatialSummary), - "Differences between 4096-sample realizations", "Sampling method", yLabel, - new int[] { 0, 1 }, - COMPARISON_METHODS.stream().map(SamplingMethod::getShortName).toArray(String[]::new), matching); - } - - private static void plotDoubling(File outputDir, String periodName, List rows, - ConvergenceSummary spatialSummary, String yLabel) throws IOException { - List matching = rows.stream() - .filter(row -> row.spatialSummary().equals(spatialSummary)).toList(); - Preconditions.checkState(!matching.isEmpty(), "No doubling rows for %s", spatialSummary); - int[] upperCounts = matching.stream().mapToInt(DoublingSummary::upperCount).distinct().sorted().toArray(); - String[] labels = new String[upperCounts.length]; - for (int i=0; i generic = new ArrayList<>(matching); -// String title = periodName+", paired sample-count increases"; - String title = "Paired sample-count increases"; - writePlot(outputDir, "convergence_paired_doubling_"+summaryPrefix(spatialSummary), - title, "Sample-count increase", yLabel, - upperCounts, labels, generic); + if (matching.isEmpty()) + return; + writePlot(outputDir, "method_comparison_"+sampleCount+"_realization_pairs_"+summaryPrefix(spatialSummary), + "Differences between "+sampleCount+"-sample realizations", "Sampling method", yLabel, + IntStream.range(0, labels.size()).toArray(), labels.toArray(String[]::new), matching); } private static void writePlot(File outputDir, String prefix, String title, String xLabel, String yLabel, int[] counts, String[] countLabels, List rows) throws IOException { + ConvergenceSummary primary = prefix.endsWith("_max_abs") ? ConvergenceSummary.MAXIMUM_ABSOLUTE + : ConvergenceSummary.MEAN_ABSOLUTE; Map> byMetric = new LinkedHashMap<>(); for (ConvergenceMetric metric : ConvergenceMetric.values()) { - List metricRows = rows.stream().filter(row -> row.metric().equals(metric)).toList(); + List metricRows = rows.stream().filter(row -> row.metric().equals(metric) + && row.spatialSummary() == primary).toList(); if (!metricRows.isEmpty()) byMetric.put(metric, metricRows); } List funcs = new ArrayList<>(); List chars = new ArrayList<>(); + List maxFuncs = new ArrayList<>(); + List maxChars = new ArrayList<>(); List medianFuncs = new ArrayList<>(); List medianChars = new ArrayList<>(); for (Map.Entry> entry : byMetric.entrySet()) { @@ -207,9 +225,25 @@ private static void writePlot(File outputDir, String prefix, String title, Strin median.setName(entry.getKey().shortLabel); medianFuncs.add(median); PlotSymbol sym = METRIC_SYMBOLS.get(entry.getKey()); + if (primary == ConvergenceSummary.MEAN_ABSOLUTE) { + ArbitrarilyDiscretizedFunc worst = new ArbitrarilyDiscretizedFunc(); + for (int i=0; i row.metric() == entry.getKey() && row.count() == count + && row.spatialSummary() == ConvergenceSummary.MAXIMUM_ABSOLUTE) + .findFirst().ifPresent(row -> worst.set((double)Arrays.binarySearch(counts, count), row.maximum())); + } + if (worst.size() > 0) { + maxFuncs.add(worst); // Unnamed, so it adds no legend entry. + maxChars.add(new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 0.5f, + PlotSymbol.getOutlineSymbol(sym), 3f, color)); + } + } medianChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, sym, 5f, color)); } // Put every envelope in the dataset first so all median lines render above all shading. + funcs.addAll(maxFuncs); + chars.addAll(maxChars); funcs.addAll(medianFuncs); chars.addAll(medianChars); @@ -223,7 +257,10 @@ private static void writePlot(File outputDir, String prefix, String title, Strin gp.getPlotPrefs().setPlotLabelFontSize(10); gp.getPlotPrefs().setLegendFontSize(8); gp.getPlotPrefs().setLegendLineLength(6d); - Range xRange = new Range(-0.2d, counts.length-0.8d); + gp.getPlotPrefs().setTickLabelFontSize(8); +// gp.getPlotPrefs().setPlotPadding(new RectangleInsets(5, 0, 0, 12)); +// Range xRange = counts.length == 1 ? new Range(-0.5, 0.5) : new Range(-0.2d, counts.length-0.8d); + Range xRange = counts.length == 1 ? new Range(-0.5, 0.5) : new Range(-0.3d, counts.length-0.7d); gp.drawGraphPanel(plot, false, true, xRange, Y_RANGE); PlotUtils.setXTick(gp, 1d); ((NumberAxis)gp.getXAxis()).setNumberFormatOverride(categoryFormat(countLabels)); @@ -273,30 +310,6 @@ private static List loadReferenceSummaries(File file) throws I return rows; } - private static List loadDoublingSummaries(File file) throws IOException { - CSVFile csv = CSVFile.readFile(file, true); - Map> groups = new LinkedHashMap<>(); - for (int row=1; row rows = new ArrayList<>(); - for (Map.Entry> entry : groups.entrySet()) { - DoublingGroup group = entry.getKey(); - double[] values = entry.getValue().stream().mapToDouble(Double::doubleValue).toArray(); - rows.add(new DoublingSummary(group.method(), group.lowerCount(), group.upperCount(), group.metric(), - group.spatialSummary(), values.length, StatUtils.min(values), - StatUtils.percentile(values, 50d), StatUtils.max(values))); - } - return rows; - } - private static List loadRealizationPairSummaries(File file) throws IOException { CSVFile csv = CSVFile.readFile(file, true); Map> groups = new LinkedHashMap<>(); @@ -328,32 +341,28 @@ private static String summaryPrefix(ConvergenceSummary summary) { return summary == ConvergenceSummary.MEAN_ABSOLUTE ? "mean_abs" : "max_abs"; } - private interface SummaryRow { + interface SummaryRow { int count(); + ConvergenceSummary spatialSummary(); ConvergenceMetric metric(); double minimum(); double median(); double maximum(); } - private record ReferenceSummary(SamplingMethod method, int sampleCount, String reference, ConvergenceMetric metric, + record ReferenceSummary(SamplingMethod method, int sampleCount, String reference, ConvergenceMetric metric, ConvergenceSummary spatialSummary, int realizations, double minimum, double median, double maximum) implements SummaryRow { @Override public int count() { return sampleCount; } } - private record DoublingSummary(SamplingMethod method, int lowerCount, int upperCount, ConvergenceMetric metric, - ConvergenceSummary spatialSummary, - int realizations, double minimum, double median, double maximum) implements SummaryRow { - @Override public int count() { return upperCount; } - } - private record MethodSummary(int methodIndex, ConvergenceMetric metric, ConvergenceSummary spatialSummary, int realizations, double minimum, double median, double maximum) implements SummaryRow { @Override public int count() { return methodIndex; } } + private record RealizationPairSummary(SamplingMethod method, int sampleCount, ConvergenceMetric metric, ConvergenceSummary spatialSummary, int realizationPairs, double minimum, double median, double maximum) {} @@ -362,10 +371,6 @@ private record ReferenceGroup(SamplingMethod method, int sampleCount, String ref ConvergenceMetric metric, ConvergenceSummary spatialSummary) {} - private record DoublingGroup(SamplingMethod method, int lowerCount, int upperCount, - ConvergenceMetric metric, - ConvergenceSummary spatialSummary) {} - private record RealizationPairGroup(SamplingMethod method, int sampleCount, ConvergenceMetric metric, ConvergenceSummary spatialSummary) {} } diff --git a/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java b/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java new file mode 100644 index 00000000..49abad0a --- /dev/null +++ b/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java @@ -0,0 +1,91 @@ +package scratch.kevin.sampling; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.junit.Test; +import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.Location; +import org.opensha.commons.logicTree.sampling.SamplingMethod; +import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc.ReturnPeriods; + +import scratch.kevin.sampling.HazardConvergenceCalcs.*; + +public class HazardConvergenceCalcsTest { + @Test public void spanReferencesRetainRemaindersAndOtherRuns() { + GriddedRegion grid = new GriddedRegion(new Location(0, 0), new Location(0.1, 0.1), + 1d, new Location(0, 0)); + assertEquals(1, grid.getNodeCount()); + RunPeriodData first = run("first", 0, 7); + RunPeriodData second = run("second", 7, 5); + ReferenceStatistics sobol = new ReferenceStatistics(HazardConvergenceCalcs.POOLED_SOBOL_REFERENCE_NAME, + null, 7, HazardConvergenceCalcs.calcHazardStatistics(first.branchMaps(), 7, new double[] { 1 })); + List rows = new ArrayList<>(); + List spans = HazardConvergenceCalcs.appendMCSSpanComparisons(rows, List.of(first, second), new int[] {2, 4}, + sobol, grid, ReturnPeriods.TWO_IN_50); + assertEquals(7, spans.size()); + // C(5,2) at size 2 plus C(2,2) at size 4, each with five metrics. + assertEquals(55, HazardConvergenceCalcs.buildRealizationPairComparisons(spans, grid).size()); + // Five two-sample spans and two four-sample spans, each with two references and five metrics. + assertEquals(70, rows.size()); + for (ReferenceComparison row : rows) { + assertEquals(0, row.startIndex() % row.sampleCount()); + assertTrue(row.startIndex()+row.sampleCount() <= row.run().maxSamples()); + if (!row.referenceName().equals(HazardConvergenceCalcs.LOO_MCS_REFERENCE_NAME)) + continue; + assertEquals(12-row.sampleCount(), row.referenceSampleCount()); + int from = (row.run().id().equals("first") ? 0 : 7)+row.startIndex(); + int to = from+row.sampleCount(); + if (row.metric() == ConvergenceMetric.STANDARD_DEVIATION) { + double[] included = java.util.stream.IntStream.range(0, 12) + .filter(i -> i < from || i >= to).mapToDouble(i -> i+1).toArray(); + double mean = Arrays.stream(included).average().orElseThrow(); + double variance = Arrays.stream(included).map(v -> (v-mean)*(v-mean)).average().orElseThrow(); + double spanVariance = (row.sampleCount()*row.sampleCount()-1d)/12d; + assertEquals(100d*(Math.sqrt(spanVariance/variance)-1), row.comparison().meanPercentChange(), 1e-10); + } + if (row.metric() == ConvergenceMetric.MEAN_HAZARD) { + double spanScale = 0, remainingScale = 0; + for (int i=0; i<12; i++) { + if (i >= from && i < to) spanScale += i+1; + else remainingScale += i+1; + } + double test = HazardConvergenceCalcs.buildCurveMeanMap(curves(spanScale), first.curveX(), + row.sampleCount(), ReturnPeriods.TWO_IN_50)[0]; + double ref = HazardConvergenceCalcs.buildCurveMeanMap(curves(remainingScale), first.curveX(), + row.referenceSampleCount(), ReturnPeriods.TWO_IN_50)[0]; + assertEquals(100d*(test/ref-1), row.comparison().meanPercentChange(), 1e-10); + } + } + } + + private static RunPeriodData run(String name, int offset, int size) { + double[][] maps = new double[size][1]; + Map boundaries = new TreeMap<>(); + double sum = 0; + for (int i=0; i rows = new ArrayList<>(); + for (ConvergenceMetric metric : ConvergenceMetric.values()) { + for (int count : new int[] {512, 1024}) + rows.add(new ReferenceSummary(SamplingMethod.OWEN_SCRAMBLED_SOBOL, count, + HazardConvergenceCalcs.MCS_REFERENCE_NAME, metric, ConvergenceSummary.MEAN_ABSOLUTE, + 2, 0.1, 0.2, 0.3)); + rows.add(new ReferenceSummary(SamplingMethod.MONTE_CARLO, 512, + HazardConvergenceCalcs.LOO_MCS_REFERENCE_NAME, metric, ConvergenceSummary.MEAN_ABSOLUTE, + 4, 0.2, 0.3, 0.4)); + rows.add(new ReferenceSummary(SamplingMethod.LATIN_HYPERCUBE, 512, + HazardConvergenceCalcs.MCS_REFERENCE_NAME, metric, ConvergenceSummary.MEAN_ABSOLUTE, + 4, 0.1, 0.2, 0.3)); + } + for (ReferenceSummary row : new ArrayList<>(rows)) + rows.add(new ReferenceSummary(row.method(), row.sampleCount(), row.reference(), row.metric(), + ConvergenceSummary.MAXIMUM_ABSOLUTE, row.realizations(), 0.5, 1, 5)); + HazardConvergencePlots.plotMethodReference(output.getRoot(), rows, false, + ConvergenceSummary.MEAN_ABSOLUTE, "Spatial mean absolute difference (%)"); + for (int count : new int[] {512, 1024}) { + assertTrue(new java.io.File(output.getRoot(), + "method_comparison_"+count+"_mcs_reference_mean_abs.png").isFile()); + } + } +} From e43461345cf5779c5afd4ac5aa3969e981eb2055 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Tue, 8 Sep 2026 14:36:17 -0700 Subject: [PATCH 61/71] removed legacy pairwise-optimization code --- .../kevin/ltSampling/LHSExampleFigures.java | 104 +++++++++++------- 1 file changed, 67 insertions(+), 37 deletions(-) diff --git a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java index c5151837..6b02385a 100644 --- a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java +++ b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java @@ -25,6 +25,10 @@ import org.opensha.commons.data.function.DefaultXY_DataSet; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; import org.opensha.commons.data.function.XY_DataSet; +import org.opensha.commons.data.sampling.PermutedPointSet; +import org.opensha.commons.data.sampling.PointSet; +import org.opensha.commons.data.sampling.optimization.PointSetHillClimber; +import org.opensha.commons.data.sampling.optimization.QuantizedIncrementalPointSetScorer; import org.opensha.commons.gui.plot.HeadlessGraphPanel; import org.opensha.commons.gui.plot.PlotCurveCharacterstics; import org.opensha.commons.gui.plot.PlotLineType; @@ -39,7 +43,7 @@ import org.opensha.commons.logicTree.LogicTreeNode; import org.opensha.commons.logicTree.LogicTreeNode.SimpleValuedNode; import org.opensha.commons.logicTree.LogicTreeNode.ValuedLogicTreeNode; -import org.opensha.commons.logicTree.lhs.PairwiseLogicTreeNodeSwapIteration; +import org.opensha.commons.logicTree.sampling.LogicTreePointSetMapper; import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.util.cpt.CPT; @@ -51,10 +55,11 @@ public class LHSExampleFigures { public static void main(String[] args) throws IOException { - int samples = 30; -// int samples = 100; -// int samples = 1000; -// int samples = 2000; +// int samples = 32; +// int samples = 128; +// int samples = 256; +// int samples = 512; + int samples = 1024; int dpi = 300; @@ -72,12 +77,33 @@ public static void main(String[] args) throws IOException { levels.add(new ContinuousDistributionSampledLevel( "Off-fault Mmax", "Off-fault Mmax", TruncatedNormalDistribution.of(7.6, 0.2, 7.15, 8.05), -1, "Sample ", "Sample", "Sample")); - long seed = 123456789l; + SamplingMethod[] sms = { + SamplingMethod.MONTE_CARLO, + SamplingMethod.LATIN_HYPERCUBE, + SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, + SamplingMethod.SOBOL, + SamplingMethod.OWEN_SCRAMBLED_SOBOL, + }; - CPT tab10cpt = GMT_CPT_Files.CATEGORICAL_TAB10.instance(); - Color[] tab10 = new Color[tab10cpt.size()]; - for (int i=0; i nodeColors = new HashMap<>(); int colorI = 0; @@ -99,7 +125,7 @@ public static void main(String[] args) throws IOException { } } - for (SamplingMethod sm : SamplingMethod.values()) { + for (SamplingMethod sm : sms) { LogicTree tree = LogicTree.buildSampled(levels, samples, seed, sm); if (sm == SamplingMethod.MONTE_CARLO) { // write tree plot @@ -202,10 +228,10 @@ public static void main(String[] args) throws IOException { int maxCount = 0; - Font nameFont = new Font(Font.SANS_SERIF, Font.BOLD, 12); - Font countFont = new Font(Font.SANS_SERIF, Font.BOLD, 12); - Font subNameFont = new Font(Font.SANS_SERIF, Font.BOLD, 10); - Font subCountFont = new Font(Font.SANS_SERIF, Font.BOLD, 10); + Font nameFont = new Font(Font.SANS_SERIF, Font.BOLD, 10); + Font countFont = new Font(Font.SANS_SERIF, Font.BOLD, 10); + Font subNameFont = new Font(Font.SANS_SERIF, Font.BOLD, 8); + Font subCountFont = new Font(Font.SANS_SERIF, Font.BOLD, 8); double offset = samples*0.01; @@ -315,7 +341,7 @@ public static void main(String[] args) throws IOException { } } - if (samples <= 30) { + if (samples <= 32) { // build branch vector plot List funcs = new ArrayList<>(); List chars = new ArrayList<>(); @@ -331,28 +357,31 @@ public static void main(String[] args) throws IOException { List origBranchIndexes = null; if (sm ==SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE) { + // do the optimization manually + LogicTreePointSetMapper mapper = new LogicTreePointSetMapper<>(levels); + PointSet pointSet = SamplingMethod.LATIN_HYPERCUBE.prepare(samples, mapper.getSamplingDimensions(), seed); + LogicTree tree2 = LogicTree.buildSampled(levels, samples, seed, SamplingMethod.LATIN_HYPERCUBE); - List levelFixedWeights = new ArrayList<>(); - for (int l=0; l level = levels.get(l); - if (level instanceof ContinuousDistributionSampledLevel) { - levelFixedWeights.add(null); - } else { - List nodes = level.getNodes(); - double[] weights = new double[nodes.size()]; - for (int n=0; n iter = new PairwiseLogicTreeNodeSwapIteration<>( - levels, tree2.getBranches(), levelFixedWeights); - iter.setTrackSwaps(true); + PermutedPointSet permuted = PermutedPointSet.independentDimensions(pointSet); + long iterations = Integer.max(100000, samples*100); + QuantizedIncrementalPointSetScorer scorer = + new QuantizedIncrementalPointSetScorer(permuted, SamplingMethod.PAIRWISE_CONTINUOUS_BINS); + System.out.println("Pairwise-optimizing sample of size "+pointSet.size()+" with "+iterations+" iterations"); + System.out.println("\tInitial 2D score:\t"+(float)scorer.getCurrentScore().getOrderMeanScore(2)); + PointSetHillClimber.optimize(scorer, iterations, new Random(new Random(seed).nextLong())); + System.out.println("\tDONE; final 2D score:\t"+(float)scorer.getCurrentScore().getOrderMeanScore(2)); - iter.iterate(Integer.max(10000, samples*100), new Random(seed), false); +// permuted.get(dpi, colorI) - origBranchIndexes = iter.getOriginalBranchIndexes(); +// origBranchIndexes = iter.getOriginalBranchIndexes(); + origBranchIndexes = new ArrayList<>(samples); + for (int n=0; n Date: Wed, 9 Sep 2026 10:06:46 -0700 Subject: [PATCH 62/71] scoring interface cleanup --- .../sampling/HazardConvergenceCalcs.java | 76 ++- .../sampling/HazardConvergencePlots.java | 81 +++- .../kevin/sampling/InitialSamplingTests.java | 24 +- .../kevin/sampling/SamplingScoreFigures.java | 458 ++++++++++-------- 4 files changed, 399 insertions(+), 240 deletions(-) diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java index 456fd688..e015357c 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java @@ -27,6 +27,7 @@ import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.function.DiscretizedFunc; import org.opensha.commons.data.function.LightFixedXFunc; +import org.opensha.commons.data.xyz.AbstractXYZ_DataSet; import org.opensha.commons.data.xyz.GriddedGeoDataSet; import org.opensha.commons.geo.GriddedRegion; import org.opensha.commons.geo.Location; @@ -36,6 +37,7 @@ import org.opensha.commons.logicTree.LogicTreeBranch; import org.opensha.commons.logicTree.sampling.SamplingMethod; import org.opensha.commons.util.RandomSeedUtils; +import org.opensha.sha.earthquake.faultSysSolution.hazard.mpj.MPJ_LogicTreeHazardCalc; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc; import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc.ReturnPeriods; @@ -96,6 +98,16 @@ public static void main(String[] args) throws IOException { new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-3") )); + /* + * LHS runs + */ + runDirs.put(SamplingMethod.LATIN_HYPERCUBE, 4096, List.of( + new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs"), + new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed") +// new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-2"), +// new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-3") + )); + /* * Pairwise-LHS runs */ @@ -173,14 +185,19 @@ private static void runSamplingConvergence(List sobolRuns, List mcsData = loadRunPeriodData(mcsRuns, gridReg, period, rp, sampleCounts); - ReferenceStatistics mcsReference = buildPooledReference(mcsData, null, gridReg, rp, + PooledHazardData pooledMCSData = buildPooledHazardData(mcsData, null, gridReg, rp, MCS_REFERENCE_NAME, MCS_REFERENCE_NAME); + ReferenceStatistics mcsReference = pooledMCSData.reference(); Map leaveOneOut = new LinkedHashMap<>(); for (RunPeriodData data : sobolData) - leaveOneOut.put(data.run(), buildPooledReference(sobolData, data.run(), gridReg, rp, - POOLED_SOBOL_REFERENCE_NAME, LOO_SOBOL_REFERENCE_NAME)); - ReferenceStatistics pooledSobol = buildPooledReference(sobolData, null, gridReg, rp, + leaveOneOut.put(data.run(), buildPooledHazardData(sobolData, data.run(), gridReg, rp, + POOLED_SOBOL_REFERENCE_NAME, LOO_SOBOL_REFERENCE_NAME).reference()); + PooledHazardData pooledSobolData = buildPooledHazardData(sobolData, null, gridReg, rp, POOLED_SOBOL_REFERENCE_NAME, LOO_SOBOL_REFERENCE_NAME); + ReferenceStatistics pooledSobol = pooledSobolData.reference(); + + writePooledHazardFiles(new File(outputDir, "pooled_mcs"), pooledMCSData, gridReg, period, rp); + writePooledHazardFiles(new File(outputDir, "pooled_sobol"), pooledSobolData, gridReg, period, rp); List comparisons = new ArrayList<>(); for (RunPeriodData data : sobolData) { @@ -320,7 +337,7 @@ private static RunPeriodData loadRunPeriodData(RunSpec run, GriddedRegion gridRe return new RunPeriodData(run, branchMaps, curveX, curveSums, checkpoints, curveBoundaries); } - private static ReferenceStatistics buildPooledReference(List allRuns, + private static PooledHazardData buildPooledHazardData(List allRuns, RunSpec excluded, GriddedRegion gridReg, ReturnPeriods rp, String pooledName, String leaveOneOutName) { int sampleCount = 0; @@ -355,8 +372,35 @@ private static ReferenceStatistics buildPooledReference(List allR Preconditions.checkState(destBranch == sampleCount); double[] curveMean = buildCurveMeanMap(curveSums, curveX, sampleCount, rp); String name = excluded == null ? pooledName : leaveOneOutName; - return new ReferenceStatistics(name, excluded == null ? null : excluded.id(), sampleCount, + ReferenceStatistics reference = new ReferenceStatistics(name, + excluded == null ? null : excluded.id(), sampleCount, calcHazardStatistics(branchMaps, sampleCount, curveMean)); + return new PooledHazardData(reference, curveX, curveSums, curveMean); + } + + private static void writePooledHazardFiles(File outputDir, PooledHazardData pooled, + GriddedRegion gridReg, double period, ReturnPeriods rp) throws IOException { + Preconditions.checkState(outputDir.exists() || outputDir.mkdir(), + "Couldn't create pooled hazard directory: %s", outputDir.getAbsolutePath()); + int sampleCount = pooled.reference().sampleCount(); + double[] curveX = pooled.curveX(); + double[][] curveSums = pooled.curveSums(); + DiscretizedFunc[] meanCurves = new DiscretizedFunc[gridReg.getNodeCount()]; + for (int n=0; n csv = new CSVFile<>(true); csv.addLine("Sampling method", "Sample count", "Reference", "Metric", "Spatial summary", "Realizations", - "Mean", "P2.5", "P16", "P50", "P84", "P97.5"); + "Mean", "Minimum", "P2.5", "P16", "P50", "P84", "P97.5", "Maximum"); for (Map.Entry> entry : groups.entrySet()) { ReferenceComparisonGroup group = entry.getKey(); for (ConvergenceSummary summary : ConvergenceSummary.values()) { @@ -603,7 +647,7 @@ private static void writeDoublingComparisonSummary(File file, List csv = new CSVFile<>(true); csv.addLine("Sampling method", "Lower sample count", "Upper sample count", "Metric", "Spatial summary", "Realizations", - "Mean", "P2.5", "P16", "P50", "P84", "P97.5"); + "Mean", "Minimum", "P2.5", "P16", "P50", "P84", "P97.5", "Maximum"); for (Map.Entry> entry : groups.entrySet()) { DoublingComparisonGroup group = entry.getKey(); for (ConvergenceSummary summary : ConvergenceSummary.values()) { @@ -673,7 +717,7 @@ private static void writeRealizationPairComparisonSummary(File file, } CSVFile csv = new CSVFile<>(true); csv.addLine("Sampling method", "Sample count", "Metric", "Spatial summary", "Realization pairs", - "Mean", "P2.5", "P16", "P50", "P84", "P97.5"); + "Mean", "Minimum", "P2.5", "P16", "P50", "P84", "P97.5", "Maximum"); for (Map.Entry> entry : groups.entrySet()) { RealizationPairComparisonGroup group = entry.getKey(); for (ConvergenceSummary summary : ConvergenceSummary.values()) { @@ -690,11 +734,13 @@ private static void writeRealizationPairComparisonSummary(File file, private static void addSummaryLine(CSVFile csv, List prefix, double[] values) { List line = new ArrayList<>(prefix); line.add(StatUtils.mean(values)+""); + line.add(StatUtils.min(values)+""); line.add(percentile(values, 2.5)+""); line.add(percentile(values, 16d)+""); line.add(percentile(values, 50d)+""); line.add(percentile(values, 84d)+""); line.add(percentile(values, 97.5)+""); + line.add(StatUtils.max(values)+""); csv.addLine(line); } @@ -718,8 +764,8 @@ static void runBootstrapTests(ModelHazardMaps reference, int[] sampleCounts, int replicateCSV.addLine("Sample count", "Replicate", "Metric", "Spatial mean % change", "Spatial mean absolute % change", "Minimum % change", "Maximum % change"); CSVFile summaryCSV = new CSVFile<>(true); - summaryCSV.addLine("Sample count", "Metric", "Spatial summary", "Mean", "P2.5", "P16", "P50", - "P84", "P97.5"); + summaryCSV.addLine("Sample count", "Metric", "Spatial summary", "Mean", "Minimum", "P2.5", "P16", "P50", + "P84", "P97.5", "Maximum"); CSVFile siteCSV = new CSVFile<>(true); siteCSV.addLine("Sample count", "Metric", "Longitude", "Latitude", "Reference value", "Mean % change", "Std. dev. % change", "P2.5", "P16", "P50", "P84", "P97.5"); @@ -793,9 +839,10 @@ private static void appendReplicateCSVs(CSVFile replicateCSV, CSVFile csv, int sampleCount, String metric, String quantity, double[] values) { - csv.addLine(sampleCount+"", metric, quantity, StatUtils.mean(values)+"", percentile(values, 2.5)+"", + csv.addLine(sampleCount+"", metric, quantity, StatUtils.mean(values)+"", StatUtils.min(values)+"", + percentile(values, 2.5)+"", percentile(values, 16d)+"", percentile(values, 50d)+"", percentile(values, 84d)+"", - percentile(values, 97.5)+""); + percentile(values, 97.5)+"", StatUtils.max(values)+""); } private static String formatDistribution(double[] values) { @@ -1095,6 +1142,9 @@ record HazardStatistics(Map metricValues) { record ReferenceStatistics(String name, String excludedRun, int sampleCount, HazardStatistics statistics) {} + private record PooledHazardData(ReferenceStatistics reference, double[] curveX, + double[][] curveSums, double[] meanMap) {} + record ReferenceComparison(RunSpec run, int sampleCount, String referenceName, int referenceSampleCount, ConvergenceMetric metric, MapComparison comparison, Location worstLocation, int startIndex) {} diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java index dc6c092c..40e9292b 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java @@ -39,6 +39,7 @@ public class HazardConvergencePlots { private static final Range Y_RANGE = new Range(1e-2, 2e1); + private static final Range SIGNED_Y_RANGE = new Range(-1d, 1d); private static final String SOBOL_REFERENCE = HazardConvergenceCalcs.LOO_SOBOL_REFERENCE_NAME; private static final String POOLED_SOBOL_REFERENCE = HazardConvergenceCalcs.POOLED_SOBOL_REFERENCE_NAME; private static final String MCS_REFERENCE = HazardConvergenceCalcs.MCS_REFERENCE_NAME; @@ -60,11 +61,17 @@ public class HazardConvergencePlots { ConvergenceMetric.CENTRAL_68_RANGE, PlotSymbol.FILLED_SQUARE, ConvergenceMetric.CENTRAL_95_RANGE, PlotSymbol.FILLED_DIAMOND); + private static String getMethodName(SamplingMethod method) { + if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL) + return SamplingMethod.SOBOL.getShortName(); + return method.getShortName(); + } + private static final Map METHOD_FILE_PREFIXES; static { Map prefixes = new HashMap<>(); for (SamplingMethod method : SamplingMethod.values()) - prefixes.put(method, method.getShortName().toLowerCase().replaceAll("-", "_")); + prefixes.put(method, getMethodName(method).toLowerCase().replaceAll("-", "_")); METHOD_FILE_PREFIXES = prefixes; } @@ -83,6 +90,7 @@ static void plotPeriod(File outputDir, String periodName) throws IOException { for (SamplingMethod method : references.stream().map(ReferenceSummary::method).distinct().sorted().toList()) { for (boolean sobolPool : new boolean[] {true, false}) { plotReference(outputDir, references, method, sobolPool, ConvergenceSummary.MEAN_ABSOLUTE); + plotReference(outputDir, references, method, sobolPool, ConvergenceSummary.MEAN_SIGNED); // // Retain the original Sobol convergence maximum plots as standalone figures. // if (method == SOBOL) // plotReference(outputDir, references, method, sobolPool, ConvergenceSummary.MAXIMUM_ABSOLUTE); @@ -113,13 +121,15 @@ private static void plotReference(File outputDir, List rows, int[] counts = matching.stream().mapToInt(ReferenceSummary::sampleCount).distinct().sorted().toArray(); if (counts.length < 2) return; - String pool = sobolPool ? "sobol_consensus" : "mcs_reference"; + String pool = sobolPool ? "pooled_sobol" : "pooled_mcs"; String prefix = "convergence_"+METHOD_FILE_PREFIXES.get(method)+"_vs_" +pool+"_"+summaryPrefix(summary); - writePlot(outputDir, prefix, method.getShortName()+" versus "+(sobolPool ? "Sobol pool" : "MCS pool"), - "Sample count", summary == ConvergenceSummary.MEAN_ABSOLUTE ? "Absolute difference (%)" - : "Maximum absolute difference (%)", counts, - Arrays.stream(counts).mapToObj(Integer::toString).toArray(String[]::new), matching); + String yLabel = summary == ConvergenceSummary.MEAN_SIGNED ? "Signed bias (%)" + : summary == ConvergenceSummary.MEAN_ABSOLUTE ? "Absolute difference (%)" + : "Maximum absolute difference (%)"; + writePlot(outputDir, prefix, getMethodName(method)+" versus "+(sobolPool ? "Sobol pool" : "MCS pool"), + "Sample count", yLabel, counts, + Arrays.stream(counts).mapToObj(Integer::toString).toArray(String[]::new), matching, summary); } static void plotMethodReference(File outputDir, List rows, @@ -145,16 +155,16 @@ && includeSummary(row.spatialSummary(), spatialSummary)) { } } if (matching.stream().anyMatch(row -> row.count() == index)) - labels.add(method.getShortName()); + labels.add(getMethodName(method)); } if (matching.isEmpty()) return; - String referencePrefix = sobolConsensus ? "sobol_consensus" : "mcs_reference"; + String referencePrefix = sobolConsensus ? "pooled_sobol" : "pooled_mcs"; String title = sampleCount+" samples versus " - +(sobolConsensus ? "pooled Sobol consensus" : MCS_REFERENCE); + +(sobolConsensus ? POOLED_SOBOL_REFERENCE : MCS_REFERENCE); writePlot(outputDir, "method_comparison_"+sampleCount+"_"+referencePrefix+"_"+summaryPrefix(spatialSummary), title, "Sampling method", yLabel, - IntStream.range(0, labels.size()).toArray(), labels.toArray(String[]::new), matching); + IntStream.range(0, labels.size()).toArray(), labels.toArray(String[]::new), matching, spatialSummary); } private static void plotRealizationPairs(File outputDir, List rows, @@ -178,19 +188,19 @@ && includeSummary(row.spatialSummary(), spatialSummary)) { } } if (matching.stream().anyMatch(row -> row.count() == index)) - labels.add(method.getShortName()); + labels.add(getMethodName(method)); } if (matching.isEmpty()) return; writePlot(outputDir, "method_comparison_"+sampleCount+"_realization_pairs_"+summaryPrefix(spatialSummary), "Differences between "+sampleCount+"-sample realizations", "Sampling method", yLabel, - IntStream.range(0, labels.size()).toArray(), labels.toArray(String[]::new), matching); + IntStream.range(0, labels.size()).toArray(), labels.toArray(String[]::new), matching, spatialSummary); } private static void writePlot(File outputDir, String prefix, String title, String xLabel, String yLabel, - int[] counts, String[] countLabels, List rows) throws IOException { - ConvergenceSummary primary = prefix.endsWith("_max_abs") ? ConvergenceSummary.MAXIMUM_ABSOLUTE - : ConvergenceSummary.MEAN_ABSOLUTE; + int[] counts, String[] countLabels, List rows, + ConvergenceSummary primary) throws IOException { + boolean signed = primary == ConvergenceSummary.MEAN_SIGNED; Map> byMetric = new LinkedHashMap<>(); for (ConvergenceMetric metric : ConvergenceMetric.values()) { List metricRows = rows.stream().filter(row -> row.metric().equals(metric) @@ -205,6 +215,13 @@ private static void writePlot(File outputDir, String prefix, String title, Strin List maxChars = new ArrayList<>(); List medianFuncs = new ArrayList<>(); List medianChars = new ArrayList<>(); + if (signed) { + ArbitrarilyDiscretizedFunc zero = new ArbitrarilyDiscretizedFunc(); + zero.set(-0.3d, 0d); + zero.set(counts.length-0.7d, 0d); + funcs.add(zero); + chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 0.5f, Color.GRAY)); + } for (Map.Entry> entry : byMetric.entrySet()) { ArbitrarilyDiscretizedFunc median = new ArbitrarilyDiscretizedFunc(); ArbitrarilyDiscretizedFunc lower = new ArbitrarilyDiscretizedFunc(); @@ -218,10 +235,13 @@ private static void writePlot(File outputDir, String prefix, String title, Strin upper.set((double)i, row.maximum()); } Color color = METRIC_COLORS.get(entry.getKey()); - UncertainArbDiscFunc uncertainty = new UncertainArbDiscFunc(median, lower, upper); - funcs.add(uncertainty); - chars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, - new Color(color.getRed(), color.getGreen(), color.getBlue(), 70))); + // Signed ranges overlap heavily, so only show the realization envelope for mean hazard. + if (!signed || entry.getKey() == ConvergenceMetric.MEAN_HAZARD) { + UncertainArbDiscFunc uncertainty = new UncertainArbDiscFunc(median, lower, upper); + funcs.add(uncertainty); + chars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, + new Color(color.getRed(), color.getGreen(), color.getBlue(), 70))); + } median.setName(entry.getKey().shortLabel); medianFuncs.add(median); PlotSymbol sym = METRIC_SYMBOLS.get(entry.getKey()); @@ -240,6 +260,14 @@ private static void writePlot(File outputDir, String prefix, String title, Strin } } medianChars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 2f, sym, 5f, color)); + PlotSymbol outlineSym = PlotSymbol.getOutlineSymbol(sym); + if (outlineSym != null) { + // add slightly darker outline overlay + median = median.deepClone(); + median.setName(null); + medianFuncs.add(median); + medianChars.add(new PlotCurveCharacterstics(outlineSym, 5f, color.darker().darker())); + } } // Put every envelope in the dataset first so all median lines render above all shading. funcs.addAll(maxFuncs); @@ -259,9 +287,9 @@ private static void writePlot(File outputDir, String prefix, String title, Strin gp.getPlotPrefs().setLegendLineLength(6d); gp.getPlotPrefs().setTickLabelFontSize(8); // gp.getPlotPrefs().setPlotPadding(new RectangleInsets(5, 0, 0, 12)); -// Range xRange = counts.length == 1 ? new Range(-0.5, 0.5) : new Range(-0.2d, counts.length-0.8d); - Range xRange = counts.length == 1 ? new Range(-0.5, 0.5) : new Range(-0.3d, counts.length-0.7d); - gp.drawGraphPanel(plot, false, true, xRange, Y_RANGE); + Range xRange = counts.length == 1 ? new Range(-0.5, 0.5) : new Range(-0.2d, counts.length-0.8d); +// Range xRange = counts.length == 1 ? new Range(-0.5, 0.5) : new Range(-0.3d, counts.length-0.7d); + gp.drawGraphPanel(plot, false, !signed, xRange, signed ? SIGNED_Y_RANGE : Y_RANGE); PlotUtils.setXTick(gp, 1d); ((NumberAxis)gp.getXAxis()).setNumberFormatOverride(categoryFormat(countLabels)); PlotUtils.writePrintPlots(outputDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, @@ -294,6 +322,8 @@ private static List loadReferenceSummaries(File file) throws I int sampleCount = Integer.parseInt(csv.get(row, 4)); String reference = csv.get(row, 5); ConvergenceMetric metric = ConvergenceMetric.fromLabel(csv.get(row, 7)); + addValue(groups, new ReferenceGroup(method, sampleCount, reference, metric, + ConvergenceSummary.MEAN_SIGNED), Double.parseDouble(csv.get(row, 8))); addValue(groups, new ReferenceGroup(method, sampleCount, reference, metric, ConvergenceSummary.MEAN_ABSOLUTE), Double.parseDouble(csv.get(row, 9))); addValue(groups, new ReferenceGroup(method, sampleCount, reference, metric, @@ -338,7 +368,12 @@ private static void addValue(Map> groups, K key, double valu } private static String summaryPrefix(ConvergenceSummary summary) { - return summary == ConvergenceSummary.MEAN_ABSOLUTE ? "mean_abs" : "max_abs"; + return switch (summary) { + case MEAN_SIGNED -> "signed_bias"; + case MEAN_ABSOLUTE -> "mean_abs"; + case P95_ABSOLUTE -> "p95_abs"; + case MAXIMUM_ABSOLUTE -> "max_abs"; + }; } interface SummaryRow { diff --git a/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java b/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java index 6657d15b..469d91a7 100644 --- a/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java +++ b/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java @@ -21,10 +21,8 @@ import org.opensha.commons.data.sampling.optimization.PointSetHillClimber; import org.opensha.commons.data.sampling.optimization.PointSetOptimizationResult; import org.opensha.commons.data.sampling.optimization.QuantizedIncrementalPointSetScorer; -import org.opensha.commons.data.sampling.scoring.ExactPointSetScorer; -import org.opensha.commons.data.sampling.scoring.PointSetScore; -import org.opensha.commons.data.sampling.scoring.PointSetScorer; -import org.opensha.commons.data.sampling.scoring.QuantizedPointSetScorer; +import org.opensha.commons.data.sampling.scoring.ProjectionDiscrepancyScore; +import org.opensha.commons.data.sampling.scoring.ProjectionDiscrepancyScorer; import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; @@ -69,20 +67,20 @@ public static void main(String[] args) { System.out.println("]"); } - PointSetScorer exactScorer = new ExactPointSetScorer(16); + ProjectionDiscrepancyScorer exactScorer = ProjectionDiscrepancyScorer.exact(16); System.out.println("\nScoring continuous case to order "+numScoringDimensions); watch.reset().start(); - PointSetScore score = exactScorer.score(samples, numScoringDimensions); + ProjectionDiscrepancyScore score = exactScorer.score(samples, numScoringDimensions); watch.stop(); System.out.println("Done in "+timeStr(watch)); System.out.println("Continuous score:\t"+score); // System.exit(0); // System.out.println("\nRe-scoring continuous case using quantized scorer"); -// PointSetScorer quantizedScorer = new QuantizedPointSetScorer(100); +// ProjectionDiscrepancyScorer quantizedScorer = ProjectionDiscrepancyScorer.quantized(100); // watch.reset().start(); -// PointSetScore quantizedScore = quantizedScorer.score(samples, numScoringDimensions); +// ProjectionDiscrepancyScore quantizedScore = quantizedScorer.score(samples, numScoringDimensions); // watch.stop(); // System.out.println("Done in "+timeStr(watch)); // System.out.println("Continuous score:\t"+quantizedScore); @@ -91,7 +89,7 @@ public static void main(String[] args) { DimensionedPointSet dimensioned = new DimensionedPointSet(samples, dimensions); System.out.println("\nScoring dimensioned set"); watch.reset().start(); - PointSetScore dimensionedScore = exactScorer.score(dimensioned, numScoringDimensions); + ProjectionDiscrepancyScore dimensionedScore = exactScorer.score(dimensioned, numScoringDimensions); watch.stop(); System.out.println("Done in "+timeStr(watch)); System.out.println("Dimensioned score:\t"+dimensionedScore); @@ -107,7 +105,7 @@ public static void main(String[] args) { System.out.println("\nScoring optimized version"); watch.reset().start(); - PointSetScore optimizedScore = exactScorer.score(permuted, numScoringDimensions); + ProjectionDiscrepancyScore optimizedScore = exactScorer.score(permuted, numScoringDimensions); watch.stop(); System.out.println("Done in "+timeStr(watch)); System.out.println("Optimized score:\t"+optimizedScore); @@ -122,14 +120,14 @@ public static void main(String[] args) { // // System.out.println("\nRe-scoring ArrayPointSet view of optimized version"); // watch.reset().start(); -// PointSetScore materializedScore = scorer.score(materialized, numScoringDimensions); +// ProjectionDiscrepancyScore materializedScore = scorer.score(materialized, numScoringDimensions); // watch.stop(); // System.out.println("Done in "+timeStr(watch)); // System.out.println("Optimized score:\t"+materializedScore); // // System.out.println("\nRe-scoring the initial continuos case (JVM test)"); // watch.reset().start(); -// PointSetScore score2 = scorer.score(samples, numScoringDimensions); +// ProjectionDiscrepancyScore score2 = scorer.score(samples, numScoringDimensions); // watch.stop(); // System.out.println("Done in "+timeStr(watch)); // System.out.println("Continuous re-score:\t"+score2); @@ -204,4 +202,4 @@ private static String timeStr(Stopwatch watch) { return timeDF.format(hours)+" h"; } -} \ No newline at end of file +} diff --git a/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java index 190283ea..404fd57b 100644 --- a/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java +++ b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java @@ -33,10 +33,10 @@ import org.opensha.commons.data.sampling.ContinuousSamplingDimension; import org.opensha.commons.data.sampling.PointSet; import org.opensha.commons.data.sampling.SamplingDimension; -import org.opensha.commons.data.sampling.scoring.ExactPointSetScorer; -import org.opensha.commons.data.sampling.scoring.PointSetScore; -import org.opensha.commons.data.sampling.scoring.PointSetScorer; -import org.opensha.commons.data.sampling.scoring.ProjectionScore; +import org.opensha.commons.data.sampling.scoring.CenteredDiscrepancy; +import org.opensha.commons.data.sampling.scoring.ProjectionDiscrepancyScore; +import org.opensha.commons.data.sampling.scoring.ProjectionDiscrepancyScorer; +import org.opensha.commons.data.sampling.scoring.ProjectionDiscrepancyScore.ProjectionResult; import org.opensha.commons.data.uncertainty.UncertainArbDiscFunc; import org.opensha.commons.data.xyz.EvenlyDiscrXYZ_DataSet; import org.opensha.commons.gui.plot.HeadlessGraphPanel; @@ -128,22 +128,23 @@ public static void main(String[] args) throws IOException { int numAvgTrials = 100; // int numAvgTrials = 500; + boolean redoNormScores = false; + boolean redoCenteredDiscrepancies = false; boolean replotIndvSamples = false; - boolean replotCombOnly = true; -// String treeName = null; -// List samplingDimensions = new ArrayList<>(); -// for (int i=0; i<10; i++) -// samplingDimensions.add(ContinuousSamplingDimension.INSTANCE); -// String samplingPrefix = "continuous_"+samplingDimensions.size()+"d"; + String treeName = null; + List samplingDimensions = new ArrayList<>(); + for (int i=0; i<10; i++) + samplingDimensions.add(ContinuousSamplingDimension.INSTANCE); + String samplingPrefix = "continuous_"+samplingDimensions.size()+"d"; // String treeName = "NSHM23-WUS"; // List samplingDimensions = getDimsNSHM23(); // String samplingPrefix = "nshm23_"+samplingDimensions.size()+"d"; - String treeName = "NSHM27-AmSam"; - List samplingDimensions = getDimsNSHM27_AmSam(); - String samplingPrefix = "nshm27_amsam_"+samplingDimensions.size()+"d"; +// String treeName = "NSHM27-AmSam"; +// List samplingDimensions = getDimsNSHM27_AmSam(); +// String samplingPrefix = "nshm27_amsam_"+samplingDimensions.size()+"d"; final int dimensions = samplingDimensions.size(); int numContinuous = 0; @@ -172,9 +173,15 @@ else if (dimensions == numCategorical) File outputDir = new File(mainDir, samplingPrefix); Preconditions.checkState(outputDir.exists() || outputDir.mkdir()); - ExactPointSetScorer serialScorer = new ExactPointSetScorer(1); -// ExactPointSetScorer serialScorer = new ExactPointSetScorer(4); - ExactPointSetScorer parallelScorer = new ExactPointSetScorer(16); + File scoresCSVFile = new File(outputDir, "combined_scores.csv"); + File centeredDiscrepancyCSVFile = new File(outputDir, "combined_centered_discrepancies.csv"); + + redoNormScores |= !scoresCSVFile.exists(); + redoCenteredDiscrepancies |= !centeredDiscrepancyCSVFile.exists(); + + ProjectionDiscrepancyScorer serialScorer = ProjectionDiscrepancyScorer.exact(1); +// ProjectionDiscrepancyScorer serialScorer = ProjectionDiscrepancyScorer.exact(4); + ProjectionDiscrepancyScorer parallelScorer = ProjectionDiscrepancyScorer.exact(16); Color[] orderColors = new Color[scoreOrders]; Color[] oderLightColors = new Color[scoreOrders]; @@ -202,12 +209,17 @@ else if (dimensions == numCategorical) Range dimXRange = new Range(1d, dimensions); Range logYRange = new Range(1e-4, 2e0); Range equivYRange = new Range(1e2, sampleCounts[sampleCounts.length-1] > 3000 ? 1e8 : 1e7); + Range centeredYRange = new Range(1e-6, 1e-1); - List>> methodScores = new ArrayList<>(); - for (int m=0; m>> methodScores = new ArrayList<>(); + List>> methodCenteredDiscrepancyScores = new ArrayList<>(); + for (int m=0; m()); + methodCenteredDiscrepancyScores.add(new ArrayList<>()); + } + - if (replotCombOnly) { + if (!redoNormScores && !redoCenteredDiscrepancies) { System.out.println("Replotting combined results only"); } else { Stopwatch totalWatch = Stopwatch.createStarted(); @@ -236,186 +248,207 @@ else if (dimensions == numCategorical) sampleFutures.add(CompletableFuture.supplyAsync(()->method.prepare(sampleCount, samplingDimensions, seed))); } - // if we only have 1 trial, do that one in parallel - // if we have many, rely on across-trial parallelism instead - PointSetScorer scorer = myTrials == 1 ? parallelScorer : serialScorer; + List samples = new ArrayList<>(myTrials); - List> scoreFutures = new ArrayList<>(); - while (!sampleFutures.isEmpty()) { - CompletableFuture sampleFuture = sampleFutures.removeFirst(); - PointSet sample = sampleFuture.join(); - if (firstPointSets[m] == null) - firstPointSets[m] = sample; - scoreFutures.add(CompletableFuture.supplyAsync(()->scorer.score(sample, scoreOrders))); - } - - List scores = scoreFutures.stream().map(F->F.join()).toList(); - - methodScores.get(m).add(scores); - - if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL) { - // rebuild it to remove the row scrambling - firstPointSets[m] = method.createGenerator(baseRand.nextLong()).generate(sampleCount, dimensions); - } + while (!sampleFutures.isEmpty()) + samples.add(sampleFutures.removeFirst().join()); - List funcs = new ArrayList<>(); - List chars = new ArrayList<>(); + if (redoNormScores) { + // if we only have 1 trial, do that one in parallel + // if we have many, rely on across-trial parallelism instead + ProjectionDiscrepancyScorer scorer = myTrials == 1 ? parallelScorer : serialScorer; + + List> scoreFutures = new ArrayList<>(); + for (PointSet sample : samples) { + if (firstPointSets[m] == null) + firstPointSets[m] = sample; + scoreFutures.add(CompletableFuture.supplyAsync(()->scorer.score(sample, scoreOrders))); + } + + List scores = scoreFutures.stream().map(F->F.join()).toList(); + + methodScores.get(m).add(scores); + + if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL) { + // rebuild it to remove the row scrambling + firstPointSets[m] = method.createGenerator(baseRand.nextLong()).generate(sampleCount, dimensions); + } + + List funcs = new ArrayList<>(); + List chars = new ArrayList<>(); - double[][][] scores2D = new double[dimensions][dimensions][myTrials]; - for (int i=0; i shadedFuncs = new ArrayList<>(); - List shadedChars = new ArrayList<>(); - - for (int order=1; order<=scoreOrders; order++) { - double overallAverage = 0d; - double[][] dimScores = new double[dimensions][scores.size()]; - double[] dimAverages = new double[dimensions]; + double[][][] scores2D = new double[dimensions][dimensions][myTrials]; + for (int i=0; i shadedFuncs = new ArrayList<>(); + List shadedChars = new ArrayList<>(); + + for (int order=1; order<=scoreOrders; order++) { + double overallAverage = 0d; + double[][] dimScores = new double[dimensions][scores.size()]; + double[] dimAverages = new double[dimensions]; + + for (int s=0; s= 1); + dimScores[d][s] /= dimCounts[d]; + dimAverages[d] += dimScores[d][s]; + } + if (s < numPlotTrials) { + // plot it + EvenlyDiscretizedFunc dimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + for (int d=0; d= 1); - dimScores[d][s] /= dimCounts[d]; - dimAverages[d] += dimScores[d][s]; - } - if (s < numPlotTrials) { - // plot it - EvenlyDiscretizedFunc dimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); - for (int d=0; d 1) { + EvenlyDiscretizedFunc upperDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + EvenlyDiscretizedFunc middleDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + EvenlyDiscretizedFunc lowerDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); + for (int d=0; d 1) { - EvenlyDiscretizedFunc upperDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); - EvenlyDiscretizedFunc middleDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); - EvenlyDiscretizedFunc lowerDimFunc = new EvenlyDiscretizedFunc(1d, dimensions, 1d); - for (int d=0; d 20 ? 2d : 1d; + + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + + gp.setRenderingOrder(DatasetRenderingOrder.REVERSE); + + gp.drawGraphPanel(plot, false, true, dimXRange, logYRange); + PlotUtils.setXTick(gp, xTick); + + if (replotIndvSamples || !new File(subDir, "scores_"+prefix+".png").exists()) + PlotUtils.writePrintPlots(subDir, "scores_"+prefix, gp, + PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 3d, 300, true, true, false); + + EvenlyDiscrXYZ_DataSet avgXYZ = new EvenlyDiscrXYZ_DataSet(dimensions, dimensions, 1d, 1d, 1d); + EvenlyDiscrXYZ_DataSet avgAbsXYZ = new EvenlyDiscrXYZ_DataSet(dimensions, dimensions, 1d, 1d, 1d); + CPT logRatioCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-1d, 1d); + logRatioCPT.setLog10(true); + CPT logAbsCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-1d, 1d).trim(0d, 1d); +// CPT logAbsCPT = logRatioCPT.trim(0d, 1d); + logAbsCPT.setLog10(true); + for (int i=0; i 20 ? 2d : 1d; - - HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); - - gp.setRenderingOrder(DatasetRenderingOrder.REVERSE); - - gp.drawGraphPanel(plot, false, true, dimXRange, logYRange); - PlotUtils.setXTick(gp, xTick); - - if (replotIndvSamples || !new File(subDir, "scores_"+prefix+".png").exists()) - PlotUtils.writePrintPlots(subDir, "scores_"+prefix, gp, - PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 3d, 300, true, true, false); - - EvenlyDiscrXYZ_DataSet avgXYZ = new EvenlyDiscrXYZ_DataSet(dimensions, dimensions, 1d, 1d, 1d); - EvenlyDiscrXYZ_DataSet avgAbsXYZ = new EvenlyDiscrXYZ_DataSet(dimensions, dimensions, 1d, 1d, 1d); - CPT logRatioCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-1d, 1d); - logRatioCPT.setLog10(true); - CPT logAbsCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-1d, 1d).trim(0d, 1d); -// CPT logAbsCPT = logRatioCPT.trim(0d, 1d); - logAbsCPT.setLog10(true); - for (int i=0; i> scoreFutures = new ArrayList<>(); + for (PointSet sample : samples) { + scoreFutures.add(CompletableFuture.supplyAsync(()->{ + double score = CenteredDiscrepancy.score(sample); +// System.out.println("Score: "+(float)score); + return score; + })); } + + List scores = scoreFutures.stream().map(F->F.join()).toList(); + + methodCenteredDiscrepancyScores.get(m).add(scores); } - XYZPlotSpec xyzPlot = new XYZPlotSpec(avgXYZ, logRatioCPT, plot.getTitle(), - "Dimension #", "Dimension #", "Average pair score / overall 2D score"); - - Range xyzRange = new Range(0.5, dimensions+0.5); - gp.drawGraphPanel(xyzPlot, false, false, xyzRange, xyzRange); - - if (replotIndvSamples || !new File(subDir, "scores_2D_"+prefix+".png").exists()) - PlotUtils.writePrintPlots(subDir, "scores_2D_"+prefix, gp, - PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, false, 300, true, true, false); - - xyzPlot = new XYZPlotSpec(avgAbsXYZ, logAbsCPT, plot.getTitle(), - "Dimension #", "Dimension #", "Average realization pair score factor"); - - gp.drawGraphPanel(xyzPlot, false, false, xyzRange, xyzRange); - - if (replotIndvSamples || !new File(subDir, "scores_2D_"+prefix+"_deviation.png").exists()) - PlotUtils.writePrintPlots(subDir, "scores_2D_"+prefix+"_deviation", gp, - PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, false, 300, true, true, false); methodWatch.stop(); System.out.println("\tDONE in "+timeStr(methodWatch)); } - if (sampleCount <= 1024) { + if (sampleCount <= 1024 && redoNormScores) { // now plot 2D scatters int[][] plotDims = { {0, 1}, @@ -477,14 +510,16 @@ else if (dimensions == numCategorical) // now combined plots String prefix = "combined_scores"; - File scoresCSVFile = new File(outputDir, prefix+".csv"); List scoreFuncs = new ArrayList<>(); List scoreChars = new ArrayList<>(); List equivCountFuncs = new ArrayList<>(); List equivCountChars = new ArrayList<>(); - CSVFile scoresCSV = replotCombOnly ? CSVFile.readFile(scoresCSVFile, true) : new CSVFile<>(true); - if (!replotCombOnly) { + List centeredFuncs = new ArrayList<>(); + List centeredChars = new ArrayList<>(); + CSVFile scoresCSV = redoNormScores ? new CSVFile<>(true) : CSVFile.readFile(scoresCSVFile, true); + CSVFile centeredScoresCSV = redoCenteredDiscrepancies ? new CSVFile<>(true) : CSVFile.readFile(centeredDiscrepancyCSVFile, true); + if (redoNormScores) { List header = new ArrayList<>(); header.add(""); for (int order=1; order<=scoreOrders; order++) @@ -492,15 +527,24 @@ else if (dimensions == numCategorical) header.add(order+"D "+sampleCounts[s]); scoresCSV.addLine(header); } + if (redoCenteredDiscrepancies) { + List header = new ArrayList<>(); + header.add(""); + for (int s=0; s scoreLine = new ArrayList<>(); scoreLine.add(method.getShortName()); + List centeredLine = new ArrayList<>(); + centeredLine.add(method.getShortName()); int colIndex = 1; @@ -514,20 +558,20 @@ else if (dimensions == numCategorical) int sampleCount = sampleCounts[s]; double avg; - if (replotCombOnly) { - avg = scoresCSV.getDouble(rowIndex, colIndex++); - } else { - List scores = methodScores.get(m).get(s); + if (redoNormScores) { + List scores = methodScores.get(m).get(s); double sum = 0d; // double min = Double.POSITIVE_INFINITY; // double max = 0d; - for (PointSetScore score : scores) { + for (ProjectionDiscrepancyScore score : scores) { double orderScore = score.getOrderMeanScore(order); sum += orderScore; // min = Math.min(min, orderScore); // max = Math.max(max, orderScore); } avg = sum / scores.size(); + } else { + avg = scoresCSV.getDouble(rowIndex, colIndex++); } scoreLine.add((float)avg+""); @@ -558,10 +602,27 @@ else if (dimensions == numCategorical) equivCountFuncs.add(equivFunc); equivCountChars.add(getForThickness(methodChar, thickness)); } - if (replotCombOnly) - rowIndex++; - else + + EvenlyDiscretizedFunc centeredFunc = new EvenlyDiscretizedFunc(0d, sampleCounts.length, 1d); + centeredFunc.setName(method.getShortName()); + for (int s=0; sd).average().getAsDouble(); + centeredLine.add((float)centered+""); + } else { + centered = centeredScoresCSV.getDouble(rowIndex, s+1); + } + centeredFunc.set(s, centered); + } + centeredFuncs.add(centeredFunc); + centeredChars.add(getForThickness(methodChar, 3f)); + + rowIndex++; + if (redoNormScores) scoresCSV.addLine(scoreLine); + if (redoCenteredDiscrepancies) + centeredScoresCSV.addLine(centeredLine); } List orderTicknessFuncs = new ArrayList<>(); List orderThicknessChars = new ArrayList<>(); @@ -618,7 +679,7 @@ public Number parse(String source, ParsePosition pos) { } }; - PlotSpec plot = new PlotSpec(scoreFuncs, scoreChars, treeName, "Sample count", "Normalized score"); + PlotSpec plot = new PlotSpec(scoreFuncs, scoreChars, treeName, "Sample count", "Normalized projection score"); // plot.setLegendInset(true); plot.setLegendVisible(true); @@ -632,7 +693,7 @@ public Number parse(String source, ParsePosition pos) { ((NumberAxis)gp.getXAxis()).setNumberFormatOverride(categoryFormat); PlotUtils.writePrintPlots(outputDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 4, 300, true, true, false); - if (!replotCombOnly) + if (redoNormScores) scoresCSV.writeToFile(scoresCSVFile); plot = new PlotSpec(equivCountFuncs, equivCountChars, treeName, "Sample count", "Equivalent MCS count"); @@ -648,6 +709,21 @@ public Number parse(String source, ParsePosition pos) { prefix = "combined_equivs"; PlotUtils.writePrintPlots(outputDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 4, 300, true, true, false); + + // now centered + plot = new PlotSpec(centeredFuncs, centeredChars, treeName, "Sample count", "Squared centered discrepancy"); +// plot.setLegendInset(true); + plot.setLegendVisible(true); + + gp.drawGraphPanel(plot, false, true, categoricalXRange, centeredYRange); + PlotUtils.setXTick(gp, 1); + ((NumberAxis)gp.getXAxis()).setNumberFormatOverride(categoryFormat); + + prefix = "combined_centered_discrepancies"; + PlotUtils.writePrintPlots(outputDir, prefix, gp, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 4, 300, true, true, false); + + if (redoCenteredDiscrepancies) + centeredScoresCSV.writeToFile(centeredDiscrepancyCSVFile); } private static PlotCurveCharacterstics getForThickness(PlotCurveCharacterstics pChar, double thickness) { From 0cb9352aa6bfe5a668c15e6718a77eb5d2239e03 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Wed, 9 Sep 2026 10:37:34 -0700 Subject: [PATCH 63/71] optimization cleanup/generalization --- .../kevin/ltSampling/LHSExampleFigures.java | 15 +++++++++------ .../kevin/sampling/InitialSamplingTests.java | 9 ++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java index 6b02385a..ea98544e 100644 --- a/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java +++ b/src/main/java/scratch/kevin/ltSampling/LHSExampleFigures.java @@ -28,7 +28,9 @@ import org.opensha.commons.data.sampling.PermutedPointSet; import org.opensha.commons.data.sampling.PointSet; import org.opensha.commons.data.sampling.optimization.PointSetHillClimber; -import org.opensha.commons.data.sampling.optimization.QuantizedIncrementalPointSetScorer; +import org.opensha.commons.data.sampling.optimization.PointSetObjective; +import org.opensha.commons.data.sampling.optimization.PointSetObjective.SwapSession; +import org.opensha.commons.data.sampling.scoring.ProjectionDiscrepancyScorer; import org.opensha.commons.gui.plot.HeadlessGraphPanel; import org.opensha.commons.gui.plot.PlotCurveCharacterstics; import org.opensha.commons.gui.plot.PlotLineType; @@ -365,12 +367,13 @@ public static void main(String[] args) throws IOException { PermutedPointSet permuted = PermutedPointSet.independentDimensions(pointSet); long iterations = Integer.max(100000, samples*100); - QuantizedIncrementalPointSetScorer scorer = - new QuantizedIncrementalPointSetScorer(permuted, SamplingMethod.PAIRWISE_CONTINUOUS_BINS); + PointSetObjective objective = ProjectionDiscrepancyScorer + .quantized(SamplingMethod.PAIRWISE_CONTINUOUS_BINS).objective(); + SwapSession session = objective.prepare(permuted); System.out.println("Pairwise-optimizing sample of size "+pointSet.size()+" with "+iterations+" iterations"); - System.out.println("\tInitial 2D score:\t"+(float)scorer.getCurrentScore().getOrderMeanScore(2)); - PointSetHillClimber.optimize(scorer, iterations, new Random(new Random(seed).nextLong())); - System.out.println("\tDONE; final 2D score:\t"+(float)scorer.getCurrentScore().getOrderMeanScore(2)); + System.out.println("\tInitial objective:\t"+(float)session.getCurrentValue()); + PointSetHillClimber.optimize(session, iterations, new Random(new Random(seed).nextLong())); + System.out.println("\tDONE; final objective:\t"+(float)session.getCurrentValue()); // permuted.get(dpi, colorI) diff --git a/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java b/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java index 469d91a7..9e5ca1e7 100644 --- a/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java +++ b/src/main/java/scratch/kevin/sampling/InitialSamplingTests.java @@ -17,10 +17,9 @@ import org.opensha.commons.data.sampling.PointSet; import org.opensha.commons.data.sampling.SamplingDimension; import org.opensha.commons.data.sampling.generator.*; -import org.opensha.commons.data.sampling.optimization.IncrementalPointSetScorer; import org.opensha.commons.data.sampling.optimization.PointSetHillClimber; -import org.opensha.commons.data.sampling.optimization.PointSetOptimizationResult; -import org.opensha.commons.data.sampling.optimization.QuantizedIncrementalPointSetScorer; +import org.opensha.commons.data.sampling.optimization.PointSetHillClimber.Result; +import org.opensha.commons.data.sampling.optimization.PointSetObjective; import org.opensha.commons.data.sampling.scoring.ProjectionDiscrepancyScore; import org.opensha.commons.data.sampling.scoring.ProjectionDiscrepancyScorer; @@ -97,8 +96,8 @@ public static void main(String[] args) { System.out.println("\nImproving pairwise with "+numIterations+" hill-climbing iterations"); watch.reset().start(); PermutedPointSet permuted = PermutedPointSet.independentDimensions(dimensioned); - IncrementalPointSetScorer incrementalScorer = new QuantizedIncrementalPointSetScorer(permuted, 100); - PointSetOptimizationResult result = PointSetHillClimber.optimize(incrementalScorer, numIterations, r); + PointSetObjective objective = ProjectionDiscrepancyScorer.quantized(100).objective(); + Result result = PointSetHillClimber.optimize(permuted, objective, numIterations, r); watch.stop(); System.out.println("Done in "+timeStr(watch)); System.out.println("Optimization result:\t"+result); From 8366305d7473444839caf7d8534639b44fe1dbc0 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Thu, 10 Sep 2026 16:10:27 -0700 Subject: [PATCH 64/71] better plots and now with maps --- .../sampling/HazardConvergenceCalcs.java | 201 +++++--- .../sampling/HazardConvergencePlots.java | 141 ++++-- .../kevin/sampling/HazardMapPlots.java | 466 ++++++++++++++++++ .../kevin/sampling/SamplingScoreFigures.java | 31 +- .../sampling/HazardConvergenceCalcsTest.java | 12 +- .../sampling/HazardConvergencePlotsTest.java | 11 +- 6 files changed, 742 insertions(+), 120 deletions(-) create mode 100644 src/main/java/scratch/kevin/sampling/HazardMapPlots.java diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java index e015357c..332491a2 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java @@ -51,15 +51,12 @@ public class HazardConvergenceCalcs { static final String POOLED_SOBOL_REFERENCE_NAME = "Pooled Sobol"; static final String LOO_SOBOL_REFERENCE_NAME = "Pooled Sobol, leave one out"; private static final int MAX_RUN_LOAD_THREADS = 4; + /** Set to {@code null} to build the Sobol consensus from every available run size. */ + static final Integer FIXED_SOBOL_CONSENSUS_SIZE = 8192; - public static void main(String[] args) throws IOException { - File outputDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence"); - Preconditions.checkState(outputDir.exists() || outputDir.mkdir(), - "Couldn't create output directory: %s", outputDir.getAbsolutePath()); - - ReturnPeriods rp = ReturnPeriods.TWO_IN_50; - - Table> runDirs = HashBasedTable.create(); + static final Table> runDirs; + static { + runDirs = HashBasedTable.create(); /* * MCS runs @@ -103,9 +100,9 @@ public static void main(String[] args) throws IOException { */ runDirs.put(SamplingMethod.LATIN_HYPERCUBE, 4096, List.of( new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs"), - new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed") -// new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-2"), -// new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-3") + new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed"), + new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-2"), + new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-3") )); /* @@ -117,6 +114,14 @@ public static void main(String[] args) throws IOException { new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-2"), new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-3") )); + } + + public static void main(String[] args) throws IOException { + File outputDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence"); + Preconditions.checkState(outputDir.exists() || outputDir.mkdir(), + "Couldn't create output directory: %s", outputDir.getAbsolutePath()); + + ReturnPeriods rp = ReturnPeriods.TWO_IN_50; List sobolRuns = loadRunSpecs(SamplingMethod.OWEN_SCRAMBLED_SOBOL, runDirs.row(SamplingMethod.OWEN_SCRAMBLED_SOBOL)); @@ -184,15 +189,31 @@ private static void runSamplingConvergence(List sobolRuns, List data.checkpoints().keySet().stream()) .mapToInt(Integer::intValue).distinct().sorted().toArray(); List mcsData = loadRunPeriodData(mcsRuns, gridReg, period, rp, sampleCounts); + List sobolConsensusData; + if (FIXED_SOBOL_CONSENSUS_SIZE == null) { + sobolConsensusData = sobolData; + System.out.println("Building Sobol consensus from all "+sobolData.size()+" runs"); + } else { + sobolConsensusData = sobolData.stream() + .filter(data -> data.run().maxSamples() == FIXED_SOBOL_CONSENSUS_SIZE) + .toList(); + Preconditions.checkState(!sobolConsensusData.isEmpty(), + "No %s-sample Sobol runs available for the fixed-size consensus", + FIXED_SOBOL_CONSENSUS_SIZE); + System.out.println("Building Sobol consensus from "+sobolConsensusData.size()+" independent " + +FIXED_SOBOL_CONSENSUS_SIZE+"-sample runs"); + } PooledHazardData pooledMCSData = buildPooledHazardData(mcsData, null, gridReg, rp, MCS_REFERENCE_NAME, MCS_REFERENCE_NAME); ReferenceStatistics mcsReference = pooledMCSData.reference(); Map leaveOneOut = new LinkedHashMap<>(); - for (RunPeriodData data : sobolData) - leaveOneOut.put(data.run(), buildPooledHazardData(sobolData, data.run(), gridReg, rp, + for (RunPeriodData data : sobolData) { + RunSpec excluded = sobolConsensusData.contains(data) ? data.run() : null; + leaveOneOut.put(data.run(), buildPooledHazardData(sobolConsensusData, excluded, gridReg, rp, POOLED_SOBOL_REFERENCE_NAME, LOO_SOBOL_REFERENCE_NAME).reference()); - PooledHazardData pooledSobolData = buildPooledHazardData(sobolData, null, gridReg, rp, + } + PooledHazardData pooledSobolData = buildPooledHazardData(sobolConsensusData, null, gridReg, rp, POOLED_SOBOL_REFERENCE_NAME, LOO_SOBOL_REFERENCE_NAME); ReferenceStatistics pooledSobol = pooledSobolData.reference(); @@ -255,15 +276,22 @@ private static List loadRunPeriodData(List runs, GriddedRegion gridReg, double period, ReturnPeriods rp, int... spanCounts) throws IOException { if (runs.isEmpty()) return List.of(); + int[] globalOffsets = new int[runs.size()]; + for (int i=1; i> futures = new ArrayList<>(runs.size()); - for (RunSpec run : runs) - futures.add(executor.submit(() -> loadRunPeriodData(run, gridReg, period, rp, spanCounts))); + for (int i=0; i loadRunPeriodData( + run, gridReg, period, rp, spanCounts, globalOffset))); + } List data = new ArrayList<>(runs.size()); // Retrieve in input order so downstream CSV and plot ordering remains stable. for (Future future : futures) { @@ -290,7 +318,7 @@ private static List loadRunPeriodData(List runs, } private static RunPeriodData loadRunPeriodData(RunSpec run, GriddedRegion gridReg, - double period, ReturnPeriods rp, int[] spanCounts) throws IOException { + double period, ReturnPeriods rp, int[] spanCounts, int globalOffset) throws IOException { System.out.println("\nLoading "+run.method().getShortName()+" run: "+run.id()); ModelHazardMaps maps = loadMaps(new File(run.directory(), "results_hazard.zip"), run.tree(), gridReg, period, rp); @@ -322,7 +350,7 @@ private static RunPeriodData loadRunPeriodData(RunSpec run, GriddedRegion gridRe boolean fullRun = count == run.maxSamples(); boolean sobolCheckpoint = run.method() == SamplingMethod.OWEN_SCRAMBLED_SOBOL && count >= 512 && Integer.bitCount(count) == 1; - if (Arrays.stream(spanCounts).anyMatch(size -> count % size == 0)) + if (Arrays.stream(spanCounts).anyMatch(size -> (globalOffset+count) % size == 0)) curveBoundaries.put(count, Arrays.stream(curveSums).map(double[]::clone).toArray(double[][]::new)); if (fullRun || sobolCheckpoint) { double[] curveMean = buildCurveMeanMap(curveSums, curveX, count, rp); @@ -403,7 +431,7 @@ private static void writePooledHazardFiles(File outputDir, PooledHazardData pool +outputDir.getAbsolutePath()); } - /** Uses disjoint full spans within each run; leftover branches still contribute to every reference. */ + /** Uses disjoint spans across the concatenated MCS pool; leftover branches still contribute to every reference. */ static List appendMCSSpanComparisons(List comparisons, List runs, int[] sampleCounts, ReferenceStatistics sobolReference, GriddedRegion gridReg, ReturnPeriods rp) { @@ -418,45 +446,72 @@ static List appendMCSSpanComparisons(List comp for (int i=0; i 1, "Too few MCS reference samples after exclusion"); - double[][] spanCurves = new double[totalCurves.length][curveX.length]; - double[][] remainingCurves = new double[totalCurves.length][curveX.length]; - double[][] before = start == 0 ? null : data.curveBoundaries().get(start); - double[][] after = data.curveBoundaries().get(end); - for (int n=0; n 1, "Too few MCS reference samples after exclusion"); + double[][] after = pooledCurvePrefix(runs, end, curveX.length); + double[][] spanCurves = new double[totalCurves.length][curveX.length]; + double[][] remainingCurves = new double[totalCurves.length][curveX.length]; + for (int n=0; n runs, int sampleCount, int curveSize) { + Preconditions.checkArgument(sampleCount > 0); + double[][] prefix = new double[runs.get(0).curveSums().length][curveSize]; + int remaining = sampleCount; + for (RunPeriodData data : runs) { + int runSamples = data.branchMaps().length; + double[][] addition; + if (remaining >= runSamples) { + addition = data.curveSums(); + remaining -= runSamples; + } else { + addition = Preconditions.checkNotNull(data.curveBoundaries().get(remaining), + "Missing pooled MCS curve boundary at local index %s", remaining); + remaining = 0; + } + for (int n=0; n= 0 && start < end && end <= rows.length); double[][] remaining = new double[rows.length-(end-start)][]; @@ -601,7 +656,8 @@ private static void writeReferenceComparisonSummary(File file, List csv = new CSVFile<>(true); csv.addLine("Sampling method", "Sample count", "Reference", "Metric", "Spatial summary", "Realizations", - "Mean", "Minimum", "P2.5", "P16", "P50", "P84", "P97.5", "Maximum"); + "Mean", "Standard deviation", "Log standard deviation", "Minimum", "P2.5", "P16", "P50", "P84", + "P97.5", "Maximum"); for (Map.Entry> entry : groups.entrySet()) { ReferenceComparisonGroup group = entry.getKey(); for (ConvergenceSummary summary : ConvergenceSummary.values()) { @@ -647,7 +703,8 @@ private static void writeDoublingComparisonSummary(File file, List csv = new CSVFile<>(true); csv.addLine("Sampling method", "Lower sample count", "Upper sample count", "Metric", "Spatial summary", "Realizations", - "Mean", "Minimum", "P2.5", "P16", "P50", "P84", "P97.5", "Maximum"); + "Mean", "Standard deviation", "Log standard deviation", "Minimum", "P2.5", "P16", "P50", "P84", + "P97.5", "Maximum"); for (Map.Entry> entry : groups.entrySet()) { DoublingComparisonGroup group = entry.getKey(); for (ConvergenceSummary summary : ConvergenceSummary.values()) { @@ -717,7 +774,8 @@ private static void writeRealizationPairComparisonSummary(File file, } CSVFile csv = new CSVFile<>(true); csv.addLine("Sampling method", "Sample count", "Metric", "Spatial summary", "Realization pairs", - "Mean", "Minimum", "P2.5", "P16", "P50", "P84", "P97.5", "Maximum"); + "Mean", "Standard deviation", "Log standard deviation", "Minimum", "P2.5", "P16", "P50", "P84", + "P97.5", "Maximum"); for (Map.Entry> entry : groups.entrySet()) { RealizationPairComparisonGroup group = entry.getKey(); for (ConvergenceSummary summary : ConvergenceSummary.values()) { @@ -734,6 +792,8 @@ private static void writeRealizationPairComparisonSummary(File file, private static void addSummaryLine(CSVFile csv, List prefix, double[] values) { List line = new ArrayList<>(prefix); line.add(StatUtils.mean(values)+""); + line.add(standardDeviation(values)+""); + line.add(logStandardDeviation(values)+""); line.add(StatUtils.min(values)+""); line.add(percentile(values, 2.5)+""); line.add(percentile(values, 16d)+""); @@ -764,8 +824,8 @@ static void runBootstrapTests(ModelHazardMaps reference, int[] sampleCounts, int replicateCSV.addLine("Sample count", "Replicate", "Metric", "Spatial mean % change", "Spatial mean absolute % change", "Minimum % change", "Maximum % change"); CSVFile summaryCSV = new CSVFile<>(true); - summaryCSV.addLine("Sample count", "Metric", "Spatial summary", "Mean", "Minimum", "P2.5", "P16", "P50", - "P84", "P97.5", "Maximum"); + summaryCSV.addLine("Sample count", "Metric", "Spatial summary", "Mean", "Standard deviation", + "Log standard deviation", "Minimum", "P2.5", "P16", "P50", "P84", "P97.5", "Maximum"); CSVFile siteCSV = new CSVFile<>(true); siteCSV.addLine("Sample count", "Metric", "Longitude", "Latitude", "Reference value", "Mean % change", "Std. dev. % change", "P2.5", "P16", "P50", "P84", "P97.5"); @@ -839,7 +899,9 @@ private static void appendReplicateCSVs(CSVFile replicateCSV, CSVFile csv, int sampleCount, String metric, String quantity, double[] values) { - csv.addLine(sampleCount+"", metric, quantity, StatUtils.mean(values)+"", StatUtils.min(values)+"", + csv.addLine(sampleCount+"", metric, quantity, StatUtils.mean(values)+"", standardDeviation(values)+"", + logStandardDeviation(values)+"", + StatUtils.min(values)+"", percentile(values, 2.5)+"", percentile(values, 16d)+"", percentile(values, 50d)+"", percentile(values, 84d)+"", percentile(values, 97.5)+"", StatUtils.max(values)+""); @@ -855,6 +917,23 @@ private static double percentile(double[] values, double percentile) { return StatUtils.percentile(values, percentile); } + static double standardDeviation(double[] values) { + return values.length < 2 ? Double.NaN : Math.sqrt(StatUtils.variance(values)); + } + + /** Sample standard deviation after a natural-log transform; undefined for nonpositive values or one observation. */ + static double logStandardDeviation(double[] values) { + if (values.length < 2) + return Double.NaN; + double[] logs = new double[values.length]; + for (int i=0; i 0d) || !Double.isFinite(values[i])) + return Double.NaN; + logs[i] = Math.log(values[i]); + } + return Math.sqrt(StatUtils.variance(logs)); + } + private static int[] bootstrapCounts(int numBranches, int sampleCount, long seed) { int[] counts = new int[numBranches]; SplittableRandom random = new SplittableRandom(seed); @@ -863,7 +942,7 @@ private static int[] bootstrapCounts(int numBranches, int sampleCount, long seed return counts; } - private static double[][] copyValues(GriddedGeoDataSet[] maps) { + static double[][] copyValues(GriddedGeoDataSet[] maps) { double[][] values = new double[maps.length][]; for (int i=0; i tree, GriddedRegion gridReg, + static ModelHazardMaps loadMaps(File hazardZip, LogicTree tree, GriddedRegion gridReg, double period, ReturnPeriods rp) throws ZipException, IOException { System.out.println("Loading maps from "+hazardZip.getAbsolutePath()); try (ZipFile zip = new ZipFile(hazardZip)) { @@ -1004,7 +1083,7 @@ private static ModelHazardMaps loadMaps(File hazardZip, LogicTree tree, Gridd } } - private static DiscretizedFunc[] loadBranchCurves(File hazardResultsDir, LogicTreeBranch branch, + static DiscretizedFunc[] loadBranchCurves(File hazardResultsDir, LogicTreeBranch branch, GriddedRegion gridReg, double period) throws IOException { File runDir = branch.getBranchDirectory(hazardResultsDir, false); File hazardDir = new File(runDir, "hazard_"+(float)gridReg.getSpacing()+"deg_grid_seis_INCLUDE"); diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java index 40e9292b..dceaa76b 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java @@ -8,6 +8,7 @@ import java.text.ParsePosition; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -21,6 +22,7 @@ import org.jfree.data.Range; import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; +import org.opensha.commons.data.function.DefaultXY_DataSet; import org.opensha.commons.data.function.XY_DataSet; import org.opensha.commons.data.uncertainty.UncertainArbDiscFunc; import org.opensha.commons.gui.plot.HeadlessGraphPanel; @@ -38,7 +40,7 @@ /** Builds paper-oriented plots from the compact convergence summary CSV files. */ public class HazardConvergencePlots { - private static final Range Y_RANGE = new Range(1e-2, 2e1); + private static final Range Y_RANGE = new Range(5e-3, 2e1); private static final Range SIGNED_Y_RANGE = new Range(-1d, 1d); private static final String SOBOL_REFERENCE = HazardConvergenceCalcs.LOO_SOBOL_REFERENCE_NAME; private static final String POOLED_SOBOL_REFERENCE = HazardConvergenceCalcs.POOLED_SOBOL_REFERENCE_NAME; @@ -47,26 +49,34 @@ public class HazardConvergencePlots { private static final SamplingMethod SOBOL = SamplingMethod.OWEN_SCRAMBLED_SOBOL; +// private static final ConvergenceMetric[] PLOT_METRICS = ConvergenceMetric.values(); + static final ConvergenceMetric[] PLOT_METRICS = { + ConvergenceMetric.MEAN_HAZARD, + ConvergenceMetric.STANDARD_DEVIATION, + ConvergenceMetric.CENTRAL_68_RANGE, + ConvergenceMetric.CENTRAL_95_RANGE + }; + private static final Map METRIC_COLORS = Map.of( ConvergenceMetric.MEAN_HAZARD, Colors.tab_blue, ConvergenceMetric.STANDARD_DEVIATION, Colors.tab_orange, - ConvergenceMetric.IQR, Colors.tab_green, - ConvergenceMetric.CENTRAL_68_RANGE, Colors.tab_red, - ConvergenceMetric.CENTRAL_95_RANGE, Colors.tab_purple); + ConvergenceMetric.CENTRAL_68_RANGE, Colors.tab_green, + ConvergenceMetric.CENTRAL_95_RANGE, Colors.tab_red, + ConvergenceMetric.IQR, Colors.tab_purple); private static final Map METRIC_SYMBOLS = Map.of( ConvergenceMetric.MEAN_HAZARD, PlotSymbol.FILLED_CIRCLE, ConvergenceMetric.STANDARD_DEVIATION, PlotSymbol.FILLED_INV_TRIANGLE, - ConvergenceMetric.IQR, PlotSymbol.FILLED_TRIANGLE, ConvergenceMetric.CENTRAL_68_RANGE, PlotSymbol.FILLED_SQUARE, - ConvergenceMetric.CENTRAL_95_RANGE, PlotSymbol.FILLED_DIAMOND); - - private static String getMethodName(SamplingMethod method) { + ConvergenceMetric.CENTRAL_95_RANGE, PlotSymbol.FILLED_DIAMOND, + ConvergenceMetric.IQR, PlotSymbol.FILLED_TRIANGLE); + + static String getMethodName(SamplingMethod method) { if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL) return SamplingMethod.SOBOL.getShortName(); return method.getShortName(); } - + private static final Map METHOD_FILE_PREFIXES; static { Map prefixes = new HashMap<>(); @@ -75,10 +85,12 @@ private static String getMethodName(SamplingMethod method) { METHOD_FILE_PREFIXES = prefixes; } + private static final boolean PLOT_INDV_MEANS = true; + public static void main(String[] args) throws IOException { File convergenceDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence"); plotPeriod(new File(convergenceDir, "pga_two_in_50"), "PGA"); - plotPeriod(new File(convergenceDir, "1s_sa_two_in_50"), "1 s SA"); + plotPeriod(new File(convergenceDir, "1s_sa_two_in_50"), "1s SA"); } static void plotPeriod(File outputDir, String periodName) throws IOException { @@ -108,6 +120,13 @@ private static String referenceFor(SamplingMethod method, boolean sobolPool) { : (method == MCS ? HazardConvergenceCalcs.LOO_MCS_REFERENCE_NAME : MCS_REFERENCE); } + private static boolean matchesReference(ReferenceSummary row, SamplingMethod method, boolean sobolPool) { + if (sobolPool && method == SOBOL) + // A fixed-size consensus only leaves out Sobol runs of that size; other sizes use the full pool. + return row.reference().equals(SOBOL_REFERENCE) || row.reference().equals(POOLED_SOBOL_REFERENCE); + return row.reference().equals(referenceFor(method, sobolPool)); + } + private static boolean includeSummary(ConvergenceSummary actual, ConvergenceSummary requested) { return actual == requested || requested == ConvergenceSummary.MEAN_ABSOLUTE && actual == ConvergenceSummary.MAXIMUM_ABSOLUTE; @@ -116,7 +135,7 @@ private static boolean includeSummary(ConvergenceSummary actual, ConvergenceSumm private static void plotReference(File outputDir, List rows, SamplingMethod method, boolean sobolPool, ConvergenceSummary summary) throws IOException { List matching = rows.stream().filter(row -> row.method() == method - && row.reference().equals(referenceFor(method, sobolPool)) + && matchesReference(row, method, sobolPool) && includeSummary(row.spatialSummary(), summary)).toList(); int[] counts = matching.stream().mapToInt(ReferenceSummary::sampleCount).distinct().sorted().toArray(); if (counts.length < 2) @@ -144,14 +163,14 @@ private static void plotMethodReference(File outputDir, List r List matching = new ArrayList<>(); List labels = new ArrayList<>(); for (SamplingMethod method : rows.stream().map(row -> row.method()).distinct().sorted().toList()) { - String reference = referenceFor(method, sobolConsensus); int index = labels.size(); for (ReferenceSummary row : rows) { if (row.method() == method && row.sampleCount() == sampleCount - && row.reference().equals(reference) + && matchesReference(row, method, sobolConsensus) && includeSummary(row.spatialSummary(), spatialSummary)) { matching.add(new MethodSummary(index, row.metric(), row.spatialSummary(), row.realizations(), - row.minimum(), row.median(), row.maximum())); + row.mean(), row.standardDeviation(), row.minimum(), row.median(), row.maximum(), + row.logStandardDeviation(), row.individualValues())); } } if (matching.stream().anyMatch(row -> row.count() == index)) @@ -184,7 +203,8 @@ private static void plotRealizationPairs(File outputDir, List row.count() == index)) @@ -202,7 +222,7 @@ private static void writePlot(File outputDir, String prefix, String title, Strin ConvergenceSummary primary) throws IOException { boolean signed = primary == ConvergenceSummary.MEAN_SIGNED; Map> byMetric = new LinkedHashMap<>(); - for (ConvergenceMetric metric : ConvergenceMetric.values()) { + for (ConvergenceMetric metric : PLOT_METRICS) { List metricRows = rows.stream().filter(row -> row.metric().equals(metric) && row.spatialSummary() == primary).toList(); if (!metricRows.isEmpty()) @@ -226,25 +246,57 @@ private static void writePlot(File outputDir, String prefix, String title, Strin ArbitrarilyDiscretizedFunc median = new ArbitrarilyDiscretizedFunc(); ArbitrarilyDiscretizedFunc lower = new ArbitrarilyDiscretizedFunc(); ArbitrarilyDiscretizedFunc upper = new ArbitrarilyDiscretizedFunc(); + DefaultXY_DataSet indvMeans = entry.getKey() == ConvergenceMetric.MEAN_HAZARD && PLOT_INDV_MEANS ? new DefaultXY_DataSet() : null; for (int i=0; i candidate.count() == count) .findFirst().orElseThrow(); - median.set((double)i, row.median()); - lower.set((double)i, row.minimum()); - upper.set((double)i, row.maximum()); + if (indvMeans != null) { + double[] values = row.individualValues(); + for (double value : values) + indvMeans.set((double)i, value); + + System.out.println("Plotting "+values.length+" mean values for "+title+", count="+count); + } + double center = signed ? row.mean() : row.median(); + median.set((double)i, center); + if (signed) { + double standardDeviation = row.standardDeviation(); + if (!Double.isFinite(standardDeviation)) + standardDeviation = 0d; + lower.set((double)i, center-standardDeviation); + upper.set((double)i, center+standardDeviation); + } else { + double logSD = row.logStandardDeviation(); + double factor = Double.isFinite(logSD) ? Math.exp(logSD) : 1d; + lower.set((double)i, row.median()/factor); + upper.set((double)i, row.median()*factor); + } } Color color = METRIC_COLORS.get(entry.getKey()); - // Signed ranges overlap heavily, so only show the realization envelope for mean hazard. + PlotSymbol sym = METRIC_SYMBOLS.get(entry.getKey()); + PlotSymbol outlineSym = PlotSymbol.getOutlineSymbol(sym); + // Signed ranges overlap heavily, so only show mean +/- one standard deviation for mean hazard. Positive quantities use the + // median-centered multiplicative range defined by one standard deviation of the log-transformed values. if (!signed || entry.getKey() == ConvergenceMetric.MEAN_HAZARD) { UncertainArbDiscFunc uncertainty = new UncertainArbDiscFunc(median, lower, upper); funcs.add(uncertainty); chars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, new Color(color.getRed(), color.getGreen(), color.getBlue(), 70))); } + if (indvMeans != null) { + medianFuncs.add(indvMeans); + medianChars.add(new PlotCurveCharacterstics(sym, 1.5f, color.darker().darker())); + } + if (outlineSym != null) { + // add slightly darker outline overlay + ArbitrarilyDiscretizedFunc clone = median.deepClone(); + clone.setName(null); + medianFuncs.add(clone); + medianChars.add(new PlotCurveCharacterstics(outlineSym, 5f, color.darker().darker())); + } median.setName(entry.getKey().shortLabel); medianFuncs.add(median); - PlotSymbol sym = METRIC_SYMBOLS.get(entry.getKey()); if (primary == ConvergenceSummary.MEAN_ABSOLUTE) { ArbitrarilyDiscretizedFunc worst = new ArbitrarilyDiscretizedFunc(); for (int i=0; i loadReferenceSummaries(File file) throws I ReferenceGroup group = entry.getKey(); double[] values = entry.getValue().stream().mapToDouble(Double::doubleValue).toArray(); rows.add(new ReferenceSummary(group.method(), group.sampleCount(), group.reference(), group.metric(), - group.spatialSummary(), values.length, StatUtils.min(values), - StatUtils.percentile(values, 50d), StatUtils.max(values))); + group.spatialSummary(), values.length, StatUtils.mean(values), + HazardConvergenceCalcs.standardDeviation(values), StatUtils.min(values), + StatUtils.percentile(values, 50d), StatUtils.max(values), + HazardConvergenceCalcs.logStandardDeviation(values), values)); } return rows; } @@ -357,8 +417,10 @@ private static List loadRealizationPairSummaries(File fi RealizationPairGroup group = entry.getKey(); double[] values = entry.getValue().stream().mapToDouble(Double::doubleValue).toArray(); rows.add(new RealizationPairSummary(group.method(), group.sampleCount(), group.metric(), - group.spatialSummary(), values.length, StatUtils.min(values), - StatUtils.percentile(values, 50d), StatUtils.max(values))); + group.spatialSummary(), values.length, StatUtils.mean(values), + HazardConvergenceCalcs.standardDeviation(values), StatUtils.min(values), + StatUtils.percentile(values, 50d), StatUtils.max(values), + HazardConvergenceCalcs.logStandardDeviation(values), values)); } return rows; } @@ -380,27 +442,34 @@ interface SummaryRow { int count(); ConvergenceSummary spatialSummary(); ConvergenceMetric metric(); + double mean(); + double standardDeviation(); double minimum(); double median(); double maximum(); + double logStandardDeviation(); + double[] individualValues(); } record ReferenceSummary(SamplingMethod method, int sampleCount, String reference, ConvergenceMetric metric, ConvergenceSummary spatialSummary, - int realizations, double minimum, double median, double maximum) implements SummaryRow { + int realizations, double mean, double standardDeviation, double minimum, double median, double maximum, + double logStandardDeviation, double[] individualValues) implements SummaryRow { @Override public int count() { return sampleCount; } } private record MethodSummary(int methodIndex, ConvergenceMetric metric, ConvergenceSummary spatialSummary, int realizations, - double minimum, double median, double maximum) implements SummaryRow { + double mean, double standardDeviation, double minimum, double median, double maximum, + double logStandardDeviation, double[] individualValues) implements SummaryRow { @Override public int count() { return methodIndex; } } private record RealizationPairSummary(SamplingMethod method, int sampleCount, ConvergenceMetric metric, ConvergenceSummary spatialSummary, int realizationPairs, - double minimum, double median, double maximum) {} + double mean, double standardDeviation, double minimum, double median, double maximum, + double logStandardDeviation, double[] individualValues) {} private record ReferenceGroup(SamplingMethod method, int sampleCount, String reference, ConvergenceMetric metric, diff --git a/src/main/java/scratch/kevin/sampling/HazardMapPlots.java b/src/main/java/scratch/kevin/sampling/HazardMapPlots.java new file mode 100644 index 00000000..7e614652 --- /dev/null +++ b/src/main/java/scratch/kevin/sampling/HazardMapPlots.java @@ -0,0 +1,466 @@ +package scratch.kevin.sampling; + +import java.awt.Color; +import java.awt.Font; +import java.io.File; +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.ui.TextAnchor; +import org.jfree.data.Range; +import org.opensha.commons.data.CSVFile; +import org.opensha.commons.data.function.DiscretizedFunc; +import org.opensha.commons.data.function.LightFixedXFunc; +import org.opensha.commons.data.xyz.GriddedGeoDataSet; +import org.opensha.commons.geo.GriddedRegion; +import org.opensha.commons.geo.Location; +import org.opensha.commons.geo.Region; +import org.opensha.commons.geo.json.Feature; +import org.opensha.commons.gui.plot.GeographicMapMaker; +import org.opensha.commons.gui.plot.HeadlessGraphPanel; +import org.opensha.commons.gui.plot.PlotSpec; +import org.opensha.commons.gui.plot.PlotUtils; +import org.opensha.commons.logicTree.LogicTree; +import org.opensha.commons.logicTree.sampling.SamplingMethod; +import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; +import org.opensha.commons.util.DataUtils.MinMaxAveTracker; +import org.opensha.commons.util.cpt.CPT; +import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc; +import org.opensha.sha.earthquake.faultSysSolution.util.SolHazardMapCalc.ReturnPeriods; + +import com.google.common.base.Preconditions; + +import scratch.kevin.sampling.HazardConvergenceCalcs.ConvergenceMetric; +import scratch.kevin.sampling.HazardConvergenceCalcs.HazardStatistics; +import scratch.kevin.sampling.HazardConvergenceCalcs.ModelHazardMaps; + +public class HazardMapPlots { + + private static final ReturnPeriods RP = ReturnPeriods.TWO_IN_50; + + public static void main(String[] args) throws IOException { + File convergenceDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence"); + int[] sizes = { 512, 1024, 2048, 4096, 8192 }; + plotPeriod(new File(convergenceDir, "pga_two_in_50"), 0d, "PGA, "+RP.label, sizes); +// plotPeriod(new File(convergenceDir, "1s_sa_two_in_50"), 1d, "1s SA, "+RP.label, sizes); + } + + private static void plotPeriod(File periodDir, double period, String perLabel, int... indvSizes) + throws IOException { + File mapDir = new File(periodDir, "hazard_maps"); + Preconditions.checkState(mapDir.exists() || mapDir.mkdir()); + + File firstMCSDir = HazardConvergenceCalcs.runDirs.row(SamplingMethod.MONTE_CARLO) + .values().iterator().next().get(0); + GriddedRegion gridReg = GriddedRegion.fromFeature( + Feature.read(new File(firstMCSDir, "gridded_region.geojson"))); + + List mcsPoolDirs = flatten(HazardConvergenceCalcs.runDirs.row(SamplingMethod.MONTE_CARLO)); + List sobolPoolDirs; + if (HazardConvergenceCalcs.FIXED_SOBOL_CONSENSUS_SIZE == null) { + sobolPoolDirs = flatten(HazardConvergenceCalcs.runDirs.row(SamplingMethod.OWEN_SCRAMBLED_SOBOL)); + } else { + sobolPoolDirs = Preconditions.checkNotNull(HazardConvergenceCalcs.runDirs.get( + SamplingMethod.OWEN_SCRAMBLED_SOBOL, + HazardConvergenceCalcs.FIXED_SOBOL_CONSENSUS_SIZE)); + } + + DecimalFormat groupedDF = new DecimalFormat("0"); + groupedDF.setGroupingSize(3); + groupedDF.setGroupingUsed(true); + + PooledHazardData mcsPool = loadPool(periodDir, "pooled_mcs", mcsPoolDirs, gridReg, period); + PooledHazardData sobolPool = loadPool(periodDir, "pooled_sobol", sobolPoolDirs, gridReg, period); + + plotMeanHazard(gridReg, sobolPool.data(), perLabel, mapDir, "pooled_sobol"); + plotMeanHazard(gridReg, mcsPool.data(), perLabel, mapDir, "pooled_mcs"); + plotComparisons(gridReg, sobolPool.data(), mcsPool.data(), perLabel, mapDir, "pooled_sobol_vs_mcs", + "Pooled Sobol ("+nStr(sobolPool.data)+") vs MCS ("+nStr(mcsPool.data)+")"); + + // Plot the first realization available for each method and requested sample count. + for (int size : indvSizes) { + File sizeDir = new File(mapDir, size+"_samples"); + Preconditions.checkState(sizeDir.exists() || sizeDir.mkdir()); + for (SamplingMethod method : SamplingMethod.values()) { + HazardData data; + HazardData refMCS; + HazardData refSobol; + if (method == SamplingMethod.MONTE_CARLO) { + // MCS comparisons use the first span of the first run and remove that span from the MCS pool. + data = loadRunPrefix(firstMCSDir, size, gridReg, period, mcsPool); + refMCS = mcsPool.without(firstMCSDir, size, data.meanCurves(), gridReg); + refSobol = sobolPool.data(); + } else { + List runDirs = HazardConvergenceCalcs.runDirs.get(method, size); + if (runDirs == null || runDirs.isEmpty()) + continue; + File runDir = runDirs.get(0); + data = loadRunPrefix(runDir, size, gridReg, period, + method == SamplingMethod.OWEN_SCRAMBLED_SOBOL ? sobolPool : null); + refMCS = mcsPool.data(); + if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL && sobolPool.contains(runDir)) + refSobol = sobolPool.without(runDir, size, data.meanCurves(), gridReg); + else + refSobol = sobolPool.data(); + } + + String name = "Individual "+HazardConvergencePlots.getMethodName(method)+" ("+nStr(data)+")"; + + plotComparisons(gridReg, data, refMCS, perLabel, sizeDir, + method.name().toLowerCase()+"_vs_pooled_mcs", name+" vs pooled MCS ("+nStr(refMCS)+")"); + plotComparisons(gridReg, data, refSobol, perLabel, sizeDir, + method.name().toLowerCase()+"_vs_pooled_sobol", name+" vs pooled Sobol ("+nStr(refSobol)+")"); + } + } + } + + private static final DecimalFormat groupedDF = new DecimalFormat("0"); + static { + groupedDF.setGroupingSize(3); + groupedDF.setGroupingUsed(true); + } + + private static String nStr(HazardData data) { + return nStr(data.numBranches()); + } + + private static String nStr(int size) { + return "N="+groupedDF.format(size); + } + + private static List flatten(Map> dirsBySize) { + List dirs = new ArrayList<>(); + dirsBySize.entrySet().stream().sorted(Map.Entry.comparingByKey()) + .forEach(entry -> dirs.addAll(entry.getValue())); + return dirs; + } + + private static PooledHazardData loadPool(File periodDir, String poolName, List runDirs, + GriddedRegion gridReg, double period) throws IOException { + Preconditions.checkState(!runDirs.isEmpty(), "No runs available for %s", poolName); + DiscretizedFunc[] meanCurves = loadCurves( + new File(new File(periodDir, poolName), + SolHazardMapCalc.getCSV_FileName("mean_curves", period)+".gz"), gridReg); + List blocks = new ArrayList<>(); + for (File runDir : runDirs) { + LogicTree tree = LogicTree.read(new File(runDir, "logic_tree_analysis.json")); + ModelHazardMaps maps = HazardConvergenceCalcs.loadMaps( + new File(runDir, "results_hazard.zip"), tree, gridReg, period, RP); + blocks.add(new RunBlock(runDir.getAbsoluteFile(), HazardConvergenceCalcs.copyValues(maps.individual()))); + } + return new PooledHazardData(buildHazardData(meanCurves, concatenate(blocks), gridReg), blocks); + } + + private static HazardData loadRunPrefix(File runDir, int sampleCount, GriddedRegion gridReg, + double period, PooledHazardData cachedPool) throws IOException { + LogicTree tree = LogicTree.read(new File(runDir, "logic_tree_analysis.json")); + Preconditions.checkState(sampleCount <= tree.size(), "Requested %s of %s branches from %s", + sampleCount, tree.size(), runDir.getName()); + double[][] allBranchMaps = cachedPool == null ? null : cachedPool.branchMaps(runDir); + if (allBranchMaps == null) { + ModelHazardMaps maps = HazardConvergenceCalcs.loadMaps( + new File(runDir, "results_hazard.zip"), tree, gridReg, period, RP); + allBranchMaps = HazardConvergenceCalcs.copyValues(maps.individual()); + } + double[][] branchMaps = Arrays.copyOf(allBranchMaps, sampleCount); + DiscretizedFunc[] meanCurves = loadMeanCurves(runDir, tree, sampleCount, gridReg, period); + return buildHazardData(meanCurves, branchMaps, gridReg); + } + + private static DiscretizedFunc[] loadMeanCurves(File runDir, LogicTree tree, int sampleCount, + GriddedRegion gridReg, double period) throws IOException { + double[] xValues = null; + double[][] sums = null; + File hazardResultsDir = new File(runDir, "results"); + for (int b=0; b blocks) { + int size = blocks.stream().mapToInt(block -> block.branchMaps().length).sum(); + double[][] values = new double[size][]; + int index = 0; + for (RunBlock block : blocks) + for (double[] row : block.branchMaps()) + values[index++] = row; + return values; + } + + private static Region getMapReagion(GriddedRegion gridReg) { + if (!gridReg.isRectangular()) + return gridReg; + MinMaxAveTracker latTrack = new MinMaxAveTracker(); + MinMaxAveTracker lonTrack = new MinMaxAveTracker(); + for (Location loc : gridReg.getNodeList()) { + latTrack.addValue(loc.lat); + lonTrack.addValue(loc.lon); + } + double halfLat = gridReg.getLatSpacing()*0.5; + double halfLon = gridReg.getLonSpacing()*0.5; + return new Region(new Location(latTrack.getMin()-halfLat, lonTrack.getMin()-halfLon), + new Location(latTrack.getMax()+halfLat, lonTrack.getMax()+halfLon)); + } + + private static void plotMeanHazard(GriddedRegion gridReg, HazardData data, + String perLabel, File outputDir, String prefix) throws IOException { + GeographicMapMaker mapMaker = new GeographicMapMaker(getMapReagion(gridReg)); + CPT hazCPT = GMT_CPT_Files.RAINBOW_UNIFORM.instance().rescale(1e-2, 3d).asLog10(); + GriddedGeoDataSet map = SolHazardMapCalc.buildMap(data.meanCurves(), gridReg, RP); + mapMaker.plotXYZData(map, hazCPT, "Mean hazard, "+perLabel+" (g)"); + mapMaker.plot(outputDir, prefix, "", PlotUtils.DEFAULT_USABLE_PAGE_WIDTH/2d, 300); + } + + private static void plotComparisons(GriddedRegion gridReg, HazardData data, HazardData reference, + String perLabel, File outputDir, String prefix, String title) throws IOException { + Region region = getMapReagion(gridReg); + GeographicMapMaker mapMaker = new GeographicMapMaker(region); + CPT pDiffCPT = GMT_CPT_Files.DIVERGING_VIK_UNIFORM.instance().rescale(-5d, 5d); + pDiffCPT.setPreferredTickInterval(1d); + + DecimalFormat df = new DecimalFormat("0.00"); + Font statsFont = new Font(Font.SANS_SERIF, Font.PLAIN, 8); + Font metricFont = new Font(Font.SANS_SERIF, Font.BOLD, 10); +// Color bgPaint = new Color(255, 255, 255, 60); +// Color bgPaint = new Color(200, 200, 200, 120); + Color bgPaint = new Color(220, 220, 220, 200); + + List plots = new ArrayList<>(); + + for (ConvergenceMetric metric : HazardConvergencePlots.PLOT_METRICS) { + GriddedGeoDataSet xyz = asGeoDataSet(gridReg, data.statistics().values(metric)); + GriddedGeoDataSet refXYZ = asGeoDataSet(gridReg, reference.statistics().values(metric)); + GriddedGeoDataSet pDiff = pDiff(xyz, refXYZ); + mapMaker.plotXYZData(pDiff, pDiffCPT, perLabel+", % change"); + + mapMaker.clearAnnotations(); + + double mean = 0d; + double meanAbs = 0d; + double min=Double.MAX_VALUE; + double max=Double.MIN_VALUE; + for (int i=0; i yRanges = new ArrayList<>(plots.size()); + for (int i=0; i> rows = new ArrayList<>(); + List curRow = null; + for (int i=0; i(); + rows.add(curRow); + } + curRow.add(plots.get(i)); + } + List gps = new ArrayList<>(rows.size()); + for (List row : rows) { + HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); + gp.drawGraphPanel(row, false, false, List.of(xRange, xRange), List.of(yRange)); + gps.add(gp); + } + + PlotUtils.stitchPlotRows(outputDir, prefix, gps, false, PlotUtils.DEFAULT_USABLE_PAGE_WIDTH, -1d, 300, true, true, true); + } +// List yRanges = new ArrayList<>(plots.size()); +// for (int i=0; i blocks) { + boolean contains(File runDir) { + return blocks.stream().anyMatch(block -> block.matches(runDir)); + } + + double[][] branchMaps(File runDir) { + return blocks.stream().filter(block -> block.matches(runDir)).findFirst() + .map(RunBlock::branchMaps).orElse(null); + } + + HazardData without(File runDir, int excludedCount, DiscretizedFunc[] excludedMean, + GriddedRegion gridReg) { + Preconditions.checkState(contains(runDir), "Run is not in pooled data: %s", runDir.getName()); + List retained = new ArrayList<>(); + for (RunBlock block : blocks) { + if (block.matches(runDir)) { + Preconditions.checkState(excludedCount <= block.branchMaps().length); + if (excludedCount < block.branchMaps().length) + retained.add(new RunBlock(block.directory(), + Arrays.copyOfRange(block.branchMaps(), excludedCount, block.branchMaps().length))); + } else { + retained.add(block); + } + } + int fullCount = data.branchMaps().length; + DiscretizedFunc[] meanCurves = subtractMeanCurves( + data.meanCurves(), fullCount, excludedMean, excludedCount); + return buildHazardData(meanCurves, concatenate(retained), gridReg); + } + } +} diff --git a/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java index 404fd57b..54c95d12 100644 --- a/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java +++ b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java @@ -109,6 +109,7 @@ public static void main(String[] args) throws IOException { SamplingMethod.MONTE_CARLO, SamplingMethod.LATIN_HYPERCUBE, SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, + SamplingMethod.CENTERED_DISCREPANCY_OPTIMIZED_LATIN_HYPERCUBE, SamplingMethod.SOBOL, SamplingMethod.OWEN_SCRAMBLED_SOBOL }; @@ -119,6 +120,8 @@ public static void main(String[] args) throws IOException { new PlotCurveCharacterstics(PlotLineType.DASHED, 1f, Colors.tab_green), SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, new PlotCurveCharacterstics(PlotLineType.SHORT_DASHED, 1f, Colors.tab_orange), + SamplingMethod.CENTERED_DISCREPANCY_OPTIMIZED_LATIN_HYPERCUBE, + new PlotCurveCharacterstics(PlotLineType.DOTTED_AND_DASHED, 1f, Colors.tab_purple), SamplingMethod.OWEN_SCRAMBLED_SOBOL, new PlotCurveCharacterstics(PlotLineType.SOLID, 1f, Colors.tab_blue)); // int numPlotTrials = 10; @@ -128,19 +131,21 @@ public static void main(String[] args) throws IOException { int numAvgTrials = 100; // int numAvgTrials = 500; - boolean redoNormScores = false; - boolean redoCenteredDiscrepancies = false; + boolean redoNormScores = true; + boolean redoCenteredDiscrepancies = true; boolean replotIndvSamples = false; - String treeName = null; - List samplingDimensions = new ArrayList<>(); - for (int i=0; i<10; i++) - samplingDimensions.add(ContinuousSamplingDimension.INSTANCE); - String samplingPrefix = "continuous_"+samplingDimensions.size()+"d"; +// String treeName = null; +//// int numD = 10; +// int numD = 5; +// List samplingDimensions = new ArrayList<>(); +// for (int i=0; i samplingDimensions = getDimsNSHM23(); -// String samplingPrefix = "nshm23_"+samplingDimensions.size()+"d"; + String treeName = "NSHM23-WUS"; + List samplingDimensions = getDimsNSHM23(); + String samplingPrefix = "nshm23_"+samplingDimensions.size()+"d"; // String treeName = "NSHM27-AmSam"; // List samplingDimensions = getDimsNSHM27_AmSam(); @@ -458,6 +463,8 @@ else if (dimensions == numCategorical) for (int p=0; p= dimensions || dim2 >= dimensions) + continue; List plots = new ArrayList<>(); Range range = new Range(0d, 1d); @@ -640,8 +647,8 @@ else if (dimensions == numCategorical) HeadlessGraphPanel gp = PlotUtils.initPrintHeadless(); PlotPreferences prefs = gp.getPlotPrefs(); prefs.setPlotLabelFontSize(10); - prefs.setLegendFontSize(8); - prefs.setLegendLineLength(8d); + prefs.setLegendFontSize(7); + prefs.setLegendLineLength(6d); prefs.getPlotPadding(); prefs.setPlotPadding(new RectangleInsets(4, 0, 0, 12)); diff --git a/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java b/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java index 49abad0a..3af8ffb7 100644 --- a/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java +++ b/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java @@ -28,18 +28,18 @@ public class HazardConvergenceCalcsTest { List rows = new ArrayList<>(); List spans = HazardConvergenceCalcs.appendMCSSpanComparisons(rows, List.of(first, second), new int[] {2, 4}, sobol, grid, ReturnPeriods.TWO_IN_50); - assertEquals(7, spans.size()); - // C(5,2) at size 2 plus C(2,2) at size 4, each with five metrics. - assertEquals(55, HazardConvergenceCalcs.buildRealizationPairComparisons(spans, grid).size()); - // Five two-sample spans and two four-sample spans, each with two references and five metrics. - assertEquals(70, rows.size()); + assertEquals(9, spans.size()); + // C(6,2) at size 2 plus C(3,2) at size 4, each with five metrics. + assertEquals(90, HazardConvergenceCalcs.buildRealizationPairComparisons(spans, grid).size()); + // Six two-sample spans and three four-sample spans, each with two references and five metrics. + assertEquals(90, rows.size()); for (ReferenceComparison row : rows) { assertEquals(0, row.startIndex() % row.sampleCount()); assertTrue(row.startIndex()+row.sampleCount() <= row.run().maxSamples()); if (!row.referenceName().equals(HazardConvergenceCalcs.LOO_MCS_REFERENCE_NAME)) continue; assertEquals(12-row.sampleCount(), row.referenceSampleCount()); - int from = (row.run().id().equals("first") ? 0 : 7)+row.startIndex(); + int from = row.startIndex(); int to = from+row.sampleCount(); if (row.metric() == ConvergenceMetric.STANDARD_DEVIATION) { double[] included = java.util.stream.IntStream.range(0, 12) diff --git a/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java b/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java index 4cedcace..20e2f588 100644 --- a/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java +++ b/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java @@ -21,22 +21,23 @@ public class HazardConvergencePlotsTest { for (int count : new int[] {512, 1024}) rows.add(new ReferenceSummary(SamplingMethod.OWEN_SCRAMBLED_SOBOL, count, HazardConvergenceCalcs.MCS_REFERENCE_NAME, metric, ConvergenceSummary.MEAN_ABSOLUTE, - 2, 0.1, 0.2, 0.3)); + 2, 0.2, 0.05, 0.1, 0.2, 0.3, 0.25, new double[] {0.15, 0.25})); rows.add(new ReferenceSummary(SamplingMethod.MONTE_CARLO, 512, HazardConvergenceCalcs.LOO_MCS_REFERENCE_NAME, metric, ConvergenceSummary.MEAN_ABSOLUTE, - 4, 0.2, 0.3, 0.4)); + 4, 0.3, 0.05, 0.2, 0.3, 0.4, 0.2, new double[] {0.2, 0.25, 0.35, 0.4})); rows.add(new ReferenceSummary(SamplingMethod.LATIN_HYPERCUBE, 512, HazardConvergenceCalcs.MCS_REFERENCE_NAME, metric, ConvergenceSummary.MEAN_ABSOLUTE, - 4, 0.1, 0.2, 0.3)); + 4, 0.2, 0.05, 0.1, 0.2, 0.3, 0.25, new double[] {0.1, 0.15, 0.25, 0.3})); } for (ReferenceSummary row : new ArrayList<>(rows)) rows.add(new ReferenceSummary(row.method(), row.sampleCount(), row.reference(), row.metric(), - ConvergenceSummary.MAXIMUM_ABSOLUTE, row.realizations(), 0.5, 1, 5)); + ConvergenceSummary.MAXIMUM_ABSOLUTE, row.realizations(), 1d, 0.25, 0.5, 1d, 5d, 0.2, + row.individualValues())); HazardConvergencePlots.plotMethodReference(output.getRoot(), rows, false, ConvergenceSummary.MEAN_ABSOLUTE, "Spatial mean absolute difference (%)"); for (int count : new int[] {512, 1024}) { assertTrue(new java.io.File(output.getRoot(), - "method_comparison_"+count+"_mcs_reference_mean_abs.png").isFile()); + "method_comparison_"+count+"_pooled_mcs_mean_abs.png").isFile()); } } } From 05780e472328a6fb788a79742ebf8f06af46f41d Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 14 Sep 2026 13:26:20 -0700 Subject: [PATCH 65/71] updated convergence calcs/plots --- .../sampling/HazardConvergenceCalcs.java | 133 +++++++++++++++++- .../sampling/HazardConvergencePlots.java | 38 ++++- .../kevin/sampling/SamplingScoreFigures.java | 31 ++-- .../sampling/HazardConvergenceCalcsTest.java | 12 ++ .../sampling/HazardConvergencePlotsTest.java | 20 +++ 5 files changed, 213 insertions(+), 21 deletions(-) diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java index 332491a2..e821de29 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java @@ -51,6 +51,8 @@ public class HazardConvergenceCalcs { static final String POOLED_SOBOL_REFERENCE_NAME = "Pooled Sobol"; static final String LOO_SOBOL_REFERENCE_NAME = "Pooled Sobol, leave one out"; private static final int MAX_RUN_LOAD_THREADS = 4; + private static final int MCS_POOL_BOOTSTRAP_REPLICATES = 200; + private static final long MCS_POOL_BOOTSTRAP_SEED = 0x5eed5eedL; /** Set to {@code null} to build the Sobol consensus from every available run size. */ static final Integer FIXED_SOBOL_CONSENSUS_SIZE = 8192; @@ -92,7 +94,9 @@ public class HazardConvergenceCalcs { new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-8192samples-sobol_scrambled"), new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed"), new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-2"), - new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-3") + new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-3"), + new File(PaperPaths.INVS_DIR, "2026_09_09-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-4"), + new File(PaperPaths.INVS_DIR, "2026_09_09-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-5") )); /* @@ -112,7 +116,9 @@ public class HazardConvergenceCalcs { new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise"), new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed"), new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-2"), - new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-3") + new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-3"), + new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-4"), + new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-5") )); } @@ -138,7 +144,7 @@ public static void main(String[] args) throws IOException { Feature.read(new File(mcsRuns.get(0).directory, "gridded_region.geojson"))); double[] periods = { 0d, 1d }; - String[] periodNames = { "PGA", "1 s SA" }; + String[] periodNames = { "PGA", "1s SA" }; String[] periodPrefixes = { "pga", "1s_sa" }; for (int p=0; p sobolRuns, List csv, List prefix, dou csv.addLine(line); } + /** + * Bootstraps the complete IID MCS pool and compares each resampled pool with the fixed Sobol consensus. Branch + * indexes are sampled once per replicate and shared across sites, preserving the spatial dependence present in + * each branch. Mean hazard is omitted because its production value is derived from mean hazard curves rather than + * the arithmetic mean of branch maps. + */ + static void runMCSPoolBootstrap(List mcsData, ReferenceStatistics mcsReference, + ReferenceStatistics sobolReference, int numReplicates, long seed, File outputDir) throws IOException { + Preconditions.checkArgument(!mcsData.isEmpty()); + Preconditions.checkArgument(numReplicates > 1); + double[][] branchMaps = mcsData.stream().flatMap(data -> Arrays.stream(data.branchMaps())) + .toArray(double[][]::new); + Preconditions.checkState(branchMaps.length == mcsReference.sampleCount()); + System.out.println("\nBootstrapping pooled MCS uncertainty: "+branchMaps.length+" branches x " + +numReplicates+" replicates"); + + List metrics = Arrays.stream(ConvergenceMetric.values()) + .filter(metric -> metric != ConvergenceMetric.MEAN_HAZARD).toList(); + @SuppressWarnings("unchecked") + Map[] comparisons = new Map[numReplicates]; + IntStream.range(0, numReplicates).parallel().forEach(r -> { + long replicateSeed = RandomSeedUtils.uniqueSeedCombination(seed, branchMaps.length, r); + int[] counts = bootstrapCounts(branchMaps.length, branchMaps.length, replicateSeed); + HazardStatistics statistics = calcBootstrapHazardStatistics(branchMaps, counts, branchMaps.length); + Map replicateComparisons = new EnumMap<>(ConvergenceMetric.class); + for (ConvergenceMetric metric : metrics) + replicateComparisons.put(metric, + compare(statistics.values(metric), sobolReference.statistics().values(metric))); + comparisons[r] = replicateComparisons; + }); + + CSVFile replicateCSV = new CSVFile<>(true); + replicateCSV.addLine("Replicate", "MCS sample count", "Reference", "Reference sample count", "Metric", + "Spatial mean % change", + "Spatial mean absolute % change", "Spatial P95 absolute % change", "Maximum absolute % change", + "Minimum % change", "Maximum % change"); + CSVFile summaryCSV = new CSVFile<>(true); + summaryCSV.addLine("MCS sample count", "Reference", "Reference sample count", "Metric", "Spatial summary", + "Original pooled MCS comparison", + "Replicates", "Mean", "Standard deviation", "Log standard deviation", "Minimum", "P2.5", + "P16", "P50", "P84", "P97.5", "Maximum"); + for (ConvergenceMetric metric : metrics) { + MapComparison original = compare(mcsReference.statistics().values(metric), + sobolReference.statistics().values(metric)); + for (int r=0; r 0 && counts.length == branchMaps.length); + Preconditions.checkArgument(sampleCount > 1); + int countSum = Arrays.stream(counts).sum(); + Preconditions.checkArgument(countSum == sampleCount, + "Bootstrap counts sum to %s, expected %s", countSum, sampleCount); + int numSites = branchMaps[0].length; + double[] standardDeviation = new double[numSites]; + double[] iqr = new double[numSites]; + double[] central68 = new double[numSites]; + double[] central95 = new double[numSites]; + double[] values = new double[sampleCount]; + for (int n=0; n -1e-12*sumSquares) + varianceNumerator = 0d; + Preconditions.checkState(varianceNumerator >= 0d, + "Negative bootstrap variance numerator at site "+n+": "+varianceNumerator); + standardDeviation[n] = Math.sqrt(varianceNumerator/sampleCount); + Arrays.sort(values); + iqr[n] = empiricalFractile(values, 0.75)-empiricalFractile(values, 0.25); + central68[n] = empiricalFractile(values, 0.84)-empiricalFractile(values, 0.16); + central95[n] = empiricalFractile(values, 0.975)-empiricalFractile(values, 0.025); + } + Map metricValues = new EnumMap<>(ConvergenceMetric.class); + metricValues.put(ConvergenceMetric.STANDARD_DEVIATION, standardDeviation); + metricValues.put(ConvergenceMetric.IQR, iqr); + metricValues.put(ConvergenceMetric.CENTRAL_68_RANGE, central68); + metricValues.put(ConvergenceMetric.CENTRAL_95_RANGE, central95); + return new HazardStatistics(metricValues); + } + /** * Resamples the reference MCS branches with replacement. Smaller resample sizes describe the error expected from * ordinary MCS at those sample counts; the full-size resample describes uncertainty in the reference itself. diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java index dceaa76b..0987fede 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java @@ -220,6 +220,7 @@ && includeSummary(row.spatialSummary(), spatialSummary)) { private static void writePlot(File outputDir, String prefix, String title, String xLabel, String yLabel, int[] counts, String[] countLabels, List rows, ConvergenceSummary primary) throws IOException { + System.out.println("Building plot: "+title); boolean signed = primary == ConvergenceSummary.MEAN_SIGNED; Map> byMetric = new LinkedHashMap<>(); for (ConvergenceMetric metric : PLOT_METRICS) { @@ -249,14 +250,17 @@ private static void writePlot(File outputDir, String prefix, String title, Strin DefaultXY_DataSet indvMeans = entry.getKey() == ConvergenceMetric.MEAN_HAZARD && PLOT_INDV_MEANS ? new DefaultXY_DataSet() : null; for (int i=0; i candidate.count() == count) - .findFirst().orElseThrow(); + // More than one accepted reference label can represent the same plotted point. In particular, + // native Sobol runs use the full fixed-size Sobol pool while prefixes of runs in that pool use + // leave-one-out references. Combine their realization values before calculating plot statistics. + SummaryRow row = combineRows(entry.getValue().stream() + .filter(candidate -> candidate.count() == count).toList()); if (indvMeans != null) { double[] values = row.individualValues(); for (double value : values) indvMeans.set((double)i, value); - System.out.println("Plotting "+values.length+" mean values for "+title+", count="+count); + System.out.println("\t"+values.length+" mean values for "+title+", count="+count); } double center = signed ? row.mean() : row.median(); median.set((double)i, center); @@ -303,7 +307,8 @@ private static void writePlot(File outputDir, String prefix, String title, Strin int count = counts[i]; rows.stream().filter(row -> row.metric() == entry.getKey() && row.count() == count && row.spatialSummary() == ConvergenceSummary.MAXIMUM_ABSOLUTE) - .findFirst().ifPresent(row -> worst.set((double)Arrays.binarySearch(counts, count), row.maximum())); + .mapToDouble(SummaryRow::maximum).max() + .ifPresent(maximum -> worst.set((double)Arrays.binarySearch(counts, count), maximum)); } if (worst.size() > 0) { maxFuncs.add(worst); // Unnamed, so it adds no legend entry. @@ -429,6 +434,26 @@ private static void addValue(Map> groups, K key, double valu groups.computeIfAbsent(key, unused -> new ArrayList<>()).add(value); } + static SummaryRow combineRows(List rows) { + if (rows.isEmpty()) + throw new IllegalArgumentException("Cannot combine an empty set of summary rows"); + SummaryRow first = rows.get(0); + int size = rows.stream().mapToInt(row -> row.individualValues().length).sum(); + double[] values = new double[size]; + int offset = 0; + for (SummaryRow row : rows) { + if (row.count() != first.count() || row.metric() != first.metric() + || row.spatialSummary() != first.spatialSummary()) + throw new IllegalArgumentException("Cannot combine summary rows for different plotted quantities"); + System.arraycopy(row.individualValues(), 0, values, offset, row.individualValues().length); + offset += row.individualValues().length; + } + return new CombinedSummary(first.count(), first.metric(), first.spatialSummary(), + StatUtils.mean(values), HazardConvergenceCalcs.standardDeviation(values), StatUtils.min(values), + StatUtils.percentile(values, 50d), StatUtils.max(values), + HazardConvergenceCalcs.logStandardDeviation(values), values); + } + private static String summaryPrefix(ConvergenceSummary summary) { return switch (summary) { case MEAN_SIGNED -> "signed_bias"; @@ -465,6 +490,11 @@ private record MethodSummary(int methodIndex, ConvergenceMetric metric, @Override public int count() { return methodIndex; } } + private record CombinedSummary(int count, ConvergenceMetric metric, + ConvergenceSummary spatialSummary, double mean, double standardDeviation, + double minimum, double median, double maximum, double logStandardDeviation, + double[] individualValues) implements SummaryRow {} + private record RealizationPairSummary(SamplingMethod method, int sampleCount, ConvergenceMetric metric, ConvergenceSummary spatialSummary, int realizationPairs, diff --git a/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java index 54c95d12..002c5d64 100644 --- a/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java +++ b/src/main/java/scratch/kevin/sampling/SamplingScoreFigures.java @@ -126,30 +126,33 @@ public static void main(String[] args) throws IOException { new PlotCurveCharacterstics(PlotLineType.SOLID, 1f, Colors.tab_blue)); // int numPlotTrials = 10; int numPlotTrials = 0; -// int numAvgTrials = 20; +// int numAvgTrials = 10; // int numAvgTrials = 50; - int numAvgTrials = 100; +// int numAvgTrials = 100; + int numAvgTrials = 200; // int numAvgTrials = 500; - boolean redoNormScores = true; - boolean redoCenteredDiscrepancies = true; + System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "16"); + + boolean redoNormScores = false; + boolean redoCenteredDiscrepancies = false; boolean replotIndvSamples = false; - + // String treeName = null; -//// int numD = 10; -// int numD = 5; +// int numD = 10; +//// int numD = 5; // List samplingDimensions = new ArrayList<>(); // for (int i=0; i samplingDimensions = getDimsNSHM23(); +// String samplingPrefix = "nshm23_"+samplingDimensions.size()+"d"; - String treeName = "NSHM23-WUS"; - List samplingDimensions = getDimsNSHM23(); - String samplingPrefix = "nshm23_"+samplingDimensions.size()+"d"; - -// String treeName = "NSHM27-AmSam"; -// List samplingDimensions = getDimsNSHM27_AmSam(); -// String samplingPrefix = "nshm27_amsam_"+samplingDimensions.size()+"d"; + String treeName = "NSHM27-AmSam"; + List samplingDimensions = getDimsNSHM27_AmSam(); + String samplingPrefix = "nshm27_amsam_"+samplingDimensions.size()+"d"; final int dimensions = samplingDimensions.size(); int numContinuous = 0; diff --git a/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java b/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java index 3af8ffb7..403f474d 100644 --- a/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java +++ b/src/test/java/scratch/kevin/sampling/HazardConvergenceCalcsTest.java @@ -88,4 +88,16 @@ private static double[][] curves(double scale) { assertSame(rows[2], HazardConvergenceCalcs.excludeSpan(rows, 0, 2)[0]); assertEquals(3, HazardConvergenceCalcs.excludeSpan(rows, 3, 5).length); } + + @Test public void weightedBootstrapStatisticsMatchExpandedSample() { + double[][] source = {{1}, {2}, {3}, {4}}; + HazardStatistics weighted = HazardConvergenceCalcs.calcBootstrapHazardStatistics( + source, new int[] {2, 0, 1, 1}, 4); + double[][] expanded = {{1}, {1}, {3}, {4}}; + HazardStatistics direct = HazardConvergenceCalcs.calcHazardStatistics(expanded, 4, new double[] {0}); + for (ConvergenceMetric metric : ConvergenceMetric.values()) { + if (metric != ConvergenceMetric.MEAN_HAZARD) + assertArrayEquals(direct.values(metric), weighted.values(metric), 0d); + } + } } diff --git a/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java b/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java index 20e2f588..fa20c442 100644 --- a/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java +++ b/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java @@ -11,6 +11,7 @@ import scratch.kevin.sampling.HazardConvergenceCalcs.ConvergenceMetric; import scratch.kevin.sampling.HazardConvergenceCalcs.ConvergenceSummary; import scratch.kevin.sampling.HazardConvergencePlots.ReferenceSummary; +import scratch.kevin.sampling.HazardConvergencePlots.SummaryRow; public class HazardConvergencePlotsTest { @Rule public TemporaryFolder output = new TemporaryFolder(); @@ -40,4 +41,23 @@ public class HazardConvergencePlotsTest { "method_comparison_"+count+"_pooled_mcs_mean_abs.png").isFile()); } } + + @Test public void combinesFullPoolAndLeaveOneOutRealizations() { + ReferenceSummary fullPool = new ReferenceSummary(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 4096, + HazardConvergenceCalcs.POOLED_SOBOL_REFERENCE_NAME, ConvergenceMetric.MEAN_HAZARD, + ConvergenceSummary.MEAN_ABSOLUTE, 4, 2.5, 0d, 1d, 2.5, 4d, 0d, + new double[] {1d, 2d, 3d, 4d}); + ReferenceSummary leaveOneOut = new ReferenceSummary(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 4096, + HazardConvergenceCalcs.LOO_SOBOL_REFERENCE_NAME, ConvergenceMetric.MEAN_HAZARD, + ConvergenceSummary.MEAN_ABSOLUTE, 5, 7d, 0d, 5d, 7d, 9d, 0d, + new double[] {5d, 6d, 7d, 8d, 9d}); + + SummaryRow combined = HazardConvergencePlots.combineRows(List.of(fullPool, leaveOneOut)); + assertArrayEquals(new double[] {1d, 2d, 3d, 4d, 5d, 6d, 7d, 8d, 9d}, + combined.individualValues(), 0d); + assertEquals(5d, combined.mean(), 0d); + assertEquals(5d, combined.median(), 0d); + assertEquals(1d, combined.minimum(), 0d); + assertEquals(9d, combined.maximum(), 0d); + } } From e61efe69d2f5eb8b2ddde33f752954bcff5a0116 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Mon, 14 Sep 2026 15:46:48 -0700 Subject: [PATCH 66/71] for upstream --- .../nshm23/hazardValidation/ComparisonCalcScriptWriter.java | 2 +- .../kevin/nshm23/hazardValidation/ComparisonPageGen.java | 2 +- .../kevin/nshm23/hazardValidation/GridPropInvestigation.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java index 20da026c..f45c90cf 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonCalcScriptWriter.java @@ -61,7 +61,7 @@ public static void main(String[] args) throws IOException { Map gmpes = new EnumMap<>(TectonicRegionType.class); gmpes.put(TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_ACTIVE); - gmpes.put(TectonicRegionType.STABLE_SHALLOW, AttenRelRef.USGS_NSHM23_STABLE); + gmpes.put(TectonicRegionType.STABLE_SHALLOW, AttenRelRef.USGS_NSHM23_STABLE_R2); extraTokens.add("origNGAW2"); gmpes.put(TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.NGAWest_2014_AVG_NOIDRISS); diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java index 35182d3d..f7cd2399 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/ComparisonPageGen.java @@ -191,7 +191,7 @@ public static void main(String[] args) throws IOException { Map gmmRefs = Map.of( TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.USGS_NSHM23_ACTIVE, - TectonicRegionType.STABLE_SHALLOW, AttenRelRef.USGS_NSHM23_STABLE); + TectonicRegionType.STABLE_SHALLOW, AttenRelRef.USGS_NSHM23_STABLE_R2); // TectonicRegionType.ACTIVE_SHALLOW, AttenRelRef.NGAWest_2014_AVG_NOIDRISS); Map gmms = new HashMap<>(); Map wrapperGMMs = gmms; diff --git a/src/main/java/scratch/kevin/nshm23/hazardValidation/GridPropInvestigation.java b/src/main/java/scratch/kevin/nshm23/hazardValidation/GridPropInvestigation.java index 179b487f..e8f4fbaf 100644 --- a/src/main/java/scratch/kevin/nshm23/hazardValidation/GridPropInvestigation.java +++ b/src/main/java/scratch/kevin/nshm23/hazardValidation/GridPropInvestigation.java @@ -49,7 +49,7 @@ public static void main(String[] args) throws IOException { GridSourceList gridList = sol.requireModule(GridSourceList.class); TectonicRegionType trt = TectonicRegionType.STABLE_SHALLOW; - ScalarIMR gmm = AttenRelRef.USGS_NSHM23_STABLE.get(); + ScalarIMR gmm = AttenRelRef.USGS_NSHM23_STABLE_R2.get(); // TectonicRegionType trt = TectonicRegionType.ACTIVE_SHALLOW; // ScalarIMR gmm = AttenRelRef.USGS_NSHM23_ACTIVE.get(); From 03bca7fc8f34cc2ecab372d7ee838ace9eea7764 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Wed, 16 Sep 2026 14:25:55 -0700 Subject: [PATCH 67/71] new plots and calcs --- .../sampling/HazardConvergenceCalcs.java | 141 ++++++++++++++---- .../sampling/HazardConvergencePlots.java | 15 +- .../kevin/sampling/HazardMapPlots.java | 57 ++++--- .../kevin/sampling/SamplingScoreFigures.java | 20 +-- .../sampling/HazardConvergencePlotsTest.java | 9 ++ 5 files changed, 180 insertions(+), 62 deletions(-) diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java index e821de29..bcb4ba77 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java @@ -19,6 +19,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.stream.IntStream; +import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; @@ -50,6 +51,7 @@ public class HazardConvergenceCalcs { static final String LOO_MCS_REFERENCE_NAME = "Pooled MCS, leave span out"; static final String POOLED_SOBOL_REFERENCE_NAME = "Pooled Sobol"; static final String LOO_SOBOL_REFERENCE_NAME = "Pooled Sobol, leave one out"; + static final String POOLED_PO_LHS_REFERENCE_NAME = "Pooled Pairwise-Optimized LHS"; private static final int MAX_RUN_LOAD_THREADS = 4; private static final int MCS_POOL_BOOTSTRAP_REPLICATES = 200; private static final long MCS_POOL_BOOTSTRAP_SEED = 0x5eed5eedL; @@ -66,7 +68,14 @@ public class HazardConvergenceCalcs { runDirs.put(SamplingMethod.MONTE_CARLO, 20000, List.of( new File(PaperPaths.INVS_DIR, "2026_07_17-nshm27-AMSAM-20000samples-mcs"), new File(PaperPaths.INVS_DIR, "2026_09_03-nshm27-AMSAM-20000samples-mcs-unique_seed"), - new File(PaperPaths.INVS_DIR, "2026_09_05-nshm27-AMSAM-20000samples-mcs-unique_seed-2") + new File(PaperPaths.INVS_DIR, "2026_09_05-nshm27-AMSAM-20000samples-mcs-unique_seed-2"), + new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-20000samples-mcs-unique_seed-3") +// new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-20000samples-mcs-unique_seed-4"), +// new File(PaperPaths.INVS_DIR, "2026_09_15-nshm27-AMSAM-20000samples-mcs-unique_seed-5"), +// new File(PaperPaths.INVS_DIR, "2026_09_15-nshm27-AMSAM-20000samples-mcs-unique_seed-6"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-20000samples-mcs-unique_seed-7"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-20000samples-mcs-unique_seed-8"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-20000samples-mcs-unique_seed-9") )); /* @@ -97,6 +106,8 @@ public class HazardConvergenceCalcs { new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-3"), new File(PaperPaths.INVS_DIR, "2026_09_09-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-4"), new File(PaperPaths.INVS_DIR, "2026_09_09-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-5") +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-6"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-7") )); /* @@ -119,7 +130,19 @@ public class HazardConvergenceCalcs { new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-3"), new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-4"), new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-5") +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-6"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-7") )); +// runDirs.put(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, 8192, List.of( +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-2"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-3"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-4"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-5"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-6"), +// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-7") +// )); } public static void main(String[] args) throws IOException { @@ -227,6 +250,14 @@ private static void runSamplingConvergence(List sobolRuns, List poLHSPoolData = largestMethodRuns(fullDesignData, + SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE); + if (!poLHSPoolData.isEmpty()) { + PooledHazardData pooledPOLHSData = buildPooledHazardData(poLHSPoolData, null, gridReg, rp, + POOLED_PO_LHS_REFERENCE_NAME, POOLED_PO_LHS_REFERENCE_NAME); + writePooledHazardFiles(new File(outputDir, "pooled_po_lhs"), + pooledPOLHSData, gridReg, period, rp); + } List comparisons = new ArrayList<>(); for (RunPeriodData data : sobolData) { @@ -280,6 +311,20 @@ private static void runSamplingConvergence(List sobolRuns, List largestMethodRuns(List allData, + SamplingMethod method) { + int largestSize = allData.stream() + .filter(data -> data.run().method() == method) + .mapToInt(data -> data.run().maxSamples()) + .max().orElse(-1); + if (largestSize < 0) + return List.of(); + return allData.stream() + .filter(data -> data.run().method() == method + && data.run().maxSamples() == largestSize) + .toList(); + } + private static List loadRunPeriodData(List runs, GriddedRegion gridReg, double period, ReturnPeriods rp, int... spanCounts) throws IOException { if (runs.isEmpty()) @@ -331,39 +376,40 @@ private static RunPeriodData loadRunPeriodData(RunSpec run, GriddedRegion gridRe ModelHazardMaps maps = loadMaps(new File(run.directory(), "results_hazard.zip"), run.tree(), gridReg, period, rp); double[][] branchMaps = copyValues(maps.individual()); - File hazardResultsDir = new File(run.directory(), "results"); double[] curveX = null; double[][] curveSums = null; Map checkpoints = new TreeMap<>(); Map curveBoundaries = new TreeMap<>(); - for (int b=0; b= 512 && Integer.bitCount(count) == 1; + if (Arrays.stream(spanCounts).anyMatch(size -> (globalOffset+count) % size == 0)) + curveBoundaries.put(count, Arrays.stream(curveSums).map(double[]::clone).toArray(double[][]::new)); + if (fullRun || sobolCheckpoint) { + double[] curveMean = buildCurveMeanMap(curveSums, curveX, count, rp); + checkpoints.put(count, calcHazardStatistics(branchMaps, count, curveMean)); + System.out.println("\tBuilt "+count+"-sample checkpoint"); } - } - int count = b+1; - boolean fullRun = count == run.maxSamples(); - boolean sobolCheckpoint = run.method() == SamplingMethod.OWEN_SCRAMBLED_SOBOL - && count >= 512 && Integer.bitCount(count) == 1; - if (Arrays.stream(spanCounts).anyMatch(size -> (globalOffset+count) % size == 0)) - curveBoundaries.put(count, Arrays.stream(curveSums).map(double[]::clone).toArray(double[][]::new)); - if (fullRun || sobolCheckpoint) { - double[] curveMean = buildCurveMeanMap(curveSums, curveX, count, rp); - checkpoints.put(count, calcHazardStatistics(branchMaps, count, curveMean)); - System.out.println("\tBuilt "+count+"-sample checkpoint"); } } Preconditions.checkState(checkpoints.containsKey(run.maxSamples())); @@ -1224,6 +1270,45 @@ static DiscretizedFunc[] loadBranchCurves(File hazardResultsDir, LogicTreeBranch return SolHazardMapCalc.loadCurvesCSV(csv, gridReg); } + static final class BranchCurveLoader implements AutoCloseable { + private final File hazardResultsDir; + private final File archiveFile; + private final ZipFile archive; + + BranchCurveLoader(File runDir) throws IOException { + hazardResultsDir = new File(runDir, "results"); + archiveFile = new File(runDir, "results_hazard_curves.zip"); + archive = archiveFile.isFile() ? new ZipFile(archiveFile) : null; + if (archive != null) + System.out.println("\tLoading branch curves from "+archiveFile.getAbsolutePath()); + } + + DiscretizedFunc[] load(LogicTreeBranch branch, GriddedRegion gridReg, + double period) throws IOException { + if (archive == null) + return loadBranchCurves(hazardResultsDir, branch, gridReg, period); + + String entryPrefix = branch.buildFileName()+"/" + +SolHazardMapCalc.getCSV_FileName("curves", period); + ZipEntry entry = archive.getEntry(entryPrefix+".gz"); + if (entry == null) + entry = archive.getEntry(entryPrefix); + Preconditions.checkNotNull(entry, "Hazard curves entry doesn't exist in %s: %s[.gz]", + archiveFile.getAbsolutePath(), entryPrefix); + InputStream raw = archive.getInputStream(entry); + try (InputStream in = entry.getName().endsWith(".gz") ? new GZIPInputStream(raw) : raw) { + CSVFile csv = CSVFile.readStream(in, true); + return SolHazardMapCalc.loadCurvesCSV(csv, gridReg); + } + } + + @Override + public void close() throws IOException { + if (archive != null) + archive.close(); + } + } + private enum HazardMetric { MEAN("Mean hazard") { @Override double[] values(StatisticMaps maps) { return maps.mean(); } diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java index 0987fede..e21be679 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java @@ -81,7 +81,7 @@ static String getMethodName(SamplingMethod method) { static { Map prefixes = new HashMap<>(); for (SamplingMethod method : SamplingMethod.values()) - prefixes.put(method, getMethodName(method).toLowerCase().replaceAll("-", "_")); + prefixes.put(method, getMethodName(method).toLowerCase().replaceAll("-", "_").replace("'", "")); METHOD_FILE_PREFIXES = prefixes; } @@ -108,9 +108,12 @@ static void plotPeriod(File outputDir, String periodName) throws IOException { // plotReference(outputDir, references, method, sobolPool, ConvergenceSummary.MAXIMUM_ABSOLUTE); } } - for (boolean sobolPool : new boolean[] {true, false}) + for (boolean sobolPool : new boolean[] {true, false}) { plotMethodReference(outputDir, references, sobolPool, ConvergenceSummary.MEAN_ABSOLUTE, "Absolute difference (%)"); + plotMethodReference(outputDir, references, sobolPool, ConvergenceSummary.MEAN_SIGNED, + "Signed bias (%)"); + } plotRealizationPairs(outputDir, realizationPairs, ConvergenceSummary.MEAN_ABSOLUTE, "Absolute difference (%)"); } @@ -146,7 +149,7 @@ && matchesReference(row, method, sobolPool) String yLabel = summary == ConvergenceSummary.MEAN_SIGNED ? "Signed bias (%)" : summary == ConvergenceSummary.MEAN_ABSOLUTE ? "Absolute difference (%)" : "Maximum absolute difference (%)"; - writePlot(outputDir, prefix, getMethodName(method)+" versus "+(sobolPool ? "Sobol pool" : "MCS pool"), + writePlot(outputDir, prefix, getMethodName(method)+" vs "+(sobolPool ? "Sobol' pool" : "MCS pool"), "Sample count", yLabel, counts, Arrays.stream(counts).mapToObj(Integer::toString).toArray(String[]::new), matching, summary); } @@ -179,8 +182,10 @@ && includeSummary(row.spatialSummary(), spatialSummary)) { if (matching.isEmpty()) return; String referencePrefix = sobolConsensus ? "pooled_sobol" : "pooled_mcs"; - String title = sampleCount+" samples versus " - +(sobolConsensus ? POOLED_SOBOL_REFERENCE : MCS_REFERENCE); +// String title = sampleCount+" samples versus " +// +(sobolConsensus ? POOLED_SOBOL_REFERENCE : MCS_REFERENCE); + String title = sampleCount+" samples vs " + +(sobolConsensus ? "Sobol' pool" : "MCS pool"); writePlot(outputDir, "method_comparison_"+sampleCount+"_"+referencePrefix+"_"+summaryPrefix(spatialSummary), title, "Sampling method", yLabel, IntStream.range(0, labels.size()).toArray(), labels.toArray(String[]::new), matching, spatialSummary); diff --git a/src/main/java/scratch/kevin/sampling/HazardMapPlots.java b/src/main/java/scratch/kevin/sampling/HazardMapPlots.java index 7e614652..5865d8e7 100644 --- a/src/main/java/scratch/kevin/sampling/HazardMapPlots.java +++ b/src/main/java/scratch/kevin/sampling/HazardMapPlots.java @@ -47,7 +47,7 @@ public static void main(String[] args) throws IOException { File convergenceDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence"); int[] sizes = { 512, 1024, 2048, 4096, 8192 }; plotPeriod(new File(convergenceDir, "pga_two_in_50"), 0d, "PGA, "+RP.label, sizes); -// plotPeriod(new File(convergenceDir, "1s_sa_two_in_50"), 1d, "1s SA, "+RP.label, sizes); + plotPeriod(new File(convergenceDir, "1s_sa_two_in_50"), 1d, "1s SA, "+RP.label, sizes); } private static void plotPeriod(File periodDir, double period, String perLabel, int... indvSizes) @@ -76,11 +76,24 @@ private static void plotPeriod(File periodDir, double period, String perLabel, i PooledHazardData mcsPool = loadPool(periodDir, "pooled_mcs", mcsPoolDirs, gridReg, period); PooledHazardData sobolPool = loadPool(periodDir, "pooled_sobol", sobolPoolDirs, gridReg, period); + List poLHSPoolDirs = largestRuns(HazardConvergenceCalcs.runDirs.row( + SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE)); + PooledHazardData poLHSPool = poLHSPoolDirs.isEmpty() ? null + : loadPool(periodDir, "pooled_po_lhs", poLHSPoolDirs, gridReg, period); plotMeanHazard(gridReg, sobolPool.data(), perLabel, mapDir, "pooled_sobol"); plotMeanHazard(gridReg, mcsPool.data(), perLabel, mapDir, "pooled_mcs"); plotComparisons(gridReg, sobolPool.data(), mcsPool.data(), perLabel, mapDir, "pooled_sobol_vs_mcs", - "Pooled Sobol ("+nStr(sobolPool.data)+") vs MCS ("+nStr(mcsPool.data)+")"); + "Pooled Sobol' ("+nStr(sobolPool.data)+") vs MCS ("+nStr(mcsPool.data)+")"); + if (poLHSPool != null) { + plotMeanHazard(gridReg, poLHSPool.data(), perLabel, mapDir, "pooled_po_lhs"); + plotComparisons(gridReg, poLHSPool.data(), mcsPool.data(), perLabel, mapDir, + "pooled_po_lhs_vs_mcs", "Pooled Pairwise-Optimized LHS ("+nStr(poLHSPool.data) + +") vs MCS ("+nStr(mcsPool.data)+")"); + plotComparisons(gridReg, poLHSPool.data(), sobolPool.data(), perLabel, mapDir, + "pooled_po_lhs_vs_sobol", "Pooled Pairwise-Optimized LHS ("+nStr(poLHSPool.data) + +") vs Sobol' ("+nStr(sobolPool.data)+")"); + } // Plot the first realization available for each method and requested sample count. for (int size : indvSizes) { @@ -114,7 +127,7 @@ private static void plotPeriod(File periodDir, double period, String perLabel, i plotComparisons(gridReg, data, refMCS, perLabel, sizeDir, method.name().toLowerCase()+"_vs_pooled_mcs", name+" vs pooled MCS ("+nStr(refMCS)+")"); plotComparisons(gridReg, data, refSobol, perLabel, sizeDir, - method.name().toLowerCase()+"_vs_pooled_sobol", name+" vs pooled Sobol ("+nStr(refSobol)+")"); + method.name().toLowerCase()+"_vs_pooled_sobol", name+" vs pooled Sobol' ("+nStr(refSobol)+")"); } } } @@ -140,6 +153,11 @@ private static List flatten(Map> dirsBySize) { return dirs; } + private static List largestRuns(Map> dirsBySize) { + return dirsBySize.entrySet().stream().max(Map.Entry.comparingByKey()) + .map(Map.Entry::getValue).orElse(List.of()); + } + private static PooledHazardData loadPool(File periodDir, String poolName, List runDirs, GriddedRegion gridReg, double period) throws IOException { Preconditions.checkState(!runDirs.isEmpty(), "No runs available for %s", poolName); @@ -176,22 +194,23 @@ private static DiscretizedFunc[] loadMeanCurves(File runDir, LogicTree tree, GriddedRegion gridReg, double period) throws IOException { double[] xValues = null; double[][] sums = null; - File hazardResultsDir = new File(runDir, "results"); - for (int b=0; b samplingDimensions = new ArrayList<>(); -// for (int i=0; i samplingDimensions = new ArrayList<>(); + for (int i=0; i samplingDimensions = getDimsNSHM23(); // String samplingPrefix = "nshm23_"+samplingDimensions.size()+"d"; - String treeName = "NSHM27-AmSam"; - List samplingDimensions = getDimsNSHM27_AmSam(); - String samplingPrefix = "nshm27_amsam_"+samplingDimensions.size()+"d"; +// String treeName = "NSHM27-AmSam"; +// List samplingDimensions = getDimsNSHM27_AmSam(); +// String samplingPrefix = "nshm27_amsam_"+samplingDimensions.size()+"d"; final int dimensions = samplingDimensions.size(); int numContinuous = 0; diff --git a/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java b/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java index fa20c442..5759bd5f 100644 --- a/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java +++ b/src/test/java/scratch/kevin/sampling/HazardConvergencePlotsTest.java @@ -34,11 +34,20 @@ public class HazardConvergencePlotsTest { rows.add(new ReferenceSummary(row.method(), row.sampleCount(), row.reference(), row.metric(), ConvergenceSummary.MAXIMUM_ABSOLUTE, row.realizations(), 1d, 0.25, 0.5, 1d, 5d, 0.2, row.individualValues())); + for (ReferenceSummary row : new ArrayList<>(rows)) + if (row.spatialSummary() == ConvergenceSummary.MEAN_ABSOLUTE) + rows.add(new ReferenceSummary(row.method(), row.sampleCount(), row.reference(), row.metric(), + ConvergenceSummary.MEAN_SIGNED, row.realizations(), -0.1, 0.05, -0.2, -0.1, 0d, + Double.NaN, new double[] {-0.15, -0.05})); HazardConvergencePlots.plotMethodReference(output.getRoot(), rows, false, ConvergenceSummary.MEAN_ABSOLUTE, "Spatial mean absolute difference (%)"); + HazardConvergencePlots.plotMethodReference(output.getRoot(), rows, false, + ConvergenceSummary.MEAN_SIGNED, "Signed bias (%)"); for (int count : new int[] {512, 1024}) { assertTrue(new java.io.File(output.getRoot(), "method_comparison_"+count+"_pooled_mcs_mean_abs.png").isFile()); + assertTrue(new java.io.File(output.getRoot(), + "method_comparison_"+count+"_pooled_mcs_signed_bias.png").isFile()); } } From 57802c625071e4bbfb5495f136a5ca888d7e6b86 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 18 Sep 2026 12:49:19 -0700 Subject: [PATCH 68/71] new runs --- .../sampling/HazardConvergenceCalcs.java | 136 ++++++++++-------- .../kevin/sampling/HazardMapPlots.java | 56 +++++++- 2 files changed, 125 insertions(+), 67 deletions(-) diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java index bcb4ba77..738defd9 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergenceCalcs.java @@ -55,6 +55,8 @@ public class HazardConvergenceCalcs { private static final int MAX_RUN_LOAD_THREADS = 4; private static final int MCS_POOL_BOOTSTRAP_REPLICATES = 200; private static final long MCS_POOL_BOOTSTRAP_SEED = 0x5eed5eedL; + /** Smallest dyadic Sobol prefix retained as a separate convergence realization. */ + static final int MIN_SOBOL_PREFIX_SAMPLE_COUNT = 512; /** Set to {@code null} to build the Sobol consensus from every available run size. */ static final Integer FIXED_SOBOL_CONSENSUS_SIZE = 8192; @@ -66,86 +68,98 @@ public class HazardConvergenceCalcs { * MCS runs */ runDirs.put(SamplingMethod.MONTE_CARLO, 20000, List.of( - new File(PaperPaths.INVS_DIR, "2026_07_17-nshm27-AMSAM-20000samples-mcs"), - new File(PaperPaths.INVS_DIR, "2026_09_03-nshm27-AMSAM-20000samples-mcs-unique_seed"), - new File(PaperPaths.INVS_DIR, "2026_09_05-nshm27-AMSAM-20000samples-mcs-unique_seed-2"), - new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-20000samples-mcs-unique_seed-3") -// new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-20000samples-mcs-unique_seed-4"), -// new File(PaperPaths.INVS_DIR, "2026_09_15-nshm27-AMSAM-20000samples-mcs-unique_seed-5"), -// new File(PaperPaths.INVS_DIR, "2026_09_15-nshm27-AMSAM-20000samples-mcs-unique_seed-6"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-20000samples-mcs-unique_seed-7"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-20000samples-mcs-unique_seed-8"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-20000samples-mcs-unique_seed-9") + new File(PaperPaths.INVS_DIR, "2026_09_03-nshm27-AMSAM-20000samples-mcs-unique_seed"), // DONE recalc on frontera + new File(PaperPaths.INVS_DIR, "2026_09_05-nshm27-AMSAM-20000samples-mcs-unique_seed-2"), // DONE recalc on frontera + new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-20000samples-mcs-unique_seed-3"), // DONE recalc on frontera + new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-20000samples-mcs-unique_seed-4"), // DONE recalc on CARC + new File(PaperPaths.INVS_DIR, "2026_09_15-nshm27-AMSAM-20000samples-mcs-unique_seed-5"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_15-nshm27-AMSAM-20000samples-mcs-unique_seed-6"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-20000samples-mcs-unique_seed-7"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-20000samples-mcs-unique_seed-8"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-20000samples-mcs-unique_seed-9") // DONE on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-10"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-11"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-12"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-13"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-14"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-15"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-16"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-17"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-18"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-19"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-20000samples-mcs-unique_seed-20") // running on frontera )); /* * Sobol runs */ - runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 512, List.of( - new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-512samples-sobol_scrambled"), - new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-512samples-sobol_scrambled-unique_seed") - )); - runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 1024, List.of( - new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-1024samples-sobol_scrambled"), - new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-1024samples-sobol_scrambled-unique_seed") - )); - runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 2048, List.of( - new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-2048samples-sobol_scrambled"), - new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-2048samples-sobol_scrambled-unique_seed") - )); - runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 4096, List.of( - new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-4096samples-sobol_scrambled"), - new File(PaperPaths.INVS_DIR, "2026_08_25-nshm27-AMSAM-4096samples-sobol_scrambled-unique_seed"), - new File(PaperPaths.INVS_DIR, "2026_08_27-nshm27-AMSAM-4096samples-sobol_scrambled-unique_seed-2"), - new File(PaperPaths.INVS_DIR, "2026_08_27-nshm27-AMSAM-4096samples-sobol_scrambled-unique_seed-3") - )); runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 8192, List.of( - new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-8192samples-sobol_scrambled"), - new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed"), - new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-2"), - new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-3"), - new File(PaperPaths.INVS_DIR, "2026_09_09-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-4"), - new File(PaperPaths.INVS_DIR, "2026_09_09-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-5") -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-6"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-7") + new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-8192samples-sobol_scrambled"), // DONE hazard recalc CARC + new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed"), // DONE hazard recalc CARC +// new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-2"), // submitted hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-3"), // submitted hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_09_09-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-4"), // submitted hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_09_09-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-5") // submitted hazard CARC + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-6"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-sobol_scrambled-unique_seed-7") // DONE on frontera )); +// runDirs.put(SamplingMethod.OWEN_SCRAMBLED_SOBOL, 16384, List.of( +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-16384samples-sobol_scrambled"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-16384samples-sobol_scrambled-unique_seed"), // running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-16384samples-sobol_scrambled-unique_seed-1"),// running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_17-nshm27-AMSAM-16384samples-sobol_scrambled-unique_seed-2"),// running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_14-nshm27-AMSAM-16384samples-sobol_scrambled-unique_seed-3"),// running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_14-nshm27-AMSAM-16384samples-sobol_scrambled-unique_seed-4"),// running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_14-nshm27-AMSAM-16384samples-sobol_scrambled-unique_seed-5"),// running on frontera +// new File(PaperPaths.INVS_DIR, "2026_09_14-nshm27-AMSAM-16384samples-sobol_scrambled-unique_seed-6") // running on frontera +// )); /* * LHS runs + * TODO add more 4096? do 8192? */ - runDirs.put(SamplingMethod.LATIN_HYPERCUBE, 4096, List.of( - new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs"), - new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed"), - new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-2"), - new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-3") - )); +// runDirs.put(SamplingMethod.LATIN_HYPERCUBE, 4096, List.of( // TODO these are ready for recalc, stage jar and submit hazard +// new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs"), // TODO: recalc hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed"), // TODO: recalc hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-2"), // TODO: recalc hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_09_08-nshm27-AMSAM-4096samples-lhs-unique_seed-3") // TODO: recalc hazard CARC +// // TODO: configure/run 4 more +// )); +// runDirs.put(SamplingMethod.LATIN_HYPERCUBE, 8192, List.of( // TODO these are ready for recalc, stage jar and submit hazard +// // TODO: configure/run 8 +// )); /* * Pairwise-LHS runs */ runDirs.put(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, 4096, List.of( - new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise"), - new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed"), - new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-2"), - new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-3"), - new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-4"), - new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-5") -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-6"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-7") +// new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise"), // submitted hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_08_28-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed"), // submitted hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-2"), // submitted hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_08_29-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-3"), // submitted hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-4"), // submitted hazard CARC +// new File(PaperPaths.INVS_DIR, "2026_09_10-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-5") // submitted hazard CARC + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-6"), // DONE on CARC + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-4096samples-lhs_pairwise-unique_seed-7") // DONE on CARC + )); + runDirs.put(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, 8192, List.of( + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-2"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-3"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-4"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-5"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-6"), // DONE on frontera + new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-7") // DONE on frontera )); -// runDirs.put(SamplingMethod.PAIRWISE_OPTIMIZED_LATIN_HYPERCUBE, 8192, List.of( -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-2"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-3"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-4"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-5"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-6"), -// new File(PaperPaths.INVS_DIR, "2026_09_16-nshm27-AMSAM-8192samples-lhs_pairwise-unique_seed-7") -// )); } public static void main(String[] args) throws IOException { + Preconditions.checkState(MIN_SOBOL_PREFIX_SAMPLE_COUNT > 0 + && Integer.bitCount(MIN_SOBOL_PREFIX_SAMPLE_COUNT) == 1, + "MIN_SOBOL_PREFIX_SAMPLE_COUNT must be a positive power of two: %s", + MIN_SOBOL_PREFIX_SAMPLE_COUNT); + File outputDir = new File(PaperPaths.FIGURES_DIR, "hazard_convergence"); Preconditions.checkState(outputDir.exists() || outputDir.mkdir(), "Couldn't create output directory: %s", outputDir.getAbsolutePath()); @@ -402,7 +416,7 @@ private static RunPeriodData loadRunPeriodData(RunSpec run, GriddedRegion gridRe int count = b+1; boolean fullRun = count == run.maxSamples(); boolean sobolCheckpoint = run.method() == SamplingMethod.OWEN_SCRAMBLED_SOBOL - && count >= 512 && Integer.bitCount(count) == 1; + && count >= MIN_SOBOL_PREFIX_SAMPLE_COUNT && Integer.bitCount(count) == 1; if (Arrays.stream(spanCounts).anyMatch(size -> (globalOffset+count) % size == 0)) curveBoundaries.put(count, Arrays.stream(curveSums).map(double[]::clone).toArray(double[][]::new)); if (fullRun || sobolCheckpoint) { diff --git a/src/main/java/scratch/kevin/sampling/HazardMapPlots.java b/src/main/java/scratch/kevin/sampling/HazardMapPlots.java index 5865d8e7..ec3ee72e 100644 --- a/src/main/java/scratch/kevin/sampling/HazardMapPlots.java +++ b/src/main/java/scratch/kevin/sampling/HazardMapPlots.java @@ -7,8 +7,10 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import org.jfree.chart.annotations.XYTextAnnotation; import org.jfree.chart.ui.TextAnchor; @@ -96,6 +98,7 @@ private static void plotPeriod(File periodDir, double period, String perLabel, i } // Plot the first realization available for each method and requested sample count. + Map fullSobolRunCache = new HashMap<>(); for (int size : indvSizes) { File sizeDir = new File(mapDir, size+"_samples"); Preconditions.checkState(sizeDir.exists() || sizeDir.mkdir()); @@ -109,17 +112,27 @@ private static void plotPeriod(File periodDir, double period, String perLabel, i refMCS = mcsPool.without(firstMCSDir, size, data.meanCurves(), gridReg); refSobol = sobolPool.data(); } else { - List runDirs = HazardConvergenceCalcs.runDirs.get(method, size); - if (runDirs == null || runDirs.isEmpty()) + File runDir = selectIndividualRun(method, size, sobolPoolDirs); + if (runDir == null) continue; - File runDir = runDirs.get(0); data = loadRunPrefix(runDir, size, gridReg, period, method == SamplingMethod.OWEN_SCRAMBLED_SOBOL ? sobolPool : null); refMCS = mcsPool.data(); - if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL && sobolPool.contains(runDir)) - refSobol = sobolPool.without(runDir, size, data.meanCurves(), gridReg); - else + if (method == SamplingMethod.OWEN_SCRAMBLED_SOBOL && sobolPool.contains(runDir)) { + int fullRunSize = sobolPool.runSize(runDir); + HazardData fullRun = data; + if (size < fullRunSize) { + fullRun = fullSobolRunCache.get(runDir.getAbsoluteFile()); + if (fullRun == null) { + fullRun = loadRunPrefix(runDir, fullRunSize, gridReg, period, sobolPool); + fullSobolRunCache.put(runDir.getAbsoluteFile(), fullRun); + } + } + // Prefixes from one scramble are not independent of its suffix, so exclude the entire parent run. + refSobol = sobolPool.without(runDir, fullRunSize, fullRun.meanCurves(), gridReg); + } else { refSobol = sobolPool.data(); + } } String name = "Individual "+HazardConvergencePlots.getMethodName(method)+" ("+nStr(data)+")"; @@ -131,6 +144,31 @@ private static void plotPeriod(File periodDir, double period, String perLabel, i } } } + + private static File selectIndividualRun(SamplingMethod method, int sampleCount, + List sobolPoolDirs) { + List exactRuns = HazardConvergenceCalcs.runDirs.get(method, sampleCount); + if (exactRuns != null && !exactRuns.isEmpty()) + return exactRuns.get(0); + if (method != SamplingMethod.OWEN_SCRAMBLED_SOBOL) + return null; + + // Sobol sequences are nested: a larger realization supplies every shorter leading prefix. Prefer a parent + // already in the consensus pool so that the comparison can apply the same leave-one-out treatment as the + // convergence calculations. + Map> sobolRuns = HazardConvergenceCalcs.runDirs.row(method); + for (Map.Entry> entry : new TreeMap<>(sobolRuns).entrySet()) { + if (entry.getKey() < sampleCount) + continue; + for (File runDir : entry.getValue()) + if (sobolPoolDirs.contains(runDir)) + return runDir; + } + for (Map.Entry> entry : new TreeMap<>(sobolRuns).entrySet()) + if (entry.getKey() >= sampleCount && !entry.getValue().isEmpty()) + return entry.getValue().get(0); + return null; + } private static final DecimalFormat groupedDF = new DecimalFormat("0"); static { @@ -462,6 +500,12 @@ boolean contains(File runDir) { .map(RunBlock::branchMaps).orElse(null); } + int runSize(File runDir) { + double[][] maps = branchMaps(runDir); + Preconditions.checkState(maps != null, "Run is not in pooled data: %s", runDir.getName()); + return maps.length; + } + HazardData without(File runDir, int excludedCount, DiscretizedFunc[] excludedMean, GriddedRegion gridReg) { Preconditions.checkState(contains(runDir), "Run is not in pooled data: %s", runDir.getName()); From 00a510e5d8d29189617bb6ea0938b45a16115d13 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 18 Sep 2026 13:34:43 -0700 Subject: [PATCH 69/71] new ColorUtils with consolidated transparent/saturate methods --- .../scratch/kevin/bbp/ShakeMoviePlotter.java | 4 ---- .../scratch/kevin/bbp/SpectraPlotter.java | 5 +++-- .../kevin/ltSampling/LHSExampleFigures.java | 3 ++- .../SimulatedAnnealingExampleAnimation.java | 3 ++- .../kevin/miscFigures/U3vsPopulationMap.java | 16 -------------- .../nshm23/AnnealingThreadTimeCompare.java | 7 ++++--- .../nshm23/BValSweepHazardComparison.java | 21 +++---------------- .../kevin/nshm23/MultiRunSummaryCompare.java | 3 ++- .../figures/BValPlusSegModelMFDPlot.java | 5 +++-- .../nshm23/figures/BranchChoiceMFDsPlot.java | 7 ++++--- .../nshm23/figures/MagExceedProbFigure.java | 3 ++- .../figures/ObservedMFDComparisons.java | 3 ++- .../ObservedUncertainMFDComparisons.java | 5 +++-- .../nshm23/figures/Regional_MFD_Plots.java | 5 +++-- .../figures/SlipRateScattersPaleoSects.java | 3 ++- .../kevin/nshm23/figures/SupraBValFigure.java | 5 +++-- .../figures/WestCacheConnectivityFigures.java | 3 ++- .../hazardValidation/ComparisonPageGen.java | 13 +++++------- .../scratch/kevin/nshm27/SamplerTest.java | 3 ++- .../kevin/nshm27/figures/BValDistFigure.java | 5 +++-- .../nshm27/figures/CombinedMFDsFigure.java | 7 ++++--- .../InterfaceLogicTreeMFDExploration.java | 7 ++++--- .../kevin/pointSources/DippingFaultTests.java | 5 +++-- .../pointSources/InvCDF_RJBTableWriter.java | 3 ++- .../SpinningFaultExceedanceFigures.java | 13 +++++------- .../scratch/kevin/prvi25/AnegadaMFDTests.java | 7 ++++--- .../GriddedRateDistributionPlotter.java | 5 +++-- .../prvi25/LogicTreeLineIntegralCalc.java | 3 ++- .../kevin/prvi25/SubductionDefModConvert.java | 9 ++++---- .../DefModelSampleLineIntegralsPlot.java | 3 ++- .../prvi25/figures/IndividualMFDPlots.java | 7 ++++--- .../sampling/HazardConvergencePlots.java | 3 ++- .../plots/SlipLengthScalingPlot.java | 7 ++++--- .../simulators/plots/StationarityPlot.java | 3 ++- .../MultifaultSeparatePageGen.java | 3 ++- .../simulators/synch/RecurrencePlotGen.java | 21 +++---------------- .../etas/ETAS_CatalogEALCalculator.java | 3 ++- 37 files changed, 103 insertions(+), 128 deletions(-) diff --git a/src/main/java/scratch/kevin/bbp/ShakeMoviePlotter.java b/src/main/java/scratch/kevin/bbp/ShakeMoviePlotter.java index 6c16fbf6..3d986873 100644 --- a/src/main/java/scratch/kevin/bbp/ShakeMoviePlotter.java +++ b/src/main/java/scratch/kevin/bbp/ShakeMoviePlotter.java @@ -342,10 +342,6 @@ else if (xRange.getLength() > 0.75) } - private static Color getWithAlpha(Color c, int alpha) { - return new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); - } - private static DecimalFormat timeDF = new DecimalFormat("0.0#"); public static void main(String[] args) throws ZipException, IOException, DocumentException { diff --git a/src/main/java/scratch/kevin/bbp/SpectraPlotter.java b/src/main/java/scratch/kevin/bbp/SpectraPlotter.java index e8b6b730..b1f6d217 100644 --- a/src/main/java/scratch/kevin/bbp/SpectraPlotter.java +++ b/src/main/java/scratch/kevin/bbp/SpectraPlotter.java @@ -19,6 +19,7 @@ import org.jfree.chart.annotations.XYTextAnnotation; import org.jfree.data.Range; import org.jfree.chart.ui.TextAnchor; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.calc.FractileCurveCalculator; import org.opensha.commons.data.Site; import org.opensha.commons.data.function.AbstractXY_DataSet; @@ -885,7 +886,7 @@ public static void plotRotDRatioPeriodDependence(List rds, Li rangeFuncs.add(rangeFunc); rangeChars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, - new Color(c.getRed(), c.getGreen(), c.getBlue(), 50))); + ColorUtils.transparent(c, 50))); meanFunc.setName((float)period+"s"); funcs.add(meanFunc); @@ -1033,7 +1034,7 @@ public static void plotRotDRatioScatter(List rds, List 0) private static Color TARGET_COLOR = Color.GRAY; private static Color SOL_COLOR = Color.BLACK; private static float LINE_THICKNESS = 4f; - private static Color UNCERT_COLOR = new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 100); + private static Color UNCERT_COLOR = ColorUtils.transparent(Color.CYAN, 100); private static boolean PLOT_UNCERT = false; private static PlotSpec buildSlipPlot(FaultSystemRupSet rupSet, diff --git a/src/main/java/scratch/kevin/miscFigures/U3vsPopulationMap.java b/src/main/java/scratch/kevin/miscFigures/U3vsPopulationMap.java index 5676f809..52f564eb 100644 --- a/src/main/java/scratch/kevin/miscFigures/U3vsPopulationMap.java +++ b/src/main/java/scratch/kevin/miscFigures/U3vsPopulationMap.java @@ -353,22 +353,6 @@ public int compare(FaultSection o1, FaultSection o2) { System.out.println("DONE"); } - private static final int saturation_steps = 1; - - private static Color saturate(Color c) { - int r = c.getRed(); - int g = c.getGreen(); - int b = c.getBlue(); - - for (int i=0; i> levels = new ArrayList<>(); levels.add(null); diff --git a/src/main/java/scratch/kevin/nshm23/figures/ObservedUncertainMFDComparisons.java b/src/main/java/scratch/kevin/nshm23/figures/ObservedUncertainMFDComparisons.java index a6ac90c4..4dcb8137 100644 --- a/src/main/java/scratch/kevin/nshm23/figures/ObservedUncertainMFDComparisons.java +++ b/src/main/java/scratch/kevin/nshm23/figures/ObservedUncertainMFDComparisons.java @@ -14,6 +14,7 @@ import org.jfree.chart.ui.RectangleAnchor; import org.jfree.data.Range; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DiscretizedFunc; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; @@ -185,7 +186,7 @@ public static void main(String[] args) throws IOException { PlotCurveCharacterstics estBoundsChar = new PlotCurveCharacterstics(PlotLineType.DASHED, 1f, Color.GRAY); Color obsColor = new Color(125, 80, 145); // "indigo" - Color obsTransColor = new Color(obsColor.getRed(), obsColor.getGreen(), obsColor.getBlue(), 60); + Color obsTransColor = ColorUtils.transparent(obsColor, 60); List> levels = new ArrayList<>(); levels.add(null); @@ -402,7 +403,7 @@ public static void main(String[] args) throws IOException { chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, color)); if (modelTotBounds != null) { - Color transColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 80); + Color transColor = ColorUtils.transparent(color, 80); modelTotBounds.setName("Model Total "+((UncertainBoundedDiscretizedFunc)modelTotBounds).getBoundName()); funcs.add(modelTotBounds); chars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 3f, transColor)); diff --git a/src/main/java/scratch/kevin/nshm23/figures/Regional_MFD_Plots.java b/src/main/java/scratch/kevin/nshm23/figures/Regional_MFD_Plots.java index b64b3223..ec4ca3d7 100644 --- a/src/main/java/scratch/kevin/nshm23/figures/Regional_MFD_Plots.java +++ b/src/main/java/scratch/kevin/nshm23/figures/Regional_MFD_Plots.java @@ -24,6 +24,7 @@ import org.jfree.chart.ui.RectangleAnchor; import org.jfree.data.Range; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; import org.opensha.commons.data.function.XY_DataSet; @@ -399,7 +400,7 @@ private static void writePlot(NSHM23_BaseRegion aReg, EvenlyDiscretizedFunc refM incrFuncs.add(dataForBounds); incrChars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, - new Color(obsColor.getRed(), obsColor.getGreen(), obsColor.getBlue(), 60))); + ColorUtils.transparent(obsColor, 60))); EvenlyDiscretizedFunc upperCumulative = getCmlAsFakeIncr(dataBounds.getUpper()); EvenlyDiscretizedFunc lowerCumulative = getCmlAsFakeIncr(dataBounds.getLower()); @@ -413,7 +414,7 @@ private static void writePlot(NSHM23_BaseRegion aReg, EvenlyDiscretizedFunc refM cmlBounded.setName(dataBounds.getBoundName()); cmlFuncs.add(cmlBounded); cmlChars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, - new Color(obsColor.getRed(), obsColor.getGreen(), obsColor.getBlue(), 60))); + ColorUtils.transparent(obsColor, 60))); } Preconditions.checkState(incrFuncs.size() == cmlFuncs.size()); diff --git a/src/main/java/scratch/kevin/nshm23/figures/SlipRateScattersPaleoSects.java b/src/main/java/scratch/kevin/nshm23/figures/SlipRateScattersPaleoSects.java index 3d7ddf20..c037bf35 100644 --- a/src/main/java/scratch/kevin/nshm23/figures/SlipRateScattersPaleoSects.java +++ b/src/main/java/scratch/kevin/nshm23/figures/SlipRateScattersPaleoSects.java @@ -17,6 +17,7 @@ import org.apache.commons.math3.stat.correlation.Covariance; import org.jfree.chart.ui.RectangleAnchor; import org.jfree.data.Range; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DefaultXY_DataSet; @@ -428,7 +429,7 @@ else if (prefix.contains("under")) funcs.add(0, fit); chars.add(0, new PlotCurveCharacterstics(PlotLineType.DASHED, 3f, - new Color(color.getRed(), color.getGreen(), color.getBlue(), 120))); + ColorUtils.transparent(color, 120))); } PlotSpec spec = new PlotSpec(funcs, chars, " ", "Slip Rate Fit z-score", "Paleoseismic Rate Fit z-score"); diff --git a/src/main/java/scratch/kevin/nshm23/figures/SupraBValFigure.java b/src/main/java/scratch/kevin/nshm23/figures/SupraBValFigure.java index fd9b49e3..1b4887dd 100644 --- a/src/main/java/scratch/kevin/nshm23/figures/SupraBValFigure.java +++ b/src/main/java/scratch/kevin/nshm23/figures/SupraBValFigure.java @@ -11,6 +11,7 @@ import org.jfree.chart.annotations.XYTextAnnotation; import org.jfree.chart.ui.TextAnchor; import org.jfree.data.Range; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.calc.FaultMomentCalc; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DefaultXY_DataSet; @@ -230,10 +231,10 @@ public static void main(String[] args) throws IOException { grPlusCharXY2.set(transBCrossover, totRateGR2); funcs.add(grPlusCharXY1); chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 2f, - new Color(darkGreen.getRed(), darkGreen.getGreen(), darkGreen.getBlue(), 120))); + ColorUtils.transparent(darkGreen, 120))); funcs.add(grPlusCharXY2); chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 2f, - new Color(brightGreen.getRed(), brightGreen.getGreen(), brightGreen.getBlue(), 120))); + ColorUtils.transparent(brightGreen, 120))); DefaultXY_DataSet grDot1 = new DefaultXY_DataSet(); grDot1.set(grB1, totRateGR1); DefaultXY_DataSet grDot2 = new DefaultXY_DataSet(); diff --git a/src/main/java/scratch/kevin/nshm23/figures/WestCacheConnectivityFigures.java b/src/main/java/scratch/kevin/nshm23/figures/WestCacheConnectivityFigures.java index 376b973a..4465108b 100644 --- a/src/main/java/scratch/kevin/nshm23/figures/WestCacheConnectivityFigures.java +++ b/src/main/java/scratch/kevin/nshm23/figures/WestCacheConnectivityFigures.java @@ -16,6 +16,7 @@ import org.jfree.chart.annotations.XYTextAnnotation; import org.jfree.chart.ui.TextAnchor; import org.jfree.data.Range; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DefaultXY_DataSet; import org.opensha.commons.data.function.XY_DataSet; @@ -145,7 +146,7 @@ public static void main(String[] args) throws IOException { List chars = new ArrayList<>(); Color grColor = Color.CYAN; - grColor = new Color(grColor.getRed(), grColor.getGreen(), grColor.getBlue(), 100); + grColor = ColorUtils.transparent(grColor, 100); IncrementalMagFreqDist redistBins = new IncrementalMagFreqDist(pureGR.getMinX(), pureGR.size(), pureGR.getDelta()); for (int i=0; i sources, BiFunction function, Col label = Label; this.function = function; this.color = color; - this.transColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 80); + this.transColor = ColorUtils.transparent(color, 80); } }; @@ -1614,8 +1615,8 @@ public static void main(String[] args) throws IOException { } // spin the centered surfaces - Color centeredHWColor = overWhite(transColor(Colors.tab_blue, 80)); - Color centeredFWColor = overWhite(transColor(Colors.tab_lightblue, 80)); + Color centeredHWColor = overWhite(ColorUtils.transparent(Colors.tab_blue, 80)); + Color centeredFWColor = overWhite(ColorUtils.transparent(Colors.tab_lightblue, 80)); if (mech == FocalMech.STRIKE_SLIP) { // simple, no hw/fw DefaultXY_DataSet xyCircle = new DefaultXY_DataSet(); @@ -2043,7 +2044,7 @@ private static void addTransOutlineFuncs(List funcs, List funcs, List funcs = new ArrayList<>(); List chars = new ArrayList<>(); diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java index e21be679..9d54f14c 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java @@ -20,6 +20,7 @@ import org.jfree.chart.ui.RectangleAnchor; import org.jfree.chart.ui.RectangleInsets; import org.jfree.data.Range; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DefaultXY_DataSet; @@ -291,7 +292,7 @@ private static void writePlot(File outputDir, String prefix, String title, Strin UncertainArbDiscFunc uncertainty = new UncertainArbDiscFunc(median, lower, upper); funcs.add(uncertainty); chars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, - new Color(color.getRed(), color.getGreen(), color.getBlue(), 70))); + ColorUtils.transparent(color, 70))); } if (indvMeans != null) { medianFuncs.add(indvMeans); diff --git a/src/main/java/scratch/kevin/simulators/plots/SlipLengthScalingPlot.java b/src/main/java/scratch/kevin/simulators/plots/SlipLengthScalingPlot.java index 101d8927..06752711 100644 --- a/src/main/java/scratch/kevin/simulators/plots/SlipLengthScalingPlot.java +++ b/src/main/java/scratch/kevin/simulators/plots/SlipLengthScalingPlot.java @@ -21,6 +21,7 @@ import org.jfree.chart.annotations.XYTextAnnotation; import org.jfree.data.Range; import org.jfree.chart.ui.TextAnchor; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DefaultXY_DataSet; import org.opensha.commons.data.function.DiscretizedFunc; @@ -503,12 +504,12 @@ private void plotExample() throws IOException { if (midSeis) { // make it a little transparent - fillColor = new Color(fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue(), 160); + fillColor = ColorUtils.transparent(fillColor, 160); } else { // make it very transparent - fillColor = new Color(fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue(), 80); + fillColor = ColorUtils.transparent(fillColor, 80); if (!slipped) - paint = new Color(paint.getRed(), paint.getGreen(), paint.getBlue(), 127); + paint = ColorUtils.transparent(paint, 127); } double[] polyElems = new double[verts.length*2]; diff --git a/src/main/java/scratch/kevin/simulators/plots/StationarityPlot.java b/src/main/java/scratch/kevin/simulators/plots/StationarityPlot.java index 0d85676c..ef130cc4 100644 --- a/src/main/java/scratch/kevin/simulators/plots/StationarityPlot.java +++ b/src/main/java/scratch/kevin/simulators/plots/StationarityPlot.java @@ -9,6 +9,7 @@ import org.jfree.chart.ui.RectangleEdge; import org.jfree.data.Range; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.data.function.ArbitrarilyDiscretizedFunc; import org.opensha.commons.data.function.DefaultXY_DataSet; import org.opensha.commons.data.function.EvenlyDiscretizedFunc; @@ -198,7 +199,7 @@ public void finalizePlot() throws IOException { straightLine.set(maxX, meanForMag); funcs.add(straightLine); chars.add(new PlotCurveCharacterstics(PlotLineType.DASHED, 2f, - new Color(c.getRed(), c.getGreen(), c.getBlue(), 100))); + ColorUtils.transparent(c, 100))); } String title = getCatalogName()+" Stationarity"; diff --git a/src/main/java/scratch/kevin/simulators/ruptures/multifaultSeparate/MultifaultSeparatePageGen.java b/src/main/java/scratch/kevin/simulators/ruptures/multifaultSeparate/MultifaultSeparatePageGen.java index a86d93fa..a740e227 100644 --- a/src/main/java/scratch/kevin/simulators/ruptures/multifaultSeparate/MultifaultSeparatePageGen.java +++ b/src/main/java/scratch/kevin/simulators/ruptures/multifaultSeparate/MultifaultSeparatePageGen.java @@ -16,6 +16,7 @@ import java.util.concurrent.Future; import org.jfree.data.Range; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.data.CSVFile; import org.opensha.commons.data.Site; import org.opensha.commons.data.function.DefaultXY_DataSet; @@ -516,7 +517,7 @@ private static void writeScatter(File outputDir, String prefix, double period, D String title = Double.isFinite(period) ? oDF.format(period)+"s SA" : "All Periods"; - color = new Color(color.getRed(), color.getGreen(), color.getBlue(), 80); + color = ColorUtils.transparent(color, 80); for (boolean log : new boolean[] {false, true}) { Range range; diff --git a/src/main/java/scratch/kevin/simulators/synch/RecurrencePlotGen.java b/src/main/java/scratch/kevin/simulators/synch/RecurrencePlotGen.java index 62b7f9c7..3bf5b240 100644 --- a/src/main/java/scratch/kevin/simulators/synch/RecurrencePlotGen.java +++ b/src/main/java/scratch/kevin/simulators/synch/RecurrencePlotGen.java @@ -39,6 +39,7 @@ import org.opensha.commons.gui.plot.jfreechart.xyzPlot.XYZPlotSpec; import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.util.ComparablePairing; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.commons.util.FileUtils; import org.opensha.commons.util.cpt.CPT; @@ -306,8 +307,8 @@ private static CPT getHybridCPT(double threshold, double maxZ) throws IOExceptio // saturate for (CPTVal v : cpt) { - v.minColor = saturate(v.minColor); - v.maxColor = saturate(v.maxColor); + v.minColor = ColorUtils.saturate(v.minColor, 2); + v.maxColor = ColorUtils.saturate(v.maxColor, 2); } cpt.setAboveMaxColor(cpt.getMaxColor()); @@ -323,22 +324,6 @@ private static CPT getHybridCPT(double threshold, double maxZ) throws IOExceptio return cpt; } - private static Color saturate(Color c) { - int r = c.getRed(); - int g = c.getGreen(); - int b = c.getBlue(); - - int saturationSteps = 2; - - for (int i=0; i myElems = Lists.newArrayList(); List myChars = Lists.newArrayList(); - Color rangeColor = new Color((c.getRed()+255)/2, (c.getGreen()+255)/2, (c.getBlue()+255)/2); + Color rangeColor = ColorUtils.saturate(c, 1); if (hasConf) { // UncertainArbDiscDataset confRange = null; // try { From ee1e375b01188ee7afa71d8b8b4946c84152a691 Mon Sep 17 00:00:00 2001 From: Kevin Milner Date: Fri, 18 Sep 2026 13:41:59 -0700 Subject: [PATCH 70/71] consolidated additional color utility methods --- .../kevin/miscFigures/SCECStatewide.java | 12 ++------ .../kevin/miscFigures/U3vsPopulationMap.java | 12 ++------ .../SpinningFaultExceedanceFigures.java | 28 ++----------------- 3 files changed, 9 insertions(+), 43 deletions(-) diff --git a/src/main/java/scratch/kevin/miscFigures/SCECStatewide.java b/src/main/java/scratch/kevin/miscFigures/SCECStatewide.java index cb8af376..c48cffba 100644 --- a/src/main/java/scratch/kevin/miscFigures/SCECStatewide.java +++ b/src/main/java/scratch/kevin/miscFigures/SCECStatewide.java @@ -24,6 +24,7 @@ import org.opensha.commons.gui.plot.PlotSymbol; import org.opensha.commons.gui.plot.PlotUtils; import org.opensha.commons.mapping.PoliticalBoundariesData; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.util.FaultUtils; import org.opensha.commons.util.Interpolate; import org.opensha.commons.util.cpt.CPT; @@ -221,7 +222,7 @@ else if (prob >= probCPT.getMaxValue()) color = Color.WHITE; } else { weight = (dist-minSaturateDist)/(maxPlotDist-minSaturateDist); - color = blend(Color.WHITE, color, weight); + color = ColorUtils.blend(color, Color.WHITE, weight); } // Preconditions.checkState(weight >= 0d && weight <= 1d, "Bad weight: %s", weight); // color = new Color(color.getRed(), color.getGreen(), color.getBlue(), (int)(255d*weight)); @@ -229,7 +230,7 @@ else if (prob >= probCPT.getMaxValue()) // int alpha = cpt.getColor((float)distScalar).getAlpha(); //// color = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); // double weight = (double)alpha -// color = blend(scecRed, color, alpha) +// color = ColorUtils.blend(color, scecRed, alpha) } chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, (float)thickness, color)); } @@ -325,11 +326,4 @@ private static void writePlot(File outputDir, String prefix, HeadlessGraphPanel PlotUtils.writePlots(outputDir, prefix, gp, 1200, true, true, true, false); } - private static Color blend(Color c1, Color c2, double weight) { - float r = (float)((weight*c1.getRed() + (1d-weight)*c2.getRed())/255d); - float g = (float)((weight*c1.getGreen() + (1d-weight)*c2.getGreen())/255d); - float b = (float)((weight*c1.getBlue() + (1d-weight)*c2.getBlue())/255d); - return new Color(r, g, b); - } - } diff --git a/src/main/java/scratch/kevin/miscFigures/U3vsPopulationMap.java b/src/main/java/scratch/kevin/miscFigures/U3vsPopulationMap.java index 52f564eb..9f301c83 100644 --- a/src/main/java/scratch/kevin/miscFigures/U3vsPopulationMap.java +++ b/src/main/java/scratch/kevin/miscFigures/U3vsPopulationMap.java @@ -21,6 +21,7 @@ import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files; import org.opensha.commons.mapping.gmt.elements.PSXYPolygon; import org.opensha.commons.mapping.gmt.elements.TopographicSlopeFile; +import org.opensha.commons.util.ColorUtils; import org.opensha.commons.util.DataUtils.MinMaxAveTracker; import org.opensha.commons.util.cpt.CPT; import org.opensha.commons.util.cpt.CPTVal; @@ -152,8 +153,8 @@ public static void main(String[] args) throws IOException, GMT_MapException { // for (int i=0; i funcs, List Date: Fri, 18 Sep 2026 14:41:36 -0700 Subject: [PATCH 71/71] option for std dev range in signed bias plots --- .../kevin/sampling/HazardConvergencePlots.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java index 9d54f14c..64367caf 100644 --- a/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java +++ b/src/main/java/scratch/kevin/sampling/HazardConvergencePlots.java @@ -49,6 +49,7 @@ public class HazardConvergencePlots { private static final SamplingMethod MCS = SamplingMethod.MONTE_CARLO; private static final SamplingMethod SOBOL = SamplingMethod.OWEN_SCRAMBLED_SOBOL; + private static final boolean INCLUDE_SIGNED_VARIABILITY_UNCERTAINTIES = true; // private static final ConvergenceMetric[] PLOT_METRICS = ConvergenceMetric.values(); static final ConvergenceMetric[] PLOT_METRICS = { @@ -286,13 +287,22 @@ private static void writePlot(File outputDir, String prefix, String title, Strin Color color = METRIC_COLORS.get(entry.getKey()); PlotSymbol sym = METRIC_SYMBOLS.get(entry.getKey()); PlotSymbol outlineSym = PlotSymbol.getOutlineSymbol(sym); - // Signed ranges overlap heavily, so only show mean +/- one standard deviation for mean hazard. Positive quantities use the - // median-centered multiplicative range defined by one standard deviation of the log-transformed values. + // Positive quantities use a shaded, median-centered multiplicative range defined by one standard + // deviation of the log-transformed values. For signed biases, retain that shading for mean hazard but + // draw the other mean +/- standard-deviation ranges as unobtrusive dotted bounds to avoid overlapping + // shaded regions. if (!signed || entry.getKey() == ConvergenceMetric.MEAN_HAZARD) { UncertainArbDiscFunc uncertainty = new UncertainArbDiscFunc(median, lower, upper); funcs.add(uncertainty); chars.add(new PlotCurveCharacterstics(PlotLineType.SHADED_UNCERTAIN, 1f, ColorUtils.transparent(color, 70))); + } else if (INCLUDE_SIGNED_VARIABILITY_UNCERTAINTIES) { + funcs.add(lower); + chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 1f, + ColorUtils.transparent(color, 120))); + funcs.add(upper); + chars.add(new PlotCurveCharacterstics(PlotLineType.DOTTED, 1f, + ColorUtils.transparent(color, 120))); } if (indvMeans != null) { medianFuncs.add(indvMeans);