Skip to content

Commit 7f88134

Browse files
committed
added geolocation variables to MMD
1 parent 9f06fba commit 7f88134

File tree

5 files changed

+248
-12
lines changed

5 files changed

+248
-12
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.bc.fiduceo.reader.smos;
2+
3+
4+
import com.bc.fiduceo.core.Interval;
5+
import com.bc.fiduceo.location.PixelLocator;
6+
import ucar.ma2.Array;
7+
import ucar.ma2.DataType;
8+
import ucar.ma2.Index;
9+
10+
import java.awt.geom.Point2D;
11+
12+
class GeolocationHandler {
13+
14+
static int LONGITUDE = 0;
15+
static int LATITUDE = 1;
16+
17+
private final PixelLocator pixelLocator;
18+
19+
GeolocationHandler(PixelLocator pixelLocator) {
20+
this.pixelLocator = pixelLocator;
21+
}
22+
23+
public Array read(int x, int y, Interval interval, int type) {
24+
final int windowWidth = interval.getX();
25+
final int windowHeight = interval.getY();
26+
27+
final Array geoArray = Array.factory(DataType.FLOAT, new int[]{windowHeight, windowWidth});
28+
final Index index = geoArray.getIndex();
29+
30+
final int offsetX = x - windowWidth / 2;
31+
final int offsetY = y - windowHeight / 2;
32+
33+
int writeX = 0;
34+
int writeY = 0;
35+
Point2D geoPoint = new Point2D.Float();
36+
for (int j = offsetY; j < offsetY + windowHeight; j++) {
37+
for (int i = offsetX; i < offsetX + windowWidth; i++) {
38+
geoPoint = pixelLocator.getGeoLocation(i + 0.5, j + 0.5, geoPoint);
39+
40+
index.set(writeY, writeX);
41+
if (geoPoint == null) {
42+
geoArray.setFloat(index, Float.NaN);
43+
} else {
44+
if (type == LATITUDE) {
45+
geoArray.setFloat(index, (float) geoPoint.getY());
46+
} else if (type == LONGITUDE) {
47+
geoArray.setFloat(index, (float) geoPoint.getX());
48+
} else {
49+
throw new RuntimeException("illegal type");
50+
}
51+
}
52+
53+
++writeX;
54+
}
55+
++writeY;
56+
writeX = 0;
57+
}
58+
return geoArray;
59+
}
60+
}

core/src/main/java/com/bc/fiduceo/reader/smos/SmosL1CDailyGriddedReader.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
import com.bc.fiduceo.reader.time.TimeLocator;
1414
import com.bc.fiduceo.util.NetCDFUtils;
1515
import com.bc.fiduceo.util.TimeUtils;
16+
import com.bc.fiduceo.util.VariableProxy;
1617
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
1718
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
1819
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
1920
import org.esa.snap.core.util.io.FileUtils;
2021
import ucar.ma2.*;
22+
import ucar.nc2.Attribute;
2123
import ucar.nc2.Variable;
2224

2325
import java.awt.geom.Rectangle2D;
@@ -28,6 +30,8 @@
2830
import java.util.Date;
2931
import java.util.List;
3032

33+
import static com.bc.fiduceo.reader.smos.GeolocationHandler.LATITUDE;
34+
import static com.bc.fiduceo.reader.smos.GeolocationHandler.LONGITUDE;
3135
import static com.bc.fiduceo.util.NetCDFUtils.getDefaultFillValue;
3236

