ShakeMapIndexerModule.java
- package gov.usgs.earthquake.shakemap;
- import java.awt.image.BufferedImage;
- import java.io.IOException;
- import java.io.InputStream;
- import java.math.BigDecimal;
- import java.util.Map;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- import javax.imageio.ImageIO;
- import gov.usgs.earthquake.indexer.DefaultIndexerModule;
- import gov.usgs.earthquake.indexer.IndexerModule;
- import gov.usgs.earthquake.indexer.ProductSummary;
- import gov.usgs.earthquake.product.Content;
- import gov.usgs.earthquake.product.Product;
- import gov.usgs.util.StreamUtils;
- /**
- * ShakeMap Indexer Module.
- *
- * Provides a higher and more specific level of support for ShakeMap products,
- * including reading additional product information out of the ShakeMap content
- * files provided with the Product and placing it into the ProductSummary for
- * the Product itself.
- */
- public class ShakeMapIndexerModule extends DefaultIndexerModule {
- private static final Logger LOGGER = Logger
- .getLogger(ShakeMapIndexerModule.class.getName());
- /** Path to overlay img */
- public static final String OVERLAY_IMAGE_PATH = "download/ii_overlay.png";
- /** Property for overlay width */
- public static final String OVERLAY_WIDTH_PROPERTY = "overlayWidth";
- /** Property for overlay height */
- public static final String OVERLAY_HEIGHT_PROPERTY = "overlayHeight";
- /** CONTAINS_EPICENTER_WEIGHT */
- public static final int CONTAINS_EPICENTER_WEIGHT = 50;
- /** CENTERED_ON_EPICENTER_WEIGHT */
- public static final int CENTERED_ON_EPICENTER_WEIGHT = 25;
- /** Number of degrees at which no additional weight will be
- * assigned based on the proximity of the map center to the
- * epicenter.
- */
- public static final double MAX_DELTA_DEGREES = 2.0;
- /** ShakeMap atlas is the most preferred ShakeMap contributor */
- public static final String SHAKEMAP_ATLAS_SOURCE = "atlas";
- /** Atlas weight */
- public static final int SHAKEMAP_ATLAS_WEIGHT = 200;
- @Override
- public int getSupportLevel(Product product) {
- int supportLevel = IndexerModule.LEVEL_UNSUPPORTED;
- String type = getBaseProductType(product.getId().getType());
- // Support only ShakeMap products that contain grid.xml
- if (type.equals("shakemap") && product.getContents().containsKey(
- ShakeMap.GRID_XML_ATTACHMENT))
- supportLevel = IndexerModule.LEVEL_SUPPORTED;
- return supportLevel;
- }
- @Override
- public ProductSummary getProductSummary(Product product) throws Exception {
- // Load additional properties into the ProductSummary by loading these
- // properties specifically through a ShakeMap product
- ProductSummary summary = super.getProductSummary(new ShakeMap(product));
- Content overlayImage = product.getContents().get(OVERLAY_IMAGE_PATH);
- if (overlayImage != null) {
- InputStream overlayInputStream = null;
- try {
- overlayInputStream = overlayImage.getInputStream();
- BufferedImage info = ImageIO.read(overlayInputStream);
- summary.getProperties().put(OVERLAY_WIDTH_PROPERTY,
- Integer.toString(info.getWidth()));
- summary.getProperties().put(OVERLAY_HEIGHT_PROPERTY,
- Integer.toString(info.getHeight()));
- LOGGER.finest("overlay width=" + info.getWidth() +
- ", overlay height=" + info.getHeight());
- } catch (IOException e) {
- LOGGER.log(Level.WARNING, "exception reading "
- + OVERLAY_IMAGE_PATH + " width/height", e);
- } finally {
- StreamUtils.closeStream(overlayInputStream);
- }
- }
- return summary;
- }
- @Override
- protected long getPreferredWeight(ProductSummary summary)
- throws Exception {
- // Get the default preferred weight value from the parent class
- long weight = super.getPreferredWeight(summary);
- if (SHAKEMAP_ATLAS_SOURCE.equals(summary.getSource())) {
- weight += SHAKEMAP_ATLAS_WEIGHT;
- }
- // check that shakemap has event properties and map extents
- Map<String, String> properties = summary.getProperties();
- if (summary.getEventLatitude() == null ||
- summary.getEventLongitude() == null ||
- properties.get(ShakeMap.MINIMUM_LATITUDE_PROPERTY) == null ||
- properties.get(ShakeMap.MAXIMUM_LATITUDE_PROPERTY) == null ||
- properties.get(ShakeMap.MINIMUM_LONGITUDE_PROPERTY) == null ||
- properties.get(ShakeMap.MAXIMUM_LONGITUDE_PROPERTY) == null) {
- return weight;
- }
- // Get properties for comparison to alter authoritative weight
- BigDecimal eventLat = summary.getEventLatitude();
- BigDecimal eventLon = summary.getEventLongitude();
- BigDecimal minLat = new BigDecimal(properties.get(
- ShakeMap.MINIMUM_LATITUDE_PROPERTY));
- BigDecimal maxLat = new BigDecimal(properties.get(
- ShakeMap.MAXIMUM_LATITUDE_PROPERTY));
- BigDecimal minLon = new BigDecimal(properties.get(
- ShakeMap.MINIMUM_LONGITUDE_PROPERTY));
- BigDecimal maxLon = new BigDecimal(properties.get(
- ShakeMap.MAXIMUM_LONGITUDE_PROPERTY));
- BigDecimal centerLat = minLat.add(maxLat).divide(new BigDecimal(2));
- BigDecimal centerLon = minLon.add(maxLon).divide(new BigDecimal(2));
- // Calculate delta in degrees between map center and event epicenter
- double latDelta = Math.abs(centerLat.doubleValue() - eventLat.doubleValue());
- double lonDelta = Math.abs(centerLon.doubleValue() - eventLon.doubleValue());
- double locationDelta = (double) Math.sqrt(Math.pow(latDelta, 2)
- + Math.pow(lonDelta, 2));
- // Increase weight dynamically if the map center is within
- // MAX_DELTA_DEGREES of the event epicenter
- if (locationDelta <= MAX_DELTA_DEGREES) {
- // Add more weight based on the map center being closer to
- // the event epicenter
- weight += Math.round((1 - (locationDelta / MAX_DELTA_DEGREES))
- * CENTERED_ON_EPICENTER_WEIGHT);
- }
- // Increase weight further if the map contains the epicenter within
- // its boundaries.
- if (eventLat.longValue() < maxLat.longValue()
- && eventLat.longValue() > minLat.longValue()
- && eventLon.longValue() < maxLon.longValue()
- && eventLon.longValue() > minLon.longValue()) {
- weight += CONTAINS_EPICENTER_WEIGHT;
- }
- return weight;
- }
- }