ucar.nc2.iosp.gempak.AbstractGempakStationFileReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of netcdf Show documentation
Show all versions of netcdf Show documentation
The NetCDF-Java Library is a Java interface to NetCDF files,
as well as to many other types of scientific data formats.
/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.nc2.iosp.gempak;
import visad.util.Trace;
import java.io.*;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeSet;
/**
* Class to hold common methods for reading surface and sounding files
*
* @author IDV Development Team
*/
public abstract class AbstractGempakStationFileReader extends GempakFileReader {
/** date key identifier */
public static final String DATE = "DATE";
/** time key identifier */
public static final String TIME = "TIME";
/** obs date format */
private static final String DATE_FORMAT = "yyMMdd'/'HHmm";
/** date/time keys */
private List dateTimeKeys;
/** station keys */
private List stationKeys;
/** unique list of dates as Strings */
private List dateList;
/** unique list of dates as Dates */
private List dates;
/** list of stations */
private List stations;
/** list of parameters */
private List params;
/** list of parameters */
private Map> partParamMap =
new HashMap>();
/** data formatter */
private SimpleDateFormat dateFmt = new SimpleDateFormat(DATE_FORMAT);
/** The file subtype */
protected String subType = "";
/**
* Default ctor
*/
AbstractGempakStationFileReader() {}
/**
* Initialize this reader. Read all the metadata
*
* @return true if successful
*
* @throws IOException problem reading the data
*/
protected boolean init() throws IOException {
return init(true);
}
/**
* Initialize this reader. Get the Grid specific info
*
* @param fullCheck check to make sure there are grids we can handle
* @return true if successful
*
* @throws IOException problem reading the data
*/
protected boolean init(boolean fullCheck) throws IOException {
//Trace.startTrace();
if ( !super.init(fullCheck)) {
return false;
}
if ((dmLabel.kftype != MFSN) && (dmLabel.kftype != MFSF)) {
logError("not a point data file ");
return false;
}
return true;
}
/**
* Read in the stations and times. Subclasses should
* call this during init()
* @param uniqueTimes make a set of unique times
* @return true if stations and times were read okay.
*/
protected boolean readStationsAndTimes(boolean uniqueTimes) {
Trace.call1("GEMPAK: making params");
for (DMPart apart : parts) {
List params = makeParams(apart);
partParamMap.put(apart.kprtnm, params);
}
Trace.call2("GEMPAK: making params");
// get the date/time keys
dateTimeKeys = getDateTimeKeys();
if ((dateTimeKeys == null) || dateTimeKeys.isEmpty()) {
return false;
}
// get the station info
stationKeys = findStationKeys();
if ((stationKeys == null) || stationKeys.isEmpty()) {
return false;
}
Trace.call1("GEMPAK: get station list");
stations = getStationList();
Trace.call2("GEMPAK: get station list");
makeFileSubType();
Trace.call1("GEMPAK: get date list");
// null out the old cached list
dates = null;
dateList = makeDateList(uniqueTimes);
Trace.call2("GEMPAK: get date list");
return true;
}
/**
* Get the date/time information
*
* @return the list of date/time keys
*/
private List getDateTimeKeys() {
Key date = findKey(DATE);
Key time = findKey(TIME);
if ((date == null) || (time == null)
|| !date.type.equals(time.type)) {
return null;
}
List dt = new ArrayList(2);
dt.add(date);
dt.add(time);
return dt;
}
/**
* Get the list of dates
*
* @param unique true for unique list
*
* @return the list of dates
*/
protected List makeDateList(boolean unique) {
Key date = dateTimeKeys.get(0);
Key time = dateTimeKeys.get(1);
List toCheck;
if (date.type.equals(ROW)) {
toCheck = headers.rowHeaders;
} else {
toCheck = headers.colHeaders;
}
List fileDates = new ArrayList();
for (int[] header : toCheck) {
if (header[0] != IMISSD) {
// convert to GEMPAK date/time
int idate = header[date.loc + 1];
int itime = header[time.loc + 1];
// TODO: Add in the century
String dateTime = GempakUtil.TI_CDTM(idate, itime);
fileDates.add(dateTime);
}
}
if (unique && !fileDates.isEmpty()) {
SortedSet uniqueTimes =
Collections.synchronizedSortedSet(new TreeSet());
uniqueTimes.addAll(fileDates);
fileDates.clear();
fileDates.addAll(uniqueTimes);
}
return fileDates;
}
/**
* Make GempakParameters from the list of
*
* @param part the part to use
*
* @return parameters from the info in that part.
*/
private List makeParams(DMPart part) {
List gemparms =
new ArrayList(part.kparms);
for (DMParam param : part.params) {
String name = param.kprmnm;
GempakParameter parm = GempakParameters.getParameter(name);
if (parm == null) {
//System.out.println("couldn't find " + name
// + " in params table");
parm = new GempakParameter(1, name, name, "", 0);
}
gemparms.add(parm);
}
return gemparms;
}
/**
* Get the list of parameters for the part
*
* @param partName name of the part
* @return list of parameters
*/
public List getParameters(String partName) {
return partParamMap.get(partName);
}
/**
* Get the station list
*
* @return the list of stations
*/
private List getStationList() {
Key slat = findKey(GempakStation.SLAT);
if (slat == null) {
return null;
}
List toCheck;
if (slat.type.equals(ROW)) {
toCheck = headers.rowHeaders;
} else {
toCheck = headers.colHeaders;
}
List fileStations = new ArrayList();
int i = 0;
for (int[] header : toCheck) {
if (header[0] != IMISSD) {
GempakStation station = makeStation(header);
if (station != null) {
station.setIndex(i + 1);
fileStations.add(station);
}
}
i++;
}
return fileStations;
}
/**
* Make a station from the header info
*
* @param header the station header
*
* @return the corresponding station
*/
private GempakStation makeStation(int[] header) {
if ((stationKeys == null) || stationKeys.isEmpty()) {
return null;
}
GempakStation newStation = new GempakStation();
for (Key key : stationKeys) {
int loc = key.loc + 1;
if (key.name.equals(GempakStation.STID)) {
newStation.setSTID(GempakUtil.ST_ITOC(header[loc]).trim());
} else if (key.name.equals(GempakStation.STNM)) {
newStation.setSTNM(header[loc]);
} else if (key.name.equals(GempakStation.SLAT)) {
newStation.setSLAT(header[loc]);
} else if (key.name.equals(GempakStation.SLON)) {
newStation.setSLON(header[loc]);
} else if (key.name.equals(GempakStation.SELV)) {
newStation.setSELV(header[loc]);
} else if (key.name.equals(GempakStation.SPRI)) {
newStation.setSPRI(header[loc]);
} else if (key.name.equals(GempakStation.STAT)) {
newStation.setSTAT(GempakUtil.ST_ITOC(header[loc]).trim());
} else if (key.name.equals(GempakStation.COUN)) {
newStation.setCOUN(GempakUtil.ST_ITOC(header[loc]).trim());
} else if (key.name.equals(GempakStation.SWFO)) {
newStation.setSWFO(GempakUtil.ST_ITOC(header[loc]).trim());
} else if (key.name.equals(GempakStation.WFO2)) {
newStation.setWFO2(GempakUtil.ST_ITOC(header[loc]).trim());
} else if (key.name.equals(GempakStation.STD2)) {
newStation.setSTD2(GempakUtil.ST_ITOC(header[loc]).trim());
}
}
return newStation;
}
/**
* Get the station key names
*
* @return the list of station key names
*/
public List getStationKeyNames() {
List keys = new ArrayList();
if ((stationKeys != null) && !stationKeys.isEmpty()) {
for (Key key : stationKeys) {
keys.add(key.name);
}
}
return keys;
}
/**
* Get the station keys
*
* @return the list of station keys
*/
private List findStationKeys() {
Key stid = findKey(GempakStation.STID);
Key stnm = findKey(GempakStation.STNM);
Key slat = findKey(GempakStation.SLAT);
Key slon = findKey(GempakStation.SLON);
Key selv = findKey(GempakStation.SELV);
Key stat = findKey(GempakStation.STAT);
Key coun = findKey(GempakStation.COUN);
Key std2 = findKey(GempakStation.STD2);
Key spri = findKey(GempakStation.SPRI);
Key swfo = findKey(GempakStation.SWFO);
Key wfo2 = findKey(GempakStation.WFO2);
if ((slat == null) || (slon == null)
|| !slat.type.equals(slon.type)) {
return null;
}
String tslat = slat.type;
// check to make sure they are all in the same set of keys
List stKeys = new ArrayList();
stKeys.add(slat);
stKeys.add(slon);
if ((stid != null) && !stid.type.equals(tslat)) {
return null;
} else if ((stnm != null) && !stnm.type.equals(tslat)) {
return null;
} else if ((selv != null) && !selv.type.equals(tslat)) {
return null;
} else if ((stat != null) && !stat.type.equals(tslat)) {
return null;
} else if ((coun != null) && !coun.type.equals(tslat)) {
return null;
} else if ((std2 != null) && !std2.type.equals(tslat)) {
return null;
} else if ((spri != null) && !spri.type.equals(tslat)) {
return null;
} else if ((swfo != null) && !swfo.type.equals(tslat)) {
return null;
} else if ((wfo2 != null) && !wfo2.type.equals(tslat)) {
return null;
}
if (stid != null) {
stKeys.add(stid);
}
if (stnm != null) {
stKeys.add(stnm);
}
if (selv != null) {
stKeys.add(selv);
}
if (stat != null) {
stKeys.add(stat);
}
if (coun != null) {
stKeys.add(coun);
}
if (std2 != null) {
stKeys.add(std2);
}
if (spri != null) {
stKeys.add(spri);
}
if (swfo != null) {
stKeys.add(swfo);
}
if (wfo2 != null) {
stKeys.add(wfo2);
}
return stKeys;
}
/**
* Get the list of stations in this file.
* @return list of stations.
*/
public List getStations() {
return stations;
}
/**
* Get the list of dates in this file.
* @return list of dates.
*/
public List getDates() {
if ((dates == null || dates.isEmpty()) && !dateList.isEmpty()) {
dates = new ArrayList(dateList.size());
dateFmt.setTimeZone(TimeZone.getTimeZone("GMT"));
for (String dateString : dateList) {
Date d = dateFmt.parse(dateString, new ParsePosition(0));
//DateFromString.getDateUsingSimpleDateFormat(dateString,
// DATE_FORMAT);
dates.add(d);
}
}
return dates;
}
/**
* Get the date string at the index
*
* @param index index (row or column)
*
* @return the date at that index
*/
protected String getDateString(int index) {
return dateList.get(index);
}
/**
* Print the list of dates in the file
*/
public void printDates() {
StringBuilder builder = new StringBuilder();
builder.append("\nDates:\n");
for (String date : dateList) {
builder.append("\t");
builder.append(date);
builder.append("\n");
}
System.out.println(builder.toString());
}
/**
* Print the list of dates in the file
* @param list true to list each station, false to list summary
*/
public void printStations(boolean list) {
StringBuilder builder = new StringBuilder();
builder.append("\nStations:\n");
if (list) {
for (GempakStation station : getStations()) {
builder.append(station);
builder.append("\n");
}
} else {
builder.append("\t");
builder.append(getStations().size());
}
System.out.println(builder.toString());
}
/**
* Find the station index for the specified station id.
* @param id station id (case sensitive)
* @return index or -1 if not found.
*/
public int findStationIndex(String id) {
for (GempakStation station : getStations()) {
if (station.getSTID().equals(id)) {
return station.getIndex();
}
}
return -1;
}
/**
* Get the type for this file
* @return file type
*/
public String getFileType() {
String type = "Unknown";
switch (dmLabel.kftype) {
case MFSN :
type = "Sounding";
break;
case MFSF :
type = "Surface";
break;
default :
}
if ( !subType.equals("")) {
type = type + " (" + subType + ")";
}
return type;
}
/**
* Subclasses need to set the subtype. This is an abstract
* method so users will implement something to set the type.
*/
protected abstract void makeFileSubType();
/**
* Get the file sub type
* @return the subtype.
*/
protected String getFileSubType() {
return subType;
}
}