Skip to content

Commit 3105b0a

Browse files
Merge branch 'develop' into 'master' to release 4.4.3
2 parents 945582d + be20d25 commit 3105b0a

File tree

5 files changed

+82
-55
lines changed

5 files changed

+82
-55
lines changed

sen2like/release-notes.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Sen2Like Release Notes
22

3+
## v4.4.3
4+
5+
### Fix
6+
7+
* Fix calculation of Sen2cor region of interest when target UTM differs from the input Landsat product UTM.
8+
39
## v4.4.2
410

511
### Release of Sen2Cor3 documentation and software version 3.01.00

sen2like/sen2like/core/product_preparation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ def _extract_product_files(self, product: S2L_Product):
318318
if (
319319
scl_dir
320320
and (not product.context.use_sen2cor)
321-
and product_reader.data_type != "Level-2A"
321+
and product_reader.data_type != "Level-2A" # Sentinel
322322
):
323323
product_reader.scene_classif_band = self._get_scl_map(scl_dir, product)
324324

sen2like/sen2like/core/sen2cor_client/sen2cor_client.py

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,41 @@
1616
# See the License for the specific language governing permissions and
1717
# limitations under the License.
1818

19-
19+
import affine
2020
import logging
2121
import os
2222
import subprocess
2323
import lxml.etree as ET
24+
25+
from osgeo import osr
26+
import mgrs
27+
2428
from core import S2L_config
25-
from grids.mgrs_framing import pixel_center
29+
from core.image_file import S2L_ImageFile
30+
2631

2732
logger = logging.getLogger("Sen2Like")
2833

2934

35+
def get_mgrs_center(tilecode: str, utm=False) -> tuple:
36+
"""Get MGRS tile center coordinates in native tile UTM or WGS84
37+
38+
Args:
39+
tilecode (str): tile to get center coords
40+
utm (bool, optional): Flag for output SRS . Defaults to False.
41+
42+
Returns:
43+
tuple: (lat,long) coords if utm=False, else (utm, N/S, easting, northing)
44+
"""
45+
if tilecode.startswith('T'):
46+
tilecode = tilecode[1:]
47+
centercode = tilecode + '5490045100'
48+
m = mgrs.MGRS()
49+
if utm:
50+
return m.MGRSToUTM(centercode)
51+
return m.toLatLon(centercode)
52+
53+
3054
class Sen2corClient:
3155

