|
| 1 | +package scratch.kevin.nshm23.prvi; |
| 2 | + |
| 3 | +import java.io.BufferedReader; |
| 4 | +import java.io.File; |
| 5 | +import java.io.IOException; |
| 6 | +import java.io.InputStreamReader; |
| 7 | +import java.util.ArrayList; |
| 8 | +import java.util.List; |
| 9 | +import java.util.Map; |
| 10 | +import java.util.zip.ZipEntry; |
| 11 | +import java.util.zip.ZipFile; |
| 12 | + |
| 13 | +import org.apache.commons.cli.CommandLine; |
| 14 | +import org.apache.commons.cli.Options; |
| 15 | +import org.opensha.commons.geo.GriddedRegion; |
| 16 | +import org.opensha.commons.geo.json.Feature; |
| 17 | +import org.opensha.commons.logicTree.LogicTree; |
| 18 | +import org.opensha.commons.logicTree.LogicTreeLevel; |
| 19 | +import org.opensha.commons.logicTree.LogicTreeLevel.FileBackedLevel; |
| 20 | +import org.opensha.commons.logicTree.LogicTreeNode; |
| 21 | +import org.opensha.commons.logicTree.LogicTreeNode.FileBackedNode; |
| 22 | +import org.opensha.commons.util.modules.ModuleContainer; |
| 23 | +import org.opensha.sha.earthquake.faultSysSolution.hazard.AbstractLogicTreeHazardCombiner; |
| 24 | +import org.opensha.sha.earthquake.faultSysSolution.hazard.mpj.MPJ_LogicTreeHazardCalc; |
| 25 | +import org.opensha.sha.earthquake.faultSysSolution.modules.SolutionLogicTree; |
| 26 | +import org.opensha.sha.earthquake.faultSysSolution.util.FaultSysTools; |
| 27 | +import org.opensha.sha.earthquake.param.IncludeBackgroundOption; |
| 28 | + |
| 29 | +import com.google.common.base.Preconditions; |
| 30 | + |
| 31 | +public class CrustalSubductionLogicTreeCombine extends AbstractLogicTreeHazardCombiner { |
| 32 | + |
| 33 | + private static final IncludeBackgroundOption GRID_SEIS_DEFAULT = IncludeBackgroundOption.EXCLUDE; |
| 34 | + private static final String RESULTS_FILE_NAME_DEFAULT = "results.zip"; |
| 35 | + private static final String HAZARD_DIR_NAME_DEFAULT = "results"; |
| 36 | + private static final String GRID_REG_FILE_NAME_DEFAULT = "results_hazard.zip"; // get region from hazard zip |
| 37 | + |
| 38 | + public static void main(String[] args) throws IOException { |
| 39 | + CommandLine cmd = FaultSysTools.parseOptions(createOptions(), args, CrustalSubductionLogicTreeCombine.class); |
| 40 | + args = cmd.getArgs(); |
| 41 | + Preconditions.checkArgument(args.length == 3, "USAGE: <crustal-dir> <subduction-dir> <output-dir>"); |
| 42 | + ModuleContainer.VERBOSE_DEFAULT = false; |
| 43 | + File crustalDir = new File(args[0]); |
| 44 | + Preconditions.checkState(crustalDir.exists(), |
| 45 | + "Crustal directory doesn't exist: %s", crustalDir.getAbsolutePath()); |
| 46 | + File subductionDir = new File(args[1]); |
| 47 | + Preconditions.checkState(subductionDir.exists(), |
| 48 | + "Subduction directory doesn't exist: %s", subductionDir.getAbsolutePath()); |
| 49 | + File outputDir = new File(args[2]); |
| 50 | + Preconditions.checkState(outputDir.exists() || outputDir.mkdir(), |
| 51 | + "Output directory doesn't exist and couldn't be created: %s", outputDir.getAbsolutePath()); |
| 52 | + |
| 53 | + String resultsFileName = RESULTS_FILE_NAME_DEFAULT; |
| 54 | + if (cmd.hasOption("results-file-name")) |
| 55 | + resultsFileName = cmd.getOptionValue("results-file-name"); |
| 56 | + String hazardDirName = HAZARD_DIR_NAME_DEFAULT; |
| 57 | + if (cmd.hasOption("hazard-dir-name")) |
| 58 | + hazardDirName = cmd.getOptionValue("hazard-dir-name"); |
| 59 | + String gridRegFileName = GRID_REG_FILE_NAME_DEFAULT; |
| 60 | + if (cmd.hasOption("grid-reg-file-name")) |
| 61 | + gridRegFileName = cmd.getOptionValue("grid-reg-file-name"); |
| 62 | + IncludeBackgroundOption bgOp = GRID_SEIS_DEFAULT; |
| 63 | + if (cmd.hasOption("gridded-seis")) |
| 64 | + bgOp = IncludeBackgroundOption.valueOf(cmd.getOptionValue("gridded-seis")); |
| 65 | + |
| 66 | + SolutionLogicTree crustalSLT = SolutionLogicTree.load(new File(crustalDir, resultsFileName)); |
| 67 | + SolutionLogicTree subductionSLT = SolutionLogicTree.load(new File(subductionDir, resultsFileName)); |
| 68 | + |
| 69 | + crustalSLT.setVerbose(false); |
| 70 | + subductionSLT.setVerbose(false); |
| 71 | + |
| 72 | + GriddedRegion gridReg = loadGridReg(new File(crustalDir, gridRegFileName)); |
| 73 | + Preconditions.checkState(gridReg.equals(loadGridReg(new File(subductionDir, gridRegFileName))), |
| 74 | + "Crustal and subduction gridded regions differ"); |
| 75 | + |
| 76 | + String outputHazardFileName; |
| 77 | + if (bgOp == IncludeBackgroundOption.EXCLUDE) |
| 78 | + outputHazardFileName = "results_hazard.zip"; |
| 79 | + else if (bgOp == IncludeBackgroundOption.INCLUDE) |
| 80 | + outputHazardFileName = "results_hazard_gridded.zip"; |
| 81 | + else if (bgOp == IncludeBackgroundOption.ONLY) |
| 82 | + outputHazardFileName = "results_hazard_gridded_only.zip"; |
| 83 | + else |
| 84 | + throw new IllegalStateException(); |
| 85 | + |
| 86 | + CrustalSubductionLogicTreeCombine combiner = new CrustalSubductionLogicTreeCombine( |
| 87 | + crustalSLT, new File(crustalDir, hazardDirName), bgOp, |
| 88 | + subductionSLT, new File(subductionDir, hazardDirName), bgOp, |
| 89 | + new File(outputDir, resultsFileName), |
| 90 | + new File(outputDir, outputHazardFileName), gridReg); |
| 91 | + |
| 92 | + if (cmd.hasOption("samples")) { |
| 93 | + int samples = Integer.parseInt(cmd.getOptionValue("samples")); |
| 94 | + int treeSize = combiner.getCombTree().size(); |
| 95 | + if (samples < treeSize) { |
| 96 | + long seed = cmd.hasOption("rand-seed") ? Long.parseLong(cmd.getOptionValue("rand-seed")) : (long)treeSize*(long)samples; |
| 97 | + combiner.sampleTree(samples, seed); |
| 98 | + } |
| 99 | + } |
| 100 | + |
| 101 | + combiner.build(); |
| 102 | + } |
| 103 | + |
| 104 | + public static Options createOptions() { |
| 105 | + Options ops = new Options(); |
| 106 | + |
| 107 | + ops.addOption(null, "samples", true, "Number of samples to draw"); |
| 108 | + ops.addOption(null, "rand-seed", true, "Random seed for use when sampling"); |
| 109 | + ops.addOption(null, "gridded-seis", true, "Gridded seismicity option. One of " |
| 110 | + +FaultSysTools.enumOptions(IncludeBackgroundOption.class)+". Default: "+GRID_SEIS_DEFAULT.name()); |
| 111 | + ops.addOption(null, "results-file-name", true, "Results file name. Default: "+RESULTS_FILE_NAME_DEFAULT); |
| 112 | + ops.addOption(null, "hazard-dir-name", true, "Hazard dir name. Default: "+HAZARD_DIR_NAME_DEFAULT); |
| 113 | + ops.addOption(null, "grid-reg-file-name", true, "Gridded region file name. Default: "+GRID_REG_FILE_NAME_DEFAULT); |
| 114 | + |
| 115 | + return ops; |
| 116 | + } |
| 117 | + |
| 118 | + public CrustalSubductionLogicTreeCombine(SolutionLogicTree outerSLT, File outerHazardDir, |
| 119 | + IncludeBackgroundOption outerBGOp, SolutionLogicTree innerSLT, File innerHazardDir, |
| 120 | + IncludeBackgroundOption innerBGOp, File outputSLTFile, File outputHazardFile, GriddedRegion gridReg) { |
| 121 | + super(outerSLT, outerHazardDir, outerBGOp, innerSLT, innerHazardDir, innerBGOp, outputSLTFile, outputHazardFile, |
| 122 | + gridReg); |
| 123 | + } |
| 124 | + |
| 125 | + private static GriddedRegion loadGridReg(File regFile) throws IOException { |
| 126 | + Preconditions.checkState(regFile.exists(), "Supplied region file doesn't exist: %s", regFile.getAbsolutePath()); |
| 127 | + if (regFile.getName().toLowerCase().endsWith(".zip")) { |
| 128 | + // it's a zip file, assume it's a prior hazard calc |
| 129 | + ZipFile zip = new ZipFile(regFile); |
| 130 | + ZipEntry regEntry = zip.getEntry(MPJ_LogicTreeHazardCalc.GRID_REGION_ENTRY_NAME); |
| 131 | + System.out.println("Reading gridded region from zip file: "+regEntry.getName()); |
| 132 | + BufferedReader bRead = new BufferedReader(new InputStreamReader(zip.getInputStream(regEntry))); |
| 133 | + GriddedRegion region = GriddedRegion.fromFeature(Feature.read(bRead)); |
| 134 | + zip.close(); |
| 135 | + return region; |
| 136 | + } else { |
| 137 | + Feature feature = Feature.read(regFile); |
| 138 | + return GriddedRegion.fromFeature(feature); |
| 139 | + } |
| 140 | + } |
| 141 | + |
| 142 | + private static void remapTree(LogicTree<?> tree, Map<LogicTreeLevel<?>, LogicTreeLevel<?>> levelRemaps, |
| 143 | + Map<LogicTreeNode, LogicTreeNode> nodeRemaps, String nameAdd, String shortNameAdd) { |
| 144 | + for (LogicTreeLevel<?> level : tree.getLevels()) { |
| 145 | + String name = level.getName(); |
| 146 | + if (name.toLowerCase().contains("crustal") || name.toLowerCase().contains("subduction")) { |
| 147 | + // keep it as is |
| 148 | + levelRemaps.put(level, level); |
| 149 | + for (LogicTreeNode node : level.getNodes()) |
| 150 | + nodeRemaps.put(node, node); |
| 151 | + } else { |
| 152 | + // remap to a file backed |
| 153 | + List<FileBackedNode> modNodes = new ArrayList<>(); |
| 154 | + for (LogicTreeNode node : level.getNodes()) { |
| 155 | + FileBackedNode modNode = new FileBackedNode(nameAdd+" "+node.getName(), node.getShortName(), |
| 156 | + node.getNodeWeight(null), shortNameAdd+node.getFilePrefix()); |
| 157 | + modNodes.add(modNode); |
| 158 | + nodeRemaps.put(node, modNode); |
| 159 | + } |
| 160 | + FileBackedLevel modLevel = new FileBackedLevel(nameAdd+" "+name, shortNameAdd+level.getShortName(), modNodes); |
| 161 | + modLevel.setAffected(level.getAffected(), level.getNotAffected(), false); |
| 162 | + levelRemaps.put(level, modLevel); |
| 163 | + } |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + @Override |
| 168 | + protected void remapOuterTree(LogicTree<?> tree, Map<LogicTreeLevel<?>, LogicTreeLevel<?>> levelRemaps, |
| 169 | + Map<LogicTreeNode, LogicTreeNode> nodeRemaps) { |
| 170 | + remapTree(tree, levelRemaps, nodeRemaps, "Crustal", "Crust"); |
| 171 | + } |
| 172 | + |
| 173 | + @Override |
| 174 | + protected void remapInnerTree(LogicTree<?> tree, Map<LogicTreeLevel<?>, LogicTreeLevel<?>> levelRemaps, |
| 175 | + Map<LogicTreeNode, LogicTreeNode> nodeRemaps) { |
| 176 | + remapTree(tree, levelRemaps, nodeRemaps, "Subduction", "Sub"); |
| 177 | + } |
| 178 | + |
| 179 | + @Override |
| 180 | + protected boolean doesOuterSupplySols() { |
| 181 | + return true; |
| 182 | + } |
| 183 | + |
| 184 | + @Override |
| 185 | + protected boolean doesInnerSupplySols() { |
| 186 | + return true; |
| 187 | + } |
| 188 | + |
| 189 | + @Override |
| 190 | + protected boolean isSerializeGridded() { |
| 191 | + // TODO |
| 192 | + return false; |
| 193 | + } |
| 194 | + |
| 195 | + @Override |
| 196 | + protected boolean canSkipLevel(LogicTreeLevel<?> level, boolean inner) { |
| 197 | + return false; |
| 198 | + } |
| 199 | + |
| 200 | +} |
0 commit comments