diff --git a/src/main/java/gov/usgs/earthquake/nshmp/DisaggCalc.java b/src/main/java/gov/usgs/earthquake/nshmp/DisaggCalc.java index dd59717afd96208dc9e6e6dfb2734cc2617f9607..ae5129376ea696e8bb007240e00c2b7c8bacc050 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/DisaggCalc.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/DisaggCalc.java @@ -166,16 +166,11 @@ public class DisaggCalc { */ Path out; if (siteColumns.size() == allColumns.size()) { + checkArgument( modelImts.containsAll(config.hazard.imts), "Config specifies IMTs not supported by model"); - - // List<Imt> imts = config.imts; - - // Path out = calc(model, config, sites, imtImlMaps, log); - double returnPeriod = config.disagg.returnPeriod; - out = calcRp(model, config, sites, returnPeriod, log); } else { @@ -189,19 +184,9 @@ public class DisaggCalc { sites.size() == imls.size(), "Sites and spectra lists different sizes"); log.info("Spectra: " + imls.size()); // 1:1 with sites - out = calcIml(model, config, sites, imls, log); - } - - // List<Map<Imt, Double>> imtImlMaps = readSpectra(siteFile, imts, - // colsToSkip); - // log.info("Spectra: " + imtImlMaps.size()); - // checkArgument(sites.size() == imtImlMaps.size(), "Sites and spectra - // lists different sizes"); - // Spectra should be checked against IMTs supported by model GMMs - - // Path out = calc(model, config, sites, imls, log); + } log.info(PROGRAM + ": finished"); @@ -346,13 +331,13 @@ public class DisaggCalc { } /* Hazard curves are already in log-x space. */ - static final Interpolator IML_INTERPOLATER = Interpolator.builder() + private static final Interpolator IML_INTERPOLATER = Interpolator.builder() .logy() .decreasingY() .build(); - // this should be in a factory - private static Map<Imt, Double> imlsForReturnPeriod( + /** Compute the return period intercepts from a hazard result. */ + public static Map<Imt, Double> imlsForReturnPeriod( Hazard hazard, double returnPeriod) { @@ -360,7 +345,6 @@ public class DisaggCalc { Map<Imt, Double> imls = new EnumMap<>(Imt.class); for (Entry<Imt, XySequence> entry : hazard.curves().entrySet()) { double iml = IML_INTERPOLATER.findX(entry.getValue(), rate); - // remove exp below by transforming disagg-epsilon to log earlier imls.put(entry.getKey(), Math.exp(iml)); } return imls; diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggController.java index 27ab4200b2d48cab86285d437dffc3bb24170e31..0642f7b0c8246e6c773a0766664f1d3d30a90d8b 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggController.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggController.java @@ -5,10 +5,10 @@ import static com.google.common.base.Preconditions.checkArgument; import java.util.Map; import java.util.Set; +import gov.usgs.earthquake.nshmp.calc.DataType; import gov.usgs.earthquake.nshmp.gmm.Imt; import gov.usgs.earthquake.nshmp.www.NshmpMicronautServlet; import gov.usgs.earthquake.nshmp.www.ServletUtil; - import io.micronaut.core.annotation.Nullable; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; @@ -92,14 +92,20 @@ public class DisaggController { @Schema( minimum = "150", maximum = "3000") @PathVariable double returnPeriod, - @Schema() @QueryValue @Nullable Set<Imt> imt) { + @QueryValue @Nullable Set<Imt> imt, + @Schema(allowableValues = { + "DISAGG_DATA", + "GMM", + "SOURCE" }) @QueryValue @Nullable Set<DataType> out) { try { Set<Imt> imts = HazardService.readImts(http); + Set<DataType> dataTypes = HazardService.readDataTypes(http); DisaggService.RequestRp request = new DisaggService.RequestRp( http, longitude, latitude, vs30, returnPeriod, - imts); + imts, + dataTypes); return DisaggService.getDisaggRp(request); } catch (Exception e) { return ServletUtil.error( @@ -113,6 +119,7 @@ public class DisaggController { * @param longitude Longitude in the range [-360..360]°. * @param latitude Latitude in decimal degrees [-90..90]°. * @param vs30 Site Vs30 value in the range [150..3000] m/s. + * @param out The data types to output */ @Operation( summary = "Disaggregate hazard at specified IMLs", @@ -133,7 +140,11 @@ public class DisaggController { maximum = "90") @PathVariable double latitude, @Schema( minimum = "150", - maximum = "3000") @PathVariable double vs30) { + maximum = "3000") @PathVariable double vs30, + @Schema(allowableValues = { + "DISAGG_DATA", + "GMM", + "SOURCE" }) @QueryValue @Nullable Set<DataType> out) { /* * Developer notes: @@ -146,10 +157,12 @@ public class DisaggController { try { Map<Imt, Double> imtImlMap = http.getParameters().asMap(Imt.class, Double.class); checkArgument(!imtImlMap.isEmpty(), "No IMLs supplied"); + Set<DataType> dataTypes = HazardService.readDataTypes(http); DisaggService.RequestIml request = new DisaggService.RequestIml( http, longitude, latitude, vs30, - imtImlMap); + imtImlMap, + dataTypes); return DisaggService.getDisaggIml(request); } catch (Exception e) { return ServletUtil.error( diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java index 842194aaa68257ee447de8a9611b85dcbc2c475d..d3934908844a3f93d413581138335d215c4f154b 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java @@ -16,6 +16,7 @@ import com.google.common.base.Stopwatch; import com.google.common.collect.Range; import gov.usgs.earthquake.nshmp.calc.CalcConfig; +import gov.usgs.earthquake.nshmp.calc.DataType; import gov.usgs.earthquake.nshmp.calc.Disaggregation; import gov.usgs.earthquake.nshmp.calc.Hazard; import gov.usgs.earthquake.nshmp.calc.HazardCalcs; @@ -27,7 +28,6 @@ import gov.usgs.earthquake.nshmp.www.ResponseBody; import gov.usgs.earthquake.nshmp.www.ServletUtil; import gov.usgs.earthquake.nshmp.www.hazard.HazardService.Metadata; import gov.usgs.earthquake.nshmp.www.meta.Parameter; - import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import jakarta.inject.Singleton; @@ -55,7 +55,7 @@ public final class DisaggService { private static Range<Double> imlRange = Range.closed(0.0001, 8.0); /** HazardController.doGetMetadata() handler. */ - public static HttpResponse<String> getMetadata(HttpRequest<?> request) { + static HttpResponse<String> getMetadata(HttpRequest<?> request) { var url = request.getUri().toString(); var usage = new Metadata(ServletUtil.model()); var response = ResponseBody.usage() @@ -69,7 +69,7 @@ public final class DisaggService { } /** HazardController.doGetDisaggIml() handler. */ - public static HttpResponse<String> getDisaggIml(RequestIml request) + static HttpResponse<String> getDisaggIml(RequestIml request) throws InterruptedException, ExecutionException { var stopwatch = Stopwatch.createStarted(); var disagg = calcDisaggIml(request); @@ -89,7 +89,7 @@ public final class DisaggService { } /** HazardController.doGetDisaggRp() handler. */ - public static HttpResponse<String> getDisaggRp(RequestRp request) + static HttpResponse<String> getDisaggRp(RequestRp request) throws InterruptedException, ExecutionException { var stopwatch = Stopwatch.createStarted(); var disagg = calcDisaggRp(request); @@ -116,7 +116,7 @@ public final class DisaggService { * */ - static Disaggregation calcDisaggIml(RequestIml request) + private static Disaggregation calcDisaggIml(RequestIml request) throws InterruptedException, ExecutionException { HazardModel model = ServletUtil.model(); @@ -124,6 +124,7 @@ public final class DisaggService { // modify config to include service endpoint arguments CalcConfig config = CalcConfig.copyOf(model.config()) .imts(request.imls.keySet()) + // .dataTypes(request.dataTypes) .build(); // TODO this needs to pick up SiteData, centralize @@ -152,7 +153,7 @@ public final class DisaggService { return disagg; } - static Disaggregation calcDisaggRp(RequestRp request) + private static Disaggregation calcDisaggRp(RequestRp request) throws InterruptedException, ExecutionException { HazardModel model = ServletUtil.model(); @@ -160,6 +161,7 @@ public final class DisaggService { // modify config to include service endpoint arguments CalcConfig config = CalcConfig.copyOf(model.config()) .imts(request.imts) + // .dataTypes(request.dataTypes) .build(); // TODO this needs to pick up SiteData, centralize @@ -176,6 +178,9 @@ public final class DisaggService { ServletUtil.TASK_EXECUTOR); Hazard hazard = hazFuture.get(); + // Map<Imt, Double> imls = DisaggCalc.imlsForReturnPeriod( + // hazard, + // request.returnPeriod); CompletableFuture<Disaggregation> disaggfuture = CompletableFuture.supplyAsync( () -> Disaggregation.atReturnPeriod( @@ -195,19 +200,22 @@ public final class DisaggService { final double latitude; final double vs30; final Map<Imt, Double> imls; + final Set<DataType> dataTypes; RequestIml( HttpRequest<?> http, double longitude, double latitude, double vs30, - Map<Imt, Double> imls) { + Map<Imt, Double> imls, + Set<DataType> dataTypes) { this.http = http; this.longitude = longitude; this.latitude = latitude; this.vs30 = vs30; this.imls = imls; + this.dataTypes = dataTypes; } } @@ -219,6 +227,7 @@ public final class DisaggService { final double vs30; final double returnPeriod; final Set<Imt> imts; + final Set<DataType> dataTypes; RequestRp( HttpRequest<?> http, @@ -226,7 +235,8 @@ public final class DisaggService { double latitude, double vs30, double returnPeriod, - Set<Imt> imts) { + Set<Imt> imts, + Set<DataType> dataTypes) { this.http = http; this.longitude = longitude; @@ -236,6 +246,7 @@ public final class DisaggService { this.imts = imts.isEmpty() ? ServletUtil.model().config().hazard.imts : imts; + this.dataTypes = dataTypes; } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java index f668b016e76468c696e0759fa3cee55077c2451e..5b41bbe78540a551a49dcb1f5239f1580a32e763 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java @@ -23,6 +23,7 @@ import org.slf4j.LoggerFactory; import com.google.common.base.Stopwatch; import gov.usgs.earthquake.nshmp.calc.CalcConfig; +import gov.usgs.earthquake.nshmp.calc.DataType; import gov.usgs.earthquake.nshmp.calc.Hazard; import gov.usgs.earthquake.nshmp.calc.HazardCalcs; import gov.usgs.earthquake.nshmp.calc.Site; @@ -38,7 +39,6 @@ import gov.usgs.earthquake.nshmp.www.ServletUtil; import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter; import gov.usgs.earthquake.nshmp.www.meta.Parameter; import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel; - import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import jakarta.inject.Singleton; @@ -155,7 +155,7 @@ public final class HazardService { } } - public static final class Request { + static final class Request { final transient HttpRequest<?> http; final double longitude; @@ -347,12 +347,19 @@ public final class HazardService { /* Read the 'imt' query values; can be comma-delimited. */ static Set<Imt> readImts(HttpRequest<?> http) { - return http.getParameters() - .getAll("imt")// TODO where are key strings? - .stream() + return http.getParameters().getAll("imt").stream() .map(s -> s.split(",")) .flatMap(Arrays::stream) .map(Imt::valueOf) .collect(toCollection(() -> EnumSet.noneOf(Imt.class))); } + + /* Read the 'imt' query values; can be comma-delimited. */ + static Set<DataType> readDataTypes(HttpRequest<?> http) { + return http.getParameters().getAll("out").stream() + .map(s -> s.split(",")) + .flatMap(Arrays::stream) + .map(DataType::valueOf) + .collect(toCollection(() -> EnumSet.noneOf(DataType.class))); + } }