//
// RadarFile.java
//
/*
This sofware is part of the Australian Integrated Forecast System (AIFS)
Copyright (C) 2017 Bureau of Meteorology
*/
package visad.bom;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import java.util.Vector;
import visad.DateTime;
import visad.VisADException;
/**
* RadarFile
*
* @author - James Kelly : J.Kelly@bom.gov.au converted from Phil Purdam's
* radl_cnvt.c
*
*
*/
public class RadarFile {
public DateTime dtTime;
public double dRadarTime;
public float rngres = 250.0f; // Resolution of range rings, in metres
public float startrng = 4000.0f; // Start Range in metres
public float azimuthres = 1.0f; // Resolution of azmuth, in degrees
public float elev = 0.0f; // Elevation of radar beam
// public float center_latitiude = -30.0f;
// public float center_longitiude = 160.0f;
private BufferedReader rf;
private int az;
// public int azimuth[];
public byte radial[][];
final static char decimal = '.';
final static char percent ='%';
final static char[] A2NXlat = {'\u0000','\u0001','\u0002','\u0003','\u0004','\u0005','\u0006',
'\u0010','\u0011','\u0012','\u0013','\u0014','\u0015','\u0016',
'\u0020','\u0021','\u0022','\u0023','\u0024','\u0025','\u0026',
'\u0030','\u0031','\u0032','\u0033','\u0034','\u0035','\u0036',
'\u0040','\u0041','\u0042','\u0043','\u0044','\u0045','\u0046',
'\u0050','\u0051','\u0052','\u0053','\u0054','\u0055','\u0056',
'\u0060','\u0061','\u0062','\u0063','\u0064','\u0065','\u0066' };
final static int maxSize = 250; // maximum number of radial values, usually 512
public byte[] bdata;
public class PolarByteData {
public double azimuth;
public byte[] bdata;
public PolarByteData() { azimuth = 0.0; bdata = new byte[maxSize];}
public PolarByteData(double az, byte[] bdata) {
azimuth = az;
this.bdata = new byte[bdata.length];
System.arraycopy(bdata, 0, this.bdata, 0, bdata.length);
}
}
public Vector pbvector = new Vector();
public PolarByteData pbdata;
public PolarByteData[] pbdataArray;
public RadarFile(String radarSource) throws IOException {
// try as a disk file first
// try {
rf = new BufferedReader( new FileReader (radarSource));
az=0;
while (rf != null) {
readRadial();
pbdata = new PolarByteData((double) az, bdata);
System.arraycopy(bdata, 0, pbdata.bdata, 0, bdata.length);
if (rf != null) pbvector.addElement(pbdata);
}
pbdataArray = new PolarByteData[pbvector.size()];
pbvector.copyInto(pbdataArray);
}
/**
* Retrieves the time of the radar image as a double.
*
* @return image time
*/
public double getTime()
{
return dRadarTime;
}
public void setTime(String radarTime)
{
try {
dRadarTime = Double.valueOf(radarTime).doubleValue();
} catch (NumberFormatException e) {
System.out.println("Exception converting Radar Time in module visad.bom.RadarFile.getTime() " + e);
dRadarTime = 0.0;
}
}
/**
* Retrieves the time of the radar image as a VisAD DateTime.
*
* @return image time
*/
public DateTime getRadarTime()
{
return (dtTime);
}
public void setRadarTime(String timeStamp)
throws VisADException
{
// TIMESTAMP: 19990915024004
int year;
int month;
int day;
int hours;
int mins;
int secs;
String[] ids = TimeZone.getAvailableIDs(0);
TimeZone timeZone = new SimpleTimeZone(0, ids[0]);
Calendar cal = new GregorianCalendar(timeZone);
year = Integer.valueOf(timeStamp.substring(0,4)).intValue();
month = Integer.valueOf(timeStamp.substring(4,6)).intValue();
day = Integer.valueOf(timeStamp.substring(6,8)).intValue();
hours = Integer.valueOf(timeStamp.substring(8,10)).intValue();
mins = Integer.valueOf(timeStamp.substring(10,12)).intValue();
secs = Integer.valueOf(timeStamp.substring(12,14)).intValue();
System.out.println("timeStamp: " + timeStamp);
System.out.println("year,month,day,hour,mins,secs: " + year+ " " + month + " " +day+ " " + hours+ " " + mins+ " " + secs);
// Subtract 1 from month since Jan = 0, Feb = 1 etc
cal.clear();
cal.set(year,month-1,day,hours,mins,secs);
System.out.println("Initialized with date: " + (cal.getTime()).toString());
dtTime = new DateTime(cal.getTime());
System.out.println("Initialized with date: " + dtTime);
}
public void readHeader(char[] cbuff ) {
String radarTime;
String thisLine = new String(cbuff);
// System.out.println("line = " + thisLine);
if (thisLine.startsWith("COUNTRY:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("NAME:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("STNID:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("DATE:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("TIME:")) {
radarTime = new String (thisLine.substring(6));
System.out.println("radarTime = " + radarTime);
} else
if (thisLine.startsWith("TIMESTAMP:")) {
try {
setRadarTime(thisLine.substring(11)) ;
} catch (VisADException e) {
System.out.println("error setting radar time " + e );
}
} else
if (thisLine.startsWith("VERS:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("RNGRES:")) {
rngres = Float.valueOf(thisLine.substring(8)).floatValue();
System.out.println("rngres = " + rngres);
} else
if (thisLine.startsWith("ANGRES:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("VIDRES:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("STARTRNG:")) {
startrng = Float.valueOf(thisLine.substring(10)).floatValue();
System.out.println("startrng = " + startrng);
} else
if (thisLine.startsWith("ENDRNG:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("PRODUCT:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("IMGFMT:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("ELEV:")) {
elev = Float.valueOf(thisLine.substring(6)).floatValue();
System.out.println("elev = " + elev);
} else
if (thisLine.startsWith("DBZLVL:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("CLEARAIR:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("DBZCALDLVL:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("DIGCALDLVL:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("BEAMWIDTH:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("PULSELENGTH:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("STCRANGE:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("TXFREQUENCY:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("TXPEAKPWR:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("ANTGAIN:")) {
System.out.println("line = " + thisLine);
} else
if (thisLine.startsWith("NOISETHRESH:")) {
System.out.println("line = " + thisLine);
}
}
/* Header format:
COUNTRY: 036
NAME: Adel
STNID: 11
DATE: 25899
TIME: 02.40
TIMESTAMP: 19990915024004
VERS: 8.13
RNGRES: 2000
ANGRES: 1.0
VIDRES: 6
STARTRNG: 4000
ENDRNG: 512000
PRODUCT: NORMAL
IMGFMT: CompPPI
ELEV: 000.5
DBZLVL: 11.8 27.8 39.0 43.8 48.6 55.0
CLEARAIR: OFF
DBZCALDLVL: 11.8 23.0 28.0 31.0 34.0 37.0 40.0 43.0 46.0 49.0 52.0 55.0 58.0 61.0 64.0
DIGCALDLVL: 17 34 43 50 56 61 68 73 77 84 90 96 101 107 113
BEAMWIDTH: 3.00
PULSELENGTH: 1.7
STCRANGE: 111
TXFREQUENCY: 2880
TXPEAKPWR: 500
ANTGAIN: 33.0
NOISETHRESH: 14
*/
public void readRadial() throws IOException {
int pos = 0;
boolean done = false;
int rptCount;
int sizeBuff;
char[] cbuff;
char thisChar;
StringBuffer sbuff;
String ipString;
sbuff = new StringBuffer();
bdata = new byte[maxSize];
//
// %ddd or %ddd.d
//
// % = first character
//
ipString = rf.readLine();
// WLH
if (ipString == null) {
rf = null;
return;
}
cbuff = ipString.toCharArray();
sizeBuff = cbuff.length;
// WLH
if (sizeBuff == 0) {
// rf = null;
return;
}
thisChar = cbuff[pos];
if ( percent == thisChar) {
// System.out.println("percent found");
pos++;
} else {
readHeader(cbuff);
}
//
// ddd = azimuthal direction (degrees)
//
thisChar = cbuff[pos++];
while (Character.isDigit(thisChar) || (thisChar == decimal)) {
sbuff.append(thisChar);
// System.out.println("thisChar, pos, sbuff =" + thisChar + " " + pos + " " + sbuff);
thisChar = cbuff[pos++];
}
try {
// System.out.println("azimuth: " + az);
// System.out.println("sbuff, length = " + sbuff + " " + sbuff.length());
if (sbuff.length() != 0)
az = Math.round((Float.valueOf(sbuff.toString())).floatValue());
}
catch (NumberFormatException e) {
System.out.println("error converting radial " + e );
}
pos--;
// assert: next char is alpha
while (!done) {
// System.out.println("assert: next char is alpha");
thisChar = cbuff[pos];
// System.out.println("thisChar = " + thisChar);
pos++;
if (thisChar >= 'A' && thisChar <= 'Y') {
thisChar -= 'A';
}
else {
if (thisChar >= 'a' && thisChar <= 'x')
thisChar -= 'H';
else
thisChar = '\u00FF';
} // endif
if (thisChar != '\u00FF') {
thisChar = A2NXlat[(int)thisChar];
rptCount = 0;
if (pos < cbuff.length) {
while (Character.isDigit( cbuff[pos]) ) {
rptCount = (rptCount * 10) + (cbuff[pos] - '0');
if (++pos >= cbuff.length) {
done = true;
break;
}
} // endwhile
}
else
done = true;
rptCount++;
if ((sizeBuff + (rptCount * 2)) > maxSize) {
rptCount = (maxSize - sizeBuff)/2;
done = true;
} // endif
while ((rptCount--) > 0) {
bdata[sizeBuff] = ((byte)((thisChar) & '\u000f'));
bdata[sizeBuff+1] = ((byte)((thisChar) >> 4));
sizeBuff +=2;
} // endwhile
}
else {
done = true;
pos++;
} // endif
// return 0;
// pos++ ;
} // endwhile
// System.out.print("bdata = ");
// for (int i=0; i < maxSize; i++) {
// System.out.print(bdata[i] + " ");
// }
// System.out.println(" ");
// System.out.println("end readRadial");
} // readRadial
} // RadarFile