📄 wfsegment.java
字号:
package org.trinet.jasi;
import java.util.*;
import java.io.*;
import org.trinet.util.*;
/**
* This class discribes a single contiguous waveform. An int array
* containing the samples is created to the proper length and is always FULL.
*/
public class WFSegment extends TimeSeriesSegment {
/** recording device */
public String rec = "";
/** data recording device */
public String source = "";
/** gram length in bytes */
// public int length;
/** Count of samples the waveform SHOULD have according to the data source.
* This may not be how many are actually in memory. */
public int samplesExpected;
// public int secsExpected;
public int bytesExpected;
/** data format (see SCEC-DC manual) */
public int fmt;
/** bias contained in the minfo file */
public int readbias;
public int bytesPerSample;
/** byte offset of the data in the file */
public int index;
/** waveform data file name */
public String filename = "";
public int status;
static final int NULL = (int) Math.pow(2.0, 31.0);
Sample maxSample;
Sample minSample;
Sample peakSample;
float biasVal = NULL;
/** Rectified background noise level with bias removed. It may be derived
* from some outside source (say a longterm average from the external datasource.)
* If calculated by this class it is
* the median of the peaks between zero-crossings for a rectified time-series
* with the bias removed. The time window for which it is calculated is set by
* a call to scanForNoiseLevel(start, end). */
float noiseLevel = Float.NaN;
/** Data and clock quality bits from Seed Header flags */
public boolean clockLocked;
public boolean ampSaturated; // clipped?
public boolean digClipped;
public boolean spikes;
public boolean glitches;
public boolean badTimeTag;
/* data format codes used by SCEC-DC
The starred formats are currently supported:
0: Unknown, or Not Applicable
*1: Standard-order 2-byte integers (i.e. SUNsparc short; big endian)
2: Reverse-order 2-byte integers (i.e. DECvax short; little endian)
*3: Standard-order 4-byte integers (i.e. SUNsparc integer)
4: Reverse-order 4-byte integers (i.e. DECvax integer)
5: IEEE 4-byte floating-point (i.e. SUNsparc float)
6: DEC 4-byte floating-point (i.e. DECvax float)
7: SEED format
*8: Steim Compressed
9: SAC binary
*/
/**
* Null constructor
*/
public WFSegment()
{
}
/**
* Constructor without allocation of 'rawSamples' array. This allows creation of
* segments without using up lots of memory.
*/
public WFSegment(Channel ch)
{
setChannelObj(ch);
}
/**
* Constructor allocated space for the time series.
*/
public WFSegment(Channel ch, int sampleCount) {
this(ch);
allocateTimeSeriesArray (sampleCount);
}
/**
* Make segment with this time series.
*/
public WFSegment(Channel ch, float timeseries[] ) {
this(ch);
setTimeSeries (timeseries);
}
/**
* Constructor
*/
public WFSegment (String net,
String sta,
String channel,
int sampleCount)
{
this(Channel.create().setChannelName(net, sta, channel));
allocateTimeSeriesArray (sampleCount);
}
/**
* Copy constructor
*/
public WFSegment (WFSegment wf) {
copy(wf);
}
/**
* Make a "deep" copy of a WFSegment header only. Time series and
* timeseries dependent values (bias, max, min) are not copied.
*/
public void copyHeader (WFSegment wf) {
chan = wf.chan; // note: this copies the reference
rec = wf.rec ;
source = wf.source ;
setStart(wf.getStart()) ;
setEnd(wf.getEnd()) ;
setSampleInterval(wf.dt) ;
// length = wf.length ;
// sampleCount = wf.sampleCount ;
fmt = wf.fmt ;
readbias = wf.readbias ;
// lenSecs = wf.lenSecs ;
bytesPerSample = wf.bytesPerSample ;
index = wf.index ;
filename = wf.filename ;
status = wf.status ;
/** Data and clock quality bits from Seed Header flags */
clockLocked = wf.clockLocked;
ampSaturated= wf.ampSaturated;
digClipped = wf.digClipped;
spikes = wf.spikes;
glitches = wf.glitches;
badTimeTag = wf.badTimeTag;
setTimeQuality(wf.getTimeQuality());
}
/**
* Make a "deep" copy of a WFSegment, including the time series.
*/
public void copy (WFSegment wfs) {
copyHeader(wfs);
if (wfs.maxSample != null) maxSample = wfs.maxSample.copy();
if (wfs.minSample != null) minSample = wfs.minSample.copy();
if (wfs.peakSample != null) peakSample= wfs.peakSample.copy();
biasVal = wfs.biasVal ;
// copy the time series
ts = wfs.getTimeSeriesCopy() ;
}
/** Return the first Sample in the segment. */
public Sample getFirstSample()
{
return sampleAtIndex(0);
}
/** Return the last sample in the segment */
public Sample getLastSample()
{
return sampleAtIndex(ts.length - 1);
}
/**
* Return the Sample closest to the given time. If the time is way outside the time
* span of the segment it will still return the closest; usually the first or last.
*/
public Sample closestSample (double dtime)
{
if (!hasTimeSeries()) return null; // no time series
if (dtime < getEpochStart()) return getFirstSample(); // before time range
if (dtime > getEpochEnd()) return getLastSample(); // after time range
// must be in the range
int sampNo = sampleIndexAtTime(dtime); // sample #
return sampleAtIndex(sampNo);
}
/** return the Sample at index of this time series. If index is out of bounds
* null is returned.
*/
public Sample sampleAtIndex (int index) {
Sample samp = new Sample();
if (index > 0 || index < size()) {
samp.value = ts[index]; // the sample value
samp.datetime = timeAtIndex(index); // the sample time
}
return samp;
}
/** Return the epoch time at this sample number. Returns -1 if index is out
of range. */
public double timeAtIndex (int index) {
if (index < 0 || index > size()) return -1;
return getEpochStart() + (index * getSampleInterval());
}
/** Return index in the 'sample[]' array of the sample closest to the time given.
* Returns -1 if time is not within this waveform segment. */
public int sampleIndexAtTime (double time) {
int idx = (int) Math.round((time - getEpochStart())/dt); // round
if (idx < 0 || idx > size()) idx = -1;
return idx;
}
/**
* Given a Collection of WFSegments, collapse them into the minimum number
* of segments that preserves time-gaps. A Collection of contiguous segs
* should return a single WFSegment. Returns a Collection containing the new
* concatinated WFSegments. */
public static Collection collapse (Collection oldList)
{
ArrayList newSegList = new ArrayList();
WFSegment seg[] = WFSegment.getArray(oldList);
int i = 0;
while (i < seg.length) {
WFSegment newseg = new WFSegment(seg[i]); // 1st seg in group
i++;
// System.out.println ("Start of group, seg # = " + i);
// This loop works as long as segs are contiguous
while (i < seg.length && WFSegment.areContiguous(newseg, seg[i])) {
newseg = WFSegment.concatinate(newseg, seg[i]);
i++;
}
// set bias, max, min, etc.
newseg.scanTimeSeries();
newSegList.add(newseg);
}
return newSegList;
}
/**
* Concatinate two WFSegments. Set all header stuff. Returns 'null'
* if segments are not contiguous. Does NOT check anything else (like are
* they the same channel, format, etc.). For speed, does NOT scan the
* resulting segment for bias, max, min, etc. You must do that when you're
* done concatinating.
*/
public static WFSegment concatinate (WFSegment seg1, WFSegment seg2)
{
// Check contiguousness
if (!WFSegment.areContiguous(seg1, seg2)) return null;
int newSize = seg1.size() + seg2.size();
int oldSeg1Size = seg1.size();
// join time series
float ns[] = new float[newSize]; // new array big enough for both
try {
// src, pos, dest, pos, length
System.arraycopy(seg1.ts, 0, ns, 0, seg1.size());
System.arraycopy(seg2.ts, 0, ns, seg1.size(), seg2.size());
} catch (Exception ex) {
System.err.println ("WFSegment.concatinate error: " + ex.toString());
}
// Update header fields
seg1.setEnd(seg2.getEnd());
// seg1.length += seg2.length; // length in bytes
// seg1.sampleCount += seg1.sample.length + seg2.sample.length;
// seg1.sampleCount = newSize ; // length in samples
// is this right? or does it skip a sample interval?
// Should be??? seg1.lenSecs = seg.tend = seg.tstart;
// seg1.lenSecs += seg2.lenSecs;
// averaging the bias is an expedient. Should recalc if you really care.
// seg1.biasVal = (seg1.biasVal + seg2.biasVal) /2.0;
/* These will be scanned for when done
seg1.biasVal = ( (seg1.biasVal * oldSeg1Size) +
(seg2.biasVal * seg2.size()))
/ newSize;
seg1.maxSample = Sample.max(seg1.maxSample, seg2.maxSample);
seg1.minSample = Sample.min(seg1.minSample, seg2.minSample);
*/
seg1.setTimeSeries(ns , false); // use new time series array
// combine (OR) quality bits
seg1.clockLocked |= seg2.clockLocked;
seg1.ampSaturated |= seg2.ampSaturated; // clipped?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -