Source code for s2d2.sentinel2_band

from collections import namedtuple
from PIL import Image, ImageDraw

import os
import numpy as np

from osgeo import gdal

from typing import Optional
from .typing import Path

from .image_coordinate_tools import map2pix
from .handler.xml import get_root_of_table, get_branch
from .handler.gml import get_xy_polygon_from_gml

from .sentinel2_instrument import MSI_SPECIFICS, dn_to_toa


[docs] class Sentinel2Band(): def __init__(self, index: str, epsg: int, geotransform: tuple, rows: int, columns: int) -> None: self.index = index # mapping specifics self.epsg = epsg self.geotransform = geotransform # image specifics self.rows = rows self.columns = columns self.unit = None self.digitalnumbers = None self.detector = None self.zenith = None self.azimuth = None self.timing = None
[docs] def read_detector_gml(self, path: Path): det_msk = np.zeros((self.rows, self.columns), dtype='int8') root = get_root_of_table(path, fname=f'MSK_DETFOO_{self.index}.gml') mask_members = get_branch(root, 'maskMembers') for k in range(len(mask_members)): pos_arr, det_num = get_xy_polygon_from_gml(mask_members, k) # transform to image coordinates i_arr, j_arr = map2pix(self.geotransform, pos_arr[:, 0], pos_arr[:, 1]) ij_arr = np.hstack((j_arr[:, np.newaxis], i_arr[:, np.newaxis])) # make mask msk = Image.new("L", [np.size(det_msk, 1), np.size(det_msk, 0)], 0) ImageDraw.Draw(msk).polygon(tuple(map(tuple, ij_arr[:, 0:2])), outline=det_num, fill=det_num) msk = np.array(msk) det_msk = np.maximum(det_msk, msk) self.detector = det_msk
[docs] def read_band(self, path: Path, fname: Optional[str]): # todo: what to do with full integration... img_path = os.path.join(path, fname) img = gdal.Open(img_path) assert img is not None, ('could not open dataset ' + fname) band = np.array(img.GetRasterBand(1).ReadAsArray()) no_dat = img.GetRasterBand(1).GetNoDataValue() np.putmask(band, band == no_dat, 0) self.digitalnumbers = band self.unit = 'DN'
[docs] def dn_to_toa(self): if self.unit == 'TOA': return assert (self.unit == 'DN'), 'input should be digital numbers' self.digitalnumbers = dn_to_toa(self.digitalnumbers) self.unit = 'TOA'