3256
gipp_template_file = os.path.join(
@@ -117,26 +141,63 @@ def _write_gipp(self, product):
117141
# ref_band = None is considered as S2 product format (S2A, S2B, S2P prisma)
118142
ref_band = self.roi_ref_band.get(product.mtl.mission, None)
119143

120-
if ref_band is None:
121-
logger.debug("For sentinel, sen2cor don't use ROI")
122-
ET.ElementTree(root).write(gipp_path, encoding='utf-8', xml_declaration=True)
123-
return gipp_path
144+
if ref_band:
145+
# Compute ROI center for landsat and fill template with result
146+
ref_band_file = product.get_band_file(ref_band)
124147

125-
ref_band_file = product.get_band_file(ref_band)
148+
y, x = self._pixel_center(ref_band_file)
126149

127-
y, x = pixel_center(ref_band_file, self.out_mgrs)
128-
logger.debug('Pixel center : (%s, %s)', y, x)
150+
logger.debug('Pixel center : (%s, %s)', y, x)
129151

130-
row0 = root.find('Common_Section/Region_Of_Interest/row0')
131-
row0.text = str(y)
132-
col0 = root.find('Common_Section/Region_Of_Interest/col0')
133-
col0.text = str(x)
152+
row0 = root.find('Common_Section/Region_Of_Interest/row0')
153+
row0.text = str(y)
154+
col0 = root.find('Common_Section/Region_Of_Interest/col0')
155+
col0.text = str(x)
134156

135-
ET.ElementTree(root).write(gipp_path, encoding='utf-8', xml_declaration=True)
157+
ET.ElementTree(root).write(gipp_path, encoding='utf-8', xml_declaration=True)
158+
159+
else:
160+
logger.debug("For sentinel, sen2cor don't use ROI")
136161

137162
logger.info('GIPP L2A : %s', gipp_path)
163+
164+
ET.ElementTree(root).write(gipp_path, encoding='utf-8', xml_declaration=True)
165+
138166
return gipp_path
139167

168+
def _pixel_center(self, image: S2L_ImageFile):
169+
"""Get mgrs tile center coordinates from tile code in image coordinates
170+
171+
Args:
172+
image (S2L_ImageFile): image to get srs from
173+
174+
Returns:
175+
tuple: (y,x) image coordinates
176+
"""
177+
178+
lat, lon = get_mgrs_center(self.out_mgrs) # pylint: disable=W0632
179+
180+
# Transform src SRS
181+
wgs84_srs = osr.SpatialReference()
182+
wgs84_srs.ImportFromEPSG(4326)
183+
184+
# Transform dst SRS
185+
image_srs = osr.SpatialReference(wkt=image.projection)
186+
187+
# convert MGRS center coordinates from lat lon to image EPSG coordinates (UTM)
188+
transformation = osr.CoordinateTransformation(wgs84_srs, image_srs)
189+
easting, northing, _ = transformation.TransformPoint(lat, lon)
190+
191+
# northing = y = latitude, easting = x = longitude
192+
tr = affine.Affine(
193+
image.yRes, 0, image.yMax,
194+
0, image.xRes, image.xMin
195+
)
196+
197+
# compute y,x in image coordinates
198+
y, x = (northing, easting) * (~ tr)
199+
return int(y), int(x)
200+
140201

141202
class Sen2corError(Exception):
142203
pass

sen2like/sen2like/grids/grids.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import sqlite3
2323
from os.path import abspath, dirname
2424

25-
import mgrs
2625
import pandas as pd
2726
from osgeo import ogr, osr
2827
from shapely.wkt import loads
@@ -59,15 +58,6 @@ def getROIfromMGRS(self, tilecode):
5958
# return as dict
6059
return roi.to_dict(orient='list')
6160

62-
def get_mgrs_center(self, tilecode, utm=False):
63-
if tilecode.startswith('T'):
64-
tilecode = tilecode[1:]
65-
centercode = tilecode + '5490045100'
66-
m = mgrs.MGRS()
67-
if utm:
68-
return m.MGRSToUTM(centercode)
69-
return m.toLatLon(centercode)
70-
7161
# Don't know why but with this method the SRS code is not added in the geojson
7262
# if the GDAL_DATA variable is set in the environment. However we need
7363
# this GDAL_DATA variable for other methods. So we do not use this method.

sen2like/sen2like/grids/mgrs_framing.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
from math import ceil
2525
from typing import NamedTuple
2626

27-
import affine
2827
import numpy as np
2928
import pandas as pd
3029
from numpy.typing import NDArray
@@ -129,35 +128,6 @@ def resample(image: S2L_ImageFile, res: int, filepath_out: str) -> S2L_ImageFile
129128
return image.duplicate(filepath_out, array=data, res=res)
130129

131130

132-
def pixel_center(image: S2L_ImageFile, tile_code: str):
133-
"""Get mgrs tile center coordinates from tile code in image SRS
134-
135-
Args:
136-
image (S2L_ImageFile): image to get srs from
137-
tile_code (str): MGRS tile code
138-
139-
Returns:
140-
tuple: y/x coordinates
141-
"""
142-
converter = grids.GridsConverter()
143-
utm, orientation, easting, northing = converter.get_mgrs_center(tile_code, utm=True)
144-
# UTM South vs. UTM North ?
145-
tile_srs = osr.SpatialReference()
146-
tile_srs.ImportFromEPSG(int('32' + ('6' if orientation == 'N' else '7') + str(utm)))
147-
image_srs = osr.SpatialReference(wkt=image.projection)
148-
if not tile_srs.IsSame(image_srs):
149-
transformation = osr.CoordinateTransformation(tile_srs, image_srs)
150-
northing, easting = transformation.TransformPoint((northing, easting))
151-
152-
# northing = y = latitude, easting = x = longitude
153-
tr = affine.Affine(
154-
image.yRes, 0, image.yMax,
155-
0, image.xRes, image.xMin
156-
)
157-
y, x = (northing, easting) * (~ tr)
158-
return int(y), int(x)
159-
160-
161131
def _reproject(filepath: str, dir_out: str, ds_src: gdal.Dataset, x_res: int, y_res: int, target_srs: osr.SpatialReference, order: int) -> ReprojectResult:
162132
"""Reproject given dataset in the target srs in the given resolution
163133

0 commit comments

Comments
 (0)