edu.iris.dmc.seed.Volume Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-4-seed Show documentation
Show all versions of java-4-seed Show documentation
Java API to work with seismic dataless seed
The newest version!
package edu.iris.dmc.seed;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import edu.iris.dmc.seed.control.dictionary.AbstractDictionaryBlockette;
import edu.iris.dmc.seed.control.dictionary.DictionaryBlockette;
import edu.iris.dmc.seed.control.index.B010;
import edu.iris.dmc.seed.control.index.B011;
import edu.iris.dmc.seed.control.index.B012;
import edu.iris.dmc.seed.control.index.IndexBlockette;
import edu.iris.dmc.seed.control.station.B050;
import edu.iris.dmc.seed.control.station.B051;
import edu.iris.dmc.seed.control.station.B052;
import edu.iris.dmc.seed.control.station.B059;
import edu.iris.dmc.seed.control.station.OverFlowBlockette;
import edu.iris.dmc.seed.control.station.ResponseBlockette;
import edu.iris.dmc.seed.control.station.SeedResponseStage;
import edu.iris.dmc.seed.control.station.StationBlockette;
import edu.iris.dmc.seed.headers.Control;
/**
* We need to examine this class and find some better representation.
*
* @author Suleiman
* @author Ronan
*/
public class Volume {
private int id = 1000;
private Blockette b005;
private Blockette b008;
private B010 b010;
private B011 b011;
private B012 b012;
private B050 b050;
private B052 b052;
private final DictionaryIndex dictionary = new DictionaryIndex();
private final Control control = new Control();
private Map ids = new HashMap<>();
private void index(Blockette blockette) {
this.ids.put(blockette.getId(), blockette);
}
private Map volumeRecords = new TreeMap<>();
private Map dictionaryRecords = new TreeMap<>();
private Map stationRecords = new TreeMap<>();
public void build() throws SeedException {
// this.records = new TreeMap<>();// make sure start clean
this.volumeRecords = new TreeMap<>();
int sequence = 1;
int recordSize = 0;
if (this.b010 == null) {
this.b010 = new B010();
}
recordSize = BigInteger.valueOf(2).pow(b010.getNthPower()).intValue();
Record record = RecordFactory.create(recordSize, sequence, 'V', false);
this.volumeRecords.put(sequence, record);
record = addVolume(record, b010);
// If you choose to build we create b011
// This is actually where the b011 is created
B011 b011 = new B011();
// find the number of records this blockette requires and update the sequence
for (B050 b050 : this.control.getB050s()) {
// place as a holder for now
b011.add(b050, sequence);
}
record = addVolume(record, b011);
sequence = record.getSequence() + 1;
record = RecordFactory.create(recordSize, sequence, 'A', false);
this.dictionaryRecords.put(sequence, record);
for (Blockette b : this.dictionary.getAll()) {
record = addDictionary(record, b);
}
// Update the b011 for the sequence of the first station code epoch found in xml,
// b011 ignores epochs so first epoch of unique station codes must be used in B011 to make it work with Rdseed
int ind = 1;
String prevStaCode ="";
String prevStaConcat ="";
for (B050 b050 : this.control.getB050s()) {
record = addStation(record, b050);
if(b050.getStationCode().equals(prevStaCode) == false ) {
if(prevStaConcat.toLowerCase().contains(b050.getStationCode().toLowerCase()) == false) {
b011.update(b050, record.getSequence());
}else {}
}
prevStaCode = b050.getStationCode();
prevStaConcat = prevStaConcat.concat(b050.getStationCode());
for (B051 b051 : b050.getB051s()) {
record = addStation(record, b051);
}
for (B052 b052 : b050.getB052s()) {
record = addStation(record, b052);
for (SeedResponseStage responseStage : b052.getResponseStages()) {
for (ResponseBlockette b61Swap : responseStage.getBlockettes()) {
// This loop must determines if a stage contains a b61. List of stage
// response types are numerically ordered so B61 has to be output
// before B57 and B58.
if(b61Swap.getType()==61 || b61Swap.getType()==62) {
if (b61Swap instanceof OverFlowBlockette) {
OverFlowBlockette ob = (OverFlowBlockette) b61Swap;
if (ob.isOverFlown()) {
for (Blockette b : ob.split()) {
record = addStation(record, b);
}
} else {
// Uncomment below for Blocketteorder test converter
//System.out.println(b61Swap.getType() + " "+ responseStage.getSequence());
record = addStation(record, b61Swap);
}
} else {
//Uncomment below for Blocketteorder test converter
//System.out.println(b61Swap.getType() + " "+ responseStage.getSequence());
record = addStation(record, b61Swap);
}
}
}
for (ResponseBlockette responseBlockette : responseStage.getBlockettes()) {
if(responseBlockette.getType()==61 || responseBlockette.getType()==62){
continue;
}else {
if (responseBlockette instanceof OverFlowBlockette) {
/**
* This blockette is the only blockette that might overflow the maximum allowed
* value of 9,999 characters. If there are more coefficients than fit in one
* record, list as many as will fit in the first occurrence of this blockette
* (the counts of Number of numerators and Number of denominators would then be
* set to the number included, not the total number). In the next record, put
* the remaining number. Be sure to write and read these blockettes in sequence,
* and be sure that the first few fields of both records are identical. Reading
* (and writing) programs have to be able to work with both blockettes as one
* after reading (or before writing). In July 2007, the FDSN adopted a
* convention that requires the coefficients to be listed in forward time order.
* As a reference, minimum-p
*/
OverFlowBlockette ob = (OverFlowBlockette) responseBlockette;
if (ob.isOverFlown()) {
for (Blockette b : ob.split()) {
record = addStation(record, b);
}
} else {
//Uncomment below for Blocketteorder test converter
//System.out.println(responseBlockette.getType() + " "+ responseStage.getSequence());
record = addStation(record, responseBlockette);
}
} else {
//Uncomment below for Blocketteorder test converter
//System.out.println(responseBlockette.getType() + " "+ responseStage.getSequence());
record = addStation(record, responseBlockette);
}
}
}
}
// Blockette 59 has to be written after the response cascade to work with pdcc
// This follows pdcc's historical logic and allows consistency between programs TR 04/14/2020.
try {
for (B059 b059 : b052.getB059s()) {
record = addStation(record, b059);
}
}catch(Exception e) {
continue;
}
}
}
this.volumeRecords = new TreeMap<>();
record = RecordFactory.create(recordSize, 1, 'V', false);
this.volumeRecords.put(1, record);
record = addVolume(record, b010);
addVolume(record, b011);
}
private Record addVolume(Record record, Blockette b) throws SeedException {
int recordLength = record.size();
int sequence = record.getSequence();
if (b instanceof B050) {
record = RecordFactory.create(recordLength, record.getSequence() + 1, 'S', false);
this.volumeRecords.put(record.getSequence(), record);
}
byte[] bytes = b.toSeedString().getBytes(StandardCharsets.US_ASCII);
while (true) {
bytes = record.add(bytes);
if (bytes == null || bytes.length == 0) {
break;
} else {
sequence++;
record = RecordFactory.create(recordLength, sequence, record.getType(), true);
this.volumeRecords.put(sequence, record);
}
}
return record;
}
private Record addDictionary(Record record, Blockette b) throws SeedException {
int recordLength = record.size();
int sequence = record.getSequence();
if (b instanceof B050) {
record = RecordFactory.create(recordLength, record.getSequence() + 1, 'S', false);
this.dictionaryRecords.put(record.getSequence(), record);
}
byte[] bytes = b.toSeedString().getBytes(StandardCharsets.US_ASCII);
while (true) {
bytes = record.add(bytes);
if (bytes == null || bytes.length == 0) {
break;
} else {
sequence++;
record = RecordFactory.create(recordLength, sequence, record.getType(), true);
this.dictionaryRecords.put(sequence, record);
}
}
return record;
}
private Record addStation(Record record, Blockette b) throws SeedException {
int recordLength = record.size();
int sequence = record.getSequence();
if (b instanceof B050) {
record = RecordFactory.create(recordLength, record.getSequence() + 1, 'S', false);
this.stationRecords.put(record.getSequence(), record);
}
byte[] bytes = b.toSeedString().getBytes(StandardCharsets.US_ASCII);
while (true) {
bytes = record.add(bytes);
if (bytes == null || bytes.length == 0) {
break;
} else {
sequence++;
record = RecordFactory.create(recordLength, sequence, record.getType(), true);
this.stationRecords.put(sequence, record);
}
}
return record;
}
// This is where the blockettes are added
public Blockette add(Blockette blockette) throws SeedException {
if (blockette == null) {
throw new IllegalArgumentException("Cannot add a null blockette to this volume");
}
if (!this.isValidType(blockette)) {
throw new IllegalArgumentException("Invalid blockette type [" + blockette.getType() + "]");
}
blockette.setId(id++);
blockette.setVolume(this);
if (blockette.getSize() > blockette.getLength() && !(blockette instanceof OverFlowBlockette)) {
throw new SeedException("Blockette " + blockette.getType() + " is too long, expected maximum 9999 but was "
+ blockette.getLength());
}
index(blockette);
if (blockette instanceof IndexBlockette) {
if (5 == blockette.getType()) {
this.b005 = blockette;
} else if (8 == blockette.getType()) {
this.b008 = blockette;
} else if (10 == blockette.getType()) {
this.b010 = (B010) blockette;
} else if (11 == blockette.getType()) {
this.b011 = (B011) blockette;
} else if (12 == blockette.getType()) {
this.b012 = (B012) blockette;
}
return blockette;
} else if (blockette instanceof StationBlockette) {
if (50 == blockette.getType()) {
this.b050 = (B050) blockette;
this.control.put(b050);
} else if (51 == blockette.getType()) {
this.b050.add((B051) blockette);
} else if (52 == blockette.getType()) {
if (this.b050 == null) {
throw new SeedException("Trying to add b052 when no b050 is present.");
}
this.b052 = (B052) blockette;
b050.add(this.b052);
} else if (59 == blockette.getType()) {
if (this.b052 == null) {
throw new SeedException("Trying to add b059 when no b052 is present.");
}
this.b052.add((B059) blockette);
}
return blockette;
} else if (blockette instanceof DictionaryBlockette) {
return this.dictionary.put((AbstractDictionaryBlockette) blockette);
} else if (blockette instanceof ResponseBlockette) {
if (this.b052 == null) {
throw new SeedException("Expected b052 but was null.");
}
this.b052.add((ResponseBlockette) blockette);
return blockette;
} else {
throw new SeedException("Couldn't add blockette " + blockette.getType());
}
}
public int getNumberOfStations() {
return this.control.getB050s().size();
}
public Blockette get(int id) {
return this.ids.get(id);
}
public Record getRecord(int sequence) {
if (this.volumeRecords.size() > sequence) {
return this.volumeRecords.get(sequence);
}
if (this.dictionaryRecords.size() > sequence) {
return this.dictionaryRecords.get(sequence);
}
if (this.stationRecords.size() > sequence) {
return this.stationRecords.get(sequence);
}
throw new IndexOutOfBoundsException();
}
public List getRecords() {
List list = new ArrayList<>(volumeRecords.values());
list.addAll(dictionaryRecords.values());
list.addAll(stationRecords.values());
return list;
}
/**
* a list of all blockettes in this volume
*
* @return a list of all blockettes ordered as they were inserted
*/
public List getAll() {
List list = new ArrayList<>();
if (b005 != null) {
list.add(this.b005);
}
if (b008 != null) {
list.add(this.b008);
}
if (b010 != null) {
list.add(this.b010);
}
if (b011 != null) {
list.add(b011);
}
if (b012 != null) {
list.add(this.b012);
}
list.addAll(this.dictionary.getAll());
list.addAll(this.control.getAll());
return list;
}
public List find(String network, String station, String channel, String location) {
List list = new ArrayList<>();
for (B050 b : this.control.getB050s()) {
if (network != null && !b.getNetworkCode().trim().equals(network)) {
continue;
}
if (station != null && !b.getStationCode().trim().equals(station)) {
continue;
}
if (channel != null) {
for (B052 b052 : b.getB052s()) {
if (b052.getChannelCode().trim().equals(channel)) {
if (location == null) {
list.add(b052);
} else {
if (b052.getLocationCode().equals(location)) {
list.add(b052);
}
}
}
}
}
}
return list;
}
public B010 getB010() {
return this.b010;
}
public B011 getB011() {
return this.b011;
}
public B012 getB012() {
return this.b012;
}
public Blockette getById(int id) {
return this.ids.get(id);
}
public DictionaryIndex getDictionary() {
return this.dictionary;
}
public Blockette getDictionaryBlockette(int type, int lookupCode) {
return this.dictionary.get(type, lookupCode);
}
public Blockette getResponseDictionaryBlockette(int lookupCode) {
return this.dictionary.getResponse(lookupCode);
}
public List getIndexBlockettes() {
Arrays.asList(this.b005, this.b008, this.b010, this.b012);
List l = new ArrayList<>();
if (b005 != null) {
l.add(b005);
}
if (b008 != null) {
l.add(b008);
}
if (b010 != null) {
l.add(b010);
}
if (b011 != null) {
l.add(b011);
}
if (b012 != null) {
l.add(b012);
}
return l;
}
public List getDictionaryBlockettes() {
return this.dictionary.getAll();
}
public List getB050s() {
return this.control.getB050s();
}
public List getControlBlockettes() {
return this.control.getAll();
}
public boolean isEmpty() {
return this.dictionary.isEmpty() && this.control.isEmpty() && b005 == null && b008 == null && b010 == null
&& b011 != null && b012 == null;
}
private boolean isValidType(int type) {
return SEED.TYPES.contains(type);
}
private boolean isValidType(Blockette blockette) {
return isValidType(blockette.getType());
}
public int size() {
return this.dictionary.size() + this.control.size();
}
class Buffer {
int size;
int remainder;
Buffer(int size) {
this.size = size;
this.remainder = size - 8;
}
int add(int length) {
if (this.remainder == 0) {
this.remainder = size - 8;
}
if (length > remainder) {
int re = length - remainder;
remainder = 0;
return re;
} else {
remainder -= length;
return 0;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy