Skip to content

Commit 1a337fa

Browse files
committed
implemented PixelLocator
1 parent 5a40e8a commit 1a337fa

File tree

10 files changed

+254
-34
lines changed

10 files changed

+254
-34
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.bc.fiduceo.location;
2+
3+
import org.esa.snap.core.dataio.geocoding.*;
4+
import org.esa.snap.core.dataio.geocoding.forward.PixelForward;
5+
import org.esa.snap.core.dataio.geocoding.inverse.PixelQuadTreeInverse;
6+
import org.esa.snap.core.datamodel.GeoPos;
7+
import org.esa.snap.core.datamodel.PixelPos;
8+
import ucar.ma2.Array;
9+
import ucar.ma2.DataType;
10+
11+
import java.awt.geom.Point2D;
12+
13+
public class PixelGeoCodingPixelLocator implements PixelLocator {
14+
15+
private final ComponentGeoCoding geoCoding;
16+
17+
public PixelGeoCodingPixelLocator(Array longitudes, Array latitudes, String lonVariableName, String latVariableName, double groundResolutionInKm, GeoChecks geoChecks) {
18+
final double[] lonArray = (double[]) longitudes.get1DJavaArray(DataType.DOUBLE);
19+
final double[] latArray = (double[]) latitudes.get1DJavaArray(DataType.DOUBLE);
20+
final int[] shape = longitudes.getShape();
21+
22+
final GeoRaster geoRaster = new GeoRaster(lonArray, latArray, lonVariableName, latVariableName, shape[1], shape[0], groundResolutionInKm);
23+
final ForwardCoding forwardCoding = ComponentFactory.getForward(PixelForward.KEY);
24+
final InverseCoding inverseCoding = ComponentFactory.getInverse(PixelQuadTreeInverse.KEY);
25+
geoCoding = new ComponentGeoCoding(geoRaster, forwardCoding, inverseCoding, geoChecks);
26+
geoCoding.initialize();
27+
}
28+
29+
@Override
30+
public Point2D getGeoLocation(double x, double y, Point2D g) {
31+
final GeoPos geoPos = geoCoding.getGeoPos(new PixelPos(x + 0.5, y + 0.5), null);
32+
return new Point2D.Double(geoPos.lon, geoPos.lat);
33+
}
34+
35+
@Override
36+
public Point2D[] getPixelLocation(double lon, double lat) {
37+
final PixelPos pixelPos = geoCoding.getPixelPos(new GeoPos(lat, lon), null);
38+
return new Point2D[]{new Point2D.Double(pixelPos.getX() - 0.5, pixelPos.getY() - 0.5)};
39+
}
40+
}

core/src/main/java/com/bc/fiduceo/reader/amsu_mhs/AMSUA_L1B_Reader.java

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.bc.fiduceo.core.Dimension;
44
import com.bc.fiduceo.core.Interval;
55
import com.bc.fiduceo.geometry.Polygon;
6+
import com.bc.fiduceo.location.PixelGeoCodingPixelLocator;
67
import com.bc.fiduceo.location.PixelLocator;
78
import com.bc.fiduceo.reader.AcquisitionInfo;
89
import com.bc.fiduceo.reader.Geometries;
@@ -15,6 +16,7 @@
1516
import com.bc.fiduceo.reader.amsu_mhs.nat.record_types.MPHR;
1617
import com.bc.fiduceo.reader.time.TimeLocator;
1718
import com.bc.fiduceo.reader.time.TimeLocator_StartStopDate;
19+
import org.esa.snap.core.dataio.geocoding.GeoChecks;
1820
import ucar.ma2.Array;
1921
import ucar.ma2.ArrayInt;
2022
import ucar.ma2.InvalidRangeException;
@@ -26,6 +28,7 @@
2628
import java.util.List;
2729

2830
import static com.bc.fiduceo.core.NodeType.UNDEFINED;
31+
import static com.bc.fiduceo.reader.amsu_mhs.nat.EPS_Constants.*;
2932

