QuakemlUtils.java
package gov.usgs.earthquake.eids;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.quakeml_1_2.CreationInfo;
import org.quakeml_1_2.Event;
import org.quakeml_1_2.IntegerQuantity;
import org.quakeml_1_2.InternalEvent;
import org.quakeml_1_2.Magnitude;
import org.quakeml_1_2.MomentTensor;
import org.quakeml_1_2.Origin;
import org.quakeml_1_2.Quakeml;
import org.quakeml_1_2.RealQuantity;
import org.quakeml_1_2.ScenarioEvent;
import org.quakeml_1_2.TimeQuantity;
import org.quakeml_1_2.FocalMechanism;
import org.quakeml_1_2.EventParameters;
/**
* Utility methods for ANSS Quakeml objects.
*/
public class QuakemlUtils {
/**
* Find the first event in a message.
*
* If a quakeml event object does not exist, check for the first internal or
* scenario event.
*
* @param eventParameters to find event from
* @return first event
*/
public static Event getFirstEvent(final EventParameters eventParameters) {
// only process first event
if (eventParameters.getEvents().size() > 0) {
// found actual event
return eventParameters.getEvents().get(0);
} else {
// check for internal/scenario events
List<Object> anies = eventParameters.getAnies();
Iterator<Object> anyIter = anies.iterator();
while (anyIter.hasNext()) {
Object next = anyIter.next();
if (next instanceof InternalEvent) {
// found internal event
return (InternalEvent) next;
} else if (next instanceof ScenarioEvent) {
// found scenario event
return (ScenarioEvent) next;
}
}
}
// no event found
return null;
}
/**
* Find the preferred Origin in an Event.
*
* @param event event
* @return Origin with publicID equal to event.getPreferredOriginID(), or null
* if not found.
*/
public static Origin getPreferredOrigin(final Event event) {
return getOrigin(event, event.getPreferredOriginID());
}
/**
* Find a specific Origin in an Event.
*
* @param event event to search
* @param id publicID to find
* @return Origin with publicID equal to id, or null if not found.
*/
public static Origin getOrigin(final Event event, final String id) {
if (id != null) {
Iterator<Origin> iter = event.getOrigins().iterator();
while (iter.hasNext()) {
Origin next = iter.next();
String originId = next.getPublicID();
if (originId != null && originId.equals(id)) {
return next;
}
}
}
return null;
}
/**
* Find the preferred Magnitude in an Event.
*
* @param event event to search
* @return Magnitude with publicID equal to event.getPreferredMagnitudeID(), or
* null if not found.
*/
public static Magnitude getPreferredMagnitude(final Event event) {
return getMagnitude(event, event.getPreferredMagnitudeID());
}
/**
* Find a specific Magnitude in an event.
*
* @param event event to search
* @param id publicID to find.
* @return Magnitude with publicID equal to id, or null if not found.
*/
public static Magnitude getMagnitude(final Event event, final String id) {
if (id != null) {
Iterator<Magnitude> iter = event.getMagnitudes().iterator();
while (iter.hasNext()) {
Magnitude next = iter.next();
String magnitudeId = next.getPublicID();
if (magnitudeId != null && magnitudeId.equals(id)) {
return next;
}
}
}
return null;
}
/**
* Find a specific FocalMechanism in an event.
*
* @param event event to search
* @param id publicID to find.
* @return FocalMechanism with publicID equal to id, or null if not found.
*/
public static FocalMechanism getFocalMechanism(final Event event, final String id) {
if (id != null) {
Iterator<FocalMechanism> iter = event.getFocalMechanisms().iterator();
while (iter.hasNext()) {
FocalMechanism next = iter.next();
String mechId = next.getPublicID();
if (mechId != null && mechId.equals(id)) {
return next;
}
}
}
return null;
}
/**
* Flatten multiple creation info objects, but using the most specific (at end
* of list) value that is not null.
*
* @param infos to flatten
* @return a CreationInfo object with the most specific properties (later in
* arguments list), which may be null.
*/
public static CreationInfo getCreationInfo(final CreationInfo... infos) {
CreationInfo info = new CreationInfo();
for (int i = 0, len = infos.length; i < len; i++) {
CreationInfo next = infos[i];
if (next == null) {
continue;
}
if (next.getAgencyID() != null) {
// set agencyid and agency uri at same time
info.setAgencyID(next.getAgencyID());
info.setAgencyURI(next.getAgencyURI());
}
if (next.getAuthor() != null) {
// author and author uri at same time
info.setAuthor(next.getAuthor());
info.setAuthorURI(next.getAuthorURI());
}
if (next.getCreationTime() != null) {
info.setCreationTime(next.getCreationTime());
}
if (next.getVersion() != null) {
info.setVersion(next.getVersion());
}
}
return info;
}
/**
* @param value RealQuantity
* @return value.getValue(), or null if value == null.
*/
public static BigDecimal getValue(final RealQuantity value) {
if (value == null) {
return null;
} else {
return value.getValue();
}
}
/**
* @param value IntegerQuantity
* @return value.getValue(), or null if value == null.
*/
public static BigInteger getValue(final IntegerQuantity value) {
if (value == null) {
return null;
} else {
return value.getValue();
}
}
/**
* @param value TimeQuantity
* @return value.getValue(), or null if value == null.
*/
public static Date getValue(final TimeQuantity value) {
if (value == null) {
return null;
} else {
return value.getValue();
}
}
/**
* @param magnitudeType to return
* @return MagntitudeType string */
public static String getMagnitudeType(final String magnitudeType) {
if (magnitudeType == null) {
return null;
}
return magnitudeType.toLowerCase();
}
/**
* @return true if list is not null and not empty.
*/
private static boolean listHasData(final List<?> list) {
if (list != null && list.size() > 0) {
return true;
}
return false;
}
/**
* Clear a list if it is not null and not empty.
*/
private static void listRemoveData(final List<?> list) {
if (list != null && list.size() > 0) {
list.clear();
}
}
/**
* Check if an event has phase data.
*
* <ul>
* <li>event.getPicks()</li>
* <li>event.getAmplitudes()</li>
* <li>event.getStationMagnitudes()</li>
* <li>event.getOrigins()
* <ul>
* <li>origin.getArrivals()</li>
* </ul>
* </li>
* <li>event.getMagnitudes()
* <ul>
* <li>magnitude.getStationMagnitudeContributions()</li>
* </ul>
* </li>
* </ul>
*
* @param event event to search.
* @return true if phase data found, false otherwise.
*/
public static boolean hasPhaseData(final Event event) {
// event level phase data
if (listHasData(event.getPicks()) || listHasData(event.getAmplitudes())
|| listHasData(event.getStationMagnitudes())) {
return true;
}
// origin level phase data
if (event.getOrigins() != null) {
Iterator<Origin> iter = event.getOrigins().iterator();
while (iter.hasNext()) {
Origin next = iter.next();
if (listHasData(next.getArrivals())) {
return true;
}
}
}
// magnitude level phase data
if (event.getMagnitudes() != null) {
Iterator<Magnitude> iter = event.getMagnitudes().iterator();
while (iter.hasNext()) {
Magnitude next = iter.next();
if (listHasData(next.getStationMagnitudeContributions())) {
return true;
}
}
}
// haven't found phase data
return false;
}
/**
* Similar to {@link #hasPhaseData(Event)}, but empties any lists that have
* phase data. Also removes <waveformID> elements from focalMechanism.
*
* @param event event to clear.
*/
public static void removePhaseData(final Event event) {
// event level phase data
listRemoveData(event.getPicks());
listRemoveData(event.getAmplitudes());
listRemoveData(event.getStationMagnitudes());
// origin level phase data
if (event.getOrigins() != null) {
Iterator<Origin> iter = event.getOrigins().iterator();
while (iter.hasNext()) {
Origin next = iter.next();
listRemoveData(next.getArrivals());
}
}
// magnitude level phase data
if (event.getMagnitudes() != null) {
Iterator<Magnitude> iter = event.getMagnitudes().iterator();
while (iter.hasNext()) {
Magnitude next = iter.next();
listRemoveData(next.getStationMagnitudeContributions());
}
}
// additionally, remove waveformIDs from focal mechanisms
if (event.getFocalMechanisms() != null) {
Iterator<FocalMechanism> iter = event.getFocalMechanisms().iterator();
while (iter.hasNext()) {
FocalMechanism next = iter.next();
listRemoveData(next.getWaveformIDs());
}
}
}
/**
* Extract the preferred origin and magnitude from the first event in a quakeml
* message.
*
* @param q the quakeml message with a preferred origin.
* @return a new Quakeml object.
*/
public static Quakeml getLightweightOrigin(final Quakeml q) {
Quakeml quakeml = new Quakeml();
EventParameters oldEventParameters = q.getEventParameters();
EventParameters eventParameters = shallowClone(oldEventParameters);
quakeml.setEventParameters(eventParameters);
Event oldEvent = getFirstEvent(q.getEventParameters());
Event event = shallowClone(oldEvent);
eventParameters.getEvents().add(event);
Origin oldOrigin = getPreferredOrigin(oldEvent);
if (oldOrigin == null) {
return null;
}
Origin origin = shallowClone(oldOrigin);
event.getOrigins().add(origin);
event.setPreferredOriginID(origin.getPublicID());
Magnitude oldMagnitude = getPreferredMagnitude(oldEvent);
if (oldMagnitude != null) {
// magnitude is not required for origin
Magnitude magnitude = shallowClone(oldMagnitude);
event.getMagnitudes().add(magnitude);
event.setPreferredMagnitudeID(magnitude.getPublicID());
}
return quakeml;
}
/**
* Extract a focalMechanism, triggering origin, derived origin, and derived
* magnitude from the first event in a quakeml message.
*
* @param q the quakeml message with a focalMechanism
* @param focalMechanismId the focalMechanism to extract.
* @return a new Quakeml object.
*/
public static Quakeml getLightweightFocalMechanism(final Quakeml q, final String focalMechanismId) {
Quakeml quakeml = new Quakeml();
EventParameters oldEventParameters = q.getEventParameters();
EventParameters eventParameters = shallowClone(oldEventParameters);
quakeml.setEventParameters(eventParameters);
Event oldEvent = getFirstEvent(q.getEventParameters());
Event event = shallowClone(oldEvent);
eventParameters.getEvents().add(event);
FocalMechanism oldMech = getFocalMechanism(oldEvent, focalMechanismId);
event.getFocalMechanisms().add(shallowClone(oldMech));
// add triggering origin
Origin triggeringOrigin = getOrigin(oldEvent, oldMech.getTriggeringOriginID());
if (triggeringOrigin != null) {
event.getOrigins().add(shallowClone(triggeringOrigin));
}
// pull in derived origin and magnitude if present
MomentTensor tensor = oldMech.getMomentTensor();
if (tensor != null) {
Origin derivedOrigin = getOrigin(oldEvent, tensor.getDerivedOriginID());
if (derivedOrigin != null) {
event.getOrigins().add(shallowClone(derivedOrigin));
}
Magnitude momentMagnitude = getMagnitude(oldEvent, tensor.getMomentMagnitudeID());
if (momentMagnitude != null) {
event.getMagnitudes().add(shallowClone(momentMagnitude));
}
}
return quakeml;
}
/**
* Create a copy of an event parameters object.
*
* omits anies, events, and other attributes.
*
* @param oldEventParameters to copy
* @return a new EventParameters object.
*/
public static EventParameters shallowClone(final EventParameters oldEventParameters) {
EventParameters eventParameters = new EventParameters();
eventParameters.getComments().addAll(oldEventParameters.getComments());
eventParameters.setCreationInfo(oldEventParameters.getCreationInfo());
eventParameters.setDescription(oldEventParameters.getDescription());
eventParameters.setPublicID(oldEventParameters.getPublicID());
return eventParameters;
}
/**
* Create a copy of an event object.
*
* omits amplitudes, anies, event descriptions, mechanisms, magnitudes, origins,
* other attributes, picks, preferred*ID, and station magnitudes.
*
* @param oldEvent to copy
* @return a new Event object.
*/
public static Event shallowClone(final Event oldEvent) {
Event event = new Event();
event.getComments().addAll(oldEvent.getComments());
event.setCreationInfo(oldEvent.getCreationInfo());
event.setDataid(oldEvent.getDataid());
event.setDatasource(oldEvent.getDatasource());
event.setEventid(oldEvent.getEventid());
event.setEventsource(oldEvent.getEventsource());
event.setPublicID(oldEvent.getPublicID());
event.setType(oldEvent.getType());
event.setTypeCertainty(oldEvent.getTypeCertainty());
return event;
}
/**
* Create a copy of an origin object.
*
* omits anies, arrivals, and other attributes.
*
* @param oldOrigin to copy
* @return a new Origin object.
*/
public static Origin shallowClone(final Origin oldOrigin) {
Origin origin = new Origin();
origin.getComments().addAll(oldOrigin.getComments());
origin.getCompositeTimes().addAll(oldOrigin.getCompositeTimes());
origin.setCreationInfo(oldOrigin.getCreationInfo());
origin.setDataid(oldOrigin.getDataid());
origin.setDatasource(oldOrigin.getDatasource());
origin.setDepth(oldOrigin.getDepth());
origin.setDepthType(oldOrigin.getDepthType());
origin.setEarthModelID(oldOrigin.getEarthModelID());
origin.setEpicenterFixed(oldOrigin.getEpicenterFixed());
origin.setEvaluationMode(oldOrigin.getEvaluationMode());
origin.setEvaluationStatus(oldOrigin.getEvaluationStatus());
origin.setEventid(oldOrigin.getEventid());
origin.setEventsource(oldOrigin.getEventsource());
origin.setLatitude(oldOrigin.getLatitude());
origin.setLongitude(oldOrigin.getLongitude());
origin.setMethodID(oldOrigin.getMethodID());
origin.setOriginUncertainty(oldOrigin.getOriginUncertainty());
origin.setPublicID(oldOrigin.getPublicID());
origin.setQuality(oldOrigin.getQuality());
origin.setReferenceSystemID(oldOrigin.getReferenceSystemID());
origin.setRegion(oldOrigin.getRegion());
origin.setTime(oldOrigin.getTime());
origin.setTimeFixed(oldOrigin.getTimeFixed());
origin.setType(oldOrigin.getType());
return origin;
}
/**
* Create a copy of a magnitude object.
*
* omits anies, other attributes, and station magnitude contributions.
*
* @param oldMagnitude to copy
* @return a new Magnitude object.
*/
public static Magnitude shallowClone(final Magnitude oldMagnitude) {
Magnitude magnitude = new Magnitude();
magnitude.setAzimuthalGap(oldMagnitude.getAzimuthalGap());
magnitude.getComments().addAll(oldMagnitude.getComments());
magnitude.setCreationInfo(getCreationInfo(oldMagnitude.getCreationInfo()));
magnitude.setDataid(oldMagnitude.getDataid());
magnitude.setDatasource(oldMagnitude.getDatasource());
magnitude.setEvaluationMode(oldMagnitude.getEvaluationMode());
magnitude.setEvaluationStatus(oldMagnitude.getEvaluationStatus());
magnitude.setEventid(oldMagnitude.getEventid());
magnitude.setEventsource(oldMagnitude.getEventsource());
magnitude.setMag(oldMagnitude.getMag());
magnitude.setMethodID(oldMagnitude.getMethodID());
magnitude.setOriginID(oldMagnitude.getOriginID());
magnitude.setPublicID(oldMagnitude.getPublicID());
magnitude.setStationCount(oldMagnitude.getStationCount());
magnitude.setType(oldMagnitude.getType());
return magnitude;
}
/**
* Create a copy of a focal mechanism object.
*
* omits anies, other attributes.
*
* @param oldMech to copy
* @return a new FocalMechanism object.
*/
public static FocalMechanism shallowClone(final FocalMechanism oldMech) {
FocalMechanism mech = new FocalMechanism();
mech.setAzimuthalGap(oldMech.getAzimuthalGap());
mech.getComments().addAll(oldMech.getComments());
mech.setCreationInfo(oldMech.getCreationInfo());
mech.setDataid(oldMech.getDataid());
mech.setDatasource(oldMech.getDatasource());
mech.setEvaluationMode(oldMech.getEvaluationMode());
mech.setEvaluationStatus(oldMech.getEvaluationStatus());
mech.setEventid(oldMech.getEventid());
mech.setEventsource(oldMech.getEventsource());
mech.setMethodID(oldMech.getMethodID());
mech.setMisfit(oldMech.getMisfit());
mech.setMomentTensor(oldMech.getMomentTensor());
mech.setNodalPlanes(oldMech.getNodalPlanes());
mech.setPrincipalAxes(oldMech.getPrincipalAxes());
mech.setPublicID(oldMech.getPublicID());
mech.setStationDistributionRatio(oldMech.getStationDistributionRatio());
mech.setStationPolarityCount(oldMech.getStationPolarityCount());
mech.setTriggeringOriginID(oldMech.getTriggeringOriginID());
mech.getWaveformIDs().addAll(oldMech.getWaveformIDs());
return mech;
}
}