def test_riomucho_simple(): with riomucho.RioMucho(['/tmp/test_1.tif'], '/tmp/test_xyz_out.tif', read_function_simple) as rm: rm.run(1) with rasterio.open('/tmp/test_xyz_out.tif') as outputsrc: assert numpy.sum(outputsrc.read(1)[:10, :10] != 0) == 0
def test_riomucho_simple_fail(tmpdir): """Invalid source file fails normally""" with pytest.raises(RasterioIOError): with riomucho.RioMucho( ["test_999.tif"], str(tmpdir.join("test_xyz_out.tif")), read_function_simple ) as rm: rm.run(1)
def test_riomucho_simple(tmpdir, test_1_tif): """Distribution of a simple user function works""" with riomucho.RioMucho( [str(test_1_tif)], str(tmpdir.join("test_xyz_out.tif")), read_function_simple ) as rm: rm.run(1) with rasterio.open(str(tmpdir.join("test_xyz_out.tif"))) as outputsrc: assert numpy.sum(outputsrc.read(1)[:10, :10] != 0) == 0
def test_riomucho_readmode_fail(): with pytest.raises(ValueError): with riomucho.RioMucho([ '/tmp/test_1.tif', ], '/tmp/test_xyz_out.tif', read_function_arrayread, mode='mucho_gusto') as rm: rm.run(4)
def atmos( ctx, atmo, contrast, bias, jobs, out_dtype, src_path, dst_path, creation_options, as_color, ): """Atmospheric correction """ if as_color: click.echo("rio color {} {} {}".format( src_path, dst_path, simple_atmo_opstring(atmo, contrast, bias))) exit(0) with rasterio.open(src_path) as src: opts = src.profile.copy() windows = [(window, ij) for ij, window in src.block_windows()] opts.update(**creation_options) opts["transform"] = guard_transform(opts["transform"]) out_dtype = out_dtype if out_dtype else opts["dtype"] opts["dtype"] = out_dtype args = { "atmo": atmo, "contrast": contrast, "bias": bias, "out_dtype": out_dtype } jobs = check_jobs(jobs) if jobs > 1: with riomucho.RioMucho( [src_path], dst_path, atmos_worker, windows=windows, options=opts, global_args=args, mode="manual_read", ) as mucho: mucho.run(jobs) else: with rasterio.open(dst_path, "w", **opts) as dest: with rasterio.open(src_path) as src: rasters = [src] for window, ij in windows: arr = atmos_worker(rasters, window, ij, args) dest.write(arr, window=window)
def test_riomucho_readmode_fail(tmpdir, test_1_tif): """Invalid mode fails with ValueError""" with pytest.raises(ValueError): with riomucho.RioMucho( [str(test_1_tif)], str(tmpdir.join("test_xyz_out.tif")), read_function_arrayread, mode="mucho_gusto", ) as rm: rm.run(4)
def test_riomucho_simple_dataset_object(tmpdir, test_1_tif): """We can pass an open dataset for output""" with rasterio.open(str(test_1_tif)) as src: options = src.profile with rasterio.open(str(tmpdir.join("output.tif")), "w", **options) as dst: with riomucho.RioMucho([str(test_1_tif)], dst, read_function_simple) as rm: rm.run(1) with rasterio.open(str(tmpdir.join("output.tif"))) as outputsrc: assert numpy.sum(outputsrc.read(1)[:10, :10] != 0) == 0
def calculate_landsat_reflectance(src_path, src_mtl, dst_path, creation_options, band, dst_dtype, processes): """ Parameters ------------ src_path: string src_mtl: string Returns --------- out: None Output is written to dst_path """ mtl = toa_utils._load_mtl(src_mtl) M = toa_utils._load_mtl_key(mtl, [ 'L1_METADATA_FILE', 'RADIOMETRIC_RESCALING', 'REFLECTANCE_MULT_BAND_' ], band) A = toa_utils._load_mtl_key( mtl, ['L1_METADATA_FILE', 'RADIOMETRIC_RESCALING', 'REFLECTANCE_ADD_BAND_'], band) E = toa_utils._load_mtl_key( mtl, ['L1_METADATA_FILE', 'IMAGE_ATTRIBUTES', 'SUN_ELEVATION']) dst_dtype = np.__dict__[dst_dtype] with rio.open(src_path) as src: dst_profile = src.profile.copy() src_nodata = src.nodata for co in creation_options: dst_profile[co] = creation_options[co] dst_profile['dtype'] = dst_dtype global_args = { 'A': A, 'M': M, 'E': E, 'src_nodata': 0, 'dst_dtype': dst_dtype } with riomucho.RioMucho([src_path], dst_path, _reflectance_worker, options=dst_profile, global_args=global_args) as rm: rm.run(processes)
def blob_nodata(src_path, dst_path, bidx, max_search_distance, nibblemask, creation_options, maskThreshold, workers, alphafy): with rio.open(src_path) as src: windows = [[window, ij] for ij, window in src.block_windows()] options = src.meta.copy() kwds = src.profile.copy() outNodata, selectNodata, outCount = test_rgb(src.count, src.nodata, alphafy, 4) options.update(**kwds) # Update withcreation options like 'compress': 'lzw'. options.update(**creation_options) options.update(count=outCount, nodata=outNodata) if bidx: try: bidx = [int(b) for b in json.loads(bidx)] except Exception as e: raise e if bidx and (len(bidx) == 0 or len(bidx) > src.count): raise ValueError("Bands %s differ from source count of %s" % (', '.join([str(b) for b in bidx]), src.count)) elif alphafy and src.count == 3: bidx = list(src.indexes) bidx.append(src.indexes[-1] + 1) else: bidx = list(src.indexes) if maskThreshold != None: maskThreshold = np.iinfo(options['dtype']).max - maskThreshold with riomucho.RioMucho( [src_path], dst_path, blob_worker, windows=windows, global_args={ 'max_search_distance': max_search_distance, 'nibblemask': nibblemask, 'bands': bidx, 'maskThreshold': maskThreshold, 'selectNodata': selectNodata }, options=options, mode='manual_read') as rm: rm.run(workers)
def runRioMuchoArrayRead(): with rasterio.open('/tmp/test_1.tif') as src: options = src.meta options.update(count=2) with riomucho.RioMucho(['/tmp/test_1.tif', '/tmp/test_2.tif'], '/tmp/test_xyz_out.tif', read_function_arrayread, mode='array_read', options=options) as rm: rm.run(4) return True
def preprocess(file1, file2, output, ratio): processes = 4 g = {"dtype": np.uint16, "weights": list(map(float, ratio.split(":")))} with rio.open(file1) as src: windows = [[window, ij] for ij, window in src.block_windows()] options = src.profile options.update({"count": 1, "compress": "lzw"}) with riomucho.RioMucho( [file1, file2], output, weight, windows=windows, global_args=g, options=options ) as mucho: mucho.run(processes)
def runRioMuchoManual(): with rasterio.open('/tmp/test_1.tif') as src: windows = [[window, ij] for ij, window in src.block_windows()] options = src.meta options.update(count=2) with riomucho.RioMucho(['/tmp/test_1.tif', '/tmp/test_2.tif'], '/tmp/test_xyz_out.tif', read_function_manual, windows=windows, global_args={}, options=options, mode='manual_read') as rm: rm.run(4) return True
def test_pool_worker_traceback_capture(tmpdir, test_1_tif, test_2_tif): """Worker tracebacks are captured""" with rasterio.open(str(test_1_tif)) as src: options = src.profile options.update(count=2) with riomucho.RioMucho( [str(test_1_tif), str(test_2_tif)], str(tmpdir.join("output.tif")), fail, mode="array_read", options=options, ) as rm: with pytest.raises(riomucho.MuchoChildError) as excinfo: rm.run(4) assert "ZeroDivisionError" in str(excinfo.value)
def test_riomucho_arrayread(): with rasterio.open('/tmp/test_1.tif') as src: options = src.profile options.update(count=2) with riomucho.RioMucho(['/tmp/test_1.tif', '/tmp/test_2.tif'], '/tmp/test_xyz_out.tif', read_function_arrayread, mode='array_read', options=options) as rm: rm.run(4) with rasterio.open('/tmp/test_1.tif') as inputsrc1: with rasterio.open('/tmp/test_2.tif') as inputsrc2: with rasterio.open('/tmp/test_xyz_out.tif') as outputsrc: assert inputsrc1.checksum(1) == outputsrc.checksum(1) assert inputsrc2.checksum(1) == outputsrc.checksum(2)
def color(jobs, out_dtype, src_path, dst_path, operations, creation_options): with rasterio.open(src_path) as src: opts = src.profile.copy() windows = [(window, ij) for ij, window in src.block_windows()] opts.update(**creation_options) opts["transform"] = guard_transform(opts["transform"]) out_dtype = out_dtype if out_dtype else opts["dtype"] opts["dtype"] = out_dtype args = {"ops_string": " ".join(operations), "out_dtype": out_dtype} # Just run this for validation this time # parsing will be run again within the worker # where its returned value will be used try: parse_operations(args["ops_string"]) except ValueError as e: import sys sys.exit(1) print(e) jobs = check_jobs(jobs) if jobs > 1: with riomucho.RioMucho( [src_path], dst_path, color_worker, windows=windows, options=opts, global_args=args, mode="manual_read", ) as mucho: mucho.run(jobs) else: with rasterio.open(dst_path, "w", **opts) as dest: with rasterio.open(src_path) as src: rasters = [src] for window, ij in windows: arr = color_worker(rasters, window, ij, args) dest.write(arr, window=window) dest.colorinterp = src.colorinterp
def add_alpha(src_path, dst_path, ndv, creation_options, processes): """ Parameters ------------ src_paths: list of strings dst_path: string ndv: list a list of floats where the length of the list = band count creation_options: dict processes: integer Returns --------- None Output is written to dst_path """ with rasterio.open(src_path) as src: dst_profile = src.profile dst_profile.update(**creation_options) dst_profile.pop("photometric", None) dst_profile.update(count=4, nodata=None) global_args = { "src_nodata": 0, "dst_dtype": dst_profile["dtype"], "ndv": ndv } with riomucho.RioMucho( [src_path], dst_path, _alpha_worker, options=dst_profile, global_args=global_args, mode="manual_read", ) as rm: rm.run(processes)
def test_riomucho_manual(): with rasterio.open('/tmp/test_1.tif') as src: windows = [[window, ij] for ij, window in src.block_windows()] options = src.meta options.update(count=2) with riomucho.RioMucho(['/tmp/test_1.tif', '/tmp/test_2.tif'], '/tmp/test_xyz_out.tif', read_function_manual, windows=windows, global_args={}, options=options, mode='manual_read') as rm: rm.run(4) with rasterio.open('/tmp/test_1.tif') as inputsrc: with rasterio.open('/tmp/test_xyz_out.tif') as outputsrc: assert inputsrc.checksum(1) == outputsrc.checksum(1)
def test_riomucho_arrayread(tmpdir, test_1_tif, test_2_tif): """Distribution of an array reading user function works""" with rasterio.open(str(test_1_tif)) as src: options = src.profile options.update(count=2) with riomucho.RioMucho( [str(test_1_tif), str(test_2_tif)], str(tmpdir.join("test_xyz_out.tif")), read_function_arrayread, mode="array_read", options=options, ) as rm: rm.run(4) with rasterio.open(str(test_1_tif)) as inumpyutsrc1: with rasterio.open(str(test_2_tif)) as inumpyutsrc2: with rasterio.open(str(tmpdir.join("test_xyz_out.tif"))) as outputsrc: assert inumpyutsrc1.checksum(1) == outputsrc.checksum(1) assert inumpyutsrc2.checksum(1) == outputsrc.checksum(2)
def test_riomucho_manual(tmpdir, test_1_tif, test_2_tif): """Distribution of a manual read user function succeeds""" with rasterio.open(str(test_1_tif)) as src: windows = [[window, ij] for ij, window in src.block_windows()] options = src.meta options.update(count=2) with riomucho.RioMucho( [str(test_1_tif), str(test_2_tif)], str(tmpdir.join("test_xyz_out.tif")), read_function_manual, windows=windows, global_args={}, options=options, mode="manual_read", ) as rm: rm.run(4) with rasterio.open(str(test_1_tif)) as inumpyutsrc: with rasterio.open(str(tmpdir.join("test_xyz_out.tif"))) as outputsrc: assert inumpyutsrc.checksum(1) == outputsrc.checksum(1)
def main(fn): # get windows from an input with rasterio.open(fn) as src: # grabbing the windows as an example. Default behavior is identical. windows = [[window, ij] for ij, window in src.block_windows()] options = src.meta # since we are only writing to 2 bands options.update(count=8, dtype=rasterio.float64) global_args = {'divide': 2} processes = 4 # run it with riomucho.RioMucho([fn], fn.replace('.tif', '.pearsonr.tif'), basic_run, windows=windows, global_args=global_args, options=options) as rm: rm.run(processes)
def apply_srem(input_raster_file: str, metadata_file: str, angle_file: str, output_raster_file: str) -> None: out_dir = os.path.join(os.path.dirname(output_raster_file)) os.makedirs(out_dir, exist_ok=True) band_id = utils.get_band_id(input_raster_file) wavelength = OLI_WAVELENGTHS[band_id] with tempfile.TemporaryDirectory() as tmp_dir: toa_file = os.path.join(tmp_dir, 'toa.tif') reflectance.calculate_landsat_reflectance( [input_raster_file], metadata_file, toa_file, rescale_factor=1.0, creation_options={}, bands=[band_id], dst_dtype='float32', processes=1, pixel_sunangle=True, clip=True) solar_angle_file, sensor_angle_file = \ utils.get_pixel_angle_files(angle_file, band_id, tmp_dir) with rasterio.open(input_raster_file) as src: options = src.profile options.update(nodata=0) with riomucho.RioMucho( [toa_file, solar_angle_file, sensor_angle_file], output_raster_file, utils.srem_worker, mode='array_read', global_args={ 'wavelength': wavelength, 'dtype': options['dtype']}, options=options) as rios: rios.run(4)
def calculate_landsat_pansharpen(src_paths, dst_path, dst_dtype, weight, verbosity, jobs, half_window, customwindow): """Parameters ------------ src_paths: list of string (pan_path, r_path, g_path, b_path) dst_path: string dst_dtype: 'uint16', 'uint8'. [Default] 'uint8' weight: float jobs: integer half_window: True/False. [Default] False customwindow: integer. [Default] 0 Returns --------- out: None Output is written to dst_path """ with rasterio.open(src_paths[0]) as pan_src: windows = _calc_windows(pan_src, customwindow) profile = pan_src.profile if profile['count'] > 1: raise RuntimeError( "Pan band must be 1 band - is {}".format(profile['count'])) dst_dtype = np.__dict__[dst_dtype] profile.update( transform=guard_transform(pan_src.transform), compress='DEFLATE', blockxsize=512, blockysize=512, dtype=dst_dtype, tiled=True, count=4, photometric='rgb') with rasterio.open(src_paths[1]) as r_src: r_meta = r_src.meta if profile['width'] <= r_meta['width'] or \ profile['height'] <= r_meta['height']: raise RuntimeError( "Pan band must be larger than RGB bands") _check_crs([r_meta, profile]) g_args = { "verb": verbosity, "half_window": half_window, "dst_dtype": dst_dtype, "weight": weight, "dst_aff": guard_transform(profile['transform']), "dst_crs": profile['crs'], "r_aff": guard_transform(r_meta['transform']), "r_crs": r_meta['crs'], "src_nodata": 0} with riomucho.RioMucho(src_paths, dst_path, _pansharpen_worker, windows=windows, global_args=g_args, options=profile, mode='manual_read') as rm: rm.run(jobs)
"""Simple reading pattern example""" import riomucho import numpy def read_function(data, window, ij, g_args): """Takes an array, and sets any value above the mean to the max, the rest to 0""" output = (data[0] > numpy.mean(data[0])).astype( data[0].dtype) * data[0].max() return output # Open w/ simple read mode, and work in parallel. with riomucho.RioMucho(["/tmp/test_1.tif"], "/tmp/test_z_out.tif", read_function, global_args={}) as rm: rm.run(4)
import riomucho import numpy # example simple read ### basic function ## takes an array, and sets any value above the mean to the max, the rest to 0 def read_function(data, window, ij, g_args): output = (data[0] > numpy.mean(data[0])).astype(data[0].dtype) * data[0].max() return output ## open w/ simple read mode, and work in parallel with riomucho.RioMucho( ['/tmp/test_1.tif'], '/tmp/test_z_out.tif', read_function, global_args={}) as rm: rm.run(4)
def calculate_landsat_reflectance(src_paths, src_mtl, dst_path, rescale_factor, creation_options, bands, dst_dtype, processes, pixel_sunangle, clip=True): """ Parameters ------------ src_paths: list of strings src_mtl: string dst_path: string rescale_factor: float creation_options: dict bands: list dst_dtype: string processes: integer pixel_sunangle: boolean clip: boolean Returns --------- None Output is written to dst_path """ mtl = toa_utils._load_mtl(src_mtl) metadata = mtl['L1_METADATA_FILE'] M = [metadata['RADIOMETRIC_RESCALING'] ['REFLECTANCE_MULT_BAND_{}'.format(b)] for b in bands] A = [metadata['RADIOMETRIC_RESCALING'] ['REFLECTANCE_ADD_BAND_{}'.format(b)] for b in bands] E = metadata['IMAGE_ATTRIBUTES']['SUN_ELEVATION'] date_collected = metadata['PRODUCT_METADATA']['DATE_ACQUIRED'] time_collected_utc = metadata['PRODUCT_METADATA']['SCENE_CENTER_TIME'] rescale_factor = toa_utils.normalize_scale(rescale_factor, dst_dtype) dst_dtype = np.__dict__[dst_dtype] for src_path in src_paths: with rasterio.open(src_path) as src: dst_profile = src.profile.copy() src_nodata = src.nodata for co in creation_options: dst_profile[co] = creation_options[co] dst_profile['dtype'] = dst_dtype global_args = { 'A': A, 'M': M, 'E': E, 'src_nodata': src_nodata, 'src_crs': dst_profile['crs'], 'dst_dtype': dst_dtype, 'rescale_factor': rescale_factor, 'clip': clip, 'pixel_sunangle': pixel_sunangle, 'date_collected': date_collected, 'time_collected_utc': time_collected_utc, 'bands': len(bands) } dst_profile.update(count=len(bands)) if len(bands) == 3: dst_profile.update(photometric='rgb') else: dst_profile.update(photometric='minisblack') with riomucho.RioMucho(list(src_paths), dst_path, _reflectance_worker, options=dst_profile, global_args=global_args, mode='manual_read') as rm: rm.run(processes)
def calculate_landsat_pansharpen(src_paths, dst_path, dst_dtype, weight, verbosity, jobs, half_window, customwindow, out_alpha, creation_opts): """Parameters ------------ src_paths: list of string (pan_path, r_path, g_path, b_path) dst_path: string dst_dtype: 'uint16', 'uint8'. weight: float jobs: integer half_window: boolean customwindow: integer out_alpha: boolean output an alpha band? creation_opts: dict creation options to update the write profile Returns --------- out: None Output is written to dst_path """ with rasterio.open(src_paths[0]) as pan_src: windows = _calc_windows(pan_src, customwindow) profile = pan_src.profile if profile['count'] > 1: raise RuntimeError("Pan band must be 1 band - is {}".format( profile['count'])) dst_dtype = np.__dict__[dst_dtype] profile.update(transform=guard_transform(pan_src.transform), dtype=dst_dtype, count=3, photometric='rgb') if out_alpha: profile['count'] = 4 if creation_opts: profile.update(**creation_opts) with rasterio.open(src_paths[1]) as r_src: r_meta = r_src.meta if profile['width'] <= r_meta['width'] or \ profile['height'] <= r_meta['height']: raise RuntimeError("Pan band must be larger than RGB bands") _check_crs([r_meta, profile]) g_args = { "verb": verbosity, "half_window": half_window, "dst_dtype": dst_dtype, "out_alpha": out_alpha, "weight": weight, "dst_aff": guard_transform(profile['transform']), "dst_crs": profile['crs'], "r_aff": guard_transform(r_meta['transform']), "r_crs": r_meta['crs'], "src_nodata": 0 } with riomucho.RioMucho(src_paths, dst_path, _pansharpen_worker, windows=windows, global_args=g_args, options=profile, mode='manual_read') as rm: rm.run(jobs)
############################################################################### if __name__ == '__main__': import sys import numpy as np import pandas as pd import rasterio as rio import riomucho # -- I'm thinking it might be able to work as such... # is the windows argument made to select out only certain windows for processing? # I am hoping to pass the 2 rasters as inputs and then to minimize memory when # processing, split both inputs into windows that will cycle through the # rasters, will probably need to overlap by 1 cell both vertically and horizontally # as they work through the raster. processes = # this should be equal to the number of cores that I want to use?? with riomucho.RioMucho([sys.argv[1], sys.argv[2]], sys.argv[3], main, windows={windows}, # do I need to specify the number of windows to use?? or the window size? global_args={global arguments}, # seems like I might be able to use to pass nodata value to options={options to write}) as rios: rios.run({processes})
# get windows from an input with rasterio.open(file_list[0]) as src: # grabbing the windows as an example. Default behavior is identical. windows = [[window, ij] for ij, window in src.block_windows()] options = src.meta # since we are only writing to 2 bands options.update(count=8, nodata=0, dtype=np.int8) global_args = {'divide': 2} processes = 4 # run it with riomucho.RioMucho(file_list, 'ndvi_pearsonr.tif', basic_run, windows=windows, global_args=global_args, options=options) as rm: rm.run(processes) with rasterio.open('ndvi_pearsonr.tif', mode='r+') as src: for i in range(1, 9): src.write_colormap(i, colormap) sys.exit() # ------ read = { 'increasing': 3, 'decreasing': 1,
def color(ctx, jobs, out_dtype, src_path, dst_path, operations, creation_options): """Color correction Operations will be applied to the src image in the specified order. Available OPERATIONS include: \b "gamma BANDS VALUE" Applies a gamma curve, brightening or darkening midtones. VALUE > 1 brightens the image. \b "sigmoidal BANDS CONTRAST BIAS" Adjusts the contrast and brightness of midtones. BIAS > 0.5 darkens the image. \b "saturation PROPORTION" Controls the saturation in LCH color space. PROPORTION = 0 results in a grayscale image PROPORTION = 1 results in an identical image PROPORTION = 2 is likely way too saturated BANDS are specified as a single arg, no delimiters \b `123` or `RGB` or `rgb` are all equivalent Example: \b rio color -d uint8 -j 4 input.tif output.tif \\ gamma 3 0.95, sigmoidal rgb 35 0.13 """ with rasterio.open(src_path) as src: opts = src.profile.copy() windows = [(window, ij) for ij, window in src.block_windows()] opts.update(**creation_options) opts["transform"] = guard_transform(opts["transform"]) out_dtype = out_dtype if out_dtype else opts["dtype"] opts["dtype"] = out_dtype args = {"ops_string": " ".join(operations), "out_dtype": out_dtype} # Just run this for validation this time # parsing will be run again within the worker # where its returned value will be used try: parse_operations(args["ops_string"]) except ValueError as e: raise click.UsageError(str(e)) jobs = check_jobs(jobs) if jobs > 1: with riomucho.RioMucho( [src_path], dst_path, color_worker, windows=windows, options=opts, global_args=args, mode="manual_read", ) as mucho: mucho.run(jobs) else: with rasterio.open(dst_path, "w", **opts) as dest: with rasterio.open(src_path) as src: rasters = [src] for window, ij in windows: arr = color_worker(rasters, window, ij, args) dest.write(arr, window=window) dest.colorinterp = src.colorinterp
def calculate_landsat_brightness_temperature(src_path, src_mtl, dst_path, temp_scale, creation_options, band, dst_dtype, processes): """Parameters ------------ src_path: list list of src_paths(strings) src_mtl: string mtl file path dst_path: string destination file path rescale_factor: float [default] float(55000.0/2**16) rescale post-TOA tifs to 55,000 or to full 16-bit creation_options: dictionary rio.options.creation_options band: list list of integers dst_dtype: strings [default] uint16 destination data dtype Returns --------- out: None Output is written to dst_path """ mtl = toa_utils._load_mtl(src_mtl) M = toa_utils._load_mtl_key( mtl, ['L1_METADATA_FILE', 'RADIOMETRIC_RESCALING', 'RADIANCE_MULT_BAND_'], band) A = toa_utils._load_mtl_key( mtl, ['L1_METADATA_FILE', 'RADIOMETRIC_RESCALING', 'RADIANCE_ADD_BAND_'], band) K1 = toa_utils._load_mtl_key( mtl, ['L1_METADATA_FILE', 'TIRS_THERMAL_CONSTANTS', 'K1_CONSTANT_BAND_'], band) K2 = toa_utils._load_mtl_key( mtl, ['L1_METADATA_FILE', 'TIRS_THERMAL_CONSTANTS', 'K2_CONSTANT_BAND_'], band) dst_dtype = np.__dict__[dst_dtype] with rio.open(src_path) as src: dst_profile = src.profile.copy() src_nodata = src.nodata for co in creation_options: dst_profile[co] = creation_options[co] dst_profile['dtype'] = dst_dtype global_args = { 'M': M, 'A': A, 'K1': K1, 'K2': K2, 'src_nodata': 0, 'temp_scale': temp_scale, 'dst_dtype': dst_dtype } with riomucho.RioMucho([src_path], dst_path, _brightness_temp_worker, options=dst_profile, global_args=global_args) as rm: rm.run(processes)