3033
public class AMSUA_L1B_Reader extends Abstract_L1B_NatReader {
3134

@@ -81,16 +84,6 @@ public String getRegEx() {
8184
return "AMSA_[A-Z0-9x]{3}_1B_M0[123]_[0-9]{14}Z_[0-9]{14}Z_[A-Z0-9x]{1}_[A-Z0-9x]{1}_[0-9]{14}Z\\.nat";
8285
}
8386

84-
@Override
85-
public PixelLocator getPixelLocator() throws IOException {
86-
throw new RuntimeException("not implemented");
87-
}
88-
89-
@Override
90-
public PixelLocator getSubScenePixelLocator(Polygon sceneGeometry) throws IOException {
91-
throw new RuntimeException("not implemented");
92-
}
93-
9487
@Override
9588
public TimeLocator getTimeLocator() throws IOException {
9689
// for the test file, the array returned contains only zeros - same as for MHS
@@ -101,8 +94,8 @@ public TimeLocator getTimeLocator() throws IOException {
10194
// Instead, we interpolate between header start and stop times tb 2025-09-04
10295
final MPHR mphr = cache.getMPHR();
10396
// @todo 2 tb this is not good, because I need to know the name, better offer explicit getters for sensing start and stop
104-
final Date sensingStart = mphr.getDate("SENSING_START");
105-
final Date sensingStop = mphr.getDate("SENSING_END");
97+
final Date sensingStart = mphr.getDate(SENSING_START_KEY);
98+
final Date sensingStop = mphr.getDate(SENSING_STOP_KEY);
10699

107100
final int numScanLines = cache.getMdrs().size();
108101
return new TimeLocator_StartStopDate(sensingStart, sensingStop, numScanLines);

core/src/main/java/com/bc/fiduceo/reader/amsu_mhs/MHS_L1B_Reader.java

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import java.util.Date;
2121
import java.util.List;
2222

23+
import static com.bc.fiduceo.reader.amsu_mhs.nat.EPS_Constants.SENSING_START_KEY;
24+
import static com.bc.fiduceo.reader.amsu_mhs.nat.EPS_Constants.SENSING_STOP_KEY;
25+
2326
public class MHS_L1B_Reader extends Abstract_L1B_NatReader {
2427

2528
public static final String RESOURCE_KEY = "MHS_L1B";
@@ -63,16 +66,6 @@ public String getRegEx() {
6366
return "MHSx_[A-Z0-9x]{3}_1B_M0[123]_[0-9]{14}Z_[0-9]{14}Z_[A-Z0-9x]{1}_[A-Z0-9x]{1}_[0-9]{14}Z\\.nat";
6467
}
6568

66-
@Override
67-
public PixelLocator getPixelLocator() throws IOException {
68-
throw new RuntimeException("not implemented");
69-
}
70-
71-
@Override
72-
public PixelLocator getSubScenePixelLocator(Polygon sceneGeometry) throws IOException {
73-
throw new RuntimeException("not implemented");
74-
}
75-
7669
@Override
7770
public TimeLocator getTimeLocator() throws IOException {
7871
// for the test file, the array returned contains only zeros - same as for AMSUA
@@ -83,8 +76,8 @@ public TimeLocator getTimeLocator() throws IOException {
8376
// Instead, we interpolate between header start and stop times tb 2025-09-04
8477
final MPHR mphr = cache.getMPHR();
8578
// @todo 2 tb this is not good, because I need to know the name, better offer explicit getters for sensing start and stop
86-
final Date sensingStart = mphr.getDate("SENSING_START");
87-
final Date sensingStop = mphr.getDate("SENSING_END");
79+
final Date sensingStart = mphr.getDate(SENSING_START_KEY);
80+
final Date sensingStop = mphr.getDate(SENSING_STOP_KEY);
8881

8982
final int numScanLines = cache.getMdrs().size();
9083
return new TimeLocator_StartStopDate(sensingStart, sensingStop, numScanLines);

core/src/main/java/com/bc/fiduceo/reader/amsu_mhs/nat/Abstract_L1B_NatReader.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,56 @@
33
import com.bc.fiduceo.core.Interval;
44
import com.bc.fiduceo.geometry.Geometry;
55
import com.bc.fiduceo.geometry.GeometryFactory;
6+
import com.bc.fiduceo.geometry.Polygon;
7+
import com.bc.fiduceo.location.PixelGeoCodingPixelLocator;
8+
import com.bc.fiduceo.location.PixelLocator;
69
import com.bc.fiduceo.reader.*;
710
import com.bc.fiduceo.reader.amsu_mhs.nat.record_types.MPHR;
11+
import org.esa.snap.core.dataio.geocoding.GeoChecks;
812
import ucar.ma2.Array;
913

1014
import java.io.File;
1115
import java.io.FileInputStream;
1216
import java.io.IOException;
1317
import java.util.Date;
1418

19+
import static com.bc.fiduceo.reader.amsu_mhs.nat.EPS_Constants.*;
20+
import static com.bc.fiduceo.reader.amsu_mhs.nat.EPS_Constants.LAT_VAR_NAME;
21+
import static com.bc.fiduceo.reader.amsu_mhs.nat.EPS_Constants.LON_VAR_NAME;
22+
1523
abstract public class Abstract_L1B_NatReader implements Reader {
1624

1725
protected VariableRegistry registry;
1826
protected EpsVariableCache cache;
1927
protected final GeometryFactory geometryFactory;
2028

29+
private PixelLocator pixelLocator;
30+
2131
public Abstract_L1B_NatReader(ReaderContext readerContext) {
2232
this.geometryFactory = readerContext.getGeometryFactory();
33+
pixelLocator = null;
34+
}
35+
36+
@Override
37+
public PixelLocator getPixelLocator() throws IOException {
38+
if (pixelLocator == null) {
39+
final Array lon = cache.getScaled(LON_VAR_NAME);
40+
final Array lat = cache.getScaled(LAT_VAR_NAME);
41+
42+
pixelLocator = new PixelGeoCodingPixelLocator(lon, lat, LON_VAR_NAME, LAT_VAR_NAME, 48.0, GeoChecks.POLES);
43+
}
44+
return pixelLocator;
45+
}
46+
47+
@Override
48+
public PixelLocator getSubScenePixelLocator(Polygon sceneGeometry) throws IOException {
49+
return getPixelLocator();
2350
}
2451

2552
protected static void setSensingDates(AcquisitionInfo acquisitionInfo, MPHR recordMPHR) throws IOException {
26-
final Date sensingStart = recordMPHR.getDate("SENSING_START");
53+
final Date sensingStart = recordMPHR.getDate(SENSING_START_KEY);
2754
acquisitionInfo.setSensingStart(sensingStart);
28-
final Date sensingEnd = recordMPHR.getDate("SENSING_END");
55+
final Date sensingEnd = recordMPHR.getDate(SENSING_STOP_KEY);
2956
acquisitionInfo.setSensingStop(sensingEnd);
3057
}
3158

@@ -49,6 +76,7 @@ public void close() throws IOException {
4976
}
5077
// @todo 2 tb/tb implement clear() method for registry
5178
registry = null;
79+
pixelLocator = null;
5280
}
5381

5482
protected Geometries extractGeometries(Array longitudes, Array latitudes, int numSplits, Interval interval) throws IOException {

core/src/main/java/com/bc/fiduceo/reader/amsu_mhs/nat/EPS_Constants.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,10 @@ public class EPS_Constants {
1010
public static final int MHS_EARTH_LOCATIONS_SCALE_FACTOR = 10000;
1111

1212
public static final int AMSUA_FOV_COUNT = 30;
13+
14+
public static String SENSING_START_KEY = "SENSING_START";
15+
public static String SENSING_STOP_KEY = "SENSING_END";
16+
17+
public static String LON_VAR_NAME = "longitude";
18+
public static String LAT_VAR_NAME = "latitude";
1319
}

core/src/main/java/com/bc/fiduceo/reader/amsu_mhs/nat/record_types/MPHR.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
import java.util.HashMap;
1212
import java.util.TimeZone;
1313

14+
import static com.bc.fiduceo.reader.amsu_mhs.nat.EPS_Constants.SENSING_START_KEY;
15+
import static com.bc.fiduceo.reader.amsu_mhs.nat.EPS_Constants.SENSING_STOP_KEY;
16+
1417
public class MPHR extends Record {
1518

1619
public static final int PRODUCT_NAME_OFFSET = 20;
@@ -26,9 +29,9 @@ public Date getDate(String key) throws IOException {
2629
String attributeValue = attributesMap.get(key);
2730
if (attributeValue == null) {
2831
int offset;
29-
if (key.equals("SENSING_START")) {
32+
if (key.equals(SENSING_START_KEY)) {
3033
offset = 700;
31-
} else if (key.equals("SENSING_END")) {
34+
} else if (key.equals(SENSING_STOP_KEY)) {
3235
offset = 748;
3336
} else {
3437
throw new IllegalStateException("Unknown attribute key: " + key);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.bc.fiduceo.location;
2+
3+
import org.esa.snap.core.dataio.geocoding.GeoChecks;
4+
import org.junit.Before;
5+
import org.junit.Test;
6+
import ucar.ma2.Array;
7+
import ucar.ma2.DataType;
8+
9+
import java.awt.geom.Point2D;
10+
11+
import static org.junit.Assert.assertEquals;
12+
13+
public class PixelGeoCodingPixelLocatorTest {
14+
15+
private PixelGeoCodingPixelLocator pixelGeoCodingPixelLocator;
16+
17+
@Before
18+
public void setUp() {
19+
final float[] longitudes = {176.4837f, 176.38458f, 176.28566f, 176.23f, 176.13022f, 176.03065f};
20+
final float[] latitudes = {-72.1376f, -72.16673f, -72.19598f, -72.17846f, -72.207436f, -72.236534f};
21+
22+
final Array lonArray = Array.factory(DataType.FLOAT, new int[]{2, 3}, longitudes);
23+
final Array latArray = Array.factory(DataType.FLOAT, new int[]{2, 3}, latitudes);
24+
25+
pixelGeoCodingPixelLocator = new PixelGeoCodingPixelLocator(lonArray, latArray, "longitude", "latituide", 35, GeoChecks.NONE);
26+
}
27+
28+
@Test
29+
public void testGetGeoLocation() {
30+
Point2D geoLocation = pixelGeoCodingPixelLocator.getGeoLocation(0, 0, null);
31+
assertEquals(176.48370361328125, geoLocation.getX(), 1e-8);
32+
assertEquals(-72.13760375976562, geoLocation.getY(), 1e-8);
33+
34+
geoLocation = pixelGeoCodingPixelLocator.getGeoLocation(1, 1, null);
35+
assertEquals(176.13021850585938, geoLocation.getX(), 1e-8);
36+
assertEquals(-72.20743560791016, geoLocation.getY(), 1e-8);
37+
38+
geoLocation = pixelGeoCodingPixelLocator.getGeoLocation(-1, 0, null);
39+
assertEquals(Double.NaN, geoLocation.getX(), 1e-8);
40+
assertEquals(Double.NaN, geoLocation.getY(), 1e-8);
41+
42+
geoLocation = pixelGeoCodingPixelLocator.getGeoLocation(1, 17, null);
43+
assertEquals(Double.NaN, geoLocation.getX(), 1e-8);
44+
assertEquals(Double.NaN, geoLocation.getY(), 1e-8);
45+
}
46+
47+
@Test
48+
public void testGetPixelLocation() {
49+
Point2D[] pixelLocation = pixelGeoCodingPixelLocator.getPixelLocation(176.48370361328125, -72.13760375976562);
50+
assertEquals(1, pixelLocation.length);
51+
assertEquals(0, pixelLocation[0].getX(), 1e-8);
52+
assertEquals(0, pixelLocation[0].getY(), 1e-8);
53+
54+
pixelLocation = pixelGeoCodingPixelLocator.getPixelLocation(176.13021850585938, -72.20743560791016);
55+
assertEquals(1, pixelLocation.length);
56+
assertEquals(1, pixelLocation[0].getX(), 1e-8);
57+
assertEquals(1, pixelLocation[0].getY(), 1e-8);
58+
59+
pixelLocation = pixelGeoCodingPixelLocator.getPixelLocation(22.9, 0.8);
60+
assertEquals(1, pixelLocation.length);
61+
assertEquals(Double.NaN, pixelLocation[0].getX(), 1e-8);
62+
assertEquals(Double.NaN, pixelLocation[0].getY(), 1e-8);
63+
}
64+
}

core/src/test/java/com/bc/fiduceo/reader/amsu_mhs/AMSUA_L1B_Reader_IO_Test.java

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
import com.bc.fiduceo.TestUtil;
55
import com.bc.fiduceo.core.NodeType;
66
import com.bc.fiduceo.geometry.*;
7+
import com.bc.fiduceo.location.PixelLocator;
78
import com.bc.fiduceo.reader.AcquisitionInfo;
89
import com.bc.fiduceo.reader.ReaderContext;
910
import com.bc.fiduceo.reader.time.TimeLocator;
1011
import org.junit.Before;
1112
import org.junit.Test;
1213
import org.junit.runner.RunWith;
1314

15+
import java.awt.geom.Point2D;
1416
import java.io.File;
1517
import java.io.IOException;
1618
import java.text.ParseException;
@@ -20,8 +22,7 @@
2022
import java.util.TimeZone;
2123

2224
import static com.bc.fiduceo.geometry.GeometryFactory.Type.S2;
23-
import static org.junit.Assert.assertEquals;
24-
import static org.junit.Assert.assertTrue;
25+
import static org.junit.Assert.*;
2526

2627
@RunWith(IOTestRunner.class)
2728
public class AMSUA_L1B_Reader_IO_Test {
@@ -117,6 +118,50 @@ public void testGetTimeLocator() throws IOException {
117118
}
118119
}
119120

121+
@Test
122+
public void testGetPixelLocator() throws IOException {
123+
final File file = createAmsuaMetopAPath("AMSA_xxx_1B_M01_20160101234924Z_20160102013124Z_N_O_20160102003323Z.nat");
124+
125+
try {
126+
reader.open(file);
127+
128+
final PixelLocator pixelLocator = reader.getPixelLocator();
129+
Point2D geoLocation = pixelLocator.getGeoLocation(0, 0, null);
130+
assertEquals(-168.0057, geoLocation.getX(), 1e-8);
131+
assertEquals(65.5792, geoLocation.getY(), 1e-8);
132+
133+
geoLocation = pixelLocator.getGeoLocation(5, 108, null);
134+
assertEquals(150.1052, geoLocation.getX(), 1e-8);
135+
assertEquals(20.8303, geoLocation.getY(), 1e-8);
136+
137+
Point2D[] pixelLocations = pixelLocator.getPixelLocation(-168.0057000002, 65.5792);
138+
assertEquals(1, pixelLocations.length);
139+
assertEquals(0, pixelLocations[0].getX(), 1e-8);
140+
assertEquals(0, pixelLocations[0].getY(), 1e-8);
141+
142+
pixelLocations = pixelLocator.getPixelLocation(150.1052, 20.8303);
143+
assertEquals(1, pixelLocations.length);
144+
assertEquals(5, pixelLocations[0].getX(), 1e-8);
145+
assertEquals(108, pixelLocations[0].getY(), 1e-8);
146+
} finally {
147+
reader.close();
148+
}
149+
}
150+
151+
@Test
152+
public void testGetSubScenePixelLocator() throws IOException {
153+
final File file = createAmsuaMetopAPath("AMSA_xxx_1B_M01_20160101234924Z_20160102013124Z_N_O_20160102003323Z.nat");
154+
try {
155+
reader.open(file);
156+
157+
final PixelLocator pixelLocator = reader.getPixelLocator();
158+
final PixelLocator subScenePixelLocator = reader.getSubScenePixelLocator(null);
159+
assertSame(pixelLocator, subScenePixelLocator);
160+
} finally {
161+
reader.close();
162+
}
163+
}
164+
120165
private File createAmsuaMetopAPath(String fileName) throws IOException {
121166
final String testFilePath = TestUtil.assembleFileSystemPath(new String[]{"amsua-ma", "v8A", "2016", "01", "01", fileName}, false);
122167
return TestUtil.getTestDataFileAsserted(testFilePath);

0 commit comments

Comments
 (0)