add SA/SB radar data support

This commit is contained in:
wyq 2024-05-23 20:36:18 +08:00
parent 1794f0def1
commit 04ac485574
14 changed files with 1664 additions and 400 deletions

View File

@ -96,7 +96,7 @@ import org.meteoinfo.data.GridData;
/** /**
* Read grid data - time * Read grid data - time
* *
* @param lonIdx Lontitude index * @param lonIdx Longitude index
* @param latIdx Latitude index * @param latIdx Latitude index
* @param varName Variable name * @param varName Variable name
* @param levelIdx Level index * @param levelIdx Level index
@ -107,7 +107,7 @@ import org.meteoinfo.data.GridData;
/** /**
* Read grid data - level * Read grid data - level
* *
* @param lonIdx Lontitude index * @param lonIdx Longitude index
* @param latIdx Latitude index * @param latIdx Latitude index
* @param varName Variable name * @param varName Variable name
* @param timeIdx Time index * @param timeIdx Time index
@ -130,7 +130,7 @@ import org.meteoinfo.data.GridData;
* Read grid data - latitude * Read grid data - latitude
* *
* @param timeIdx Time index * @param timeIdx Time index
* @param lonIdx Lontitude index * @param lonIdx Longitude index
* @param varName Variable name * @param varName Variable name
* @param levelIdx Level index * @param levelIdx Level index
* @return Grid data * @return Grid data

View File

@ -41,6 +41,9 @@ import java.util.ArrayList;
import org.meteoinfo.data.meteodata.numpy.NumpyDataInfo; import org.meteoinfo.data.meteodata.numpy.NumpyDataInfo;
import org.meteoinfo.data.meteodata.radar.CMARadarBaseDataInfo; import org.meteoinfo.data.meteodata.radar.CMARadarBaseDataInfo;
import org.meteoinfo.data.meteodata.radar.RadarDataType;
import org.meteoinfo.data.meteodata.radar.RadarDataUtil;
import org.meteoinfo.data.meteodata.radar.cinrad.CinradDataInfo;
import org.meteoinfo.ndarray.math.ArrayMath; import org.meteoinfo.ndarray.math.ArrayMath;
import org.meteoinfo.projection.ProjectionInfo; import org.meteoinfo.projection.ProjectionInfo;
import java.util.List; import java.util.List;
@ -471,31 +474,31 @@ public class MeteoDataInfo {
* @return Data info * @return Data info
*/ */
public DataInfo getDataInfo(String fileName) { public DataInfo getDataInfo(String fileName) {
DataInfo di = null; DataInfo di = RadarDataUtil.getDataInfo(fileName);
try { if (di == null) {
RandomAccessFile raf = new RandomAccessFile(fileName, "r"); try {
if (GrADSDataInfo.class.getDeclaredConstructor().newInstance().isValidFile(raf)) { RandomAccessFile raf = new RandomAccessFile(fileName, "r");
di = new GrADSDataInfo(); if (GrADSDataInfo.class.getDeclaredConstructor().newInstance().isValidFile(raf)) {
} else if (NetcdfFiles.canOpen(fileName)) { di = new GrADSDataInfo();
di = new NetCDFDataInfo(); } else if (NetcdfFiles.canOpen(fileName)) {
} else if (ARLDataInfo.class.getDeclaredConstructor().newInstance().isValidFile(raf)) { di = new NetCDFDataInfo();
di = new ARLDataInfo(); } else if (ARLDataInfo.class.getDeclaredConstructor().newInstance().isValidFile(raf)) {
} else if (CMARadarBaseDataInfo.canOpen(fileName)) { di = new ARLDataInfo();
di = new CMARadarBaseDataInfo(); } else if (MatLabDataInfo.class.getDeclaredConstructor().newInstance().isValidFile(raf)) {
} else if (MatLabDataInfo.class.getDeclaredConstructor().newInstance().isValidFile(raf)) { di = new MatLabDataInfo();
di = new MatLabDataInfo(); } else {
} else { di = MICAPSDataInfo.getDataInfo(raf);
di = MICAPSDataInfo.getDataInfo(raf); }
raf.close();
} catch (IOException | NoSuchMethodException ex) {
return null;
} catch (InvocationTargetException e) {
return null;
} catch (InstantiationException e) {
return null;
} catch (IllegalAccessException e) {
return null;
} }
raf.close();
} catch (IOException | NoSuchMethodException ex) {
return null;
} catch (InvocationTargetException e) {
return null;
} catch (InstantiationException e) {
return null;
} catch (IllegalAccessException e) {
return null;
} }
return di; return di;

View File

@ -0,0 +1,546 @@
package org.meteoinfo.data.meteodata.radar;
import org.meteoinfo.data.dimarray.Dimension;
import org.meteoinfo.data.meteodata.Attribute;
import org.meteoinfo.data.meteodata.DataInfo;
import org.meteoinfo.data.meteodata.Variable;
import org.meteoinfo.ndarray.*;
import org.meteoinfo.ndarray.math.ArrayMath;
import org.meteoinfo.ndarray.math.ArrayUtil;
import java.io.RandomAccessFile;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public abstract class BaseRadarDataInfo extends DataInfo {
protected final Map<Integer, String> productMap = Stream.of(new Object[][]{{1,"dBT"}, {2,"dBZ"},
{3,"V"}, {4,"W"}, {5,"SQI"}, {6,"CPA"}, {7,"ZDR"}, {8,"LDR"}, {9,"CC"}, {10,"PhiDP"},
{11,"KDP"}, {12,"CP"}, {13,"Flag"}, {14,"HCL"}, {15,"CF"}, {16,"SNRH"}, {17,"SNRV"},
{18,"Flag"}, {19,"Flag"}, {20,"Flag"}, {21,"Flag"}, {22,"Flag"}, {23,"Flag"},
{24,"Flag"}, {25,"Flag"}, {26,"Flag"}, {27,"Flag"}, {28,"Flag"}, {29,"Flag"},
{30,"Flag"}, {31,"Flag"}, {32,"Zc"}, {33,"Vc"}, {34,"Wc"}, {35,"ZDRc"}, {0,"Flag"}
}).collect(Collectors.toMap(data -> (Integer) data[0], data -> (String) data[1]));
protected final Map<String, RadialRecord> recordMap = new HashMap<>();
protected final List<String> velocityGroup = new ArrayList<>(Arrays.asList("V", "W"));
protected Dimension radialDim, scanDim, gateRDim, gateVDim;
protected float antennaHeight = 0;
protected float beamWidthVert = 1.f;
protected int logResolution = 1000;
protected int dopplerResolution = 1000;
/**
* Get record map
* @return Record map
*/
public Map<String, RadialRecord> getRecordMap() {
return this.recordMap;
}
/**
* Is a radial record is in velocity group or not
* @param record The radial record
* @return Velocity group or not
*/
public boolean isVelocityGroup(RadialRecord record) {
return velocityGroup.contains(record.product);
}
/**
* Is a product is in velocity group or not
* @param product The product name
* @return Velocity group or not
*/
public boolean isVelocityGroup(String product) {
return velocityGroup.contains(product);
}
protected void makeRefVariables(RadialRecord refRadialRecord) {
Dimension[] dimensions = new Dimension[]{scanDim, radialDim, gateRDim};
for (RadialRecord radialRecord : this.recordMap.values()) {
if (!radialRecord.isVelocityGroup())
radialRecord.makeVariable(this, dimensions);
}
//coordinate variables
Variable elevation = new Variable();
elevation.setName("elevationR");
elevation.setDataType(DataType.FLOAT);
elevation.addDimension(scanDim);
elevation.addDimension(radialDim);
elevation.addAttribute(new Attribute("units", "degree"));
elevation.addAttribute(new Attribute("long_name", "elevation angle in degrees"));
this.addVariable(elevation);
Variable azimuth = new Variable();
azimuth.setName("azimuthR");
azimuth.setDataType(DataType.FLOAT);
azimuth.addDimension(scanDim);
azimuth.addDimension(radialDim);
azimuth.addAttribute(new Attribute("units", "degree"));
azimuth.addAttribute(new Attribute("long_name", "azimuth angle in degrees"));
this.addVariable(azimuth);
Variable distance = new Variable();
distance.setName("distanceR");
distance.setDataType(DataType.FLOAT);
distance.addDimension(gateRDim);
distance.addAttribute(new Attribute("units", "m"));
distance.addAttribute(new Attribute("long_name", "radial distance to start of gate"));
this.addVariable(distance);
Variable nRadials = new Variable();
nRadials.setName("numRadialsR");
nRadials.setDataType(DataType.INT);
nRadials.addDimension(scanDim);
nRadials.addAttribute(new Attribute("long_name", "number of valid radials in this scan"));
this.addVariable(nRadials);
Variable nGates = new Variable();
nGates.setName("numGatesR");
nGates.setDataType(DataType.INT);
nGates.addDimension(scanDim);
nGates.addAttribute(new Attribute("long_name", "number of valid gates in this scan"));
this.addVariable(nGates);
int nScan = scanDim.getLength();
int nRadial = radialDim.getLength();
int nGate = gateRDim.getLength();
Array elevData = Array.factory(DataType.FLOAT, new int[]{nScan, nRadial});
Array aziData = Array.factory(DataType.FLOAT, new int[]{nScan, nRadial});
Array nRData = Array.factory(DataType.INT, new int[]{nScan});
Array nGData = Array.factory(DataType.INT, new int[]{nScan});
Index elevIndex = elevData.getIndex();
Index aziIndex = aziData.getIndex();
for (int i = 0; i < nScan; i++) {
List<Float> elevList = refRadialRecord.elevation.get(i);
List<Float> aziList = refRadialRecord.azimuth.get(i);
nRData.setInt(i, aziList.size());
nGData.setInt(i, (int) refRadialRecord.distance.get(i).getSize());
for (int j = 0; j < nRadial; j++) {
if (j < elevList.size()) {
elevData.setFloat(elevIndex.set(i, j), elevList.get(j));
aziData.setFloat(aziIndex.set(i, j), aziList.get(j));
} else {
elevData.setFloat(elevIndex.set(i, j), Float.NaN);
aziData.setFloat(aziIndex.set(i, j), Float.NaN);
}
}
}
Array disData = refRadialRecord.distance.get(0);
elevation.setCachedData(elevData);
azimuth.setCachedData(aziData);
distance.setCachedData(disData);
nRadials.setCachedData(nRData);
nGates.setCachedData(nGData);
}
protected void makeVelVariables(RadialRecord velRadialRecord) {
Dimension[] dimensions = new Dimension[]{scanDim, radialDim, gateVDim};
for (RadialRecord radialRecord : this.recordMap.values()) {
if (radialRecord.isVelocityGroup())
radialRecord.makeVariable(this, dimensions);
}
//coordinate variables
Variable elevation = new Variable();
elevation.setName("elevationV");
elevation.setDataType(DataType.FLOAT);
elevation.addDimension(scanDim);
elevation.addDimension(radialDim);
elevation.addAttribute(new Attribute("units", "degree"));
elevation.addAttribute(new Attribute("long_name", "elevation angle in degrees"));
this.addVariable(elevation);
Variable azimuth = new Variable();
azimuth.setName("azimuthV");
azimuth.setDataType(DataType.FLOAT);
azimuth.addDimension(scanDim);
azimuth.addDimension(radialDim);
azimuth.addAttribute(new Attribute("units", "degree"));
azimuth.addAttribute(new Attribute("long_name", "azimuth angle in degrees"));
this.addVariable(azimuth);
Variable distance = new Variable();
distance.setName("distanceV");
distance.setDataType(DataType.FLOAT);
distance.addDimension(gateVDim);
distance.addAttribute(new Attribute("units", "m"));
distance.addAttribute(new Attribute("long_name", "radial distance to start of gate"));
this.addVariable(distance);
Variable nRadials = new Variable();
nRadials.setName("numRadialsR");
nRadials.setDataType(DataType.INT);
nRadials.addDimension(scanDim);
nRadials.addAttribute(new Attribute("long_name", "number of valid radials in this scan"));
this.addVariable(nRadials);
Variable nGates = new Variable();
nGates.setName("numGatesR");
nGates.setDataType(DataType.INT);
nGates.addDimension(scanDim);
nGates.addAttribute(new Attribute("long_name", "number of valid gates in this scan"));
this.addVariable(nGates);
int nScan = scanDim.getLength();
int nRadial = radialDim.getLength();
int nGate = gateVDim.getLength();
Array elevData = Array.factory(DataType.FLOAT, new int[]{nScan, nRadial});
Array aziData = Array.factory(DataType.FLOAT, new int[]{nScan, nRadial});
Array nRData = Array.factory(DataType.INT, new int[]{nScan});
Array nGData = Array.factory(DataType.INT, new int[]{nScan});
Index elevIndex = elevData.getIndex();
Index aziIndex = aziData.getIndex();
for (int i = 0; i < nScan; i++) {
List<Float> elevList = velRadialRecord.elevation.get(i);
List<Float> aziList = velRadialRecord.azimuth.get(i);
nRData.setInt(i, aziList.size());
nGData.setInt(i, (int) velRadialRecord.distance.get(i).getSize());
for (int j = 0; j < nRadial; j++) {
if (j < elevList.size()) {
elevData.setFloat(elevIndex.set(i, j), elevList.get(j));
aziData.setFloat(aziIndex.set(i, j), aziList.get(j));
} else {
elevData.setFloat(elevIndex.set(i, j), Float.NaN);
aziData.setFloat(aziIndex.set(i, j), Float.NaN);
}
}
}
Array disData = velRadialRecord.distance.get(0);
elevation.setCachedData(elevData);
azimuth.setCachedData(aziData);
distance.setCachedData(disData);
nRadials.setCachedData(nRData);
nGates.setCachedData(nGData);
}
/**
* Get product names
* @return product names
*/
public List<String> getProducts() {
List<String> products = new ArrayList<>();
for (String product : this.recordMap.keySet()) {
products.add(product);
}
return products;
}
/**
* Get scan elevations
* @return Scan elevations
*/
public List<Float> getElevations(String product) {
RadialRecord radialRecord = this.recordMap.get(product);
return radialRecord.fixedElevation;
}
@Override
public Array read(String varName) {
Variable var = this.getVariable(varName);
int n = var.getDimNumber();
int[] origin = new int[n];
int[] size = new int[n];
int[] stride = new int[n];
for (int i = 0; i < n; i++) {
origin[i] = 0;
size[i] = var.getDimLength(i);
stride[i] = 1;
}
Array r = read(varName, origin, size, stride);
return r;
}
@Override
public Array read(String varName, int[] origin, int[] size, int[] stride) {
try {
Variable variable = this.getVariable(varName);
if (variable.hasCachedData()) {
return variable.getCachedData().section(origin, size, stride).copy();
}
Section section = new Section(origin, size, stride);
RadialRecord record = this.recordMap.get(varName);
Array dataArray = Array.factory(DataType.FLOAT, section.getShape());
Range zRange = section.getRange(0);
Range yRange = section.getRange(1);
Range xRange = section.getRange(2);
IndexIterator iter = dataArray.getIndexIterator();
for (int s = zRange.first(); s <= zRange.last(); s += zRange.stride()) {
List<Array> arrays = record.getDataArray(s);
for (int i = yRange.first(); i <= yRange.last(); i += yRange.stride()) {
if (i < arrays.size()) {
Array array = arrays.get(i);
for (int j = xRange.first(); j <= xRange.last(); j += xRange.stride()) {
if (j < array.getSize())
iter.setFloatNext(array.getFloat(j));
else
iter.setFloatNext(Float.NaN);
}
} else {
for (int j = xRange.first(); j <= xRange.last(); j += xRange.stride()) {
iter.setFloatNext(Float.NaN);
}
}
}
}
Attribute aoAttr = variable.findAttribute("add_offset");
Attribute sfAttr = variable.findAttribute("scale_factor");
if (aoAttr != null || sfAttr != null) {
Number add_offset = 0.f;
Number scale_factor = 1.f;
if (aoAttr != null) {
switch (aoAttr.getDataType()) {
case DOUBLE:
add_offset = aoAttr.getValues().getDouble(0);
break;
case FLOAT:
case INT:
add_offset = aoAttr.getValues().getFloat(0);
break;
}
}
if (sfAttr != null) {
switch (sfAttr.getDataType()) {
case DOUBLE:
scale_factor = sfAttr.getValues().getDouble(0);
break;
case FLOAT:
case INT:
scale_factor = sfAttr.getValues().getFloat(0);
break;
}
}
dataArray = ArrayMath.add(ArrayMath.mul(dataArray, scale_factor), add_offset);
}
return dataArray;
} catch (InvalidRangeException e) {
return null;
}
}
@Override
public List<Attribute> getGlobalAttributes() {
return this.attributes;
}
/**
* Read grid ppi data
* @param varName Variable name
* @param scanIdx Scan index
* @param xa X coordinates array
* @param ya Y coordinates array
* @param h Radar height
* @return Grid ppi data
*/
public Array readGridData(String varName, int scanIdx, Array xa, Array ya, Float h) {
RadialRecord record = this.recordMap.get(varName);
if (h == null) {
h = antennaHeight;
}
Array[] rr = Transform.cartesianToAntennaElevation(xa, ya, record.fixedElevation.get(scanIdx), h);
Array azimuth = rr[0];
Array ranges = rr[1];
Array data = Array.factory(DataType.FLOAT, xa.getShape());
IndexIterator iterA = azimuth.getIndexIterator();
IndexIterator iterR = ranges.getIndexIterator();
IndexIterator iterData = data.getIndexIterator();
float v;
while (iterData.hasNext()) {
v = record.interpolateValue(scanIdx, iterA.getFloatNext(), iterR.getFloatNext());
iterData.setFloatNext(v);
}
return data;
}
/**
* Read CR data
* @param varName Variable name
* @param xa X coordinates array - 2D
* @param ya Y coordinates array - 2D
* @param h Radar height
* @return CR data
*/
public Array getCRData(String varName, Array xa, Array ya, Float h) {
RadialRecord record = this.recordMap.get(varName);
int nScan = record.getScanNumber();
if (h == null) {
h = antennaHeight;
}
int[] shape = xa.getShape();
int ny = shape[0];
int nx = shape[1];
Array data = Array.factory(DataType.FLOAT, shape);
Index2D index2D = (Index2D) data.getIndex();
float v;
for (int s = 0; s < nScan; s++) {
Array[] rr = Transform.cartesianToAntennaElevation(xa, ya, record.fixedElevation.get(s), h);
Array azimuth = rr[0];
Array ranges = rr[1];
IndexIterator iterA = azimuth.getIndexIterator();
IndexIterator iterR = ranges.getIndexIterator();
if (s == 0) {
for (int i = 0; i < ny; i++) {
for (int j = 0; j < nx; j++) {
v = record.interpolateValue(s, iterA.getFloatNext(), iterR.getFloatNext());
data.setFloat(index2D.set(i, j), v);
}
}
} else {
float v1;
for (int i = 0; i < ny; i++) {
for (int j = 0; j < nx; j++) {
v = record.interpolateValue(s, iterA.getFloatNext(), iterR.getFloatNext());
index2D.set(i, j);
v1 = data.getFloat(index2D);
if (Float.isNaN(v1) || (v > v1))
data.setFloat(index2D, v);
}
}
}
}
return data;
}
/**
* Read CAPPI data
* @param varName Variable name
* @param xa X coordinates array
* @param ya Y coordinates array
* @param z Z coordinates value
* @param h Radar height
* @return Grid ppi data
*/
public Array getCAPPIData(String varName, Array xa, Array ya, float z, Float h) {
RadialRecord record = this.recordMap.get(varName);
if (h == null) {
h = antennaHeight;
}
Array[] rr = Transform.cartesianToAntenna(xa, ya, z, h);
Array azimuth = rr[0];
Array ranges = rr[1];
Array elevation = rr[2];
Array data = Array.factory(DataType.FLOAT, xa.getShape());
IndexIterator iterA = azimuth.getIndexIterator();
IndexIterator iterR = ranges.getIndexIterator();
IndexIterator iterE = elevation.getIndexIterator();
IndexIterator iterData = data.getIndexIterator();
float v;
float halfBeamWidth = beamWidthVert / 2;
while (iterData.hasNext()) {
v = record.interpolateValue(iterE.getFloatNext(), iterA.getFloatNext(),
iterR.getFloatNext(), halfBeamWidth);
iterData.setFloatNext(v);
}
return data;
}
/**
* Read grid 3d data
* @param varName Variable name
* @param xa X coordinates array
* @param ya Y coordinates array
* @param z Z coordinates array
* @param h Radar height
* @return Grid ppi data
*/
public Array getGrid3DData(String varName, Array xa, Array ya, Array za, Float h) {
RadialRecord record = this.recordMap.get(varName);
if (h == null) {
h = antennaHeight;
}
int nz = (int) za.getSize();
int[] shape2D = xa.getShape();
int[] shape3D = new int[]{nz, shape2D[0], shape2D[1]};
Array data = Array.factory(DataType.FLOAT, shape3D);
IndexIterator iterData = data.getIndexIterator();
IndexIterator iterZ = za.getIndexIterator();
float halfBeamWidth = beamWidthVert / 2;
while(iterZ.hasNext()) {
float z = iterZ.getFloatNext();
Array[] rr = Transform.cartesianToAntenna(xa, ya, z, h);
Array azimuth = rr[0];
Array ranges = rr[1];
Array elevation = rr[2];
IndexIterator iterA = azimuth.getIndexIterator();
IndexIterator iterR = ranges.getIndexIterator();
IndexIterator iterE = elevation.getIndexIterator();
float v;
while (iterA.hasNext()) {
v = record.interpolateValue(iterE.getFloatNext(), iterA.getFloatNext(),
iterR.getFloatNext(), halfBeamWidth);
iterData.setFloatNext(v);
}
}
return data;
}
/**
* Get VCS data
* @param varName Variable name
* @param startX Start x, km
* @param startY Start y, km
* @param endX End x, km
* @param endY End y, km
* @return VCS data
*/
public Array[] getVCSData(String varName, float startX, float startY, float endX, float endY) {
RadialRecord record = this.recordMap.get(varName);
int nScan = record.getScanNumber();
float halfBeamWidth = this.beamWidthVert / 2;
float binRes = isVelocityGroup(varName) ? this.dopplerResolution : this.logResolution;
float height = this.antennaHeight;
float startEndDistance = (float) Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
int nPoints = (int) (startEndDistance * 1000 / binRes + 1);
Array xa = ArrayUtil.lineSpace(startX, endX, nPoints);
Array ya = ArrayUtil.lineSpace(startY, endY, nPoints);
Array aa = Transform.xyToAzimuth(xa, ya);
int[] shape = new int[]{nScan, 2, nPoints};
Array data = Array.factory(DataType.FLOAT, shape);
Array meshXY = Array.factory(DataType.FLOAT, shape);
Array meshZ = Array.factory(DataType.FLOAT, shape);
Index dataIndex = data.getIndex();
Index meshXYIndex = meshXY.getIndex();
Index meshZIndex = meshZ.getIndex();
float x, y, z1, z2, dis, azi, v, ele;
for (int i = 0; i < nScan; i++) {
ele = record.fixedElevation.get(i);
for (int j = 0; j < nPoints; j++) {
x = xa.getFloat(j);
y = ya.getFloat(j);
dis = (float) Math.sqrt(x * x + y * y);
azi = aa.getFloat(j);
v = record.getValue(i, azi, dis * 1000);
z1 = Transform.toCartesianZ(dis * 1000, (float) Math.toRadians(ele -
halfBeamWidth), height) / 1000.f;
z2 = Transform.toCartesianZ(dis * 1000, (float) Math.toRadians(ele +
halfBeamWidth), height) / 1000.f;
for (int k = 0; k < 2; k++) {
data.setFloat(dataIndex.set(i, k, j), v);
meshXY.setFloat(meshXYIndex.set(i, k, j), dis);
}
meshZ.setFloat(meshZIndex.set(i, 0, j), z1);
meshZ.setFloat(meshZIndex.set(i, 1, j), z2);
}
}
return new Array[]{data, meshXY, meshZ};
}
}

View File

@ -0,0 +1,275 @@
package org.meteoinfo.data.meteodata.radar;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.meteoinfo.data.dimarray.Dimension;
import org.meteoinfo.data.meteodata.Attribute;
import org.meteoinfo.data.meteodata.DataInfo;
import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.DataType;
import org.meteoinfo.ndarray.math.ArrayUtil;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class CCRadarDataInfo extends BaseRadarDataInfo implements IRadarDataInfo {
@Override
public boolean isValidFile(java.io.RandomAccessFile raf) {
return false;
}
void setScaleOffset(RadialRecord record, int vResolution) {
switch (record.product) {
case "dBZ":
record.scale = 0.5f;
record.offset = -33.f;
break;
case "V":
if (vResolution == 2) {
record.scale = 0.5f;
record.offset = -64.5f;
} else {
record.scale = 1.f;
record.offset = -129.f;
}
break;
case "W":
record.scale = 0.5f;
record.offset = -64.5f;
break;
}
}
@Override
public void readDataInfo(String fileName) {
this.fileName = fileName;
if (fileName.endsWith(".bz2")) {
try {
BZip2CompressorInputStream inputStream = new BZip2CompressorInputStream(Files.newInputStream(Paths.get(fileName)));
readDataInfo(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
try {
BufferedInputStream inputStream = new BufferedInputStream(Files.newInputStream(Paths.get(fileName)));
readDataInfo(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
void readDataInfo(InputStream is) {
try {
int index = 0;
byte[] rhBytes = new byte[SABRadarDataInfo.RadialHeader.length];
while (is.read(rhBytes) != -1) {
SABRadarDataInfo.RadialHeader radialHeader = new SABRadarDataInfo.RadialHeader(rhBytes);
if (index == 0) {
this.logResolution = radialHeader.gateSizeOfReflectivity;
this.dopplerResolution = radialHeader.gateSizeOfDoppler;
}
if (!radialHeader.hasReflectivityData()) {
is.read(new byte[460]);
}
for (String product : radialHeader.getProducts()) {
RadialRecord record;
if (this.recordMap.containsKey(product)) {
record = this.recordMap.get(product);
} else {
record = new RadialRecord(product);
record.setBinLength(1);
setScaleOffset(record, radialHeader.resolutionOfVelocity);
this.recordMap.put(product, record);
}
if (radialHeader.radialNumber == 1) {
record.fixedElevation.add(radialHeader.getElevation());
record.elevation.add(new ArrayList<>());
record.azimuth.add(new ArrayList<>());
record.azimuthMinIndex.add(0);
if (isVelocityGroup(record)) {
record.disResolution.add(radialHeader.gateSizeOfDoppler);
record.distance.add(ArrayUtil.arrayRange1(radialHeader.rangeToFirstGateOfDop,
radialHeader.gatesNumberOfDoppler, radialHeader.gateSizeOfDoppler));
} else {
record.disResolution.add(radialHeader.gateSizeOfReflectivity);
record.distance.add(ArrayUtil.arrayRange1(radialHeader.rangeToFirstGateOfRef,
radialHeader.gatesNumberOfReflectivity, radialHeader.gateSizeOfReflectivity));
}
record.newScanData();
}
record.elevation.get(record.elevation.size() - 1).add(radialHeader.getElevation());
record.addAzimuth(radialHeader.getAzimuth());
int dataLength = isVelocityGroup(record) ? radialHeader.gatesNumberOfDoppler : radialHeader.gatesNumberOfReflectivity;
byte[] bytes = new byte[dataLength];
is.read(bytes);
record.addDataBytes(bytes);
if (isVelocityGroup(record)) {
if (dataLength < 920) {
is.read(new byte[920 - dataLength]);
}
} else {
if (dataLength < 460) {
is.read(new byte[460 - dataLength]);
}
}
}
if (!radialHeader.hasDopplerData()) {
is.read(new byte[920 + 920]);
}
is.read(new byte[4]);
index += 1;
}
is.close();
this.addAttribute(new Attribute("featureType", "RADIAL"));
this.addAttribute(new Attribute("DataType", "Radial"));
//Add dimensions and variables
RadialRecord refRadialRecord = this.recordMap.get("dBZ");
radialDim = new Dimension();
radialDim.setName("radial");
radialDim.setLength(refRadialRecord.getMaxRadials());
this.addDimension(radialDim);
scanDim = new Dimension();
scanDim.setName("scan");
scanDim.setLength(refRadialRecord.getScanNumber());
this.addDimension(scanDim);
gateRDim = new Dimension();
gateRDim.setName("gateR");
gateRDim.setLength(refRadialRecord.getGateNumber(0));
this.addDimension(gateRDim);
makeRefVariables(refRadialRecord);
RadialRecord velRadialRecord = this.recordMap.get("V");
gateVDim = new Dimension();
gateVDim.setName("gateV");
gateVDim.setLength(velRadialRecord.getGateNumber(0));
this.addDimension(gateVDim);
makeVelVariables(velRadialRecord);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public RadarDataType getRadarDataType() {
return RadarDataType.SAB;
}
static class RadialHeader {
public static int length = 128;
public int mSecond; // collection time for this radial, msecs since midnight
public short julianDate; // prob "collection time"
public short uRange; // unambiguous range
public int azimuth; // azimuth angle
public short radialNumber; // radial number within the elevation
public short radialStatus;
public short elevation;
public short elNumber; // elevation number
public int rangeToFirstGateOfRef; // range to first gate of reflectivity (m) may be negative
public int rangeToFirstGateOfDop; // range to first gate of doppler (m) may be negative
public int gateSizeOfReflectivity; // reflectivity data gate size (m)
public int gateSizeOfDoppler; // doppler data gate size (m)
public int gatesNumberOfReflectivity; // number of reflectivity gates
public int gatesNumberOfDoppler; // number of velocity or spectrum width gates
public short cutSectorNumber;
public int calibrationConst;
public short ptrOfReflectivity;
public short ptrOfVelocity;
public short ptrOfSpectrumWidth;
public int resolutionOfVelocity;
public short vcpNumber;
public short nyquist;
/**
* Constructor
* @param is InputStream
*/
public RadialHeader(byte[] inBytes) throws IOException {
ByteBuffer byteBuffer = ByteBuffer.wrap(inBytes);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.position(28);
mSecond = byteBuffer.getInt();
julianDate = byteBuffer.getShort();
uRange = byteBuffer.getShort();
azimuth = DataType.unsignedShortToInt(byteBuffer.getShort());
radialNumber = byteBuffer.getShort();
radialStatus = byteBuffer.getShort();
elevation = byteBuffer.getShort();
elNumber = byteBuffer.getShort();
rangeToFirstGateOfRef = byteBuffer.getShort();
rangeToFirstGateOfDop = byteBuffer.getShort();
gateSizeOfReflectivity = byteBuffer.getShort();
gateSizeOfDoppler = byteBuffer.getShort();
gatesNumberOfReflectivity = byteBuffer.getShort();
gatesNumberOfDoppler = byteBuffer.getShort();
cutSectorNumber = byteBuffer.getShort();
calibrationConst = byteBuffer.getShort();
ptrOfReflectivity = byteBuffer.getShort();
ptrOfVelocity = byteBuffer.getShort();
ptrOfSpectrumWidth = byteBuffer.getShort();
resolutionOfVelocity = byteBuffer.getShort();
vcpNumber = byteBuffer.getShort();
byteBuffer.position(byteBuffer.position() + 14);
nyquist = byteBuffer.getShort();
}
/**
* Has reflectivity data or not
* @return Has reflectivity data
*/
public boolean hasReflectivityData() {
return gatesNumberOfReflectivity > 0;
}
/**
* Has doppler data or not
* @return Has doppler data
*/
public boolean hasDopplerData() {
return gatesNumberOfDoppler > 0;
}
/**
* Get product names
* @return Product names
*/
public List<String> getProducts() {
List<String> products = new ArrayList<>();
if (hasReflectivityData()) {
products.add("dBZ");
}
if (hasDopplerData()) {
products.add("V");
products.add("W");
}
return products;
}
/**
* Get azimuth
* @return Azimuth
*/
public float getAzimuth() {
return azimuth / 8.f * 180.f / 4096.f;
}
/**
* Get elevation
* @return Elevation
*/
public float getElevation() {
return elevation / 8.f * 180.f / 4096.f;
}
}
}

View File

@ -20,23 +20,13 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo { public class CMARadarBaseDataInfo extends BaseRadarDataInfo implements IRadarDataInfo {
private GenericHeader genericHeader; private GenericHeader genericHeader;
private SiteConfig siteConfig; private SiteConfig siteConfig;
private TaskConfig taskConfig; private TaskConfig taskConfig;
private List<CutConfig> cutConfigs; private List<CutConfig> cutConfigs;
private List<RadialHeader> radialHeaders; private List<RadialHeader> radialHeaders;
private final Map<Integer, String> productMap = Stream.of(new Object[][]{{1,"dBT"}, {2,"dBZ"},
{3,"V"}, {4,"W"}, {5,"SQI"}, {6,"CPA"}, {7,"ZDR"}, {8,"LDR"}, {9,"CC"}, {10,"PhiDP"},
{11,"KDP"}, {12,"CP"}, {13,"Flag"}, {14,"HCL"}, {15,"CF"}, {16,"SNRH"}, {17,"SNRV"},
{18,"Flag"}, {19,"Flag"}, {20,"Flag"}, {21,"Flag"}, {22,"Flag"}, {23,"Flag"},
{24,"Flag"}, {25,"Flag"}, {26,"Flag"}, {27,"Flag"}, {28,"Flag"}, {29,"Flag"},
{30,"Flag"}, {31,"Flag"}, {32,"Zc"}, {33,"Vc"}, {34,"Wc"}, {35,"ZDRc"}, {0,"Flag"}
}).collect(Collectors.toMap(data -> (Integer) data[0], data -> (String) data[1]));
private final Map<String, RadialRecord> recordMap = new HashMap<>();
private final List<String> velocityGroup = new ArrayList<>(Arrays.asList("V", "W"));
private Dimension radialDim, scanDim, gateRDim, gateVDim;
/** /**
* Constructor * Constructor
@ -45,6 +35,15 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
this.meteoDataType = MeteoDataType.RADAR; this.meteoDataType = MeteoDataType.RADAR;
} }
/**
* Get radar data type
* @return Radar data type
*/
@Override
public RadarDataType getRadarDataType() {
return RadarDataType.STANDARD;
}
/** /**
* Get generic header * Get generic header
* @return Generic header * @return Generic header
@ -85,78 +84,6 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
return this.radialHeaders; return this.radialHeaders;
} }
/**
* Get record map
* @return Record map
*/
public Map<String, RadialRecord> getRecordMap() {
return this.recordMap;
}
@Override
public GridArray getGridArray(String varName) {
return null;
}
@Override
public GridData getGridData_LonLat(int timeIdx, String varName, int levelIdx) {
return null;
}
@Override
public GridData getGridData_TimeLat(int lonIdx, String varName, int levelIdx) {
return null;
}
@Override
public GridData getGridData_TimeLon(int latIdx, String varName, int levelIdx) {
return null;
}
@Override
public GridData getGridData_LevelLat(int lonIdx, String varName, int timeIdx) {
return null;
}
@Override
public GridData getGridData_LevelLon(int latIdx, String varName, int timeIdx) {
return null;
}
@Override
public GridData getGridData_LevelTime(int latIdx, String varName, int lonIdx) {
return null;
}
@Override
public GridData getGridData_Time(int lonIdx, int latIdx, String varName, int levelIdx) {
return null;
}
@Override
public GridData getGridData_Level(int lonIdx, int latIdx, String varName, int timeIdx) {
return null;
}
@Override
public GridData getGridData_Lon(int timeIdx, int latIdx, String varName, int levelIdx) {
return null;
}
@Override
public GridData getGridData_Lat(int timeIdx, int lonIdx, String varName, int levelIdx) {
return null;
}
/**
* Is a radial record is in velocity group or not
* @param record The radial record
* @return Velocity group or not
*/
public boolean isVelocityGroup(RadialRecord record) {
return velocityGroup.contains(record.product);
}
@Override @Override
public boolean isValidFile(RandomAccessFile raf) { public boolean isValidFile(RandomAccessFile raf) {
try { try {
@ -229,6 +156,8 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
try { try {
genericHeader = new GenericHeader(raf); genericHeader = new GenericHeader(raf);
siteConfig = new SiteConfig(raf); siteConfig = new SiteConfig(raf);
this.antennaHeight = siteConfig.antennaHeight;
this.beamWidthVert = siteConfig.beamWidthVert;
//Add global attributes //Add global attributes
this.addAttribute(new Attribute("StationCode", siteConfig.siteCode)); this.addAttribute(new Attribute("StationCode", siteConfig.siteCode));
@ -248,8 +177,14 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
//Read radial data //Read radial data
cutConfigs = new ArrayList<>(); cutConfigs = new ArrayList<>();
CutConfig cutConfig;
for (int i = 0; i < taskConfig.cutNumber; i++) { for (int i = 0; i < taskConfig.cutNumber; i++) {
cutConfigs.add(new CutConfig(raf)); cutConfig = new CutConfig(raf);
cutConfigs.add(cutConfig);
if (i == 0) {
this.logResolution = cutConfig.logResolution;
this.dopplerResolution = cutConfig.dopplerResolution;
}
} }
radialHeaders = new ArrayList<>(); radialHeaders = new ArrayList<>();
byte[] rhBytes = new byte[RadialHeader.length]; byte[] rhBytes = new byte[RadialHeader.length];
@ -264,8 +199,8 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
} else { } else {
record = new RadialRecord(product); record = new RadialRecord(product);
record.setBinLength(momentHeader.binLength); record.setBinLength(momentHeader.binLength);
record.scale = momentHeader.scale; record.scale = 1.f / momentHeader.scale;
record.offset = momentHeader.offset; record.offset = -momentHeader.offset / (float) momentHeader.scale;
this.recordMap.put(product, record); this.recordMap.put(product, record);
} }
if (radialHeader.radialNumber == 1) { if (radialHeader.radialNumber == 1) {
@ -331,181 +266,6 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
} }
} }
private void makeRefVariables(RadialRecord refRadialRecord) {
Dimension[] dimensions = new Dimension[]{scanDim, radialDim, gateRDim};
for (RadialRecord radialRecord : this.recordMap.values()) {
if (!radialRecord.isVelocityGroup())
radialRecord.makeVariable(this, dimensions);
}
//coordinate variables
Variable elevation = new Variable();
elevation.setName("elevationR");
elevation.setDataType(DataType.FLOAT);
elevation.addDimension(scanDim);
elevation.addDimension(radialDim);
elevation.addAttribute(new Attribute("units", "degree"));
elevation.addAttribute(new Attribute("long_name", "elevation angle in degrees"));
this.addVariable(elevation);
Variable azimuth = new Variable();
azimuth.setName("azimuthR");
azimuth.setDataType(DataType.FLOAT);
azimuth.addDimension(scanDim);
azimuth.addDimension(radialDim);
azimuth.addAttribute(new Attribute("units", "degree"));
azimuth.addAttribute(new Attribute("long_name", "azimuth angle in degrees"));
this.addVariable(azimuth);
Variable distance = new Variable();
distance.setName("distanceR");
distance.setDataType(DataType.FLOAT);
distance.addDimension(gateRDim);
distance.addAttribute(new Attribute("units", "m"));
distance.addAttribute(new Attribute("long_name", "radial distance to start of gate"));
this.addVariable(distance);
Variable nRadials = new Variable();
nRadials.setName("numRadialsR");
nRadials.setDataType(DataType.INT);
nRadials.addDimension(scanDim);
nRadials.addAttribute(new Attribute("long_name", "number of valid radials in this scan"));
this.addVariable(nRadials);
Variable nGates = new Variable();
nGates.setName("numGatesR");
nGates.setDataType(DataType.INT);
nGates.addDimension(scanDim);
nGates.addAttribute(new Attribute("long_name", "number of valid gates in this scan"));
this.addVariable(nGates);
int nScan = scanDim.getLength();
int nRadial = radialDim.getLength();
int nGate = gateRDim.getLength();
Array elevData = Array.factory(DataType.FLOAT, new int[]{nScan, nRadial});
Array aziData = Array.factory(DataType.FLOAT, new int[]{nScan, nRadial});
Array nRData = Array.factory(DataType.INT, new int[]{nScan});
Array nGData = Array.factory(DataType.INT, new int[]{nScan});
Index elevIndex = elevData.getIndex();
Index aziIndex = aziData.getIndex();
for (int i = 0; i < nScan; i++) {
List<Float> elevList = refRadialRecord.elevation.get(i);
List<Float> aziList = refRadialRecord.azimuth.get(i);
nRData.setInt(i, aziList.size());
nGData.setInt(i, (int) refRadialRecord.distance.get(i).getSize());
for (int j = 0; j < nRadial; j++) {
if (j < elevList.size()) {
elevData.setFloat(elevIndex.set(i, j), elevList.get(j));
aziData.setFloat(aziIndex.set(i, j), aziList.get(j));
} else {
elevData.setFloat(elevIndex.set(i, j), Float.NaN);
aziData.setFloat(aziIndex.set(i, j), Float.NaN);
}
}
}
Array disData = refRadialRecord.distance.get(0);
elevation.setCachedData(elevData);
azimuth.setCachedData(aziData);
distance.setCachedData(disData);
nRadials.setCachedData(nRData);
nGates.setCachedData(nGData);
}
private void makeVelVariables(RadialRecord velRadialRecord) {
Dimension[] dimensions = new Dimension[]{scanDim, radialDim, gateVDim};
for (RadialRecord radialRecord : this.recordMap.values()) {
if (radialRecord.isVelocityGroup())
radialRecord.makeVariable(this, dimensions);
}
//coordinate variables
Variable elevation = new Variable();
elevation.setName("elevationV");
elevation.setDataType(DataType.FLOAT);
elevation.addDimension(scanDim);
elevation.addDimension(radialDim);
elevation.addAttribute(new Attribute("units", "degree"));
elevation.addAttribute(new Attribute("long_name", "elevation angle in degrees"));
this.addVariable(elevation);
Variable azimuth = new Variable();
azimuth.setName("azimuthV");
azimuth.setDataType(DataType.FLOAT);
azimuth.addDimension(scanDim);
azimuth.addDimension(radialDim);
azimuth.addAttribute(new Attribute("units", "degree"));
azimuth.addAttribute(new Attribute("long_name", "azimuth angle in degrees"));
this.addVariable(azimuth);
Variable distance = new Variable();
distance.setName("distanceV");
distance.setDataType(DataType.FLOAT);
distance.addDimension(gateVDim);
distance.addAttribute(new Attribute("units", "m"));
distance.addAttribute(new Attribute("long_name", "radial distance to start of gate"));
this.addVariable(distance);
Variable nRadials = new Variable();
nRadials.setName("numRadialsR");
nRadials.setDataType(DataType.INT);
nRadials.addDimension(scanDim);
nRadials.addAttribute(new Attribute("long_name", "number of valid radials in this scan"));
this.addVariable(nRadials);
Variable nGates = new Variable();
nGates.setName("numGatesR");
nGates.setDataType(DataType.INT);
nGates.addDimension(scanDim);
nGates.addAttribute(new Attribute("long_name", "number of valid gates in this scan"));
this.addVariable(nGates);
int nScan = scanDim.getLength();
int nRadial = radialDim.getLength();
int nGate = gateVDim.getLength();
Array elevData = Array.factory(DataType.FLOAT, new int[]{nScan, nRadial});
Array aziData = Array.factory(DataType.FLOAT, new int[]{nScan, nRadial});
Array nRData = Array.factory(DataType.INT, new int[]{nScan});
Array nGData = Array.factory(DataType.INT, new int[]{nScan});
Index elevIndex = elevData.getIndex();
Index aziIndex = aziData.getIndex();
for (int i = 0; i < nScan; i++) {
List<Float> elevList = velRadialRecord.elevation.get(i);
List<Float> aziList = velRadialRecord.azimuth.get(i);
nRData.setInt(i, aziList.size());
nGData.setInt(i, (int) velRadialRecord.distance.get(i).getSize());
for (int j = 0; j < nRadial; j++) {
if (j < elevList.size()) {
elevData.setFloat(elevIndex.set(i, j), elevList.get(j));
aziData.setFloat(aziIndex.set(i, j), aziList.get(j));
} else {
elevData.setFloat(elevIndex.set(i, j), Float.NaN);
aziData.setFloat(aziIndex.set(i, j), Float.NaN);
}
}
}
Array disData = velRadialRecord.distance.get(0);
elevation.setCachedData(elevData);
azimuth.setCachedData(aziData);
distance.setCachedData(disData);
nRadials.setCachedData(nRData);
nGates.setCachedData(nGData);
}
/**
* Get product names
* @return product names
*/
public List<String> getProducts() {
List<String> products = new ArrayList<>();
for (String product : this.recordMap.keySet()) {
products.add(product);
}
return products;
}
/** /**
* Get scan elevations * Get scan elevations
* @return Scan elevations * @return Scan elevations
@ -520,104 +280,6 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
return elevations; return elevations;
} }
/**
* Get scan elevations
* @return Scan elevations
*/
public List<Float> getElevations(String product) {
RadialRecord radialRecord = this.recordMap.get(product);
return radialRecord.fixedElevation;
}
@Override
public Array read(String varName) {
Variable var = this.getVariable(varName);
int n = var.getDimNumber();
int[] origin = new int[n];
int[] size = new int[n];
int[] stride = new int[n];
for (int i = 0; i < n; i++) {
origin[i] = 0;
size[i] = var.getDimLength(i);
stride[i] = 1;
}
Array r = read(varName, origin, size, stride);
return r;
}
@Override
public Array read(String varName, int[] origin, int[] size, int[] stride) {
try {
Variable variable = this.getVariable(varName);
if (variable.hasCachedData()) {
return variable.getCachedData().section(origin, size, stride).copy();
}
Section section = new Section(origin, size, stride);
RadialRecord record = this.recordMap.get(varName);
Array dataArray = Array.factory(DataType.FLOAT, section.getShape());
Range zRange = section.getRange(0);
Range yRange = section.getRange(1);
Range xRange = section.getRange(2);
IndexIterator iter = dataArray.getIndexIterator();
for (int s = zRange.first(); s <= zRange.last(); s += zRange.stride()) {
List<Array> arrays = record.getDataArray(s);
for (int i = yRange.first(); i <= yRange.last(); i += yRange.stride()) {
if (i < arrays.size()) {
Array array = arrays.get(i);
for (int j = xRange.first(); j <= xRange.last(); j += xRange.stride()) {
if (j < array.getSize())
iter.setFloatNext(array.getFloat(j));
else
iter.setFloatNext(Float.NaN);
}
} else {
for (int j = xRange.first(); j <= xRange.last(); j += xRange.stride()) {
iter.setFloatNext(Float.NaN);
}
}
}
}
Attribute aoAttr = variable.findAttribute("add_offset");
Attribute sfAttr = variable.findAttribute("scale_factor");
if (aoAttr != null || sfAttr != null) {
Number add_offset = 0.f;
Number scale_factor = 1.f;
if (aoAttr != null) {
switch (aoAttr.getDataType()) {
case DOUBLE:
add_offset = aoAttr.getValues().getDouble(0);
break;
case FLOAT:
case INT:
add_offset = aoAttr.getValues().getFloat(0);
break;
}
}
if (sfAttr != null) {
switch (sfAttr.getDataType()) {
case DOUBLE:
scale_factor = sfAttr.getValues().getDouble(0);
break;
case FLOAT:
case INT:
scale_factor = sfAttr.getValues().getFloat(0);
break;
}
}
dataArray = ArrayMath.div(ArrayMath.sub(dataArray, add_offset), scale_factor);
}
return dataArray;
} catch (InvalidRangeException e) {
return null;
}
}
@Override @Override
public List<Attribute> getGlobalAttributes() { public List<Attribute> getGlobalAttributes() {
return this.attributes; return this.attributes;

View File

@ -0,0 +1,10 @@
package org.meteoinfo.data.meteodata.radar;
public interface IRadarDataInfo {
/**
* Get radar data type
* @return Radar data type
*/
public abstract RadarDataType getRadarDataType();
}

View File

@ -0,0 +1,11 @@
package org.meteoinfo.data.meteodata.radar;
public enum RadarDataType {
STANDARD,
SAB,
CC,
CC20,
SC,
PA,
UN_DEFINED
}

View File

@ -0,0 +1,148 @@
package org.meteoinfo.data.meteodata.radar;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.meteoinfo.common.DataConvert;
import org.meteoinfo.data.meteodata.DataInfo;
import java.io.RandomAccessFile;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
public class RadarDataUtil {
/**
* Get radar data type
* @param raf RandomAccessFile object
* @return Radar data type
*/
public static RadarDataType getRadarDataType(RandomAccessFile raf) {
try {
raf.seek(0);
byte[] bytes = new byte[136];
raf.read(bytes);
byte[] magicBytes = Arrays.copyOf(bytes, 4);
int magic = DataConvert.bytes2Int(magicBytes, ByteOrder.LITTLE_ENDIAN);
if (magic == 1297371986) {
return RadarDataType.STANDARD;
}
magicBytes = Arrays.copyOfRange(bytes, 14, 16);
if (Arrays.equals(magicBytes, new byte[]{1, 0})) {
return RadarDataType.SAB;
}
magicBytes = Arrays.copyOfRange(bytes, 8, 12);
if (Arrays.equals(magicBytes, new byte[]{16, 0, 0, 0})) {
return RadarDataType.PA;
}
String radarT = new String(bytes);
if (radarT.contains("CINRAD/SC") || radarT.contains("CINRAD/CD")) {
return RadarDataType.SC;
} else if (radarT.contains("CINRADC")) {
return RadarDataType.CC;
} else if (!radarT.contains("CINRADC") && radarT.contains("CINRAD/CC")) {
return RadarDataType.CC20;
}
} catch (Exception e) {
return null;
}
return null;
}
/**
* Get radar data type
* @param fileName Data file name
* @return Radar data type
*/
public static RadarDataType getRadarDataType(String fileName) {
try {
byte[] bytes = new byte[136];
if (fileName.endsWith("bz2")) {
BZip2CompressorInputStream inputStream = new BZip2CompressorInputStream(Files.newInputStream(Paths.get(fileName)));
inputStream.read(bytes);
inputStream.close();
} else {
RandomAccessFile raf = new RandomAccessFile(fileName, "r");
raf.seek(0);
raf.read(bytes);
raf.close();
}
byte[] magicBytes = Arrays.copyOf(bytes, 4);
int magic = DataConvert.bytes2Int(magicBytes, ByteOrder.LITTLE_ENDIAN);
if (magic == 1297371986) {
return RadarDataType.STANDARD;
}
magicBytes = Arrays.copyOfRange(bytes, 14, 16);
if (Arrays.equals(magicBytes, new byte[]{1, 0})) {
return RadarDataType.SAB;
}
magicBytes = Arrays.copyOfRange(bytes, 8, 12);
if (Arrays.equals(magicBytes, new byte[]{16, 0, 0, 0})) {
return RadarDataType.PA;
}
String radarT = new String(bytes);
if (radarT.contains("CINRAD/SC") || radarT.contains("CINRAD/CD")) {
return RadarDataType.SC;
} else if (radarT.contains("CINRADC")) {
return RadarDataType.CC;
} else if (!radarT.contains("CINRADC") && radarT.contains("CINRAD/CC")) {
return RadarDataType.CC20;
}
} catch (Exception e) {
return null;
}
return null;
}
/**
* Get radar data info
* @param radarDataType Radar data type
* @return The DataInfo object
*/
public static DataInfo getDataInfo(RadarDataType radarDataType) {
if (radarDataType == null) {
return null;
} else {
switch (radarDataType) {
case STANDARD:
return new CMARadarBaseDataInfo();
case SAB:
return new SABRadarDataInfo();
/*case CC:
return new CCRadarDataInfo();
case SC:
return new SCRadarDataInfo();*/
default:
return null;
}
}
}
/**
* Get radar data info
* @param raf RandomAccessFile object
* @return The DataInfo object
*/
public static DataInfo getDataInfo(RandomAccessFile raf) {
RadarDataType radarDataType = getRadarDataType(raf);
return getDataInfo(radarDataType);
}
/**
* Get radar data info
* @param fileName Data file name
* @return The DataInfo object
*/
public static DataInfo getDataInfo(String fileName) {
RadarDataType radarDataType = getRadarDataType(fileName);
return getDataInfo(radarDataType);
}
}

View File

@ -19,8 +19,8 @@ public class RadialRecord {
private int binLength; private int binLength;
private DataType dataType; private DataType dataType;
private int fillValue; private int fillValue;
public int scale; public float scale = 1;
public int offset; public float offset = 0;
public List<Float> fixedElevation = new ArrayList<>(); public List<Float> fixedElevation = new ArrayList<>();
public List<List<Float>> elevation = new ArrayList<>(); public List<List<Float>> elevation = new ArrayList<>();
public List<List<Float>> azimuth = new ArrayList<>(); public List<List<Float>> azimuth = new ArrayList<>();
@ -113,6 +113,18 @@ public class RadialRecord {
this.data.add(new ArrayList<>()); this.data.add(new ArrayList<>());
} }
/**
* Add a data array
* @param array Data array
*/
public void addDataArray(Array array) {
if (this.data.isEmpty()) {
this.data.add(new ArrayList<>());
}
this.data.get(this.data.size() - 1).add(array);
}
/** /**
* Add a data bytes * Add a data bytes
* @param bytes Data bytes * @param bytes Data bytes
@ -151,7 +163,7 @@ public class RadialRecord {
array = Array.factory(this.dataType, new int[]{bytes.length}); array = Array.factory(this.dataType, new int[]{bytes.length});
for (int i = 0; i < bytes.length; i++) { for (int i = 0; i < bytes.length; i++) {
v = (float) DataType.unsignedByteToShort(bytes[i]); v = (float) DataType.unsignedByteToShort(bytes[i]);
v = (v - offset) / scale; v = v * scale + offset;
array.setFloat(i, v); array.setFloat(i, v);
} }
} else { } else {
@ -160,7 +172,7 @@ public class RadialRecord {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
short s = DataConvert.bytes2Short(new byte[]{bytes[i*2], bytes[i*2+1]}, ByteOrder.LITTLE_ENDIAN); short s = DataConvert.bytes2Short(new byte[]{bytes[i*2], bytes[i*2+1]}, ByteOrder.LITTLE_ENDIAN);
v = (float) DataType.unsignedShortToInt(s); v = (float) DataType.unsignedShortToInt(s);
v = (v - offset) / scale; v = v * scale + offset;
array.setFloat(i, v); array.setFloat(i, v);
} }
} }
@ -244,7 +256,7 @@ public class RadialRecord {
* @param dataInfo The data info * @param dataInfo The data info
* @param dimensions Dimensions * @param dimensions Dimensions
*/ */
public void makeVariable(CMARadarBaseDataInfo dataInfo, Dimension[] dimensions) { public void makeVariable(BaseRadarDataInfo dataInfo, Dimension[] dimensions) {
Variable variable = new Variable(); Variable variable = new Variable();
variable.setName(this.product); variable.setName(this.product);
variable.setDataType(this.dataType); variable.setDataType(this.dataType);
@ -261,7 +273,7 @@ public class RadialRecord {
* @param dataInfo The data info * @param dataInfo The data info
* @param xyzDim xyz dimension * @param xyzDim xyz dimension
*/ */
public void makeVariables(CMARadarBaseDataInfo dataInfo, Dimension xyzDim) { public void makeVariables(BaseRadarDataInfo dataInfo, Dimension xyzDim) {
for (int i = 0; i < getScanNumber(); i++) { for (int i = 0; i < getScanNumber(); i++) {
String suffix = "_s" + String.valueOf(i + 1); String suffix = "_s" + String.valueOf(i + 1);
Dimension radialDim = new Dimension(DimensionType.Y); Dimension radialDim = new Dimension(DimensionType.Y);
@ -495,7 +507,7 @@ public class RadialRecord {
} }
if (!Float.isNaN(v)) if (!Float.isNaN(v))
v = (v - this.offset) / this.scale; v = v * scale + this.offset;
return v; return v;
} }
@ -575,7 +587,7 @@ public class RadialRecord {
} }
if (!Float.isNaN(v)) if (!Float.isNaN(v))
v = (v - this.offset) / this.scale; v = v * this.scale + this.offset;
return v; return v;
} }

View File

@ -0,0 +1,280 @@
package org.meteoinfo.data.meteodata.radar;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.meteoinfo.common.DataConvert;
import org.meteoinfo.data.dimarray.Dimension;
import org.meteoinfo.data.meteodata.Attribute;
import org.meteoinfo.data.meteodata.DataInfo;
import org.meteoinfo.data.meteodata.Variable;
import org.meteoinfo.ndarray.*;
import org.meteoinfo.ndarray.math.ArrayUtil;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SABRadarDataInfo extends BaseRadarDataInfo implements IRadarDataInfo {
@Override
public boolean isValidFile(java.io.RandomAccessFile raf) {
return false;
}
void setScaleOffset(RadialRecord record, int vResolution) {
switch (record.product) {
case "dBZ":
record.scale = 0.5f;
record.offset = -33.f;
break;
case "V":
if (vResolution == 2) {
record.scale = 0.5f;
record.offset = -64.5f;
} else {
record.scale = 1.f;
record.offset = -129.f;
}
break;
case "W":
record.scale = 0.5f;
record.offset = -64.5f;
break;
}
}
@Override
public void readDataInfo(String fileName) {
this.fileName = fileName;
if (fileName.endsWith(".bz2")) {
try {
BZip2CompressorInputStream inputStream = new BZip2CompressorInputStream(Files.newInputStream(Paths.get(fileName)));
readDataInfo(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
try {
BufferedInputStream inputStream = new BufferedInputStream(Files.newInputStream(Paths.get(fileName)));
readDataInfo(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
void readDataInfo(InputStream is) {
try {
int index = 0;
byte[] rhBytes = new byte[RadialHeader.length];
while (is.read(rhBytes) != -1) {
RadialHeader radialHeader = new RadialHeader(rhBytes);
if (index == 0) {
this.logResolution = radialHeader.gateSizeOfReflectivity;
this.dopplerResolution = radialHeader.gateSizeOfDoppler;
}
if (!radialHeader.hasReflectivityData()) {
is.read(new byte[460]);
}
for (String product : radialHeader.getProducts()) {
RadialRecord record;
if (this.recordMap.containsKey(product)) {
record = this.recordMap.get(product);
} else {
record = new RadialRecord(product);
record.setBinLength(1);
setScaleOffset(record, radialHeader.resolutionOfVelocity);
this.recordMap.put(product, record);
}
if (radialHeader.radialNumber == 1) {
record.fixedElevation.add(radialHeader.getElevation());
record.elevation.add(new ArrayList<>());
record.azimuth.add(new ArrayList<>());
record.azimuthMinIndex.add(0);
if (isVelocityGroup(record)) {
record.disResolution.add(radialHeader.gateSizeOfDoppler);
record.distance.add(ArrayUtil.arrayRange1(radialHeader.rangeToFirstGateOfDop,
radialHeader.gatesNumberOfDoppler, radialHeader.gateSizeOfDoppler));
} else {
record.disResolution.add(radialHeader.gateSizeOfReflectivity);
record.distance.add(ArrayUtil.arrayRange1(radialHeader.rangeToFirstGateOfRef,
radialHeader.gatesNumberOfReflectivity, radialHeader.gateSizeOfReflectivity));
}
record.newScanData();
}
record.elevation.get(record.elevation.size() - 1).add(radialHeader.getElevation());
record.addAzimuth(radialHeader.getAzimuth());
int dataLength = isVelocityGroup(record) ? radialHeader.gatesNumberOfDoppler : radialHeader.gatesNumberOfReflectivity;
byte[] bytes = new byte[dataLength];
is.read(bytes);
record.addDataBytes(bytes);
if (isVelocityGroup(record)) {
if (dataLength < 920) {
is.read(new byte[920 - dataLength]);
}
} else {
if (dataLength < 460) {
is.read(new byte[460 - dataLength]);
}
}
}
if (!radialHeader.hasDopplerData()) {
is.read(new byte[920 + 920]);
}
is.read(new byte[4]);
index += 1;
}
is.close();
this.addAttribute(new Attribute("featureType", "RADIAL"));
this.addAttribute(new Attribute("DataType", "Radial"));
//Add dimensions and variables
RadialRecord refRadialRecord = this.recordMap.get("dBZ");
radialDim = new Dimension();
radialDim.setName("radial");
radialDim.setLength(refRadialRecord.getMaxRadials());
this.addDimension(radialDim);
scanDim = new Dimension();
scanDim.setName("scan");
scanDim.setLength(refRadialRecord.getScanNumber());
this.addDimension(scanDim);
gateRDim = new Dimension();
gateRDim.setName("gateR");
gateRDim.setLength(refRadialRecord.getGateNumber(0));
this.addDimension(gateRDim);
makeRefVariables(refRadialRecord);
RadialRecord velRadialRecord = this.recordMap.get("V");
gateVDim = new Dimension();
gateVDim.setName("gateV");
gateVDim.setLength(velRadialRecord.getGateNumber(0));
this.addDimension(gateVDim);
makeVelVariables(velRadialRecord);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public RadarDataType getRadarDataType() {
return RadarDataType.SAB;
}
static class RadialHeader {
public static int length = 128;
public int mSecond; // collection time for this radial, msecs since midnight
public short julianDate; // prob "collection time"
public short uRange; // unambiguous range
public int azimuth; // azimuth angle
public short radialNumber; // radial number within the elevation
public short radialStatus;
public short elevation;
public short elNumber; // elevation number
public int rangeToFirstGateOfRef; // range to first gate of reflectivity (m) may be negative
public int rangeToFirstGateOfDop; // range to first gate of doppler (m) may be negative
public int gateSizeOfReflectivity; // reflectivity data gate size (m)
public int gateSizeOfDoppler; // doppler data gate size (m)
public int gatesNumberOfReflectivity; // number of reflectivity gates
public int gatesNumberOfDoppler; // number of velocity or spectrum width gates
public short cutSectorNumber;
public int calibrationConst;
public short ptrOfReflectivity;
public short ptrOfVelocity;
public short ptrOfSpectrumWidth;
public int resolutionOfVelocity;
public short vcpNumber;
public short nyquist;
/**
* Constructor
* @param is InputStream
*/
public RadialHeader(byte[] inBytes) throws IOException {
ByteBuffer byteBuffer = ByteBuffer.wrap(inBytes);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.position(28);
mSecond = byteBuffer.getInt();
julianDate = byteBuffer.getShort();
uRange = byteBuffer.getShort();
azimuth = DataType.unsignedShortToInt(byteBuffer.getShort());
radialNumber = byteBuffer.getShort();
radialStatus = byteBuffer.getShort();
elevation = byteBuffer.getShort();
elNumber = byteBuffer.getShort();
rangeToFirstGateOfRef = byteBuffer.getShort();
rangeToFirstGateOfDop = byteBuffer.getShort();
gateSizeOfReflectivity = byteBuffer.getShort();
gateSizeOfDoppler = byteBuffer.getShort();
gatesNumberOfReflectivity = byteBuffer.getShort();
gatesNumberOfDoppler = byteBuffer.getShort();
cutSectorNumber = byteBuffer.getShort();
calibrationConst = byteBuffer.getShort();
ptrOfReflectivity = byteBuffer.getShort();
ptrOfVelocity = byteBuffer.getShort();
ptrOfSpectrumWidth = byteBuffer.getShort();
resolutionOfVelocity = byteBuffer.getShort();
vcpNumber = byteBuffer.getShort();
byteBuffer.position(byteBuffer.position() + 14);
nyquist = byteBuffer.getShort();
}
/**
* Has reflectivity data or not
* @return Has reflectivity data
*/
public boolean hasReflectivityData() {
return gatesNumberOfReflectivity > 0;
}
/**
* Has doppler data or not
* @return Has doppler data
*/
public boolean hasDopplerData() {
return gatesNumberOfDoppler > 0;
}
/**
* Get product names
* @return Product names
*/
public List<String> getProducts() {
List<String> products = new ArrayList<>();
if (hasReflectivityData()) {
products.add("dBZ");
}
if (hasDopplerData()) {
products.add("V");
products.add("W");
}
return products;
}
/**
* Get azimuth
* @return Azimuth
*/
public float getAzimuth() {
return azimuth / 8.f * 180.f / 4096.f;
}
/**
* Get elevation
* @return Elevation
*/
public float getElevation() {
return elevation / 8.f * 180.f / 4096.f;
}
}
}

View File

@ -0,0 +1,34 @@
package org.meteoinfo.data.meteodata.radar;
import org.meteoinfo.data.meteodata.DataInfo;
import org.meteoinfo.ndarray.Array;
import java.io.RandomAccessFile;
public class SCRadarDataInfo extends DataInfo implements IRadarDataInfo {
@Override
public boolean isValidFile(RandomAccessFile raf) {
return false;
}
@Override
public void readDataInfo(String fileName) {
}
@Override
public Array read(String varName) {
return null;
}
@Override
public Array read(String varName, int[] origin, int[] size, int[] stride) {
return null;
}
@Override
public RadarDataType getRadarDataType() {
return RadarDataType.SAB;
}
}

View File

@ -0,0 +1,208 @@
package org.meteoinfo.data.meteodata.radar.cinrad;
public class Cinrad2Record {
/** Reflectivity moment identifier */
public static final int REFLECTIVITY = 1;
/** Radial Velocity moment identifier */
public static final int VELOCITY_HI = 2;
/** Radial Velocity moment identifier */
public static final int VELOCITY_LOW = 4;
/** Spectrum Width moment identifier */
public static final int SPECTRUM_WIDTH = 3;
/** Low doppler resolution code */
public static final int DOPPLER_RESOLUTION_LOW_CODE = 4;
/** High doppler resolution code */
public static final int DOPPLER_RESOLUTION_HIGH_CODE = 2;
/** Horizontal beam width */
public static final float HORIZONTAL_BEAM_WIDTH = (float) 1.5; // LOOK
public static byte MISSING_DATA = (byte) 1;
public static final byte BELOW_THRESHOLD = (byte) 0;
/** Size of the file header, aka title */
static int FILE_HEADER_SIZE = 0;
/** Size of the CTM record header */
private static int CTM_HEADER_SIZE = 14;
/** Size of the message header, to start of the data message */
private static final int MESSAGE_HEADER_SIZE = 28;
/** Size of the entire message, if its a radar data message */
private static int RADAR_DATA_SIZE = 2432;
public static String getDatatypeName(int datatype) {
switch (datatype) {
case REFLECTIVITY:
return "Reflectivity";
case VELOCITY_HI:
case VELOCITY_LOW:
return "RadialVelocity";
case SPECTRUM_WIDTH:
return "SpectrumWidth";
default:
throw new IllegalArgumentException();
}
}
public static String getDatatypeUnits(int datatype) {
switch (datatype) {
case REFLECTIVITY:
return "dBz";
case VELOCITY_HI:
case VELOCITY_LOW:
case SPECTRUM_WIDTH:
return "m/s";
}
throw new IllegalArgumentException();
}
public static float getDatatypeScaleFactor(int datatype) {
switch (datatype) {
case REFLECTIVITY:
if (CinradDataInfo.isCC)
return 0.1f;
if (CinradDataInfo.isCC20)
return 0.5f;
else
return 0.5f;
case VELOCITY_LOW:
if (CinradDataInfo.isSC)
return 0.3673f;
else if (CinradDataInfo.isCC)
return 0.1f;
else
return 1.0f;
case VELOCITY_HI:
case SPECTRUM_WIDTH:
if (CinradDataInfo.isSC)
return 0.1822f;
else if (CinradDataInfo.isCC)
return 0.1f;
else if (CinradDataInfo.isCC20)
return 1.0f;
else
return 0.5f;
default:
throw new IllegalArgumentException();
}
}
public static float getDatatypeAddOffset(int datatype) {
switch (datatype) {
case REFLECTIVITY:
if (CinradDataInfo.isSC)
return -32.0f;
else if (CinradDataInfo.isCC)
return 0.0f;
else if (CinradDataInfo.isCC20)
return -32.0f;
else
return -33.0f;
case VELOCITY_LOW:
if (CinradDataInfo.isSC)
return 0.0f;
else if (CinradDataInfo.isCC)
return 0.0f;
else if (CinradDataInfo.isCC20)
return 0.0f;
else
return -129.0f;
case VELOCITY_HI:
case SPECTRUM_WIDTH:
if (CinradDataInfo.isSC)
return 0.0f;
else if (CinradDataInfo.isCC)
return 0.0f;
else if (CinradDataInfo.isCC20)
return 0.0f;
else
return -64.5f;
default:
throw new IllegalArgumentException();
}
}
public static String getMessageTypeName(int code) {
switch (code) {
case 1:
return "digital radar data";
case 2:
return "RDA status data";
case 3:
return "performance/maintainence data";
case 4:
return "console message - RDA to RPG";
case 5:
return "maintainence log data";
case 6:
return "RDA control ocmmands";
case 7:
return "volume coverage pattern";
case 8:
return "clutter censor zones";
case 9:
return "request for data";
case 10:
return "console message - RPG to RDA";
case 11:
return "loop back test - RDA to RPG";
case 12:
return "loop back test - RPG to RDA";
case 13:
return "clutter filter bypass map - RDA to RPG";
case 14:
return "edited clutter filter bypass map - RDA to RPG";
case 15:
return "Notchwidth Map";
case 18:
return "RDA Adaptation data";
default:
return "unknown " + code;
}
}
public static String getRadialStatusName(int code) {
switch (code) {
case 0:
return "start of new elevation";
case 1:
return "intermediate radial";
case 2:
return "end of elevation";
case 3:
return "begin volume scan";
case 4:
return "end volume scan";
default:
return "unknown " + code;
}
}
public static String getVolumeCoveragePatternName(int code) {
switch (code) {
case 11:
return "16 elevation scans every 5 mins";
case 12:
return "14 elevation scan every 4.1 mins";
case 21:
return "11 elevation scans every 6 mins";
case 31:
return "8 elevation scans every 10 mins";
case 32:
return "7 elevation scans every 10 mins";
case 121:
return "9 elevations, 20 scans every 5 minutes";
default:
return "unknown " + code;
}
}
}

View File

@ -0,0 +1,75 @@
package org.meteoinfo.data.meteodata.radar.cinrad;
import org.meteoinfo.data.GridArray;
import org.meteoinfo.data.GridData;
import org.meteoinfo.data.meteodata.DataInfo;
import org.meteoinfo.data.meteodata.IGridDataInfo;
import org.meteoinfo.ndarray.Array;
import java.io.IOException;
import java.io.RandomAccessFile;
public class CinradDataInfo extends DataInfo {
private static final int MISSING_INT = -9999;
private static final float MISSING_FLOAT = Float.NaN;
public static boolean isSC = false;
public static boolean isCC = false;
public static boolean isCC20 = false;
@Override
public boolean isValidFile(RandomAccessFile raf) {
return isCINRAD(raf);
}
public boolean isCINRAD(RandomAccessFile raf) {
try {
raf.seek(0);
byte[] b128 = new byte[136];
raf.read(b128);
String radarT = new String(b128);
if (radarT.contains("CINRAD/SC") || radarT.contains("CINRAD/CD")) {
isSC = true;
isCC = false;
isCC20 = false;
return true;
} else if (radarT.contains("CINRADC")) {
isCC = true;
isSC = false;
isCC20 = false;
return true;
} else if (!radarT.contains("CINRADC") && radarT.contains("CINRAD/CC")) {
isCC20 = true;
isSC = false;
isCC = false;
return true;
} else {
isSC = false;
isCC = false;
isCC20 = false;
return false;
}
} catch (IOException ioe) {
return false;
}
}
@Override
public void readDataInfo(String fileName) {
}
@Override
public Array read(String varName) {
return null;
}
@Override
public Array read(String varName, int[] origin, int[] size, int[] stride) {
return null;
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile"> <MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\dataframe"> <Path OpenPath="D:\Working\MIScript\Jython\mis\io\radar\cinrad">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\scatter"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\scatter"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\satellite"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\chart"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\chart"/>
@ -12,21 +12,21 @@
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\netcdf"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\netcdf"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar\cinrad"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\dataframe\series"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\dataframe\series"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\dataframe"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\dataframe"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar\cinrad"/>
</Path> </Path>
<File> <File>
<OpenedFiles> <OpenedFiles>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\test_read_1.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\test_read_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\radar_cma_base_cappi.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\radar_cma_base_cappi.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\dataframe\isin_1.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\radar_sc_1.py"/>
</OpenedFiles> </OpenedFiles>
<RecentFiles> <RecentFiles>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\test_read_1.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\test_read_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\radar_cma_base_cappi.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\radar_cma_base_cappi.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\dataframe\isin_1.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\io\radar\cinrad\radar_sc_1.py"/>
</RecentFiles> </RecentFiles>
</File> </File>
<Font> <Font>
@ -34,5 +34,5 @@
</Font> </Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/> <LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/> <Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,0" MainFormSize="1354,829"/> <Startup MainFormLocation="-7,-7" MainFormSize="1293,765"/>
</MeteoInfo> </MeteoInfo>