Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new super-res level 3 products #438

Merged
merged 1 commit into from
Aug 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 80 additions & 70 deletions cdm/radial/src/main/java/ucar/nc2/iosp/nids/Nidsheader.java
Original file line number Diff line number Diff line change
Expand Up @@ -1653,10 +1653,20 @@ int pcode_radial(ByteBuffer bos, int hoff, int hedsiz, boolean isZ, byte[] data,
addParameter(vName, lName, ncfile, dims1, att, DataType.DOUBLE, "milliseconds since 1970-01-01 00:00 UTC", hoff,
hedsiz, isZ, 0);
// add RAW, BRIT variables for all radial variable
if (pcode == 182 || pcode == 99 || pcode == 180) {
if (pcode == 182 || pcode == 99 || pcode == 180 || pcode == 154) {
levels = getTDWRLevels(nlevel, threshold);
iscale = 10;
} else if (pcode == 186 || pcode == 94) {
} else if (pcode == 155) {
// ICD v19 3-34
// "For product 155, data levels 129 through 152
// denote data values starting from the minimum data value in even data increments."
// Let's compute the correct offset based on the fact that the levels start at 129
// and not 0. We need 129 to correspond to what was in threshold 0 when the scale is applied
// First two levels are missing and range folded (set in getTDWRLevels), so we use 127, not 129.
threshold[0] += -127 * threshold[1];
levels = getTDWRLevels(nlevel, threshold);
iscale = 10;
} else if (pcode == 186 || pcode == 94 || pcode == 153) {
threshold[0] = -320;
threshold[1] = 5;
threshold[2] = 254;
Expand All @@ -1672,7 +1682,7 @@ int pcode_radial(ByteBuffer bos, int hoff, int hedsiz, boolean isZ, byte[] data,
levels = getTDWRLevels2(nlevel, threshold);
iscale = 1;
} else if (pcode == 159 || pcode == 161 || pcode == 163 || pcode == 170 || pcode == 172 || pcode == 173
|| pcode == 174 || pcode == 175 || pcode == 165 || pcode == 177) {
|| pcode == 174 || pcode == 175 || pcode == 165 || pcode == 177 || pcode == 167 || pcode == 168) {

levels = getDualpolLevels(threshold);
iscale = 100;
Expand Down Expand Up @@ -2190,20 +2200,20 @@ private void setProductInfo(int prod_type, Pinfo pinfo) {
cmemo = "Base Specturm Width " + prod_elevation / 10 + " DEG " + cmode[pinfo.opmode];

ctilt = pname_lookup(pcode, prod_elevation / 10);
ctitle = "BREF: Base Spectrum Width";
ctitle = "Base Spectrum Width";
cunit = "Knots";
cname = "SpectrumWidth";
summary =
ctilt + " is a radial image of base reflectivity at tilt " + (prod_elevation / 10 + 1) + " and range 124 nm";
summary = ctilt + " is a radial image of base spectrum width at tilt " + (prod_elevation / 10 + 1)
+ " and range 124 nm";
if (pcode == 28) {
t1 = t1 * 0.25;
t2 = t2 * 0.25;
lat_min = latitude - t1;
lat_max = latitude + t1;
lon_min = longitude + t2; // * Math.cos(Math.toRadians(lat_min));
lon_max = longitude - t2; // * Math.cos(Math.toRadians(lat_min));
summary =
ctilt + " is a radial image of base reflectivity at tilt " + (prod_elevation / 10 + 1) + " and range 32 nm";
summary = ctilt + " is a radial image of base spectrum width at tilt " + (prod_elevation / 10 + 1)
+ " and range 32 nm";
}
} else if (prod_type == DigitalDifferentialReflectivity) {
radial = 1;
Expand Down Expand Up @@ -2260,15 +2270,15 @@ private void setProductInfo(int prod_type, Pinfo pinfo) {
} else if (prod_type == HypridHydrometeorClassification) {
radial = 1;
prod_elevation = pinfo.p3;
cmemo = "Hyprid Hydrometeor Classification " + prod_elevation / 10 + " DEG " + cmode[pinfo.opmode];
cmemo = "Hybrid Hydrometeor Classification " + prod_elevation / 10 + " DEG " + cmode[pinfo.opmode];

int pLevel = getProductLevel(prod_elevation);
ctilt = pname_lookup(18, pLevel);

ctitle = "Dualpol: Hyprid Hydrometeor Classification";
ctitle = "Dualpol: Hybrid Hydrometeor Classification";
cunit = " ";
cname = "HypridHydrometeorClassification";
summary = ctilt + " is a radial image of dual pol Hyprid Hydrometeor Classification field and its range 162 nm";
summary = ctilt + " is a radial image of dual pol Hybrid Hydrometeor Classification field and its range 162 nm";

} else if (prod_type == OneHourAccumulation) {
radial = 1;
Expand Down Expand Up @@ -2309,7 +2319,7 @@ private void setProductInfo(int prod_type, Pinfo pinfo) {
} else if (prod_type == Accumulation3Hour) {
radial = 1;
prod_elevation = pinfo.p3;
cmemo = "Hyprid Hydrometeor Classification " + prod_elevation / 10 + " DEG " + cmode[pinfo.opmode];
cmemo = "Hybrid Hydrometeor Classification " + prod_elevation / 10 + " DEG " + cmode[pinfo.opmode];
int pLevel = getProductLevel(prod_elevation);
ctilt = pname_lookup(18, pLevel);
ctitle = "Dualpol: 3-hour Accumulation";
Expand Down Expand Up @@ -3062,13 +3072,14 @@ Pinfo read_proddesc(ByteBuffer buf, int offset) {
buf.get(b2, 0, 2);
p3 = (short) getInt(b2, 2);
off += 40;
if (pcode == 182 || pcode == 186 || pcode == 32 || pcode == 94 || pcode == 99 || pcode == 180) {
if (pcode == 182 || pcode == 186 || pcode == 32 || pcode == 94 || pcode == 99 || pcode == 180 || pcode == 153
|| pcode == 154 || pcode == 155) {
for (int i = 0; i < 16; i++) {
buf.get(b2, 0, 2);
threshold[i] = (short) bytesToInt(b2[0], b2[1], false);
}
} else if (pcode == 159 || pcode == 161 || pcode == 163 || pcode == 170 || pcode == 172 || pcode == 173
|| pcode == 174 || pcode == 175) {
|| pcode == 174 || pcode == 175 || pcode == 167 || pcode == 168) {
// Scale hw 31 32
buf.get(b4, 0, 4);
byte[] b44 = {b4[3], b4[2], b4[1], b4[0]};
Expand Down Expand Up @@ -3499,41 +3510,39 @@ byte[] GetZlibedNexr(byte[] buf, int buflen, int hoff) throws IOException {
*/
static int code_typelookup(int code) {
int type;
int[] types = {Other, Other, Other, Other, Other, /* 0- 9 */
Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, /* 10- 19 */
Other, Base_Reflect, Base_Reflect, Base_Reflect, Base_Reflect, BaseReflect248, Base_Reflect, Velocity, /*
* 20- 29
*/
Velocity, Velocity, Velocity, Velocity, Velocity, SPECTRUM, SPECTRUM, SPECTRUM, Other, DigitalHybridReflect,
Other, Other, /* 30- 39 */
Comp_Reflect, Comp_Reflect, Comp_Reflect, Comp_Reflect, Other, Other, Echo_Tops, Other, Other, Other, /*
* 40- 49
*/
Other, Other, Other, VAD, Other, Other, Other, Other, Other, Other, /* 50- 59 */
StrmRelMeanVel, StrmRelMeanVel, Vert_Liquid, Other, Other, Other, Other, Other, Layer_Reflect_Avg, /* 60- 69 */
Layer_Reflect_Avg, Layer_Reflect_Max, Layer_Reflect_Max, Other, Other, Other, Other, Other, Other, Other,
Other, /* 70- 79 */
Other, Other, Other, Precip_1, Precip_3, Precip_Accum, Precip_Array, Other, /* 80- 89 */
Other, Other, Other, Other, Other, Other, Layer_Reflect_Avg, Layer_Reflect_Max, Other, Other, Other, /*
* 90- 99
*/
BaseReflectivityDR, Other, Other, Other, Other, BaseVelocityDV, Other, Other, Other, Other, Other, /* 100-109 */
Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, /* 110-119 */
Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, /* 120-129 */
Other, Other, Other, Other, Other, Other, Other, Other, Other, DigitalVert_Liquid, /* 130-139 */
EnhancedEcho_Tops, Other, Other, DigitalStormTotalPrecip, Other, Other, Other, Other, Other, Other, /*
* 140-149
*/
Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, /* 150-159 */
Other, Other, Other, Other, DigitalDifferentialReflectivity, Other, DigitalCorrelationCoefficient, Other,
DigitalDifferentialPhase, Other,
/* 160-169 */
HydrometeorClassification, Other, Other, Other, OneHourAccumulation, DigitalAccumulationArray,
StormTotalAccumulation, DigitalStormTotalAccumulation, Accumulation3Hour,
Digital1HourDifferenceAccumulation, /* 170-179 */
DigitalTotalDifferenceAccumulation, DigitalInstantaneousPrecipitationRate, HypridHydrometeorClassification,
Other, Other, Reflect1, Reflect1, Velocity1, Velocity1, Other, /* 180-189 */
SPECTRUM1, Reflect1, Reflect1, Other, Other,};
int[] types = {Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, // 0 - 9
Other, Other, Other, Other, Other, Other, Base_Reflect, Base_Reflect, Base_Reflect, Base_Reflect, // 10 - 19
BaseReflect248, Base_Reflect, Velocity, Velocity, Velocity, // 20 - 24
Velocity, Velocity, Velocity, SPECTRUM, SPECTRUM, // 25 - 29
SPECTRUM, Other, DigitalHybridReflect, Other, Other, // 30 - 34
Comp_Reflect, Comp_Reflect, Comp_Reflect, Comp_Reflect, Other, // 35 - 39
Other, Echo_Tops, Other, Other, Other, // 40 - 44
Other, Other, Other, VAD, Other, Other, Other, Other, Other, Other, // 45- 54
StrmRelMeanVel, StrmRelMeanVel, Vert_Liquid, Other, Other, // 55 - 59
Other, Other, Other, Layer_Reflect_Avg, Layer_Reflect_Avg, // 60 - 64
Layer_Reflect_Max, Layer_Reflect_Max, Other, Other, Other, // 65 - 69
Other, Other, Other, Other, Other, // 70 - 74
Other, Other, Other, Precip_1, Precip_3, // 75 - 79
Precip_Accum, Precip_Array, Other, Other, Other, // 80 - 84
Other, Other, Other, Other, Layer_Reflect_Avg, // 85 - 89
Layer_Reflect_Max, Other, Other, Other, BaseReflectivityDR, // 90 - 94
Other, Other, Other, Other, BaseVelocityDV, // 95 - 99
Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, // 100 - 109
Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, // 110 - 119
Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, // 120 - 129
Other, Other, Other, Other, DigitalVert_Liquid, // 130 - 134
EnhancedEcho_Tops, Other, Other, DigitalStormTotalPrecip, Other, // 135 - 139
Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, // 140 - 149
Other, Other, Other, BaseReflectivityDR, BaseVelocityDV, // 150 - 154
SPECTRUM, Other, Other, Other, DigitalDifferentialReflectivity, // 155 - 159
Other, DigitalCorrelationCoefficient, Other, DigitalDifferentialPhase, Other, // 160 - 164
HydrometeorClassification, Other, DigitalCorrelationCoefficient, Other, // 165 - 168
OneHourAccumulation, DigitalAccumulationArray, // 169 - 170
StormTotalAccumulation, DigitalStormTotalAccumulation, Accumulation3Hour, // 171 - 173
Digital1HourDifferenceAccumulation, DigitalTotalDifferenceAccumulation, // 174 - 175
DigitalInstantaneousPrecipitationRate, HypridHydrometeorClassification, Other, Other, // 176 - 179
Reflect1, Reflect1, Velocity1, Velocity1, Other, // 180 - 184
SPECTRUM1, Reflect1, Reflect1, Other, Other}; // 185 - 189

if (code < 0 || code > 189) {
type = Other;
Expand Down Expand Up @@ -3694,6 +3703,7 @@ static String pname_lookup(int code, int elevation) {
case 183:
pname = "V";
break;
case 155:
case 185:
pname = "SW";
break;
Expand Down Expand Up @@ -3733,8 +3743,8 @@ static double code_reslookup(int code) {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 120-129 */
0, 0, 0, 0, 1, 1, 0, 0, 1, 0, /* 130-139 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 140-149 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0.25, /* 150-159 */
0, 0.25, 0, 0.25, 0, 0.25, 0, 0, 0, 2, /* 160-169 */
0, 0, 0, 0.25, 0.25, 0.25, 0, 0, 0, 0.25, /* 150-159 */
0, 0.25, 0, 0.25, 0, 0.25, 0, 0.25, 0.25, 2, /* 160-169 */
0.25, 2, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0, 0, /* 170-179 */
150, 150.0, 150.0, 0, 0, 0, 300.0, 0, 0, 0, /* 180-189 */
};
Expand All @@ -3760,25 +3770,25 @@ static int code_levelslookup(int code) {

int level;

int[] levels = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0- 9 */
0, 0, 0, 0, 0, 0, 8, 8, 8, 16, /* 10- 19 */
16, 16, 8, 8, 8, 16, 16, 16, 8, 0, /* 20- 29 */
8, 0, 256, 0, 0, 8, 8, 16, 16, 0, /* 30- 39 */
0, 16, 0, 0, 0, 0, 0, 0, 0, 0, /* 40- 49 */
0, 0, 0, 0, 0, 16, 16, 16, 0, 0, /* 50- 59 */
0, 0, 0, 8, 8, 8, 8, 0, 0, 0, /* 60- 69 */
0, 0, 0, 0, 0, 0, 0, 0, 16, 16, /* 70- 79 */
16, 256, 0, 0, 0, 0, 0, 0, 0, 8, /* 80- 89 */
8, 0, 0, 0, 256, 0, 0, 0, 0, 256, /* 90- 99 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 100-109 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 110-119 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 120-129 */
0, 0, 0, 0, 256, 199, 0, 0, 256, 0, /* 130-139 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 140-149 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 256, /* 150-159 */
0, 256, 0, 256, 0, 256, 0, 0, 0, 16, /* 160-169 */
256, 16, 256, 256, 0, 0, 0, 16, 0, 0, /* 170-179 */
256, 16, 256, 0, 0, 0, 256, 0, 0, 0, /* 180-189 */
int[] levels = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0- 9
0, 0, 0, 0, 0, 0, 8, 8, 8, 16, // 10- 19
16, 16, 8, 8, 8, 16, 16, 16, 8, 0, // 20- 29
8, 0, 256, 0, 0, 8, 8, 16, 16, 0, // 30- 39
0, 16, 0, 0, 0, 0, 0, 0, 0, 0, // 40- 49
0, 0, 0, 0, 0, 16, 16, 16, 0, 0, // 50- 59
0, 0, 0, 8, 8, 8, 8, 0, 0, 0, // 60- 69
0, 0, 0, 0, 0, 0, 0, 0, 16, 16, // 70- 79
16, 256, 0, 0, 0, 0, 0, 0, 0, 8, // 80- 89
8, 0, 0, 0, 256, 0, 0, 0, 0, 256, // 90- 99
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 100-109
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 110-119
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 120-129
0, 0, 0, 0, 256, 199, 0, 0, 256, 0, // 130-139
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140-149
0, 0, 0, 256, 256, 256, 0, 0, 0, 256, // 150-159
0, 256, 0, 256, 0, 256, 0, 256, 256, 16, // 160-169
256, 16, 256, 256, 0, 0, 0, 16, 0, 0, // 170-179
256, 16, 256, 0, 0, 0, 256, 0, 0, 0, // 180-189
};

if (code < 0 || code > 189) {
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
85 changes: 85 additions & 0 deletions cdm/radial/src/test/java/ucar/nc2/iosp/nids/TestNids.java
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,91 @@ public void testRadialImageMessagePcode180() throws IOException {
}
}

@Test
public void testRadialImageMessagePcode153() throws IOException {
// Radial Image message, product code 153 (super res reflectivity).
double comparisonTolerance = 0.1;
String datafile = TestDir.localTestDataDir + "nids/H0Z_20200812_1318";
try (NetcdfFile ncf = NetcdfFiles.open(datafile)) {
Variable bref = ncf.findVariable("BaseReflectivityDR");
Array data = bref.read();
double max = MAMath.getMaximum(data);
// expected max reflectivity value obtained from metpy decoder.
assertThat(max).isWithin(comparisonTolerance).of(59.0);
// test that range of the radial axis variable is good.
Variable gate = ncf.findVariable("gate");
Array gateValues = gate.read();
MinMax minMax = MAMath.getMinMax(gateValues);
assertThat(minMax.min).isWithin(comparisonTolerance).of(0);
// within 1 km of 460 km.
assertThat(minMax.max).isWithin(1000).of(460000);
}
}

@Test
public void testRadialImageMessagePcode154() throws IOException {
// Radial Image message, product code 154 (super res velocity).
double comparisonTolerance = 0.1;
String datafile = TestDir.localTestDataDir + "nids/H0V_20200812_1309";
try (NetcdfFile ncf = NetcdfFiles.open(datafile)) {
Variable bref = ncf.findVariable("BaseVelocityDV");
Array data = bref.read();
double max = MAMath.getMaximum(data);
// expected max velocity value obtained from metpy decoder.
assertThat(max).isWithin(comparisonTolerance).of(44.5);
// test that range of the radial axis variable is good.
Variable gate = ncf.findVariable("gate");
Array gateValues = gate.read();
MinMax minMax = MAMath.getMinMax(gateValues);
assertThat(minMax.min).isWithin(comparisonTolerance).of(0);
// within 1 km of 300 km.
assertThat(minMax.max).isWithin(1000).of(300000);
}
}

@Test
public void testRadialImageMessagePcode155() throws IOException {
// Radial Image message, product code 155 (super res spectrum width).
double comparisonTolerance = 0.1;
String datafile = TestDir.localTestDataDir + "nids/H0W_20200812_1305";
try (NetcdfFile ncf = NetcdfFiles.open(datafile)) {
Variable bref = ncf.findVariable("SpectrumWidth");
Array data = bref.read();
double max = MAMath.getMaximum(data);
// expected max spectrum width value obtained from metpy decoder.
assertThat(max).isWithin(comparisonTolerance).of(15.0);
// test that range of the radial axis variable is good.
Variable gate = ncf.findVariable("gate");
Array gateValues = gate.read();
MinMax minMax = MAMath.getMinMax(gateValues);
assertThat(minMax.min).isWithin(comparisonTolerance).of(0);
// within 1 km of 300 km.
assertThat(minMax.max).isWithin(1000).of(300000);
}
}

@Test
public void testRadialImageMessagePcode167() throws IOException {
// Radial Image message, product code 167 (super res digital correlation coefficient).
double comparisonTolerance = 0.1;
String datafile = TestDir.localTestDataDir + "nids/H0C_20200814_0417";
try (NetcdfFile ncf = NetcdfFiles.open(datafile)) {
Variable bref = ncf.findVariable("CorrelationCoefficient");
Array data = bref.read();
double max = MAMath.getMaximum(data);
// expected max correlation coefficient value obtained from metpy decoder.
// can be greater than 1 due to the way it is measured, but should not be much greater than one.
assertThat(max).isWithin(comparisonTolerance).of(1.05167);
// test that range of the radial axis variable is good.
Variable gate = ncf.findVariable("gate");
Array gateValues = gate.read();
MinMax minMax = MAMath.getMinMax(gateValues);
assertThat(minMax.min).isWithin(comparisonTolerance).of(0);
// within 1 km of 300 km.
assertThat(minMax.max).isWithin(1000).of(300000);
}
}

private void testReadData(Variable v) {
Array a = null;
assert (null != v);
Expand Down