QuakemlUtils.java

  1. package gov.usgs.earthquake.eids;

  2. import java.math.BigDecimal;
  3. import java.math.BigInteger;
  4. import java.util.Date;
  5. import java.util.Iterator;
  6. import java.util.List;

  7. import org.quakeml_1_2.CreationInfo;
  8. import org.quakeml_1_2.Event;
  9. import org.quakeml_1_2.IntegerQuantity;
  10. import org.quakeml_1_2.InternalEvent;
  11. import org.quakeml_1_2.Magnitude;
  12. import org.quakeml_1_2.MomentTensor;
  13. import org.quakeml_1_2.Origin;
  14. import org.quakeml_1_2.Quakeml;
  15. import org.quakeml_1_2.RealQuantity;
  16. import org.quakeml_1_2.ScenarioEvent;
  17. import org.quakeml_1_2.TimeQuantity;
  18. import org.quakeml_1_2.FocalMechanism;
  19. import org.quakeml_1_2.EventParameters;

  20. /**
  21.  * Utility methods for ANSS Quakeml objects.
  22.  */
  23. public class QuakemlUtils {

  24.     /**
  25.      * Find the first event in a message.
  26.      *
  27.      * If a quakeml event object does not exist, check for the first internal or
  28.      * scenario event.
  29.      *
  30.      * @param eventParameters to find event from
  31.      * @return first event
  32.      */
  33.     public static Event getFirstEvent(final EventParameters eventParameters) {
  34.         // only process first event
  35.         if (eventParameters.getEvents().size() > 0) {
  36.             // found actual event
  37.             return eventParameters.getEvents().get(0);
  38.         } else {
  39.             // check for internal/scenario events
  40.             List<Object> anies = eventParameters.getAnies();
  41.             Iterator<Object> anyIter = anies.iterator();
  42.             while (anyIter.hasNext()) {
  43.                 Object next = anyIter.next();
  44.                 if (next instanceof InternalEvent) {
  45.                     // found internal event
  46.                     return (InternalEvent) next;
  47.                 } else if (next instanceof ScenarioEvent) {
  48.                     // found scenario event
  49.                     return (ScenarioEvent) next;
  50.                 }
  51.             }
  52.         }
  53.         // no event found
  54.         return null;
  55.     }

  56.     /**
  57.      * Find the preferred Origin in an Event.
  58.      *
  59.      * @param event event
  60.      * @return Origin with publicID equal to event.getPreferredOriginID(), or null
  61.      *         if not found.
  62.      */
  63.     public static Origin getPreferredOrigin(final Event event) {
  64.         return getOrigin(event, event.getPreferredOriginID());
  65.     }

  66.     /**
  67.      * Find a specific Origin in an Event.
  68.      *
  69.      * @param event event to search
  70.      * @param id    publicID to find
  71.      * @return Origin with publicID equal to id, or null if not found.
  72.      */
  73.     public static Origin getOrigin(final Event event, final String id) {
  74.         if (id != null) {
  75.             Iterator<Origin> iter = event.getOrigins().iterator();
  76.             while (iter.hasNext()) {
  77.                 Origin next = iter.next();
  78.                 String originId = next.getPublicID();
  79.                 if (originId != null && originId.equals(id)) {
  80.                     return next;
  81.                 }
  82.             }
  83.         }
  84.         return null;
  85.     }

  86.     /**
  87.      * Find the preferred Magnitude in an Event.
  88.      *
  89.      * @param event event to search
  90.      * @return Magnitude with publicID equal to event.getPreferredMagnitudeID(), or
  91.      *         null if not found.
  92.      */
  93.     public static Magnitude getPreferredMagnitude(final Event event) {
  94.         return getMagnitude(event, event.getPreferredMagnitudeID());
  95.     }

  96.     /**
  97.      * Find a specific Magnitude in an event.
  98.      *
  99.      * @param event event to search
  100.      * @param id    publicID to find.
  101.      * @return Magnitude with publicID equal to id, or null if not found.
  102.      */
  103.     public static Magnitude getMagnitude(final Event event, final String id) {
  104.         if (id != null) {
  105.             Iterator<Magnitude> iter = event.getMagnitudes().iterator();
  106.             while (iter.hasNext()) {
  107.                 Magnitude next = iter.next();
  108.                 String magnitudeId = next.getPublicID();
  109.                 if (magnitudeId != null && magnitudeId.equals(id)) {
  110.                     return next;
  111.                 }
  112.             }
  113.         }
  114.         return null;
  115.     }

  116.     /**
  117.      * Find a specific FocalMechanism in an event.
  118.      *
  119.      * @param event event to search
  120.      * @param id    publicID to find.
  121.      * @return FocalMechanism with publicID equal to id, or null if not found.
  122.      */
  123.     public static FocalMechanism getFocalMechanism(final Event event, final String id) {
  124.         if (id != null) {
  125.             Iterator<FocalMechanism> iter = event.getFocalMechanisms().iterator();
  126.             while (iter.hasNext()) {
  127.                 FocalMechanism next = iter.next();
  128.                 String mechId = next.getPublicID();
  129.                 if (mechId != null && mechId.equals(id)) {
  130.                     return next;
  131.                 }
  132.             }
  133.         }
  134.         return null;
  135.     }

  136.     /**
  137.      * Flatten multiple creation info objects, but using the most specific (at end
  138.      * of list) value that is not null.
  139.      *
  140.      * @param infos to flatten
  141.      * @return a CreationInfo object with the most specific properties (later in
  142.      *         arguments list), which may be null.
  143.      */
  144.     public static CreationInfo getCreationInfo(final CreationInfo... infos) {
  145.         CreationInfo info = new CreationInfo();

  146.         for (int i = 0, len = infos.length; i < len; i++) {
  147.             CreationInfo next = infos[i];
  148.             if (next == null) {
  149.                 continue;
  150.             }

  151.             if (next.getAgencyID() != null) {
  152.                 // set agencyid and agency uri at same time
  153.                 info.setAgencyID(next.getAgencyID());
  154.                 info.setAgencyURI(next.getAgencyURI());
  155.             }

  156.             if (next.getAuthor() != null) {
  157.                 // author and author uri at same time
  158.                 info.setAuthor(next.getAuthor());
  159.                 info.setAuthorURI(next.getAuthorURI());
  160.             }

  161.             if (next.getCreationTime() != null) {
  162.                 info.setCreationTime(next.getCreationTime());
  163.             }

  164.             if (next.getVersion() != null) {
  165.                 info.setVersion(next.getVersion());
  166.             }
  167.         }

  168.         return info;
  169.     }

  170.     /**
  171.      * @param value RealQuantity
  172.      * @return value.getValue(), or null if value == null.
  173.      */
  174.     public static BigDecimal getValue(final RealQuantity value) {
  175.         if (value == null) {
  176.             return null;
  177.         } else {
  178.             return value.getValue();
  179.         }
  180.     }

  181.     /**
  182.      * @param value IntegerQuantity
  183.      * @return value.getValue(), or null if value == null.
  184.      */
  185.     public static BigInteger getValue(final IntegerQuantity value) {
  186.         if (value == null) {
  187.             return null;
  188.         } else {
  189.             return value.getValue();
  190.         }
  191.     }

  192.     /**
  193.      * @param value TimeQuantity
  194.      * @return value.getValue(), or null if value == null.
  195.      */
  196.     public static Date getValue(final TimeQuantity value) {
  197.         if (value == null) {
  198.             return null;
  199.         } else {
  200.             return value.getValue();
  201.         }
  202.     }

  203.     /**
  204.      * @param magnitudeType to return
  205.      * @return MagntitudeType string */
  206.     public static String getMagnitudeType(final String magnitudeType) {
  207.         if (magnitudeType == null) {
  208.             return null;
  209.         }

  210.         return magnitudeType.toLowerCase();
  211.     }

  212.     /**
  213.      * @return true if list is not null and not empty.
  214.      */
  215.     private static boolean listHasData(final List<?> list) {
  216.         if (list != null && list.size() > 0) {
  217.             return true;
  218.         }
  219.         return false;
  220.     }

  221.     /**
  222.      * Clear a list if it is not null and not empty.
  223.      */
  224.     private static void listRemoveData(final List<?> list) {
  225.         if (list != null && list.size() > 0) {
  226.             list.clear();
  227.         }
  228.     }

  229.     /**
  230.      * Check if an event has phase data.
  231.      *
  232.      * <ul>
  233.      * <li>event.getPicks()</li>
  234.      * <li>event.getAmplitudes()</li>
  235.      * <li>event.getStationMagnitudes()</li>
  236.      * <li>event.getOrigins()
  237.      * <ul>
  238.      * <li>origin.getArrivals()</li>
  239.      * </ul>
  240.      * </li>
  241.      * <li>event.getMagnitudes()
  242.      * <ul>
  243.      * <li>magnitude.getStationMagnitudeContributions()</li>
  244.      * </ul>
  245.      * </li>
  246.      * </ul>
  247.      *
  248.      * @param event event to search.
  249.      * @return true if phase data found, false otherwise.
  250.      */
  251.     public static boolean hasPhaseData(final Event event) {
  252.         // event level phase data
  253.         if (listHasData(event.getPicks()) || listHasData(event.getAmplitudes())
  254.                 || listHasData(event.getStationMagnitudes())) {
  255.             return true;
  256.         }

  257.         // origin level phase data
  258.         if (event.getOrigins() != null) {
  259.             Iterator<Origin> iter = event.getOrigins().iterator();
  260.             while (iter.hasNext()) {
  261.                 Origin next = iter.next();
  262.                 if (listHasData(next.getArrivals())) {
  263.                     return true;
  264.                 }
  265.             }
  266.         }

  267.         // magnitude level phase data
  268.         if (event.getMagnitudes() != null) {
  269.             Iterator<Magnitude> iter = event.getMagnitudes().iterator();
  270.             while (iter.hasNext()) {
  271.                 Magnitude next = iter.next();
  272.                 if (listHasData(next.getStationMagnitudeContributions())) {
  273.                     return true;
  274.                 }
  275.             }
  276.         }

  277.         // haven't found phase data
  278.         return false;
  279.     }

  280.     /**
  281.      * Similar to {@link #hasPhaseData(Event)}, but empties any lists that have
  282.      * phase data. Also removes &lt;waveformID&gt; elements from focalMechanism.
  283.      *
  284.      * @param event event to clear.
  285.      */
  286.     public static void removePhaseData(final Event event) {
  287.         // event level phase data
  288.         listRemoveData(event.getPicks());
  289.         listRemoveData(event.getAmplitudes());
  290.         listRemoveData(event.getStationMagnitudes());

  291.         // origin level phase data
  292.         if (event.getOrigins() != null) {
  293.             Iterator<Origin> iter = event.getOrigins().iterator();
  294.             while (iter.hasNext()) {
  295.                 Origin next = iter.next();
  296.                 listRemoveData(next.getArrivals());
  297.             }
  298.         }

  299.         // magnitude level phase data
  300.         if (event.getMagnitudes() != null) {
  301.             Iterator<Magnitude> iter = event.getMagnitudes().iterator();
  302.             while (iter.hasNext()) {
  303.                 Magnitude next = iter.next();
  304.                 listRemoveData(next.getStationMagnitudeContributions());
  305.             }
  306.         }

  307.         // additionally, remove waveformIDs from focal mechanisms
  308.         if (event.getFocalMechanisms() != null) {
  309.             Iterator<FocalMechanism> iter = event.getFocalMechanisms().iterator();
  310.             while (iter.hasNext()) {
  311.                 FocalMechanism next = iter.next();
  312.                 listRemoveData(next.getWaveformIDs());
  313.             }
  314.         }
  315.     }

  316.     /**
  317.      * Extract the preferred origin and magnitude from the first event in a quakeml
  318.      * message.
  319.      *
  320.      * @param q the quakeml message with a preferred origin.
  321.      * @return a new Quakeml object.
  322.      */
  323.     public static Quakeml getLightweightOrigin(final Quakeml q) {
  324.         Quakeml quakeml = new Quakeml();

  325.         EventParameters oldEventParameters = q.getEventParameters();
  326.         EventParameters eventParameters = shallowClone(oldEventParameters);
  327.         quakeml.setEventParameters(eventParameters);

  328.         Event oldEvent = getFirstEvent(q.getEventParameters());
  329.         Event event = shallowClone(oldEvent);
  330.         eventParameters.getEvents().add(event);

  331.         Origin oldOrigin = getPreferredOrigin(oldEvent);
  332.         if (oldOrigin == null) {
  333.             return null;
  334.         }
  335.         Origin origin = shallowClone(oldOrigin);
  336.         event.getOrigins().add(origin);
  337.         event.setPreferredOriginID(origin.getPublicID());

  338.         Magnitude oldMagnitude = getPreferredMagnitude(oldEvent);
  339.         if (oldMagnitude != null) {
  340.             // magnitude is not required for origin
  341.             Magnitude magnitude = shallowClone(oldMagnitude);
  342.             event.getMagnitudes().add(magnitude);
  343.             event.setPreferredMagnitudeID(magnitude.getPublicID());
  344.         }

  345.         return quakeml;
  346.     }

  347.     /**
  348.      * Extract a focalMechanism, triggering origin, derived origin, and derived
  349.      * magnitude from the first event in a quakeml message.
  350.      *
  351.      * @param q                the quakeml message with a focalMechanism
  352.      * @param focalMechanismId the focalMechanism to extract.
  353.      * @return a new Quakeml object.
  354.      */
  355.     public static Quakeml getLightweightFocalMechanism(final Quakeml q, final String focalMechanismId) {
  356.         Quakeml quakeml = new Quakeml();

  357.         EventParameters oldEventParameters = q.getEventParameters();
  358.         EventParameters eventParameters = shallowClone(oldEventParameters);
  359.         quakeml.setEventParameters(eventParameters);

  360.         Event oldEvent = getFirstEvent(q.getEventParameters());
  361.         Event event = shallowClone(oldEvent);
  362.         eventParameters.getEvents().add(event);

  363.         FocalMechanism oldMech = getFocalMechanism(oldEvent, focalMechanismId);
  364.         event.getFocalMechanisms().add(shallowClone(oldMech));

  365.         // add triggering origin
  366.         Origin triggeringOrigin = getOrigin(oldEvent, oldMech.getTriggeringOriginID());
  367.         if (triggeringOrigin != null) {
  368.             event.getOrigins().add(shallowClone(triggeringOrigin));
  369.         }

  370.         // pull in derived origin and magnitude if present
  371.         MomentTensor tensor = oldMech.getMomentTensor();
  372.         if (tensor != null) {
  373.             Origin derivedOrigin = getOrigin(oldEvent, tensor.getDerivedOriginID());
  374.             if (derivedOrigin != null) {
  375.                 event.getOrigins().add(shallowClone(derivedOrigin));
  376.             }
  377.             Magnitude momentMagnitude = getMagnitude(oldEvent, tensor.getMomentMagnitudeID());
  378.             if (momentMagnitude != null) {
  379.                 event.getMagnitudes().add(shallowClone(momentMagnitude));
  380.             }
  381.         }

  382.         return quakeml;
  383.     }

  384.     /**
  385.      * Create a copy of an event parameters object.
  386.      *
  387.      * omits anies, events, and other attributes.
  388.      *
  389.      * @param oldEventParameters to copy
  390.      * @return a new EventParameters object.
  391.      */
  392.     public static EventParameters shallowClone(final EventParameters oldEventParameters) {
  393.         EventParameters eventParameters = new EventParameters();
  394.         eventParameters.getComments().addAll(oldEventParameters.getComments());
  395.         eventParameters.setCreationInfo(oldEventParameters.getCreationInfo());
  396.         eventParameters.setDescription(oldEventParameters.getDescription());
  397.         eventParameters.setPublicID(oldEventParameters.getPublicID());
  398.         return eventParameters;
  399.     }

  400.     /**
  401.      * Create a copy of an event object.
  402.      *
  403.      * omits amplitudes, anies, event descriptions, mechanisms, magnitudes, origins,
  404.      * other attributes, picks, preferred*ID, and station magnitudes.
  405.      *
  406.      * @param oldEvent to copy
  407.      * @return a new Event object.
  408.      */
  409.     public static Event shallowClone(final Event oldEvent) {
  410.         Event event = new Event();
  411.         event.getComments().addAll(oldEvent.getComments());
  412.         event.setCreationInfo(oldEvent.getCreationInfo());
  413.         event.setDataid(oldEvent.getDataid());
  414.         event.setDatasource(oldEvent.getDatasource());
  415.         event.setEventid(oldEvent.getEventid());
  416.         event.setEventsource(oldEvent.getEventsource());
  417.         event.setPublicID(oldEvent.getPublicID());
  418.         event.setType(oldEvent.getType());
  419.         event.setTypeCertainty(oldEvent.getTypeCertainty());
  420.         return event;
  421.     }

  422.     /**
  423.      * Create a copy of an origin object.
  424.      *
  425.      * omits anies, arrivals, and other attributes.
  426.      *
  427.      * @param oldOrigin to copy
  428.      * @return a new Origin object.
  429.      */
  430.     public static Origin shallowClone(final Origin oldOrigin) {
  431.         Origin origin = new Origin();
  432.         origin.getComments().addAll(oldOrigin.getComments());
  433.         origin.getCompositeTimes().addAll(oldOrigin.getCompositeTimes());
  434.         origin.setCreationInfo(oldOrigin.getCreationInfo());
  435.         origin.setDataid(oldOrigin.getDataid());
  436.         origin.setDatasource(oldOrigin.getDatasource());
  437.         origin.setDepth(oldOrigin.getDepth());
  438.         origin.setDepthType(oldOrigin.getDepthType());
  439.         origin.setEarthModelID(oldOrigin.getEarthModelID());
  440.         origin.setEpicenterFixed(oldOrigin.getEpicenterFixed());
  441.         origin.setEvaluationMode(oldOrigin.getEvaluationMode());
  442.         origin.setEvaluationStatus(oldOrigin.getEvaluationStatus());
  443.         origin.setEventid(oldOrigin.getEventid());
  444.         origin.setEventsource(oldOrigin.getEventsource());
  445.         origin.setLatitude(oldOrigin.getLatitude());
  446.         origin.setLongitude(oldOrigin.getLongitude());
  447.         origin.setMethodID(oldOrigin.getMethodID());
  448.         origin.setOriginUncertainty(oldOrigin.getOriginUncertainty());
  449.         origin.setPublicID(oldOrigin.getPublicID());
  450.         origin.setQuality(oldOrigin.getQuality());
  451.         origin.setReferenceSystemID(oldOrigin.getReferenceSystemID());
  452.         origin.setRegion(oldOrigin.getRegion());
  453.         origin.setTime(oldOrigin.getTime());
  454.         origin.setTimeFixed(oldOrigin.getTimeFixed());
  455.         origin.setType(oldOrigin.getType());
  456.         return origin;
  457.     }

  458.     /**
  459.      * Create a copy of a magnitude object.
  460.      *
  461.      * omits anies, other attributes, and station magnitude contributions.
  462.      *
  463.      * @param oldMagnitude to copy
  464.      * @return a new Magnitude object.
  465.      */
  466.     public static Magnitude shallowClone(final Magnitude oldMagnitude) {
  467.         Magnitude magnitude = new Magnitude();
  468.         magnitude.setAzimuthalGap(oldMagnitude.getAzimuthalGap());
  469.         magnitude.getComments().addAll(oldMagnitude.getComments());
  470.         magnitude.setCreationInfo(getCreationInfo(oldMagnitude.getCreationInfo()));
  471.         magnitude.setDataid(oldMagnitude.getDataid());
  472.         magnitude.setDatasource(oldMagnitude.getDatasource());
  473.         magnitude.setEvaluationMode(oldMagnitude.getEvaluationMode());
  474.         magnitude.setEvaluationStatus(oldMagnitude.getEvaluationStatus());
  475.         magnitude.setEventid(oldMagnitude.getEventid());
  476.         magnitude.setEventsource(oldMagnitude.getEventsource());
  477.         magnitude.setMag(oldMagnitude.getMag());
  478.         magnitude.setMethodID(oldMagnitude.getMethodID());
  479.         magnitude.setOriginID(oldMagnitude.getOriginID());
  480.         magnitude.setPublicID(oldMagnitude.getPublicID());
  481.         magnitude.setStationCount(oldMagnitude.getStationCount());
  482.         magnitude.setType(oldMagnitude.getType());
  483.         return magnitude;
  484.     }

  485.     /**
  486.      * Create a copy of a focal mechanism object.
  487.      *
  488.      * omits anies, other attributes.
  489.      *
  490.      * @param oldMech to copy
  491.      * @return a new FocalMechanism object.
  492.      */
  493.     public static FocalMechanism shallowClone(final FocalMechanism oldMech) {
  494.         FocalMechanism mech = new FocalMechanism();
  495.         mech.setAzimuthalGap(oldMech.getAzimuthalGap());
  496.         mech.getComments().addAll(oldMech.getComments());
  497.         mech.setCreationInfo(oldMech.getCreationInfo());
  498.         mech.setDataid(oldMech.getDataid());
  499.         mech.setDatasource(oldMech.getDatasource());
  500.         mech.setEvaluationMode(oldMech.getEvaluationMode());
  501.         mech.setEvaluationStatus(oldMech.getEvaluationStatus());
  502.         mech.setEventid(oldMech.getEventid());
  503.         mech.setEventsource(oldMech.getEventsource());
  504.         mech.setMethodID(oldMech.getMethodID());
  505.         mech.setMisfit(oldMech.getMisfit());
  506.         mech.setMomentTensor(oldMech.getMomentTensor());
  507.         mech.setNodalPlanes(oldMech.getNodalPlanes());
  508.         mech.setPrincipalAxes(oldMech.getPrincipalAxes());
  509.         mech.setPublicID(oldMech.getPublicID());
  510.         mech.setStationDistributionRatio(oldMech.getStationDistributionRatio());
  511.         mech.setStationPolarityCount(oldMech.getStationPolarityCount());
  512.         mech.setTriggeringOriginID(oldMech.getTriggeringOriginID());
  513.         mech.getWaveformIDs().addAll(oldMech.getWaveformIDs());
  514.         return mech;
  515.     }

  516. }