3337
class SmosL1CDailyGriddedReader extends NetCDFReader {
@@ -41,6 +45,7 @@ class SmosL1CDailyGriddedReader extends NetCDFReader {
4145
private File productDir;
4246
private PixelLocator pixelLocator;
4347
private TimeLocator timeLocator;
48+
private GeolocationHandler geolocationHandler;
4449

4550

4651
SmosL1CDailyGriddedReader(ReaderContext readerContext) {
@@ -83,6 +88,7 @@ public void close() throws IOException {
8388

8489
pixelLocator = null;
8590
timeLocator = null;
91+
geolocationHandler = null;
8692
if (productDir != null) {
8793
readerContext.deleteTempFile(productDir);
8894
productDir = null;
@@ -173,14 +179,23 @@ public int[] extractYearMonthDayFromFilename(String fileName) {
173179

174180
@Override
175181
public Array readRaw(int centerX, int centerY, Interval interval, String variableName) throws IOException, InvalidRangeException {
176-
if (variables2D.contains(variableName)) {
182+
if (variableName.equals("lon") || variableName.equals("lat")) {
183+
final GeolocationHandler geoHandler = getGeolocationHandler();
184+
int type;
185+
if (variableName.equals("lon")) {
186+
type = LONGITUDE;
187+
} else {
188+
type = LATITUDE;
189+
}
190+
return geoHandler.read(centerX, centerY, interval, type);
191+
} else if (variables2D.contains(variableName)) {
177192
final Array array = arrayCache.get(variableName);
178193
final Number fillValue = arrayCache.getNumberAttributeValue(NetCDFUtils.CF_FILL_VALUE_NAME, variableName);
179194
return RawDataReader.read(centerX, centerY, interval, fillValue, array, getProductSize());
180195
} else {
181196
final int extensionIdx = variableName.lastIndexOf("_");
182197
final int layerIndex = layerExtension.getIndex(variableName.substring(extensionIdx));
183-
final String ncVariableName = variableName.substring(0, extensionIdx);
198+
final String ncVariableName = variableName.substring(0, extensionIdx);
184199

185200
final Array array = arrayCache.get(ncVariableName);
186201
final Number fillValue = arrayCache.getNumberAttributeValue(NetCDFUtils.CF_FILL_VALUE_NAME, ncVariableName);
@@ -194,10 +209,23 @@ public Array readRaw(int centerX, int centerY, Interval interval, String variabl
194209
}
195210
}
196211

212+
private GeolocationHandler getGeolocationHandler() throws IOException {
213+
if (geolocationHandler == null) {
214+
geolocationHandler = new GeolocationHandler(getPixelLocator());
215+
}
216+
217+
return geolocationHandler;
218+
}
219+
197220
@Override
198221
public Array readScaled(int centerX, int centerY, Interval interval, String variableName) throws IOException, InvalidRangeException {
199222
final Array rawArray = readRaw(centerX, centerY, interval, variableName);
200223

224+
// we know that these are already scaled tb 2022-11-01
225+
if (variableName.equals("lon") || variableName.equals("lat")) {
226+
return rawArray;
227+
}
228+
201229
final String ncVariableName;
202230
if (variables2D.contains(variableName)) {
203231
ncVariableName = variableName;
@@ -280,6 +308,19 @@ public List<Variable> getVariables() throws InvalidRangeException, IOException {
280308
exportVariables.addAll(bandVariables);
281309
}
282310

311+
// add two proxies for the geolocation variables tb 2022-11-01
312+
final ArrayList<Attribute> attributes = new ArrayList<>();
313+
attributes.add(new Attribute("_FillValue", Float.NaN));
314+
attributes.add(new Attribute("units", "degrees_east"));
315+
attributes.add(new Attribute("long_name", "longitude"));
316+
exportVariables.add(new VariableProxy("lon", DataType.FLOAT, attributes));
317+
318+
attributes.clear();
319+
attributes.add(new Attribute("_FillValue", Float.NaN));
320+
attributes.add(new Attribute("units", "degrees_north"));
321+
attributes.add(new Attribute("long_name", "latitude"));
322+
exportVariables.add(new VariableProxy("lat", DataType.FLOAT, attributes));
323+
283324
return exportVariables;
284325
}
285326

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package com.bc.fiduceo.reader.smos;
2+
3+
import com.bc.fiduceo.core.Interval;
4+
import org.junit.Before;
5+
import org.junit.Test;
6+
import ucar.ma2.Array;
7+
import ucar.ma2.Index;
8+
9+
import java.awt.geom.Rectangle2D;
10+
11+
import static com.bc.fiduceo.reader.smos.GeolocationHandler.LATITUDE;
12+
import static com.bc.fiduceo.reader.smos.GeolocationHandler.LONGITUDE;
13+
import static org.junit.Assert.assertArrayEquals;
14+
import static org.junit.Assert.assertEquals;
15+
16+
17+
public class GeolocationHandlerTest {
18+
19+
private GeolocationHandler geolocationHandler;
20+
21+
@Before
22+
public void setUp() {
23+
final float[] longitudes = {-180.f, -150.f, -120.f, -90.f, -60.f, -30.f, 0.f, 30.f, 60.f, 90.f, 120.f, 150.f, 180.f};
24+
final float[] latitudes = {-90.f, -60.f, -30.f, 0.f, 30.f, 60.f, 90.f};
25+
final Rectangle2D.Float geoBoundary = new Rectangle2D.Float(-180.f, -90.f, 360.f, 180.f);
26+
final RasterPixelLocator pixelLocator = new RasterPixelLocator(longitudes, latitudes, geoBoundary);
27+
28+
geolocationHandler = new GeolocationHandler(pixelLocator);
29+
}
30+
31+
@Test
32+
public void testGetLon() {
33+
final Interval interval = new Interval(1, 3);
34+
final Array lonArray = geolocationHandler.read(3, 2, interval, LONGITUDE);
35+
36+
assertArrayEquals(new int[]{3, 1}, lonArray.getShape());
37+
final Index index = lonArray.getIndex();
38+
index.set(0, 0);
39+
assertEquals(-90.f, lonArray.getFloat(index), 1e-8);
40+
index.set(1, 0);
41+
assertEquals(-90.f, lonArray.getFloat(index), 1e-8);
42+
index.set(2, 0);
43+
assertEquals(-90.f, lonArray.getFloat(index), 1e-8);
44+
}
45+
46+
@Test
47+
public void testGetLat() {
48+
final Interval interval = new Interval(3, 3);
49+
final Array latArray = geolocationHandler.read(4, 3, interval, LATITUDE);
50+
51+
assertArrayEquals(new int[]{3, 3}, latArray.getShape());
52+
final Index index = latArray.getIndex();
53+
index.set(0, 0);
54+
assertEquals(-30.f, latArray.getFloat(index), 1e-8);
55+
index.set(1, 1);
56+
assertEquals(0.f, latArray.getFloat(index), 1e-8);
57+
index.set(2, 2);
58+
assertEquals(30.f, latArray.getFloat(index), 1e-8);
59+
}
60+
61+
@Test
62+
public void testGetLon_outsideUpperRight() {
63+
final Interval interval = new Interval(3, 3);
64+
final Array lonArray = geolocationHandler.read(12, 0, interval, LONGITUDE);
65+
66+
assertArrayEquals(new int[]{3, 3}, lonArray.getShape());
67+
final Index index = lonArray.getIndex();
68+
index.set(0, 0);
69+
assertEquals(Float.NaN, lonArray.getFloat(index), 1e-8);
70+
index.set(0, 2);
71+
assertEquals(Float.NaN, lonArray.getFloat(index), 1e-8);
72+
index.set(1, 0);
73+
assertEquals(150.f, lonArray.getFloat(index), 1e-8);
74+
index.set(1, 1);
75+
assertEquals(180.f, lonArray.getFloat(index), 1e-8);
76+
index.set(1, 2);
77+
assertEquals(Float.NaN, lonArray.getFloat(index), 1e-8);
78+
}
79+
80+
@Test
81+
public void testGetLat_outsideLowerLeft() {
82+
final Interval interval = new Interval(3, 3);
83+
final Array latArray = geolocationHandler.read(0, 6, interval, LATITUDE);
84+
85+
assertArrayEquals(new int[]{3, 3}, latArray.getShape());
86+
final Index index = latArray.getIndex();
87+
index.set(0, 0);
88+
assertEquals(Float.NaN, latArray.getFloat(index), 1e-8);
89+
index.set(0, 1);
90+
assertEquals(60.f, latArray.getFloat(index), 1e-8);
91+
index.set(0, 2);
92+
assertEquals(60.f, latArray.getFloat(index), 1e-8);
93+
index.set(1, 0);
94+
assertEquals(Float.NaN, latArray.getFloat(index), 1e-8);
95+
index.set(1, 1);
96+
assertEquals(90.f, latArray.getFloat(index), 1e-8);
97+
index.set(1, 2);
98+
assertEquals(90.f, latArray.getFloat(index), 1e-8);
99+
100+
index.set(2, 2);
101+
assertEquals(Float.NaN, latArray.getFloat(index), 1e-8);
102+
}
103+
}

core/src/test/java/com/bc/fiduceo/reader/smos/SmosL1CDailyGriddedReader_IO_Test.java

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -173,22 +173,13 @@ public void testGetPixelLocator_CDF3TA() throws IOException {
173173

174174
@Test
175175
public void testGetVariables_CDF3TD() throws IOException, InvalidRangeException {
176-
// X_Swath, Grid_Point_Mask
177-
// BT_H(15), BT_V(15), BT_3(15), BT_4(15),
178-
// Pixel_Radiometric_Accuracy_H(15), Pixel_Radiometric_Accuracy_V(15), Pixel_Radiometric_Accuracy_3(15), Pixel_Radiometric_Accuracy_4(15)
179-
// Pixel_BT_Standard_Deviation_H(15), Pixel_BT_Standard_Deviation_V(15), Pixel_BT_Standard_Deviation_3(15), Pixel_BT_Standard_Deviation_4(15)
180-
// Incidence_Angle(15), Azimuth_Angle(15), Footprint_Axis1(15), Footprint_Axis2(15),
181-
// Xi(15), Eta(15), Nviews(15), Nb_RFI_Flags(15), Nb_SUN_Flags(15)
182-
// Days(15), UTC_Seconds(15), UTC_Microseconds(15)
183-
// 362 variables total
184-
185176
final File file = getCDF3TAFile();
186177

187178
try {
188179
reader.open(file);
189180

190181
final List<Variable> variables = reader.getVariables();
191-
assertEquals(338, variables.size());
182+
assertEquals(340, variables.size());
192183

193184
Variable variable = variables.get(0);
194185
assertEquals("X_Swath", variable.getShortName());
@@ -246,6 +237,13 @@ public void testGetVariables_CDF3TD() throws IOException, InvalidRangeException
246237
NCTestUtils.assertAttribute(variable, "_FillValue", "-2147483647");
247238
NCTestUtils.assertAttribute(variable, "units", "10-6s");
248239
NCTestUtils.assertAttribute(variable, "long_name", "UTC Time at which the averaged BT was taken, in EE CFI transport time format. Microseconds");
240+
241+
variable = variables.get(339);
242+
assertEquals("lat", variable.getShortName());
243+
assertEquals(DataType.FLOAT, variable.getDataType());
244+
NCTestUtils.assertAttribute(variable, "_FillValue", "NaN");
245+
NCTestUtils.assertAttribute(variable, "units", "degrees_north");
246+
NCTestUtils.assertAttribute(variable, "long_name", "latitude");
249247
} finally {
250248
reader.close();
251249
}
@@ -427,6 +425,38 @@ public void testReadScaled_3D_CDF3TA_outsideLeft() throws IOException, InvalidRa
427425
}
428426
}
429427

428+
@Test
429+
public void testReadRaw_lon_CDF3TD() throws IOException, InvalidRangeException {
430+
final File file = getCDF3TDFile();
431+
432+
try {
433+
reader.open(file);
434+
435+
final Array array = reader.readRaw(674, 311, new Interval(3, 3), "lon");
436+
NCTestUtils.assertValueAt(-5.317002773284912, 0, 1, array);
437+
NCTestUtils.assertValueAt(-5.057636737823486, 1, 1, array);
438+
NCTestUtils.assertValueAt(-4.7982707023620605, 2, 1, array);
439+
} finally {
440+
reader.close();
441+
}
442+
}
443+
444+
@Test
445+
public void testReadScaled_lat_CDF3TA() throws IOException, InvalidRangeException {
446+
final File file = getCDF3TAFile();
447+
448+
try {
449+
reader.open(file);
450+
451+
final Array array = reader.readScaled(675, 312, new Interval(3, 3), "lat");
452+
NCTestUtils.assertValueAt(3.827965021133423, 1, 0, array);
453+
NCTestUtils.assertValueAt(4.024578094482422, 1, 1, array);
454+
NCTestUtils.assertValueAt(4.2212371826171875, 1, 2, array);
455+
} finally {
456+
reader.close();
457+
}
458+
}
459+
430460
private File getCDF3TAFile() throws IOException {
431461
final String testFilePath = TestUtil.assembleFileSystemPath(new String[]{"miras-smos-CDF3TA", "re07", "2016", "162", "SM_RE07_MIR_CDF3TA_20160610T000000_20160610T235959_330_001_7.tgz"}, false);
432462
return TestUtil.getTestDataFileAsserted(testFilePath);

matchup-tool/src/test/java/com/bc/fiduceo/matchup/MatchupToolIntegrationTest_SMOSL1_drifter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ public void testMatchup() throws IOException, SQLException, ParseException, Inva
7777
NCTestUtils.assert3DVariable("miras-smos-CDF3TD_Nb_SUN_Flags_525", 2, 0, 11, 0, mmd);
7878
NCTestUtils.assert3DVariable("miras-smos-CDF3TD_Nviews_575", 0, 1, 12, 14, mmd);
7979
NCTestUtils.assert3DVariable("miras-smos-CDF3TD_Pixel_BT_Standard_Deviation_3_625", 1, 1, 13, -32768, mmd);
80+
NCTestUtils.assert3DVariable("miras-smos-CDF3TD_lon", 2, 1, 13, -48.37175750732422, mmd);
81+
NCTestUtils.assert3DVariable("miras-smos-CDF3TD_lat", 0, 2, 14, 36.3758544921875, mmd);
8082
}
8183
}
8284

0 commit comments

Comments
 (0)