Source code for geopathfinder.naming_conventions.eodr_naming

# Copyright (c) 2025, TU Wien
# of Geodesy and Geoinformation (GEO).
# All rights reserved.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL VIENNA UNIVERSITY OF TECHNOLOGY,
# DEPARTMENT OF GEODESY AND GEOINFORMATION BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
eoDR file name definition.

"""

import copy
import os
from datetime import datetime
from collections import OrderedDict

from geopathfinder.file_naming import SmartFilename


[docs] class EODRFilename(SmartFilename): """ eoDataReaders file name definition using SmartFilename class. """ fields_def = OrderedDict([('counter', { 'len': 5 }), ('id', { 'len': 12 }), ('dt_1', { 'len': 15 }), ('dt_2', { 'len': 15 }), ('file_num', {}), ('band', {})]) pad = "-" delimiter = "_" def __init__(self, fields, ext='.vrt', convert=False, compact=False): """ Constructor of eoDRFilename class. Parameters ---------- fields: dict Dictionary specifying the different parts of the filename. ext: str, optional Extension of the filename (default is '.vrt' for GDAL VRT files) convert: bool, optional If true, decoding is applied to parts of the filename, where such an operation is available (default is False). """ self.dt_format = "%Y%m%dT%H%M%S" fields_def_ext = copy.deepcopy(EODRFilename.fields_def) fields_def_ext['counter']['decoder'] = lambda x: self.decode_counter(x) fields_def_ext['counter']['encoder'] = lambda x: self.encode_counter(x) fields_def_ext['dt_1']['decoder'] = lambda x: self.decode_datetime(x) fields_def_ext['dt_1']['encoder'] = lambda x: self.encode_datetime(x) fields_def_ext['dt_2']['decoder'] = lambda x: self.decode_datetime(x) fields_def_ext['dt_2']['encoder'] = lambda x: self.encode_datetime(x) fields_def_ext['file_num']['decoder'] = lambda x: int(x) fields_def_ext['file_num']['encoder'] = lambda x: str(x) fields_def_ext['band']['encoder'] = lambda x: str(x) fields_def_keys = list(fields_def_ext.keys()) for key in fields.keys(): if key not in fields_def_keys: fields_def_ext[key] = {} super(EODRFilename, self).__init__(fields, fields_def_ext, delimiter=EODRFilename.delimiter, pad=EODRFilename.pad, ext=ext, convert=convert, compact=compact)
[docs] @classmethod def from_filename(cls, filename_str, convert=False, compact=False): """ Converts a filename given as a string into an EODRFilename class object. Parameters ---------- filename_str : str Filename without any paths (e.g., "00001_123456------_20181220T232333_---------------_2_B5_34_aug.vrt"). convert: bool, optional If true, decoding is applied to parts of the filename, where such an operation is available (default is False). Returns ------- EODRFilename Class representing an EODR filename. """ fn_parts = os.path.splitext(os.path.basename(filename_str))[0].split( EODRFilename.delimiter) fields_def_ext = copy.deepcopy(EODRFilename.fields_def) fields_def_ext['file_num']['len'] = len(fn_parts[4]) fields_def_ext['band']['len'] = len( fn_parts[5]) # get length of the band in the filename # if the filename consists of more than 4 parts, additional "dimensions" are added to the fields dictionary if len(fn_parts) > 6: for i, fn_part in enumerate(fn_parts[6:]): key = 'd' + str(i + 1) fields_def_ext[key] = {'len': len(fn_part)} return super().from_filename(filename_str, fields_def_ext, pad=EODRFilename.pad, delimiter=EODRFilename.delimiter, convert=convert, compact=compact)
@property def stime(self): """ Start time. Returns ------- datetime.datetime Start time. """ try: if "-" not in self['dt_1']: return self.decode_datetime(self['dt_1']) else: return None except TypeError: return None @property def etime(self): """" End time. Returns ------- datetime.datetime End time. """ try: if "-" not in self['dt_2']: return self.decode_datetime(self['dt_2']) else: return None except TypeError: return None
[docs] def decode_datetime(self, string): """ Decodes a string into a datetime object. The format is given by the class. Parameters ---------- string: str, object String needed to be decoded to a datetime object. Returns ------- datetime.datetime, object Original object or datetime object parsed from the given string. """ if isinstance(string, str): return datetime.strptime(string, self.dt_format) else: return string
[docs] def encode_datetime(self, time_obj): """ Encodes a datetime object into a string. The format is given by the class. Parameters ---------- time_obj: datetime.datetime, object Datetime object needed to be encoded to a string. Returns ------- str, object Original object or str object parsed from the given datetime object. """ if isinstance(time_obj, datetime): return time_obj.strftime(self.dt_format) else: return time_obj
[docs] def decode_counter(self, string): """ Decodes a string into an integer. Parameters ---------- string: str, object String needed to be decoded to an integer. Returns ------- int, object Original object or integer object parsed from the given string. """ if isinstance(string, str): return int(string) else: return string
[docs] def encode_counter(self, file_counter): """ Encodes a file counter into a string. Parameters ---------- file_counter: int Integer needed to be encoded to a string. Returns ------- str, object Original object or str object parsed from the given integer. """ if isinstance(file_counter, int): return "{:05d}".format(file_counter) else: return file_counter
if __name__ == '__main__': pass