def read_color_file(self, color_filename_or_lines: Optional[Union[PathLikeOrStr, 'ColorPalette', Sequence]]): if isinstance(color_filename_or_lines, ColorPalette): return self elif color_filename_or_lines is None: self.pal.clear() return self elif base.is_path_like(color_filename_or_lines): color_filename_or_lines = open(color_filename_or_lines).readlines() elif not isinstance(color_filename_or_lines, Sequence): raise Exception('unknown input {}'.format(color_filename_or_lines)) self.pal.clear() for line in color_filename_or_lines: split_line = line.strip().split(' ', 1) if len(split_line) < 2: continue try: color = self.pal_color_to_rgb(split_line[1]) key = split_line[0].strip() except: raise Exception('Error reading palette line: {}'.format(line)) try: key = base.num(key) except ValueError: # should be percent self._all_numeric = False pass self.pal[key] = color
def __init__(self, filename_or_ds: PathOrDS, silent_fail=False, *args, **kwargs): self.ds: Optional[gdal.Dataset] = None self.filename: Optional[PathLikeOrStr] = None if is_path_like(filename_or_ds): self.filename = os.fspath(filename_or_ds) else: self.ds = filename_or_ds self.args = args self.kwargs = kwargs self.own = False self.silent_fail = silent_fail
def test_utils_py_0(): for b in (False, 'False', 'OfF', 'no'): assert not base.is_true(b) for b in (True, 'TruE', 'ON', 'yes'): assert base.is_true(b) assert base.enum_to_str(Extent.UNION) == 'UNION' assert base.enum_to_str('UNION') == 'UNION' filename = Path('abc') / Path('def') / Path('a.txt') assert base.is_path_like(Path(filename)) assert base.is_path_like(str(filename)) assert not base.is_path_like(None) assert not base.is_path_like([filename]) assert base.get_suffix(filename) == '.txt' assert base.get_extension(filename) == 'txt' for idx, b in enumerate((0x23, 0xc1, 0xab, 0x00)): byte = base.get_byte(0xab_c1_23, idx) assert byte == b assert base.path_join(filename, 'a', 'b') == str(filename / 'a' / 'b') assert base.num(42) == 42 assert base.num('42') == 42 assert isinstance(base.num('42'), int) assert base.num(42.0) == 42.0 assert base.num('42.0') == 42.0 assert isinstance(base.num('42.0'), float) assert base.num('42.') == 42.0 assert isinstance(base.num('42.'), float) assert base.num(42.5) == 42.5 assert base.num('42.5') == 42.5 assert base.num_or_none('') is None assert base.num_or_none(None) is None assert base.num_or_none('1a') is None assert base.num_or_none('42') == 42 assert base.num_or_none('42.0') == 42.0
def read(self, filename_or_strings: Optional[ColorPaletteOrPathOrStrings]): if filename_or_strings is None: self.pal.clear() return elif isinstance(filename_or_strings, ColorPalette): self.assign(filename_or_strings) elif base.is_path_like(filename_or_strings): self.read_file(filename_or_strings) elif isinstance(filename_or_strings, Sequence): self.read_file_txt(lines=filename_or_strings) else: raise Exception('Unknown input {}'.format(filename_or_strings))
def get_file_from_strings(color_palette: ColorPaletteOrPathOrStrings): temp_color_filename = None if isinstance(color_palette, ColorPalette): temp_color_filename = tempfile.mktemp(suffix='.txt') color_filename = temp_color_filename color_palette.write_color_file(temp_color_filename) elif base.is_path_like(color_palette): color_filename = color_palette elif isinstance(color_palette, Sequence): temp_color_filename = tempfile.mktemp(suffix='.txt') color_filename = temp_color_filename with open(temp_color_filename, 'w') as f: for item in color_palette: f.write(item + '\n') else: raise Exception('Unknown color palette type {}'.format(color_palette)) return color_filename, temp_color_filename
def gdallocationinfo( filename_or_ds: PathOrDS, x: ArrayOrScalarLike, y: ArrayOrScalarLike, srs: CoordinateTransformationOrSRS = None, axis_order: Optional[OAMS_AXIS_ORDER] = None, open_options: Optional[dict] = None, ovr_idx: Optional[int] = None, band_nums: Optional[Sequence[int]] = None, inline_xy_replacement: bool = False, return_ovr_pixel_line: bool = False, transform_round_digits: Optional[float] = None, allow_xy_outside_extent: bool = True, pixel_offset: Real = -0.5, line_offset: Real = -0.5, resample_alg=gdalconst.GRIORA_NearestNeighbour, quiet_mode: bool = True, ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ds = open_ds(filename_or_ds, open_options=open_options) filename = filename_or_ds if is_path_like(filename_or_ds) else '' if ds is None: raise Exception(f'Could not open {filename}.') if not isinstance(x, ArrayLike.__args__): x = [x] if not isinstance(y, ArrayLike.__args__): y = [y] if len(x) != len(y): raise Exception( f'len(x)={len(x)} should be the same as len(y)={len(y)}') point_count = len(x) dtype = np.float64 if not isinstance(x, np.ndarray) or not isinstance(y, np.ndarray): x = np.array(x, dtype=dtype) y = np.array(y, dtype=dtype) inline_xy_replacement = True if srs is None: srs = LocationInfoSRS.PixelLine # Build Spatial Reference object based on coordinate system, fetched from the opened dataset if srs != LocationInfoSRS.PixelLine: if srs != LocationInfoSRS.SameAsDS_SRS: ds_srs = ds.GetSpatialRef() ct = None if isinstance(srs, osr.CoordinateTransformation): ct = srs else: if srs == LocationInfoSRS.SameAsDS_SRS_GeogCS: points_srs = ds_srs.CloneGeogCS() else: points_srs = get_srs(srs, axis_order=axis_order) ct = get_transform(points_srs, ds_srs) if ct is not None: if not inline_xy_replacement: x = x.copy() y = y.copy() inline_xy_replacement = True transform_points(ct, x, y) if transform_round_digits is not None: x.round(transform_round_digits, out=x) y.round(transform_round_digits, out=y) # Read geotransform matrix and calculate corresponding pixel coordinates geotransform = ds.GetGeoTransform() inv_geotransform = gdal.InvGeoTransform(geotransform) if inv_geotransform is None: raise Exception("Failed InvGeoTransform()") # can we inline this transformation ? x, y = \ (inv_geotransform[0] + inv_geotransform[1] * x + inv_geotransform[2] * y), \ (inv_geotransform[3] + inv_geotransform[4] * x + inv_geotransform[5] * y) inline_xy_replacement = True xsize, ysize = ds.RasterXSize, ds.RasterYSize bands = get_bands(ds, band_nums, ovr_idx=ovr_idx) ovr_xsize, ovr_ysize = bands[0].XSize, bands[0].YSize pixel_fact, line_fact = (ovr_xsize / xsize, ovr_ysize / ysize) if ovr_idx else (1, 1) bnd_count = len(bands) shape = (bnd_count, point_count) np_dtype, np_dtype = GDALTypeCodeAndNumericTypeCodeFromDataSet(ds) results = np.empty(shape=shape, dtype=np_dtype) check_outside = not quiet_mode or not allow_xy_outside_extent if check_outside and (np.any(x < 0) or np.any(x >= xsize) or np.any(y < 0) or np.any(y >= ysize)): msg = 'Passed coordinates are not in dataset extent!' if not allow_xy_outside_extent: raise Exception(msg) elif not quiet_mode: print(msg) if pixel_fact == 1: pixels_q = x elif return_ovr_pixel_line: x *= pixel_fact pixels_q = x else: pixels_q = x * pixel_fact if line_fact == 1: lines_q = y elif return_ovr_pixel_line: y *= line_fact lines_q = y else: lines_q = y * line_fact buf_xsize = buf_ysize = 1 buf_type, typecode = GDALTypeCodeAndNumericTypeCodeFromDataSet(ds) buf_obj = np.empty([buf_ysize, buf_xsize], dtype=typecode) for idx, (pixel, line) in enumerate(zip(pixels_q, lines_q)): for bnd_idx, band in enumerate(bands): if BandRasterIONumPy(band, 0, pixel - 0.5, line - 0.5, 1, 1, buf_obj, buf_type, resample_alg, None, None) == 0: results[bnd_idx][idx] = buf_obj[0][0] is_scaled, scales, offsets = get_scales_and_offsets(bands) if is_scaled: for bnd_idx, (scale, offset) in enumerate(zip(scales, offsets)): results[bnd_idx] = results[bnd_idx] * scale + offset return x, y, results
def Calc(calc: MaybeSequence[str], outfile: Optional[PathLikeOrStr] = None, NoDataValue: Optional[Number] = None, type: Optional[Union[GDALDataType, str]] = None, format: Optional[str] = None, creation_options: Optional[Sequence[str]] = None, allBands: str = '', overwrite: bool = False, hideNoData: bool = False, projectionCheck: bool = False, color_table: Optional[ColorTableLike] = None, extent: Optional[Extent] = None, projwin: Optional[Union[Tuple, GeoRectangle]] = None, user_namespace: Optional[Dict]=None, debug: bool = False, quiet: bool = False, **input_files): if debug: print(f"gdal_calc.py starting calculation {calc}") # Single calc value compatibility if isinstance(calc, (list, tuple)): calc = calc else: calc = [calc] calc = [c.strip('"') for c in calc] creation_options = creation_options or [] # set up global namespace for eval with all functions of gdal_array, numpy global_namespace = {key: getattr(module, key) for module in [gdal_array, numpy] for key in dir(module) if not key.startswith('__')} if user_namespace: global_namespace.update(user_namespace) if not calc: raise Exception("No calculation provided.") elif not outfile and format.upper() != 'MEM': raise Exception("No output file provided.") if format is None: format = GetOutputDriverFor(outfile) if isinstance(extent, GeoRectangle): pass elif projwin: if isinstance(projwin, GeoRectangle): extent = projwin else: extent = GeoRectangle.from_lurd(*projwin) elif not extent: extent = Extent.IGNORE else: extent = extent_util.parse_extent(extent) compatible_gt_eps = 0.000001 gt_diff_support = { GT.INCOMPATIBLE_OFFSET: extent != Extent.FAIL, GT.INCOMPATIBLE_PIXEL_SIZE: False, GT.INCOMPATIBLE_ROTATION: False, GT.NON_ZERO_ROTATION: False, } gt_diff_error = { GT.INCOMPATIBLE_OFFSET: 'different offset', GT.INCOMPATIBLE_PIXEL_SIZE: 'different pixel size', GT.INCOMPATIBLE_ROTATION: 'different rotation', GT.NON_ZERO_ROTATION: 'non zero rotation', } ################################################################ # fetch details of input layers ################################################################ # set up some lists to store data for each band myFileNames = [] # input filenames myFiles = [] # input DataSets myBands = [] # input bands myAlphaList = [] # input alpha letter that represents each input file myDataType = [] # string representation of the datatype of each input file myDataTypeNum = [] # datatype of each input file myNDV = [] # nodatavalue for each input file DimensionsCheck = None # dimensions of the output Dimensions = [] # Dimensions of input files ProjectionCheck = None # projection of the output GeoTransformCheck = None # GeoTransform of the output GeoTransforms = [] # GeoTransform of each input file GeoTransformDiffer = False # True if we have inputs with different GeoTransforms myTempFileNames = [] # vrt filename from each input file myAlphaFileLists = [] # list of the Alphas which holds a list of inputs # loop through input files - checking dimensions for alphas, filenames in input_files.items(): if isinstance(filenames, (list, tuple)): # alpha is a list of files myAlphaFileLists.append(alphas) elif is_path_like(filenames) or isinstance(filenames, gdal.Dataset): # alpha is a single filename or a Dataset filenames = [filenames] alphas = [alphas] else: # I guess this alphas should be in the global_namespace, # It would have been better to pass it as user_namepsace, but I'll accept it anyway global_namespace[alphas] = filenames continue for alpha, filename in zip(alphas * len(filenames), filenames): if not alpha.endswith("_band"): # check if we have asked for a specific band... alpha_band = f"{alpha}_band" if alpha_band in input_files: myBand = input_files[alpha_band] else: myBand = 1 myF_is_ds = not is_path_like(filename) if myF_is_ds: myFile = filename filename = None else: myFile = open_ds(filename, gdal.GA_ReadOnly) if not myFile: raise IOError(f"No such file or directory: '{filename}'") myFileNames.append(filename) myFiles.append(myFile) myBands.append(myBand) myAlphaList.append(alpha) dt = myFile.GetRasterBand(myBand).DataType myDataType.append(gdal.GetDataTypeName(dt)) myDataTypeNum.append(dt) myNDV.append(None if hideNoData else myFile.GetRasterBand(myBand).GetNoDataValue()) # check that the dimensions of each layer are the same myFileDimensions = [myFile.RasterXSize, myFile.RasterYSize] if DimensionsCheck: if DimensionsCheck != myFileDimensions: GeoTransformDiffer = True if extent in [Extent.IGNORE, Extent.FAIL]: raise Exception( f"Error! Dimensions of file {filename} ({myFileDimensions[0]:d}, " f"{myFileDimensions[1]:d}) are different from other files " f"({DimensionsCheck[0]:d}, {DimensionsCheck[1]:d}). Cannot proceed") else: DimensionsCheck = myFileDimensions # check that the Projection of each layer are the same myProjection = myFile.GetProjection() if ProjectionCheck: if projectionCheck and ProjectionCheck != myProjection: raise Exception( f"Error! Projection of file {filename} {myProjection} " f"are different from other files {ProjectionCheck}. Cannot proceed") else: ProjectionCheck = myProjection # check that the GeoTransforms of each layer are the same myFileGeoTransform = myFile.GetGeoTransform(can_return_null=True) if extent == Extent.IGNORE: GeoTransformCheck = myFileGeoTransform else: Dimensions.append(myFileDimensions) GeoTransforms.append(myFileGeoTransform) if not GeoTransformCheck: GeoTransformCheck = myFileGeoTransform else: my_gt_diff = extent_util.gt_diff(GeoTransformCheck, myFileGeoTransform, eps=compatible_gt_eps, diff_support=gt_diff_support) if my_gt_diff not in [GT.SAME, GT.ALMOST_SAME]: GeoTransformDiffer = True if my_gt_diff != GT.COMPATIBLE_DIFF: raise Exception( f"Error! GeoTransform of file {filename} {myFileGeoTransform} is incompatible " f"({gt_diff_error[my_gt_diff]}), first file GeoTransform is {GeoTransformCheck}. " f"Cannot proceed") if debug: print( f"file {alpha}: {filename}, dimensions: " f"{DimensionsCheck[0]}, {DimensionsCheck[1]}, type: {myDataType[-1]}") # process allBands option allBandsIndex = None allBandsCount = 1 if allBands: if len(calc) > 1: raise Exception("Error! --allBands implies a single --calc") try: allBandsIndex = myAlphaList.index(allBands) except ValueError: raise Exception(f"Error! allBands option was given but Band {allBands} not found. Cannot proceed") allBandsCount = myFiles[allBandsIndex].RasterCount if allBandsCount <= 1: allBandsIndex = None else: allBandsCount = len(calc) if extent not in [Extent.IGNORE, Extent.FAIL] and ( GeoTransformDiffer or isinstance(extent, GeoRectangle)): # mixing different GeoTransforms/Extents GeoTransformCheck, DimensionsCheck, ExtentCheck = extent_util.calc_geotransform_and_dimensions( GeoTransforms, Dimensions, extent) if GeoTransformCheck is None: raise Exception("Error! The requested extent is empty. Cannot proceed") for i in range(len(myFileNames)): temp_vrt_filename, temp_vrt_ds = extent_util.make_temp_vrt(myFiles[i], ExtentCheck) myTempFileNames.append(temp_vrt_filename) myFiles[i] = None # close original ds myFiles[i] = temp_vrt_ds # replace original ds with vrt_ds # update the new precise dimensions and gt from the new ds GeoTransformCheck = temp_vrt_ds.GetGeoTransform() DimensionsCheck = [temp_vrt_ds.RasterXSize, temp_vrt_ds.RasterYSize] temp_vrt_ds = None ################################################################ # set up output file ################################################################ # open output file exists if outfile and os.path.isfile(outfile) and not overwrite: if allBandsIndex is not None: raise Exception("Error! allBands option was given but Output file exists, must use --overwrite option!") if len(calc) > 1: raise Exception( "Error! multiple calc options were given but Output file exists, must use --overwrite option!") if debug: print(f"Output file {outfile} exists - filling in results into file") myOut = open_ds(outfile, gdal.GA_Update) if myOut is None: error = 'but cannot be opened for update' elif [myOut.RasterXSize, myOut.RasterYSize] != DimensionsCheck: error = 'but is the wrong size' elif ProjectionCheck and ProjectionCheck != myOut.GetProjection(): error = 'but is the wrong projection' elif GeoTransformCheck and GeoTransformCheck != myOut.GetGeoTransform(can_return_null=True): error = 'but is the wrong geotransform' else: error = None if error: raise Exception( f"Error! Output exists, {error}. Use the --overwrite option " f"to automatically overwrite the existing file") myOutB = myOut.GetRasterBand(1) myOutNDV = myOutB.GetNoDataValue() myOutType = myOutB.DataType else: if outfile: # remove existing file and regenerate if os.path.isfile(outfile): os.remove(outfile) # create a new file if debug: print(f"Generating output file {outfile}") else: outfile = '' # find data type to use if not type: # use the largest type of the input files myOutType = max(myDataTypeNum) else: myOutType = type if isinstance(myOutType, str): myOutType = gdal.GetDataTypeByName(myOutType) # create file myOutDrv = gdal.GetDriverByName(format) myOut = myOutDrv.Create( os.fspath(outfile), DimensionsCheck[0], DimensionsCheck[1], allBandsCount, myOutType, creation_options) # set output geo info based on first input layer if not GeoTransformCheck: GeoTransformCheck = myFiles[0].GetGeoTransform(can_return_null=True) if GeoTransformCheck: myOut.SetGeoTransform(GeoTransformCheck) if not ProjectionCheck: ProjectionCheck = myFiles[0].GetProjection() if ProjectionCheck: myOut.SetProjection(ProjectionCheck) if NoDataValue is None: myOutNDV = None if hideNoData else DefaultNDVLookup[ myOutType] # use the default noDataValue for this datatype elif isinstance(NoDataValue, str) and NoDataValue.lower() == 'none': myOutNDV = None # not to set any noDataValue else: myOutNDV = NoDataValue # use the given noDataValue for i in range(1, allBandsCount + 1): myOutB = myOut.GetRasterBand(i) if myOutNDV is not None: myOutB.SetNoDataValue(myOutNDV) if color_table: # set color table and color interpretation if is_path_like(color_table): color_table = get_color_table(color_table) myOutB.SetRasterColorTable(color_table) myOutB.SetRasterColorInterpretation(gdal.GCI_PaletteIndex) myOutB = None # write to band myOutTypeName = gdal.GetDataTypeName(myOutType) if debug: print(f"output file: {outfile}, dimensions: {myOut.RasterXSize}, {myOut.RasterYSize}, type: {myOutTypeName}") ################################################################ # find block size to chop grids into bite-sized chunks ################################################################ # use the block size of the first layer to read efficiently myBlockSize = myFiles[0].GetRasterBand(myBands[0]).GetBlockSize() # find total x and y blocks to be read nXBlocks = (int)((DimensionsCheck[0] + myBlockSize[0] - 1) / myBlockSize[0]) nYBlocks = (int)((DimensionsCheck[1] + myBlockSize[1] - 1) / myBlockSize[1]) myBufSize = myBlockSize[0] * myBlockSize[1] if debug: print(f"using blocksize {myBlockSize[0]} x {myBlockSize[1]}") # variables for displaying progress ProgressCt = -1 ProgressMk = -1 ProgressEnd = nXBlocks * nYBlocks * allBandsCount ################################################################ # start looping through each band in allBandsCount ################################################################ for bandNo in range(1, allBandsCount + 1): ################################################################ # start looping through blocks of data ################################################################ # store these numbers in variables that may change later nXValid = myBlockSize[0] nYValid = myBlockSize[1] # loop through X-lines for X in range(0, nXBlocks): # in case the blocks don't fit perfectly # change the block size of the final piece if X == nXBlocks - 1: nXValid = DimensionsCheck[0] - X * myBlockSize[0] # find X offset myX = X * myBlockSize[0] # reset buffer size for start of Y loop nYValid = myBlockSize[1] myBufSize = nXValid * nYValid # loop through Y lines for Y in range(0, nYBlocks): ProgressCt += 1 if 10 * ProgressCt / ProgressEnd % 10 != ProgressMk and not quiet: ProgressMk = 10 * ProgressCt / ProgressEnd % 10 from sys import version_info if version_info >= (3, 0, 0): exec('print("%d.." % (10*ProgressMk), end=" ")') else: exec('print 10*ProgressMk, "..",') # change the block size of the final piece if Y == nYBlocks - 1: nYValid = DimensionsCheck[1] - Y * myBlockSize[1] myBufSize = nXValid * nYValid # find Y offset myY = Y * myBlockSize[1] # create empty buffer to mark where nodata occurs myNDVs = None # make local namespace for calculation local_namespace = {} val_lists = defaultdict(list) # fetch data for each input layer for i, Alpha in enumerate(myAlphaList): # populate lettered arrays with values if allBandsIndex is not None and allBandsIndex == i: myBandNo = bandNo else: myBandNo = myBands[i] myval = gdal_array.BandReadAsArray(myFiles[i].GetRasterBand(myBandNo), xoff=myX, yoff=myY, win_xsize=nXValid, win_ysize=nYValid) if myval is None: raise Exception(f'Input block reading failed from filename {filename[i]}') # fill in nodata values if myNDV[i] is not None: # myNDVs is a boolean buffer. # a cell equals to 1 if there is NDV in any of the corresponding cells in input raster bands. if myNDVs is None: # this is the first band that has NDV set. we initializes myNDVs to a zero buffer # as we didn't see any NDV value yet. myNDVs = numpy.zeros(myBufSize) myNDVs.shape = (nYValid, nXValid) myNDVs = 1 * numpy.logical_or(myNDVs == 1, myval == myNDV[i]) # add an array of values for this block to the eval namespace if Alpha in myAlphaFileLists: val_lists[Alpha].append(myval) else: local_namespace[Alpha] = myval myval = None for lst in myAlphaFileLists: local_namespace[lst] = val_lists[lst] # try the calculation on the array blocks this_calc = calc[bandNo - 1 if len(calc) > 1 else 0] try: myResult = eval(this_calc, global_namespace, local_namespace) except: print(f"evaluation of calculation {this_calc} failed") raise # Propagate nodata values (set nodata cells to zero # then add nodata value to these cells). if myNDVs is not None and myOutNDV is not None: myResult = ((1 * (myNDVs == 0)) * myResult) + (myOutNDV * myNDVs) elif not isinstance(myResult, numpy.ndarray): myResult = numpy.ones((nYValid, nXValid)) * myResult # write data block to the output file myOutB = myOut.GetRasterBand(bandNo) if gdal_array.BandWriteArray(myOutB, myResult, xoff=myX, yoff=myY) != 0: raise Exception('Block writing failed') myOutB = None # write to band # remove temp files for idx, tempFile in enumerate(myTempFileNames): myFiles[idx] = None os.remove(tempFile) gdal.ErrorReset() myOut.FlushCache() if gdal.GetLastErrorMsg() != '': raise Exception('Dataset writing failed') if not quiet: print("100 - Done") return myOut
def is_supported_format(self, filename: PathLikeOrStr): if base.is_path_like(filename): ext = base.get_extension().lower() return ext in self.get_supported_extenstions() return False
def gdallocationinfo( filename_or_ds: PathOrDS, x: NumpyCompatibleArrayOrReal, y: NumpyCompatibleArrayOrReal, gis_order: bool = False, open_options: Optional[dict] = None, ovr_idx: Optional[int] = None, band_nums: Optional[Sequence[int]] = None, srs: CoordinateTransformationOrSRS = None, inline_xy_replacement: bool = True, quiet_mode: bool = True, allow_xy_outside_extent: bool = True, pixel_offset: Real = -0.5, line_offset: Real = -0.5, resample_alg=gdalconst.GRIORA_NearestNeighbour ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ds = open_ds(filename_or_ds, open_options=open_options) filename = filename_or_ds if is_path_like(filename_or_ds) else '' if ds is None: raise Exception(f'Could not open {filename}.') if not isinstance(x, NumpyCompatibleArray.__args__): x = [x] if not isinstance(y, NumpyCompatibleArray.__args__): y = [y] if len(x) != len(y): raise Exception( f'len(x)={len(x)} should be the same as len(y)={len(y)}') point_count = len(x) if not isinstance(x, np.ndarray): x = np.ndarray(x) if not isinstance(y, np.ndarray): y = np.ndarray(y) if srs is None: srs = LocationInfoSRS.PixelLine # Build Spatial Reference object based on coordinate system, fetched from the opened dataset if srs != LocationInfoSRS.PixelLine: if srs != LocationInfoSRS.SameAsDS_SRS: ds_srs = ds.GetSpatialRef() ct = None if isinstance(srs, osr.CoordinateTransformation): ct = srs else: if srs == LocationInfoSRS.SameAsDS_SRS_GeogCS: points_srs = ds_srs.CloneGeogCS() else: points_srs = get_srs(srs, gis_order=gis_order) ct = get_transform(points_srs, ds_srs) x, y, _z = transform_points(ct, x, y) # Read geotransform matrix and calculate corresponding pixel coordinates geomatrix = ds.GetGeoTransform() inv_geometrix = gdal.InvGeoTransform(geomatrix) if inv_geometrix is None: raise Exception("Failed InvGeoTransform()") x, y = \ (inv_geometrix[0] + inv_geometrix[1] * x + inv_geometrix[2] * y), \ (inv_geometrix[3] + inv_geometrix[4] * x + inv_geometrix[5] * y) xsize, ysize = ds.RasterXSize, ds.RasterYSize bands = get_bands(ds, band_nums, ovr_idx=ovr_idx) ovr_xsize, ovr_ysize = bands[0].XSize, bands[0].YSize pixel_fact, line_fact = (ovr_xsize / xsize, ovr_ysize / ysize) if ovr_idx else (1, 1) bnd_count = len(bands) shape = (bnd_count, point_count) np_dtype, np_dtype = GDALTypeCodeAndNumericTypeCodeFromDataSet(ds) results = np.empty(shape=shape, dtype=np_dtype) check_outside = not quiet_mode or not allow_xy_outside_extent if check_outside and (np.any(x < 0) or np.any(x >= xsize) or np.any(y < 0) or np.any(y >= ysize)): msg = 'Passed coordinates are not in dataset extent!' if not allow_xy_outside_extent: raise Exception(msg) elif not quiet_mode: print(msg) pixels = np.clip(x * pixel_fact + pixel_offset, 0, ovr_xsize - 1, out=x if inline_xy_replacement else None) lines = np.clip(y * line_fact + line_offset, 0, ovr_ysize - 1, out=y if inline_xy_replacement else None) for idx, (pixel, line) in enumerate(zip(pixels, lines)): for bnd_idx, band in enumerate(bands): val = band.ReadAsArray(pixel, line, 1, 1, resample_alg=resample_alg) val = val[0][0] results[bnd_idx][idx] = val is_scaled, scales, offsets = get_scales_and_offsets(bands) if is_scaled: for bnd_idx, scale, offset in enumerate(zip(scales, offsets)): results[bnd_idx] = results[bnd_idx] * scale + offset return pixels, lines, results