def main(): """ FlowFill """ # netCDF4 try: from netCDF4 import Dataset except: g.fatal( _("netCDF4 not detected. Install pip3 and " "then type at the command prompt: " '"pip3 install netCDF4".')) options, flags = gscript.parser() _input = options["input"] _np = options["np"] _threshold = options["threshold"] _h_runoff = options["h_runoff"] _h_runoff_raster = options["h_runoff_raster"] _ties = options["ties"] _ffpath = options["ffpath"] _output = options["output"] _water = options["water"] """ import os import numpy as np from netCDF4 import Dataset # GRASS from grass import script as gscript from grass.script import array as garray from grass.pygrass.modules.shortcuts import raster as r from grass.pygrass.modules.shortcuts import general as g # FOR TESTING: _input = 'DEM_MODFLOW' _np = 4 _threshold = 0.001 #_h_runoff = 1. _h_runoff = '' #_h_runoff_raster = '' _h_runoff_raster = 'DEM_MODFLOW' _ties = 'PREF' _ffpath = 'flowfill' _output = 'tmpout' _water = 'tmpout_water' """ # Check for overwrite -- should be unnecessary thanks to GRASS parser _rasters = np.array(gscript.parse_command("g.list", type="raster").keys()) if (_rasters == _output).any() or (_water == _output).any(): if gscript.overwrite() is False: g.fatal(_("output would overwrite " + _output)) # Check for proper number of processors try: _np = int(_np) except: g.fatal(_("Number of processors must be an integer.")) if _np < 3: g.fatal(_("FlowFill requires 3 or more processors.")) # Check for proper option set if _h_runoff is not "": # ????? possible ????? if _h_runoff_raster is not "": g.fatal( _('Only one of "h_runoff" and "h_runoff_raster" may be set')) elif _h_runoff_raster is "": g.fatal(_('Either "h_runoff" or "h_runoff_raster" must be set')) if _output is "" and _water is "": g.warning(_("No output is set.")) # Set up runoff options if _h_runoff_raster is not "": _runoff_bool = "Y" else: _h_runoff = float(_h_runoff) _runoff_bool = "N" # Get computational region n_columns = gscript.region()["cols"] n_rows = gscript.region()["rows"] # Output DEM as temporary file for FORTRAN temp_FlowFill_input_file = gscript.tempfile(create=False) dem = garray.array(_input, null=-999999) dem_array = np.array(dem[:]).astype(np.float32) del dem newnc = Dataset(temp_FlowFill_input_file, "w", format="NETCDF4") newnc.createDimension("x", n_columns) newnc.createDimension("y", n_rows) newnc.createVariable("value", "f4", ("y", "x")) # z newnc.variables["value"][:] = dem_array newnc.close() del newnc # r.out_gdal(input=_input, output=temp_DEM_input_file, format='netCDF', # overwrite=True) # Output runoff raster as temporary file for FORTRAN if _h_runoff_raster is not "": temp_FlowFill_runoff_file = gscript.tempfile(create=False) rr = garray.array(_h_runoff_raster, null=0.0) rr_array = np.array(rr[:]).astype(np.float32) del rr newnc = Dataset(temp_FlowFill_runoff_file, "w", format="NETCDF4") newnc.createDimension("x", n_columns) newnc.createDimension("y", n_rows) newnc.createVariable("value", "f4", ("y", "x")) # z newnc.variables["value"][:] = rr_array newnc.close() # Get the mean value for the floating-point depressions correction _h_runoff = np.mean(rr_array[dem_array != -999999]) else: _h_runoff_raster = "NoRaster" # A dummy value for the parser temp_FlowFill_runoff_file = "" # Run FlowFill temp_FlowFill_output_file = gscript.tempfile(create=False) mpirunstr = ("mpirun -np " + str(_np) + " " + _ffpath + " " + str(_h_runoff) + " " + temp_FlowFill_input_file + " " + str(n_columns) + " " + str(n_rows) + " " + str(_threshold) + " " + temp_FlowFill_output_file + " " + _runoff_bool + " " + temp_FlowFill_runoff_file + " " + _ties) print("") print("Sending command to FlowFill:") print(mpirunstr) print("") _mpirun_error_flag = False popen = subprocess.Popen(mpirunstr, stdout=subprocess.PIPE, shell=True, universal_newlines=True) for stdout_line in iter(popen.stdout.readline, ""): print(stdout_line), if "mpirun was unable to find the specified executable file" in stdout_line: _mpirun_error_flag = True popen.stdout.close() if _mpirun_error_flag: print("") g.fatal( _("FlowFill executable not found.\n" "If you have not installed FlowFill, please download it " "from https://github.com/KCallaghan/FlowFill, " "and follow the directions in the README to compile and " "install it on your system.\n" 'This should then work with the default "ffpath". ' "Otherwise, you may simply have typed in an incorrect " '"ffpath".')) # _stdout = subprocess.Popen(mpirunstr, shell=True, stdout=subprocess.PIPE) # # if 'mpirun was unable to find the specified executable file' in \ # ''.join(_stdout.stdout.readlines()): # else: # g.message('FlowFill Executable Found.') # print('') # subprocess.Popen(mpirunstr, shell=True).wait() # os.system(mpirunstr) # subprocess.Popen(mpirunstr, shell=True) # Import the output -- padded by two cells (remove these) outrast = np.fromfile(temp_FlowFill_output_file + ".dat", dtype=np.float32) outrast_water = np.fromfile(temp_FlowFill_output_file + "_water.dat", dtype=np.float32) outrast = outrast.reshape(n_rows + 2, n_columns + 2)[:-2, 1:-1] outrast_water = outrast_water.reshape(n_rows + 2, n_columns + 2)[:-2, 1:-1] # Mask to return NAN to NAN in GRASS -- FIX SHIFT ISSUE WITH KERRY dem_array_mask = dem_array.copy() dem_array_mask[dem_array_mask == -999999] = np.nan dem_array_mask = dem_array_mask * 0 + 1 outrast *= dem_array_mask outrast_water *= dem_array_mask # Save the output to GRASS GIS dem = garray.array() dem[:] = outrast dem.write(_output, overwrite=gscript.overwrite()) dem[:] = outrast_water dem.write(_water, overwrite=gscript.overwrite()) del dem
def main(): """ Main program """ # Temporary filenames # The following three are meant for a test step-by-step cwv estimation, see # unused functions! # tmp_ti_mean = tmp_map_name('ti_mean') # for cwv # tmp_tj_mean = tmp_map_name('tj_mean') # for cwv # tmp_ratio = tmp_map_name('ratio') # for cwv tmp_avg_lse = tmp_map_name('avg_lse') tmp_delta_lse = tmp_map_name('delta_lse') tmp_cwv = tmp_map_name('cwv') #tmp_lst = tmp_map_name('lst') # basic equation for mapcalc global equation, citation_lst equation = "{result} = {expression}" # user input mtl_file = options['mtl'] if not options['prefix']: b10 = options['b10'] b11 = options['b11'] t10 = options['t10'] t11 = options['t11'] if not options['clouds']: qab = options['qab'] cloud_map = False else: qab = False cloud_map = options['clouds'] elif options['prefix']: prefix = options['prefix'] b10 = prefix + '10' b11 = prefix + '11' if not options['clouds']: qab = prefix + 'QA' cloud_map = False else: cloud_map = options['clouds'] qab = False qapixel = options['qapixel'] lst_output = options['lst'] # save Brightness Temperature maps? global brightness_temperature_prefix if options['prefix_bt']: brightness_temperature_prefix = options['prefix_bt'] else: brightness_temperature_prefix = None global cwv_output cwv_window_size = int(options['window']) assertion_for_cwv_window_size_msg = ('A spatial window of size 5^2 or less is not ' 'recommended. Please select a larger window. ' 'Refer to the manual\'s notes for details.') assert cwv_window_size >= 7, assertion_for_cwv_window_size_msg cwv_output = options['cwv'] # optional maps average_emissivity_map = options['emissivity'] delta_emissivity_map = options['delta_emissivity'] # output for in-between maps? global emissivity_output, delta_emissivity_output emissivity_output = options['emissivity_out'] delta_emissivity_output = options['delta_emissivity_out'] global landcover_map, emissivity_class landcover_map = options['landcover'] emissivity_class = options['emissivity_class'] # flags global info, null info = flags['i'] scene_extent = flags['e'] timestamping = flags['t'] null = flags['n'] global rounding rounding = flags['r'] global celsius celsius = flags['c'] # ToDo: # shell = flags['g'] # # Pre-production actions # # Set Region if scene_extent: grass.use_temp_region() # safely modify the region msg = "\n|! Matching region extent to map {name}" # ToDo: check if extent-B10 == extent-B11? Unnecessary? # Improve below! if b10: run('g.region', rast=b10, align=b10) msg = msg.format(name=b10) elif t10: run('g.region', rast=t10, align=t10) msg = msg.format(name=t10) g.message(msg) elif scene_extent: grass.warning(_('Operating on current region')) # # 1. Mask clouds # if cloud_map: # user-fed cloud map? msg = '\n|i Using {cmap} as a MASK'.format(cmap=cloud_map) g.message(msg) r.mask(raster=cloud_map, flags='i', overwrite=True) else: # using the quality assessment band and a "QA" pixel value mask_clouds(qab, qapixel) # # 2. TIRS > Brightness Temperatures # if mtl_file: # if MTL and b10 given, use it to compute at-satellite temperature t10 if b10: # convert DNs to at-satellite temperatures t10 = tirs_to_at_satellite_temperature(b10, mtl_file) # likewise for b11 -> t11 if b11: # convert DNs to at-satellite temperatures t11 = tirs_to_at_satellite_temperature(b11, mtl_file) # # Initialise a SplitWindowLST object # split_window_lst = SplitWindowLST(emissivity_class) citation_lst = split_window_lst.citation # # 3. Land Surface Emissivities # # use given fixed class? if emissivity_class: if split_window_lst.landcover_class is False: # replace with meaningful error g.warning('Unknown land cover class string! Note, this string ' 'input option is case sensitive.') if emissivity_class == 'Random': msg = "\n|! Random emissivity class selected > " + \ split_window_lst.landcover_class + ' ' else: msg = '\n|! Retrieving average emissivities *only* for {eclass} ' if info: msg += '| Average emissivities (channels 10, 11): ' msg += str(split_window_lst.emissivity_t10) + ', ' + \ str(split_window_lst.emissivity_t11) msg = msg.format(eclass=split_window_lst.landcover_class) g.message(msg) # use the FROM-GLC map elif landcover_map: if average_emissivity_map: tmp_avg_lse = average_emissivity_map if not average_emissivity_map: determine_average_emissivity(tmp_avg_lse, landcover_map, split_window_lst.average_lse_mapcalc) if options['emissivity_out']: tmp_avg_lse = options['emissivity_out'] if delta_emissivity_map: tmp_delta_lse = delta_emissivity_map if not delta_emissivity_map: determine_delta_emissivity(tmp_delta_lse, landcover_map, split_window_lst.delta_lse_mapcalc) if options['delta_emissivity_out']: tmp_delta_lse = options['delta_emissivity_out'] # # 4. Modified Split-Window Variance-Covariance Matrix > Column Water Vapor # if info: msg = '\n|i Spatial window of size {n} for Column Water Vapor estimation: ' msg = msg.format(n=cwv_window_size) g.message(msg) cwv = Column_Water_Vapor(cwv_window_size, t10, t11) citation_cwv = cwv.citation estimate_cwv_big_expression(tmp_cwv, t10, t11, cwv._big_cwv_expression()) if cwv_output: tmp_cwv = cwv_output # # 5. Estimate Land Surface Temperature # if info and emissivity_class == 'Random': msg = '\n|* Will pick a random emissivity class!' grass.verbose(msg) estimate_lst(lst_output, t10, t11, tmp_avg_lse, tmp_delta_lse, tmp_cwv, split_window_lst.sw_lst_mapcalc) # # Post-production actions # # remove MASK r.mask(flags='r', verbose=True) # time-stamping if timestamping: add_timestamp(mtl_file, lst_output) if cwv_output: add_timestamp(mtl_file, cwv_output) # Apply color table if celsius: run('r.colors', map=lst_output, color='celsius') else: # color table for kelvin run('r.colors', map=lst_output, color='kelvin') # ToDo: helper function for r.support # strings for metadata history_lst = '\n' + citation_lst history_lst += '\n\n' + citation_cwv history_lst += '\n\nSplit-Window model: ' history_lst += split_window_lst._equation # :wsw_lst_mapcalc description_lst = ('Land Surface Temperature derived from a split-window algorithm. ') if celsius: title_lst = 'Land Surface Temperature (C)' units_lst = 'Celsius' else: title_lst = 'Land Surface Temperature (K)' units_lst = 'Kelvin' landsat8_metadata = Landsat8_MTL(mtl_file) source1_lst = landsat8_metadata.scene_id source2_lst = landsat8_metadata.origin # history entry run("r.support", map=lst_output, title=title_lst, units=units_lst, description=description_lst, source1=source1_lst, source2=source2_lst, history=history_lst) # (re)name the LST product #run("g.rename", rast=(tmp_lst, lst_output)) # restore region if scene_extent: grass.del_temp_region() # restoring previous region settings g.message("|! Original Region restored") # print citation if info: print '\nSource: ' + citation_lst
def main(): """ Main program """ # Temporary filenames # The following three are meant for a test step-by-step cwv estimation, see # unused functions! # tmp_ti_mean = tmp_map_name('ti_mean') # for cwv # tmp_tj_mean = tmp_map_name('tj_mean') # for cwv # tmp_ratio = tmp_map_name('ratio') # for cwv tmp_avg_lse = tmp_map_name('avg_lse') tmp_delta_lse = tmp_map_name('delta_lse') tmp_cwv = tmp_map_name('cwv') #tmp_lst = tmp_map_name('lst') # basic equation for mapcalc global equation, citation_lst equation = "{result} = {expression}" # user input mtl_file = options['mtl'] if not options['prefix']: b10 = options['b10'] b11 = options['b11'] t10 = options['t10'] t11 = options['t11'] if not options['clouds']: qab = options['qab'] cloud_map = False else: qab = False cloud_map = options['clouds'] elif options['prefix']: prefix = options['prefix'] b10 = prefix + '10' b11 = prefix + '11' if not options['clouds']: qab = prefix + 'QA' cloud_map = False else: cloud_map = options['clouds'] qab = False qapixel = options['qapixel'] lst_output = options['lst'] # save Brightness Temperature maps? global brightness_temperature_prefix if options['prefix_bt']: brightness_temperature_prefix = options['prefix_bt'] else: brightness_temperature_prefix = None global cwv_output cwv_window_size = int(options['window']) assertion_for_cwv_window_size_msg = ( 'A spatial window of size 5^2 or less is not ' 'recommended. Please select a larger window. ' 'Refer to the manual\'s notes for details.') assert cwv_window_size >= 7, assertion_for_cwv_window_size_msg cwv_output = options['cwv'] # optional maps average_emissivity_map = options['emissivity'] delta_emissivity_map = options['delta_emissivity'] # output for in-between maps? global emissivity_output, delta_emissivity_output emissivity_output = options['emissivity_out'] delta_emissivity_output = options['delta_emissivity_out'] global landcover_map, emissivity_class landcover_map = options['landcover'] emissivity_class = options['emissivity_class'] # flags global info, null info = flags['i'] scene_extent = flags['e'] timestamping = flags['t'] null = flags['n'] global rounding rounding = flags['r'] global celsius celsius = flags['c'] # ToDo: # shell = flags['g'] # # Pre-production actions # # Set Region if scene_extent: grass.use_temp_region() # safely modify the region msg = "\n|! Matching region extent to map {name}" # ToDo: check if extent-B10 == extent-B11? Unnecessary? # Improve below! if b10: run('g.region', rast=b10, align=b10) msg = msg.format(name=b10) elif t10: run('g.region', rast=t10, align=t10) msg = msg.format(name=t10) g.message(msg) elif scene_extent: grass.warning(_('Operating on current region')) # # 1. Mask clouds # if cloud_map: # user-fed cloud map? msg = '\n|i Using {cmap} as a MASK'.format(cmap=cloud_map) g.message(msg) r.mask(raster=cloud_map, flags='i', overwrite=True) else: # using the quality assessment band and a "QA" pixel value mask_clouds(qab, qapixel) # # 2. TIRS > Brightness Temperatures # if mtl_file: # if MTL and b10 given, use it to compute at-satellite temperature t10 if b10: # convert DNs to at-satellite temperatures t10 = tirs_to_at_satellite_temperature(b10, mtl_file) # likewise for b11 -> t11 if b11: # convert DNs to at-satellite temperatures t11 = tirs_to_at_satellite_temperature(b11, mtl_file) # # Initialise a SplitWindowLST object # split_window_lst = SplitWindowLST(emissivity_class) citation_lst = split_window_lst.citation # # 3. Land Surface Emissivities # # use given fixed class? if emissivity_class: if split_window_lst.landcover_class is False: # replace with meaningful error g.warning('Unknown land cover class string! Note, this string ' 'input option is case sensitive.') if emissivity_class == 'Random': msg = "\n|! Random emissivity class selected > " + \ split_window_lst.landcover_class + ' ' else: msg = '\n|! Retrieving average emissivities *only* for {eclass} ' if info: msg += '| Average emissivities (channels 10, 11): ' msg += str(split_window_lst.emissivity_t10) + ', ' + \ str(split_window_lst.emissivity_t11) msg = msg.format(eclass=split_window_lst.landcover_class) g.message(msg) # use the FROM-GLC map elif landcover_map: if average_emissivity_map: tmp_avg_lse = average_emissivity_map if not average_emissivity_map: determine_average_emissivity(tmp_avg_lse, landcover_map, split_window_lst.average_lse_mapcalc) if options['emissivity_out']: tmp_avg_lse = options['emissivity_out'] if delta_emissivity_map: tmp_delta_lse = delta_emissivity_map if not delta_emissivity_map: determine_delta_emissivity(tmp_delta_lse, landcover_map, split_window_lst.delta_lse_mapcalc) if options['delta_emissivity_out']: tmp_delta_lse = options['delta_emissivity_out'] # # 4. Modified Split-Window Variance-Covariance Matrix > Column Water Vapor # if info: msg = '\n|i Spatial window of size {n} for Column Water Vapor estimation: ' msg = msg.format(n=cwv_window_size) g.message(msg) cwv = Column_Water_Vapor(cwv_window_size, t10, t11) citation_cwv = cwv.citation estimate_cwv_big_expression(tmp_cwv, t10, t11, cwv._big_cwv_expression()) if cwv_output: tmp_cwv = cwv_output # # 5. Estimate Land Surface Temperature # if info and emissivity_class == 'Random': msg = '\n|* Will pick a random emissivity class!' grass.verbose(msg) estimate_lst(lst_output, t10, t11, tmp_avg_lse, tmp_delta_lse, tmp_cwv, split_window_lst.sw_lst_mapcalc) # # Post-production actions # # remove MASK r.mask(flags='r', verbose=True) # time-stamping if timestamping: add_timestamp(mtl_file, lst_output) if cwv_output: add_timestamp(mtl_file, cwv_output) # Apply color table if celsius: run('r.colors', map=lst_output, color='celsius') else: # color table for kelvin run('r.colors', map=lst_output, color='kelvin') # ToDo: helper function for r.support # strings for metadata history_lst = '\n' + citation_lst history_lst += '\n\n' + citation_cwv history_lst += '\n\nSplit-Window model: ' history_lst += split_window_lst._equation # :wsw_lst_mapcalc description_lst = ( 'Land Surface Temperature derived from a split-window algorithm. ') if celsius: title_lst = 'Land Surface Temperature (C)' units_lst = 'Celsius' else: title_lst = 'Land Surface Temperature (K)' units_lst = 'Kelvin' landsat8_metadata = Landsat8_MTL(mtl_file) source1_lst = landsat8_metadata.scene_id source2_lst = landsat8_metadata.origin # history entry run("r.support", map=lst_output, title=title_lst, units=units_lst, description=description_lst, source1=source1_lst, source2=source2_lst, history=history_lst) # (re)name the LST product #run("g.rename", rast=(tmp_lst, lst_output)) # restore region if scene_extent: grass.del_temp_region() # restoring previous region settings g.message("|! Original Region restored") # print citation if info: print '\nSource: ' + citation_lst