Skip to content

Commit 4285da5

Browse files
committed
implemented pixel locator
1 parent 2d64287 commit 4285da5

File tree

4 files changed

+226
-19
lines changed

4 files changed

+226
-19
lines changed

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

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,28 @@
33
import com.bc.fiduceo.location.PixelLocator;
44

55
import java.awt.geom.Point2D;
6+
import java.awt.geom.Rectangle2D;
67

78
class RasterPixelLocator implements PixelLocator {
89

910
private final float[] lons;
1011
private final float[] lats;
12+
private final Rectangle2D.Float boundary;
1113

1214
/**
1315
* Pixel locator for rectangular rasters, lon and lat axes supplied as vectors.
1416
* Ordering:
1517
* lons[0] is westernmost,
1618
* lats[0] is southernmost
17-
* @param lons the longitude axis
18-
* @param lats the latitude axis
19+
*
20+
* @param lons the longitude axis
21+
* @param lats the latitude axis
22+
* @param boundary the raster boundaries
1923
*/
20-
RasterPixelLocator(float[] lons, float[] lats) {
24+
RasterPixelLocator(float[] lons, float[] lats, Rectangle2D.Float boundary) {
2125
this.lons = lons;
2226
this.lats = lats;
27+
this.boundary = boundary;
2328
}
2429

2530
@Override
@@ -44,6 +49,42 @@ public Point2D getGeoLocation(double x, double y, Point2D point) {
4449

4550
@Override
4651
public Point2D[] getPixelLocation(double lon, double lat) {
47-
throw new RuntimeException("not implemented");
52+
if (!boundary.contains(new Point2D.Float((float) lon, (float) lat))) {
53+
return new Point2D[0];
54+
}
55+
56+
int x_break = getIndexLargerThan(lon, lons);
57+
x_break = adjustForClosest(x_break, lon, lons);
58+
59+
int y_break = getIndexLargerThan(lat, lats);
60+
y_break = adjustForClosest(y_break, lat, lats);
61+
62+
return new Point2D[]{new Point2D.Float(x_break + 0.5f, y_break + 0.5f)};
63+
}
64+
65+
private static int adjustForClosest(int targetIndex, double location, float[] locations) {
66+
// check which lon is closer
67+
if (targetIndex > 0) {
68+
final double delta_r = Math.abs(locations[targetIndex] - location);
69+
final double delta_l = Math.abs(locations[targetIndex - 1] - location);
70+
if (delta_l < delta_r) {
71+
targetIndex -= 1;
72+
}
73+
} else if (targetIndex == -1) {
74+
// we ran beyond the last lon, but are within the boundary, so: last lon
75+
targetIndex = locations.length - 1;
76+
}
77+
return targetIndex;
78+
}
79+
80+
private static int getIndexLargerThan(double location, float[] locations) {
81+
int x_break = -1;
82+
for (int i = 0; i < locations.length; i++) {
83+
if (location <= locations[i]) {
84+
x_break = i;
85+
break;
86+
}
87+
}
88+
return x_break;
4889
}
4990
}

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
import org.esa.snap.core.util.io.FileUtils;
1818
import ucar.ma2.Array;
1919
import ucar.ma2.ArrayInt;
20+
import ucar.ma2.DataType;
2021
import ucar.ma2.InvalidRangeException;
2122
import ucar.nc2.Variable;
2223

24+
import java.awt.geom.Rectangle2D;
2325
import java.io.*;
2426
import java.nio.file.Files;
2527
import java.util.ArrayList;
@@ -29,11 +31,14 @@
2931
class SmosL1CDailyGriddedReader extends NetCDFReader {
3032

3133
private final ReaderContext readerContext;
34+
private final Rectangle2D.Float boundary;
3235

3336
private File productDir;
37+
private PixelLocator pixelLocator;
3438

3539
SmosL1CDailyGriddedReader(ReaderContext readerContext) {
3640
this.readerContext = readerContext;
41+
this.boundary = new Rectangle2D.Float(-180.f, -86.72f, 360.f, 173.44f);
3742
}
3843

3944
@Override
@@ -57,6 +62,8 @@ public void open(File file) throws IOException {
5762
@Override
5863
public void close() throws IOException {
5964
super.close();
65+
66+
pixelLocator = null;
6067
if (productDir != null) {
6168
readerContext.deleteTempFile(productDir);
6269
productDir = null;
@@ -93,12 +100,21 @@ public String getRegEx() {
93100

94101
@Override
95102
public PixelLocator getPixelLocator() throws IOException {
96-
throw new IllegalStateException("not implemented");
103+
if (pixelLocator == null) {
104+
final Array longitudes = arrayCache.get("lon");
105+
final Array latitudes = arrayCache.get("lat");
106+
107+
pixelLocator = new RasterPixelLocator((float[]) longitudes.get1DJavaArray(DataType.FLOAT),
108+
(float[]) latitudes.get1DJavaArray(DataType.FLOAT),
109+
boundary);
110+
}
111+
112+
return pixelLocator;
97113
}
98114

99115
@Override
100116
public PixelLocator getSubScenePixelLocator(Polygon sceneGeometry) throws IOException {
101-
throw new IllegalStateException("not implemented");
117+
return getPixelLocator(); // no distinction between pixel locators tb 2022-09-29
102118
}
103119

104120
@Override
Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,42 @@
11
package com.bc.fiduceo.reader.smos;
22

33
import com.bc.fiduceo.location.PixelLocator;
4+
import org.junit.Before;
45
import org.junit.Test;
56

67
import java.awt.geom.Point2D;
8+
import java.awt.geom.Rectangle2D;
79

810
import static org.junit.Assert.assertEquals;
911
import static org.junit.Assert.assertNull;
1012

1113
public class RasterPixelLocatorTest {
1214

15+
private PixelLocator rasterPixelLocator;
16+
17+
@Before
18+
public void setUp() {
19+
final float[] lons = {-170, -130, -90, -50, -10, 10, 50, 90, 130, 170};
20+
final float[] lats = {-80, -50, -20, 0, 20, 50, 80};
21+
22+
Rectangle2D.Float boundary = new Rectangle2D.Float(-180, -88, 360, 176);
23+
24+
rasterPixelLocator = new RasterPixelLocator(lons, lats, boundary);
25+
}
26+
1327
@Test
1428
public void testGetGeoLocation() {
15-
final float[] lons = {-180, -140, -100, -60, -20, 20, 60, 100, 140, 180};
16-
final float[] lats = {-90, -60, -30, 0, 30, 60, 90};
17-
18-
final PixelLocator rasterPixelLocator = new RasterPixelLocator(lons, lats);
1929
Point2D geoLocation = rasterPixelLocator.getGeoLocation(0.5, 0.5, null);
20-
assertEquals(-180, geoLocation.getX(), 1e-8);
21-
assertEquals(-90, geoLocation.getY(), 1e-8);
30+
assertEquals(-170, geoLocation.getX(), 1e-8);
31+
assertEquals(-80, geoLocation.getY(), 1e-8);
2232

2333
geoLocation = rasterPixelLocator.getGeoLocation(4.5, 2.5, null);
24-
assertEquals(-20, geoLocation.getX(), 1e-8);
25-
assertEquals(-30, geoLocation.getY(), 1e-8);
34+
assertEquals(-10, geoLocation.getX(), 1e-8);
35+
assertEquals(-20, geoLocation.getY(), 1e-8);
2636
}
2737

2838
@Test
2939
public void testGetGeoLocation_outside() {
30-
final float[] lons = {-180, -140, -100, -60, -20, 20, 60, 100, 140, 180};
31-
final float[] lats = {-90, -60, -30, 0, 30, 60, 90};
32-
33-
final PixelLocator rasterPixelLocator = new RasterPixelLocator(lons, lats);
34-
3540
Point2D geoLocation = rasterPixelLocator.getGeoLocation(-1, 0.5, null);
3641
assertNull(geoLocation);
3742

@@ -44,4 +49,75 @@ public void testGetGeoLocation_outside() {
4449
geoLocation = rasterPixelLocator.getGeoLocation(1.5, 8.5, null);
4550
assertNull(geoLocation);
4651
}
52+
53+
@Test
54+
public void testGetPixelLocation() {
55+
// on the location
56+
Point2D[] locations = rasterPixelLocator.getPixelLocation(100, 20);
57+
assertEquals(1, locations.length);
58+
assertEquals(7.5, locations[0].getX(), 1e-8);
59+
assertEquals(4.5, locations[0].getY(), 1e-8);
60+
61+
// select closest from west
62+
locations = rasterPixelLocator.getPixelLocation(-144, 0);
63+
assertEquals(1, locations.length);
64+
assertEquals(1.5, locations[0].getX(), 1e-8);
65+
assertEquals(3.5, locations[0].getY(), 1e-8);
66+
67+
// select closest from east
68+
locations = rasterPixelLocator.getPixelLocation(-46, -20);
69+
assertEquals(1, locations.length);
70+
assertEquals(3.5, locations[0].getX(), 1e-8);
71+
assertEquals(2.5, locations[0].getY(), 1e-8);
72+
73+
// select closest from south
74+
locations = rasterPixelLocator.getPixelLocation(10, 18);
75+
assertEquals(1, locations.length);
76+
assertEquals(5.5, locations[0].getX(), 1e-8);
77+
assertEquals(4.5, locations[0].getY(), 1e-8);
78+
79+
// select closest from north
80+
locations = rasterPixelLocator.getPixelLocation(50, 22);
81+
assertEquals(1, locations.length);
82+
assertEquals(6.5, locations[0].getX(), 1e-8);
83+
assertEquals(4.5, locations[0].getY(), 1e-8);
84+
}
85+
86+
@Test
87+
public void testGetPixelLocation_outsideVectorButInsideRectangle() {
88+
// west of lon axis
89+
Point2D[] locations = rasterPixelLocator.getPixelLocation(-174, 50);
90+
assertEquals(1, locations.length);
91+
assertEquals(0.5, locations[0].getX(), 1e-8);
92+
assertEquals(5.5, locations[0].getY(), 1e-8);
93+
94+
// east of lon axis
95+
locations = rasterPixelLocator.getPixelLocation(177, 80);
96+
assertEquals(1, locations.length);
97+
assertEquals(9.5, locations[0].getX(), 1e-8);
98+
assertEquals(6.5, locations[0].getY(), 1e-8);
99+
100+
// south of lat axis
101+
locations = rasterPixelLocator.getPixelLocation(-170, -84);
102+
assertEquals(1, locations.length);
103+
assertEquals(0.5, locations[0].getX(), 1e-8);
104+
assertEquals(0.5, locations[0].getY(), 1e-8);
105+
106+
// north of lat axis
107+
locations = rasterPixelLocator.getPixelLocation(-130, 84);
108+
assertEquals(1, locations.length);
109+
assertEquals(1.5, locations[0].getX(), 1e-8);
110+
assertEquals(6.5, locations[0].getY(), 1e-8);
111+
}
112+
113+
@Test
114+
public void testGetPixelLocation_outside() {
115+
// south
116+
Point2D[] locations = rasterPixelLocator.getPixelLocation(90, -89);
117+
assertEquals(0, locations.length);
118+
119+
// north
120+
locations = rasterPixelLocator.getPixelLocation(130, 88.5);
121+
assertEquals(0, locations.length);
122+
}
47123
}

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.bc.fiduceo.core.Dimension;
66
import com.bc.fiduceo.core.NodeType;
77
import com.bc.fiduceo.geometry.*;
8+
import com.bc.fiduceo.location.PixelLocator;
89
import com.bc.fiduceo.reader.AcquisitionInfo;
910
import com.bc.fiduceo.reader.ReaderContext;
1011
import com.bc.fiduceo.util.TempFileUtils;
@@ -13,6 +14,7 @@
1314
import org.junit.Test;
1415
import org.junit.runner.RunWith;
1516

17+
import java.awt.geom.Point2D;
1618
import java.io.File;
1719
import java.io.IOException;
1820
import java.util.Date;
@@ -92,6 +94,7 @@ public void testReadAcquisitionInfo_CDF3TA() throws IOException {
9294
@Test
9395
public void testGetProductSize_CDF3TD() throws IOException {
9496
final File file = getCDF3TDFile();
97+
9598
try {
9699
reader.open(file);
97100

@@ -104,6 +107,77 @@ public void testGetProductSize_CDF3TD() throws IOException {
104107
}
105108
}
106109

110+
@Test
111+
public void testGetPixelLocator_CDF3TA() throws IOException {
112+
final File file = getCDF3TAFile();
113+
114+
try {
115+
reader.open(file);
116+
117+
final PixelLocator pixelLocator = reader.getPixelLocator();
118+
assertNotNull(pixelLocator);
119+
120+
Point2D geoLocation = pixelLocator.getGeoLocation(0.5, 0.5, null);
121+
assertEquals(-179.8703155517578, geoLocation.getX(), 1e-8);
122+
assertEquals(-83.51713562011719, geoLocation.getY(), 1e-8);
123+
124+
Point2D[] pixelLocations = pixelLocator.getPixelLocation(-179.8703155517578, -83.51713562011719);
125+
assertEquals(1, pixelLocations.length);
126+
assertEquals(0.5, pixelLocations[0].getX(), 1e-8);
127+
assertEquals(0.5, pixelLocations[0].getY(), 1e-8);
128+
129+
geoLocation = pixelLocator.getGeoLocation(762.5, 404.5, null);
130+
assertEquals(17.766571044921875, geoLocation.getX(), 1e-8);
131+
assertEquals(22.638275146484375, geoLocation.getY(), 1e-8);
132+
133+
pixelLocations = pixelLocator.getPixelLocation(17.766571044921875, 22.638275146484375);
134+
assertEquals(1, pixelLocations.length);
135+
assertEquals(762.5, pixelLocations[0].getX(), 1e-8);
136+
assertEquals(404.5, pixelLocations[0].getY(), 1e-8);
137+
138+
geoLocation = pixelLocator.getGeoLocation(1387.5, 583.5, null);
139+
assertEquals(179.8703155517578, geoLocation.getX(), 1e-8);
140+
assertEquals(83.51713562011719, geoLocation.getY(), 1e-8);
141+
142+
pixelLocations = pixelLocator.getPixelLocation(179.9, 83.6);
143+
assertEquals(1, pixelLocations.length);
144+
assertEquals(1387.5, pixelLocations[0].getX(), 1e-8);
145+
assertEquals(583.5, pixelLocations[0].getY(), 1e-8);
146+
147+
// check outside locations
148+
geoLocation = pixelLocator.getGeoLocation(-1, 0.5, null);
149+
assertNull(geoLocation);
150+
151+
geoLocation = pixelLocator.getGeoLocation(22.5, 685.5, null);
152+
assertNull(geoLocation);
153+
154+
pixelLocations = pixelLocator.getPixelLocation(116.7, -89.6);
155+
assertEquals(0, pixelLocations.length);
156+
157+
pixelLocations = pixelLocator.getPixelLocation(116.7, 89.6);
158+
assertEquals(0, pixelLocations.length);
159+
160+
} finally {
161+
reader.close();
162+
}
163+
}
164+
165+
@Test
166+
public void testGetSubScenePixelLocator_CDF3TD() throws IOException {
167+
final File file = getCDF3TDFile();
168+
169+
try {
170+
reader.open(file);
171+
172+
final PixelLocator subScenePixelLocator = reader.getSubScenePixelLocator(null);// geometry is not used here tb 2022-09-29
173+
final PixelLocator pixelLocator = reader.getPixelLocator();
174+
175+
assertSame(pixelLocator, subScenePixelLocator);
176+
} finally {
177+
reader.close();
178+
}
179+
}
180+
107181
private File getCDF3TAFile() throws IOException {
108182
final String testFilePath = TestUtil.assembleFileSystemPath(new String[]{"miras-smos-CDF3TA", "re07", "2016", "162", "SM_RE07_MIR_CDF3TA_20160610T000000_20160610T235959_330_001_7.tgz"}, false);
109183
return TestUtil.getTestDataFileAsserted(testFilePath);

0 commit comments

Comments
 (0)