📄 hypoformat.java
字号:
package org.trinet.jasi;
import java.io.*;
import java.util.*;
//import java.text.*;
import java.text.SimpleDateFormat;
import java.lang.*;
import org.trinet.util.*;
import org.trinet.util.gazetteer.*;
import org.trinet.jdbc.*;
import org.trinet.util.Format; // CoreJava printf-like Format class
import org.trinet.jdbc.datatypes.DataDouble;
import org.trinet.jdbc.datatypes.DataLong;
import org.trinet.jdbc.datatypes.DataString;
/**
* Create and parse Hypoinverse formatted lines
*/
public class HypoFormat
{
static final int ARC_STRING_SIZE = 110;
/**
* Null constructor
*/
public void HypoFormat()
{
}
/**
* Make a string in .arc format (new hypo2000 version) from the contents of Phase.
*/
/*
1 2 3 4 5 6 7 8 9 10 11
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
STATNnt cCMP pr yearmodyhrmnseconPresPwtS-secSr sSrespek2pekmmSwtPdlySdlyDistAngADPerRCodaAzmDurMagPimpSimpSFX
MCV NC VVHZ PU0199806262007 4310 -9110 0 0 0 0 0 0 0 0 1616400 0 159297404 0 502 0WD
HMT CI VVHZ 199811102059 0 0 0 5632IS 0 -27 151 0 0 0 0 708 9000 0 0228 0 0 0
RDM CI HHHZ 199902101612 1584iS 0
HMT CI VVLN 200004071235 0 0 1285 S0 TPO G P V EP+2199811120254 3783 90 0 0 0 0 0 0 0 0 01334 7000 0 0154 0 0 0 0
QAL G P V 0199811120254 0 0 0 5709ES 2 301 0 0 0 0 01359 7000 0 0174 0 0 0 0
*/
public static String toArchiveString (Phase ph) {
StringBuffer str = new StringBuffer(ARC_STRING_SIZE); // make a space filled string buffer
for (int i = 0; i < ARC_STRING_SIZE; i++) str.append(' ');
Format fmt1 = new Format("%1s"); // for efficiency
Channel chan = ph.getChannelObj();
str = overlay(str, 0, new Format("%-5s").form(chan.getSta()) );
str = overlay(str, 5, new Format("%-2s ").form(chan.getNet()) );
str = overlay(str, 8, fmt1.form(chan.getChannel().substring(0,1) ) ); // 1st character of component
// str = overlay(str, 9, new Format("%3s ").form(chan.getChannel()));
// changed to SEED component names
str = overlay(str, 9, new Format("%3s ").form(chan.getSeedchan()));
/*
1 2 3 4 5 6 7 8 9 10 11
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
STATNnt cCMP pr yearmodyhrmnseconPresPwtS-secSr sSrespek2pekmmSwtPdlySdlyDistAngADPerRCodaAzmDurMagPimpSimpSFX
MCV NC VVHZ PU0199806262007 4310 -9110 0 0 0 0 0 0 0 0 1616400 0 159297404 0 502 0WD
SIO CI HHLE P0 200001130934 2647 704 75
DTP CI EHZ 0200209122043 0 0 0 4582 S 3 -2 0 0 54 0 0 504 9000 0 0148 0 0 0 141
CLC CI HHZ PU1200209122043 3985 2163 0 0 0 0 0 0 0 0 515 9000 0 0 69 0 0 362 0
WWP CI VEHZ PD2200209122043 3308 -1 0 106
WWP CI VEHZ 200209122043 3458 S 1 -1 0 106
*/
// <P> wave Phase description, example: "IPU1"
if (ph.description.iphase.equals("P")) {
str = overlay(str, 13, ph.description.toMediumString());
// phase time
str = overlay(str, 17, arcTimeString(ph.datetime.doubleValue()) ); // "YEARMODYHRMNSS.SS"
if (!ph.residual.isNull())
str = overlay(str, 34, new Format("%4d").form((int) (ph.residual.doubleValue()*100) ));
if (!ph.weightOut.isNull())
str = overlay(str, 38, new Format("%3d").form((int) (ph.weightOut.doubleValue()*100) ));
}
/*
1 2 3 4 5 6 7 8 9 10 11
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
STATNnt cCMP pr yearmodyhrmnseconPresPwtS-secSr sSrespek2pekmmSwtPdlySdlyDistAngADPerRCodaAzmDurMagPimpSimpSFX
QAL G P V 0199811120254 0 0 0 5709ES 2 301 0 0 0 0 01359 7000 0 0174 0 0 0 0
Note: a station that is not "setup" will return a line as follows:
LVA2 CI HHHN 199909072229 0 0 1018iSc1 0
*/
// <S> wave
else if (ph.description.iphase.equals("S")) {
// Must set P-Weight to bogus = 4
str = overlay(str, 16, Integer.toString(4) );
// phase time, S arrival time description is split in the format
str = overlay(str, 17, arcYMDHMString(ph.datetime.doubleValue()) ); // "YEARMODYHRMN"
// field actually starts at 41, but we are doing 4 digits max so use 42.
str = overlay(str, 42, arcSecString(ph.datetime.doubleValue()) ); // "SSss"= SS.ss*100
// str = overlay(str, 46, ph.description.toShortString());
str = overlay(str, 46, ph.description.toMediumString());
if (!ph.residual.isNull())
str = overlay(str, 50, new Format("%4d").form((int) (ph.residual.doubleValue()*100) ));
if (!ph.weightOut.isNull())
str = overlay(str, 63, new Format("%3d").form((int) (ph.weightOut.doubleValue()*100) ));
} else {
System.out.println ("* Phase type that Hypoinverse can't handle: " +
str + " "+ph.description.iphase);
return (str.toString());
}
// AssocArO parts
// weight "actually used"
if (!ph.weightIn.isNull())
str = overlay(str, 38, new Format("%3d").form((int) (ph.weightIn.doubleValue()*100) ));
if (!ph.getChannelObj().dist.isNull())
str = overlay(str, 74, new Format("%4d").form((int) (ph.getDistance()*10.0) ) ) ;
// Emergence angle (is using incidence here bogus?)
if (!ph.incidence.isNull())
str = overlay(str, 78, new Format("%3d").form((int) ph.incidence.doubleValue()) ) ;
if (!(ph.getAzimuth() == 0.0))
str = overlay(str, 91, new Format("%3d").form((int) ph.getAzimuth()) ) ;
/* DK 08/24/02
* if(ph.coda != null)
* {
* str = overlay(str, 87, new Format("%4d").form( ph.coda.tau.intValue()) ) ;
* str = overlay(str, 82, new Format("%1d").form( Coda.Weight_Jiggle2HI(ph.coda.weightIn.doubleValue())) ) ;
* }
*/
return (str.toString());
// return (str.toString().trim());
}
/**
* The StringBuffer doesn't really have a simple overlay method. Its insert()
* method shoves bytes to the right as it inserts.
*/
private static StringBuffer overlay (StringBuffer sb, int start, String str) {
int end = start + str.length();
return sb.replace(start, end, str);
}
/*
1 2 3 4 5 6 7 8 9 10 11
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
STATNnt cCMP pr yearmodyhrmnseconPresPwtS-secSr sSrespek2pekmmSwtPdlySdlyDistAngADPerRCodaAzmDurMagPimpSimpSFX
MCV NC VVHZ PU0199806262007 4310 -9110 0 0 0 0 0 0 0 0 1616400 0 159297404 0 502 0WD
HMT CI VVHZ 199811102059 0 0 0 5632IS 0 -27 151 0 0 0 0 708 9000 0 0228 0 0 0
WOF G P V IPD0199811120254 2436 7172 0 0 0 0 0 0 0 0 49610100 0 0165 0 0 174 0
GTM CI EHZ P00199912080004 4174 -9155 0 0 0 0 0 0 0 0 264 9000 0 0201 0 0 741 0
Note: a station that is not "setup" will return a line as follows:
LVA2 CI HHHN 199909072229 0 0 1018iSc1 0
HDB CI EEHZ P3 200001130933 4050 312 25
*/
// TODO: Need to handle P and S on a single card
/**
* Parse .arc format station line into new Phase object.
* <tt>
01234567890
DTP CI EHZ 0200209122043 0 0 0 4582 S 3 -2 0 0 54 0 0 504 9000 0 0148 0 0 0 141
CLC CI HHZ PU1200209122043 3985 2163 0 0 0 0 0 0 0 0 515 9000 0 0 69 0 0 362 0
WWP CI VEHZ PD2200209122043 3308 -1 0 106
WWP CI VEHZ 200209122043 3458 S 1 -1 0 106
WOR CI VEHZ PU1200209122043 3330 -1 0 118
* </tt>
*/
public static Phase parseArcToPhase (String str) {
double val; // general variable
if (str.startsWith(" ")) return null; // not an arrival line
Phase ph = Phase.create();
// Channel name, Note that it is incomplete. Note .trim() to remove trailing blanks.
String sta = str.substring(0,5).trim();
String net = str.substring(5,7).trim();
String comp = str.substring(9,12).trim();
// note putting channel in both 'channel' & 'seedchan'
ph.setChannelObj(Channel.create().setChannelName(net, sta, comp, comp));
// Phase description, example: "IPU1"
/* WARNING: it is possible for Hypoinverse to combine p and S readings on a
single card. If so, this method will miss the S on a P card.
Also, using str.substring(46,47).equals("S") seemed to return 'false' even
when it wasn't but str.substring(46,47).equalsIgnoreCase("S") seems to work. */
// Read P info
if (str.substring(14,15).equalsIgnoreCase("P")) // its a P-wave
{
String desc = str.substring(13, 17);
ph.description.parseHypoinverseString(desc);
// ph.weightIn.setValue(parseVal(str, 38, 41) );
// ph.weightIn.setValue(ph.description.quality); // operator assigned quality
// ph.residual.setValue(parseVal(str, 34, 38) / 100.0) ; // residual
// *******************************************************
// there's an error in the dbase constraints that won't allow negatives!
// double residual = Math.abs(parseVal(str, 34, 38) / 100.0);
// CONSTRAINT NOW CORRECTED
// *******************************************************
ph.residual.setValue(parseVal(str, 34, 38) / 100.0) ; // residual
// Hypoinverse Weights (from the program) seem to be in the range 0.0 -> 2.0
// To fit into dbase constraint of 0.0 -> 1.0 I just /10.
val = parseVal(str, 38, 41)/100;
ph.weightOut.setValue(scaleWeight(val));
ph.datetime.setValue(parseArcPTime(str));
}
// DK CODE CHANGE 121802
// The string was checked for length > 41. This doesn't
// seem to be a valid check (atleast based on hi 2000 at MP) becauese
// the distance(9999) always gets included on the end of lines that are not
// in the station file, or do not have a valid location, or for some reason
// cannot be associated with the location.
// So we want to check one of the "association values" to make sure it is on
// the line, before we go plotting blindly ahead trying to parse numbers out
// of blank spaces or parsing passed the end of the string.
// check that string is long enough to test
// if (str.length() > 41) {
// check that there is atleast one "association based value" calculated
if (parseNumber(str, 91, 94)!= null) {
// Read S info
if (str.substring(47,48).equalsIgnoreCase("S")) // its a S-wave
{
String desc = str.substring(46,50);
ph.description.parseHypoinverseString(desc);
// ph.weightIn.setValue(ph.description.quality); // operator assigned quality
double residual = parseVal(str, 50, 54) / 100.0;
// *******************************************************
// there was an error in the dbase constraints that won't allow negatives!
// double residual = Math.abs(parseVal(str, 50, 54) / 100.0);
// constraint if now fixed
// *******************************************************
ph.residual.setValue(residual); // residual
// Hypoinverse Weights (from the program) seem to be in the range 0.0 -> 2.0
// To fit into dbase constraint of 0.0 -> 1.0 I just /10.
val = parseVal(str, 63, 66)/100 ;
ph.weightOut.setValue(scaleWeight(val));
ph.datetime.setValue(parseArcSTime(str));
}
/* double val = parseVal(str, 78, 81); // emergence angle
if (val != -1.0) ph.incidence.setValue(val);
val = parseVal(str, 74, 78);
if (val != -1.0) ph.distance.setValue(val / 10.0);
val = parseVal(str, 91, 94);
if (val != -1.0) ph.azimuth.setValue(val) ; // station azimuth
*/
ph.incidence.setValue(parseNumber(str, 78, 81) ) ; // emergence angle
Number num = parseNumber(str, 74, 78); // must check nullness
if (num != null)
ph.setDistance(num.doubleValue() / 10.0); // before /10
ph.setAzimuth(parseNumber(str, 91, 94).doubleValue()) ; // station azimuth
}
else // DK CODE CHANGE 121802
{
// DK CODE CHANGE 121802
// We didn't get association information, do we still want the phase????
}
/* 82,1 Dur Mag Weight Code
87,4 Coda Dur (seconds)
94,3,2Dur Mag value
*/
Number num;
if((num = parseNumber(str, 87, 91)) != null && (num.intValue() != 0))
{
Coda newCoda = Coda.create();
newCoda.tau = new DataDouble(num.intValue());
newCoda.tCodaTerm = new DataDouble(newCoda.tau.doubleValue() +
ph.datetime.doubleValue());
if((num = parseNumber(str, 82, 83)) != null)
newCoda.weightIn = new DataDouble(Coda.Weight_HI2Jiggle(num.intValue()));
if((num = parseNumber(str, 94, 97)) != null)
{
ChannelMag newChanMag = new ChannelMag();
newChanMag.set(num.doubleValue()/100);
newChanMag.weight = newCoda.weightIn;
newChanMag.importance = newCoda.weightIn;
newCoda.setChannelMag(newChanMag);
}
newCoda.setChannelObj(ph.getChannelObj());
// ph.coda = newCoda; // this line requires Md mod to coda
}
return (ph);
}
/** Hypoinverse weights (from the program) seem to be in the range 0.0 -> 2.0
* So scale to fit into dbase constraint of 0.0 -> 1.0 by dividing by 2.0. */
public static double scaleWeight (double val) {
double newVal = val / 2.0;
if (newVal > 1.0) newVal = 1.0; // insure no constrain violations
if (newVal < 0.0) newVal = 0.0;
return newVal;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -