📄 eventmatch.java
字号:
/*******************************************************************
* THIS WILL BE LOADED INTO ORACLE
* MUST COMPILE UNDER JDK1.1.X AND USE ONLY LIBRARIES LOADED IN ORACLE
*******************************************************************/
package org.trinet.eventmatch;
import java.sql.*;
import java.util.*;
/**
@version 1.0
* Implementation of the rules determining when two events are considered to be
* the same. This logic is used when an event is inserted in the dbase to
* retain the original 'evid' number if its just an update or another version
* of the same event from another source.<p>
* The rules for a match are:<p>
*
* 1) The "score" must be less then or equal to the value of passingScore. <p>
*
* 2) The subsource's must not be equal (i.e. no canibalism - this is intended to
* allow foreshocks and closely spaced events to survive).<p>
*
* 3) Force a match if the 'evid' of the new event matches the 'locevid' of
* an existing event. (This would represent a reload of the same event).<p>
*
* The value of passingScore exists in the table EventMatchPassingScore as
* column passingScore.
*
* All methods are static so they will work from within <b>Oracle</B> as
* stored procedures.<p>
*
* THIS CLASS MUST BE COMPILED UNDER JDK1.1.X AND USE ONLY LIBRARIES LOADED IN ORACLE. Oracle 8i cannot do JDK1.2.x yet.<p>
*
* Load this code into Oracle with:<p>
* % loadJavaIntoOracle<p>
*
* That file builds and loads the java code and defines the PL/SQL interface.<p>
@see org.trinet.eventmatch.PassingScore <p>
*/
public class EventMatch
{
// behavior constents
/** Search for matches in window +- this many seconds */
static double windowSize = 60.0;
/** Consider it a match if score is better (lower) then this value. */
// static public final double passingScore = 5.0;
static public final double passingScore = PassingScore.getPassingScore();
/** Constent by which dOT is multipled in calculating score <br>
The equation is: score = dOT * otWeight + dLoc */
static double otWeight = 3.0;
/** Constructor is not used. All methods are static. */
public EventMatch() {};
/** Calculate the score.The equation is:<p>
score = (dOT * otWeight) + dLoc <p>
The units are roughtly km-seconds. <br>
NOTE: we use 'latlonz.horizontalDistanceFrom()' so bad depths don't
contribute to higher scores. */
public static double getScore (long evid1, long evid2) {
CatEntry ce1 = CatEntry.getCatEntryByEvid(evid1);
if (ce1 == null) return Double.MAX_VALUE;
CatEntry ce2 = CatEntry.getCatEntryByEvid(evid2);
if (ce2 == null) return Double.MAX_VALUE;
return getScore (ce1, ce2);
}
/** Calculate the score.The equation is:<p>
score = (dOT * otWeight) + dLoc <p>
The units are roughtly km-seconds. <br>
NOTE: we use 'latlonz.horizontalDistanceFrom()' so bad depths don't
contribute to higher scores. */
protected static double getScore (CatEntry cat1, CatEntry cat2) {
double dot = Math.abs(cat1.ot - cat2.ot);
double ddist = cat1.latlonz.horizontalDistanceFrom(cat2.latlonz);
double score = ddist + ( otWeight * dot);
/*
String bang = " ";
if (score < passingScore) bang = "*";
System.out.println(bang+"SCORE: "+score + " dDist= "+ ddist+ " dOT= "+dot);
*/
return score;
}
/**
* Set the half-size of the search window in seconds. A window this many
* seconds before and after the origin time of the primary event will be
* searched for matching events. The default value is 60.0 seconds. */
public static void setWindowSize(double halfValue) {
windowSize = halfValue;
}
/**
* Set weight given the origin time relative to the event distance in the
* calculation of the score. The default value is 3.0 seconds.
@see EventMatch#getScore(long, long) */
public static void setOtWeight(double value) {
otWeight = value;
}
// //////////////////////////////////////////////////////////////////
// this is where the logic really resides
// //////////////////////////////////////////////////////////////////
/** Return a match for this CatEntry. The CatEntry may not be fully specified
by the caller, the evid and subsource are the most likely to be missing. */
public static CatEntry getMatch (CatEntry cat) {
CatEntry bestCat = null;
double bestScore = Double.MAX_VALUE;
double score;
// Prefilter events by only getting those close in time
CatEntry catList[] = getEventsInWindow (cat.ot);
if (catList == null) return bestCat; // null
// check for match using the rules
for (int i = 0; i<catList.length; i++) {
// System.out.println(">>: "+catList[i]); // debug
// if an evid/locevid match we're done
if (cat.evid == catList[i].locevid) return catList[i];
// Only check score if our 'source' is undefined OR
// if it is defined the event from the dbase is different
if (cat.source == "" || !cat.source.equals(catList[i].source)) {
// calc a score
score = getScore(cat, catList[i]);
if (score < passingScore && score < bestScore) {
bestScore = score;
bestCat = catList[i];
}
}
}
return bestCat;
}
/**
* Get all valid dbase events in the time window defined by this
* epoch centerTime +- the values of 'windowSize'.
*/
protected static CatEntry[] getEventsInWindow (double centerTime) {
return CatEntry.getEventsInWindow (centerTime - windowSize,
centerTime + windowSize);
}
/** Return a match, as an evid, for this CatEntry. */
public static long getMatchEvid (CatEntry cat) {
CatEntry catm = getMatch(cat);
if (catm == null) return -1;
return catm.evid;
}
/**
* Return a match as an evid.Reject any potential matching events with a
* Origin.subsource field equal to 'subsource'. This prevents event
* "canibalism". In other words, events from a single source will never
* replace one another. This allows very close multiples to be inserted.
* Note that it is Origin.subsource and not Event.subsource that is checked.
* Event.subsource will not be changed from an RT system value even if
* a CUSP event ORIGIN is set as 'prefor'.*/
public static long getMatchEvid
(double lat, double lon, double z, double ot, String subsource) {
CatEntry catm =
getMatch(new CatEntry(new LatLonZ(lat, lon, z), ot, subsource));
if (catm == null) return -1;
return catm.evid;
}
/**
* Return a match as an evid.Reject any potential matching events with a
* Origin.subsource field equal to 'subsource'. This prevents event
* "canibalism". In other words, events from a single source will never
* replace one another. This allows very close multiples to be inserted.
* Note that it is Origin.subsource and not Event.subsource that is checked.
* Event.subsource will not be changed from an RT system value even if
* a CUSP event ORIGIN is set as 'prefor'.*/
public static long getMatchEvid
(double lat, double lon, double z, double ot, String subsource, long evid) {
CatEntry catm =
getMatch(new CatEntry(new LatLonZ(lat, lon, z), ot, subsource, evid));
if (catm == null) return -1;
return catm.evid;
}
/**
* This method will not check 'subsource' :. events from a source could
* replace events from the same source. */
public static long getMatchEvid
(double lat, double lon, double z, double ot) {
CatEntry catm = getMatch(new CatEntry(new LatLonZ(lat, lon, z), ot));
if (catm == null) return -1;
return catm.evid;
}
/**
*
*/
public static long getMatchOrid (CatEntry cat) {
CatEntry catm = getMatch(cat);
if (catm == null) return -1;
return catm.orid;
}
/**
*
*/
public static long getMatchOrid
(double lat, double lon, double z, double ot) {
CatEntry catm = getMatch(new CatEntry(new LatLonZ(lat, lon, z), ot));
if (catm == null) return -1;
return catm.orid;
}
/**
* Get the passing score from the database. It is kept in a table called:
* EventMatchPassingScore that has one column called passingScore.
*/
public double getPassingScore () {
return PassingScore.getPassingScore();
}
// ------------------------------------------------------------------
public static void main (String args[]) {
// this should find event # 9529225 & 9529105
CatEntry cat = new CatEntry(new LatLonZ(33.44, -117.67, 0), 950047144.0);
CatEntry catx = getMatch (cat);
System.out.println ("\ncat = "+ cat.toString());
if (catx == null) {
System.out.println ("No matches!");
} else {
System.out.println ("match = "+ catx.toString());
}
// this shouldn't match because 'subsource is the same'
// cat = new CatEntry(new LatLonZ(32.6141, -116.167, 0), 948198526.0, "RT1");
cat = new CatEntry(new LatLonZ(33.44, -117.67, 0), 950047144.0, "CUSP");
catx = getMatch (cat);
System.out.println ("\ncat = "+ cat.toString());
if (catx == null) {
System.out.println ("No matches!");
} else {
System.out.println ("match = "+ catx.toString());
}
cat = new CatEntry(new LatLonZ(33.44, -117.67, 0), 950047144.0, "CUSP", 9531901);
catx = getMatch (cat);
System.out.println ("\ncat = "+ cat.toString());
if (catx == null) {
System.out.println ("No matches!");
} else {
System.out.println ("match = "+ catx.toString());
}
// another test
System.out.println ("\nEventMatch.getScore(9531805, 9138173) = "+
EventMatch.getScore(9531805, 9138173) );
System.out.println (" passingScore = "+passingScore);
}
} // end of class EventMatch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -