def geocode(scene, dem, tempdir, outdir, targetres, scaling='linear', func_geoback=1, func_interp=2, nodata=(0, -99), sarSimCC=False, osvdir=None, allow_RES_OSV=False, cleanup=True, normalization_method=2, export_extra=None): """ general function for geocoding SAR images with GAMMA Parameters ---------- scene: str or ~pyroSAR.drivers.ID the SAR scene to be processed dem: str the reference DEM in GAMMA format tempdir: str a temporary directory for writing intermediate files outdir: str the directory for the final GeoTiff output files targetres: int the target resolution in meters scaling: {'linear', 'db'} or list the value scaling of the backscatter values; either 'linear', 'db' or a list of both, i.e. ['linear', 'db'] func_geoback: {0, 1, 2, 3, 4, 5, 6, 7} backward geocoding interpolation mode (see GAMMA command geocode_back) - 0: nearest-neighbor - 1: bicubic spline (default) - 2: bicubic-spline, interpolate log(data) - 3: bicubic-spline, interpolate sqrt(data) - 4: B-spline interpolation (default B-spline degree: 5) - 5: B-spline interpolation sqrt(x) (default B-spline degree: 5) - 6: Lanczos interpolation (default Lanczos function order: 5) - 7: Lanczos interpolation sqrt(x) (default Lanczos function order: 5) NOTE: log and sqrt interpolation modes should only be used with non-negative data! NOTE: Gamma reccomendation for MLI data: "The interpolation should be performed on the square root of the data. A mid-order (3 to 5) B-spline interpolation is recommended." func_interp: {0, 1, 2, 3} output lookup table values in regions of layover, shadow, or DEM gaps (see GAMMA command gc_map) - 0: set to (0., 0.) - 1: linear interpolation across these regions - 2: actual value - 3: nn-thinned nodata: tuple the nodata values for the output files; defined as a tuple with two values, the first for linear, the second for logarithmic scaling sarSimCC: bool perform geocoding with SAR simulation cross correlation? If False, geocoding is performed with the Range-Doppler approach using orbit state vectors osvdir: str a directory for Orbit State Vector files; this is currently only used by for Sentinel-1 where two subdirectories POEORB and RESORB are created; if set to None, a subdirectory OSV is created in the directory of the unpacked scene. allow_RES_OSV: bool also allow the less accurate RES orbit files to be used? Otherwise the function will raise an error if no POE file exists cleanup: bool should all files written to the temporary directory during function execution be deleted after processing? normalization_method: {1, 2} the topographic normalization approach to be used - 1: first geocoding, then terrain flattening - 2: first terrain flattening, then geocoding; see `Small 2011 <https://doi.org/10.1109/Tgrs.2011.2120616>`_ export_extra: list or None a list of image file IDs to be exported to outdir - format is GeoTiff if the file is geocoded and ENVI otherwise. Non-geocoded images can be converted via Gamma command data2tiff yet the output was found impossible to read with GIS software - scaling of SAR image products is applied as defined by parameter `scaling` - see Notes for ID options Returns ------- Note ---- | intermediate output files | DEM products are named <scene identifier>_<ID>, e.g. `S1A__IW___A_20141012T162337_inc_geo` | SAR products will additionally contain the polarization, e.g. `S1A__IW___A_20141012T162337_VV_grd_mli` | IDs in brackets are only written if selected by `export_extra` - images in range-Doppler geometry * **grd**: the ground range detected SAR intensity image * **grd_mli**: the multi-looked grd image with approached target resolution * specific to normalization method 2: + **pix_ellip_sigma0**: ellipsoid-based pixel area + **pix_area_sigma0**: actual illuminated area as obtained from integrating DEM-facets (command pixel_area) + **pix_fine**: refined pixel area normalization factor (pix_ellip_sigma0 / pix_area_sigma0) + **grd_mli_pan**: the pixel area normalized MLI (grd_mli * pix_fine) - images in map geometry * **dem_seg_geo**: dem subsetted to the extent of the intersect between input DEM and SAR image * (**u_geo**): zenith angle of surface normal vector n (angle between z and n) * (**v_geo**): orientation angle of n (between x and projection of n in xy plane) * **inc_geo**: local incidence angle (between surface normal and look vector) * (**psi_geo**): projection angle (between surface normal and image plane normal) * **pix_geo**: pixel area normalization factor (command gc_map) * **ls_map_geo**: layover and shadow map (in map projection) * (**sim_sar_geo**): simulated SAR backscatter image - additional files * **lut_init**: initial geocoding lookup table - files specific to SAR simulation cross-correlation geocoding * **lut_fine**: refined geocoding lookup table * **diffpar**: ISP offset/interferogram parameter file * **offs**: offset estimates (fcomplex) * **coffs**: culled range and azimuth offset estimates (fcomplex) * **coffsets**: culled offset estimates and cross correlation values (text format) * **ccp**: cross-correlation of each patch (0.0->1.0) (float) Examples -------- geocode a Sentinel-1 scene and export the local incidence angle map with it >>> from pyroSAR.gamma import geocode >>> filename = 'S1A_IW_GRDH_1SDV_20180829T170656_20180829T170721_023464_028DE0_F7BD.zip' >>> geocode(scene=filename, dem='demfile', outdir='outdir', targetres=20, scaling='db', >>> export_extra=['dem_seg_geo', 'inc_geo', 'ls_map_geo']) .. figure:: figures/gamma_geocode.png :scale: 25% :align: center Workflow diagram for function geocode using normalization method 2 for processing a Sentinel-1 Ground Range Detected (GRD) scene to radiometrically terrain corrected (RTC) backscatter. """ if normalization_method == 2 and func_interp != 2: raise RuntimeError( 'parameter func_interp must be set to 2 if normalization_method is set to 2; ' 'see documentation of Gamma command pixel_area') if isinstance(scene, ID): scene = identify(scene.scene) elif isinstance(scene, str): scene = identify(scene) else: raise RuntimeError("'scene' must be of type str or pyroSAR.ID") if scene.sensor not in ['S1A', 'S1B']: raise IOError( 'this method is currently only available for Sentinel-1. Please stay tuned...' ) if sarSimCC: raise IOError( 'geocoding with cross correlation offset refinement is still in the making. Please stay tuned...' ) if export_extra is not None and not isinstance(export_extra, list): raise TypeError( "parameter 'export_extra' must either be None or a list") for dir in [tempdir, outdir]: if not os.path.isdir(dir): os.makedirs(dir) if scene.is_processed(outdir): print('scene {} already processed'.format(scene.outname_base())) return scaling = [scaling] if isinstance( scaling, str) else scaling if isinstance(scaling, list) else [] scaling = union(scaling, ['db', 'linear']) if len(scaling) == 0: raise IOError('wrong input type for parameter scaling') if scene.compression is not None: print('unpacking scene..') try: scene.unpack(tempdir) except RuntimeError: print('scene was attempted to be processed before, exiting') return else: scene.scene = os.path.join(tempdir, os.path.basename(scene.file)) os.makedirs(scene.scene) shellscript = os.path.join(scene.scene, scene.outname_base() + '_commands.sh') path_log = os.path.join(scene.scene, 'logfiles') if not os.path.isdir(path_log): os.makedirs(path_log) if scene.sensor in ['S1A', 'S1B']: print('removing border noise..') scene.removeGRDBorderNoise() print('converting scene to GAMMA format..') convert2gamma(scene, scene.scene, logpath=path_log, outdir=scene.scene, shellscript=shellscript) if scene.sensor in ['S1A', 'S1B']: print('updating orbit state vectors..') if allow_RES_OSV: osvtype = ['POE', 'RES'] else: osvtype = 'POE' try: correctOSV(id=scene, osvdir=osvdir, osvType=osvtype, logpath=path_log, outdir=scene.scene, shellscript=shellscript) except RuntimeError: print('orbit state vector correction failed for scene {}'.format( scene.scene)) return calibrate(scene, scene.scene, logpath=path_log, outdir=scene.scene, shellscript=shellscript) images = [ x for x in scene.getGammaImages(scene.scene) if x.endswith('_grd') or x.endswith('_slc_cal') ] products = list(images) print('multilooking..') for image in images: multilook(infile=image, outfile=image + '_mli', targetres=targetres, logpath=path_log, outdir=scene.scene, shellscript=shellscript) images = [x + '_mli' for x in images] products.extend(images) master = images[0] # create output names for files to be written # appreciated files will be written # depreciated files will be set to '-' in the GAMMA function call and are thus not written n = Namespace(scene.scene, scene.outname_base()) n.appreciate( ['dem_seg_geo', 'lut_init', 'pix_geo', 'inc_geo', 'ls_map_geo']) n.depreciate(['sim_sar_geo', 'u_geo', 'v_geo', 'psi_geo']) # if sarSimCC: # n.appreciate(['ccp', 'lut_fine']) if export_extra is not None: n.appreciate(export_extra) ovs_lat, ovs_lon = ovs(dem + '.par', targetres) master_par = ISPPar(master + '.par') gc_map_args = { 'DEM_par': dem + '.par', 'DEM': dem, 'DEM_seg_par': n.dem_seg_geo + '.par', 'DEM_seg': n.dem_seg_geo, 'lookup_table': n.lut_init, 'lat_ovr': ovs_lat, 'lon_ovr': ovs_lon, 'sim_sar': n.sim_sar_geo, 'u': n.u_geo, 'v': n.v_geo, 'inc': n.inc_geo, 'psi': n.psi_geo, 'pix': n.pix_geo, 'ls_map': n.ls_map_geo, 'frame': 8, 'ls_mode': func_interp, 'logpath': path_log, 'shellscript': shellscript, 'outdir': scene.scene } print('creating DEM products..') if master_par.image_geometry == 'GROUND_RANGE': gc_map_args.update({'GRD_par': master + '.par'}) diff.gc_map_grd(**gc_map_args) else: gc_map_args.update({'MLI_par': master + '.par', 'OFF_par': '-'}) diff.gc_map(**gc_map_args) for item in [ 'dem_seg_geo', 'sim_sar_geo', 'u_geo', 'v_geo', 'psi_geo', 'pix_geo', 'inc_geo', 'ls_map_geo' ]: if n.isappreciated(item): mods = {'data_type': 1} if item == 'ls_map_geo' else None par2hdr(n.dem_seg_geo + '.par', n.get(item) + '.hdr', mods) sim_width = ISPPar(n.dem_seg_geo + '.par').width if sarSimCC: raise IOError( 'geocoding with cross correlation offset refinement is still in the making. Please stay tuned...' ) else: lut_final = n.lut_init ###################################################################### # normalization and backward geocoding approach 1 #################### ###################################################################### print('geocoding and normalization..') if normalization_method == 1: method_suffix = 'geo_norm' for image in images: diff.geocode_back(data_in=image, width_in=master_par.range_samples, lookup_table=lut_final, data_out=image + '_geo', width_out=sim_width, interp_mode=func_geoback, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(n.dem_seg_geo + '.par', image + '_geo.hdr') lat.product(data_1=image + '_geo', data_2=n.pix_geo, product=image + '_geo_pan', width=sim_width, bx=1, by=1, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(n.dem_seg_geo + '.par', image + '_geo_pan.hdr') lat.sigma2gamma(pwr1=image + '_geo_pan', inc=n.inc_geo, gamma=image + '_{}'.format(method_suffix), width=sim_width, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(n.dem_seg_geo + '.par', image + '_{}.hdr'.format(method_suffix)) products.extend([image + '_geo', image + '_geo_pan']) ###################################################################### # normalization and backward geocoding approach 2 #################### ###################################################################### elif normalization_method == 2: method_suffix = 'norm_geo' # newer versions of Gamma enable creating the ratio of ellipsoid based # pixel area and DEM-facet pixel area directly with command pixel_area if hasarg(diff.pixel_area, 'sigma0_ratio'): n.appreciate(['pix_fine']) n.depreciate(['pix_area_sigma0']) diff.pixel_area(MLI_par=master + '.par', DEM_par=n.dem_seg_geo + '.par', DEM=n.dem_seg_geo, lookup_table=lut_final, ls_map=n.ls_map_geo, inc_map=n.inc_geo, pix_sigma0=n.pix_area_sigma0, sigma0_ratio=n.pix_fine, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(master + '.par', n.pix_fine + '.hdr') else: n.appreciate(['pix_area_sigma0', 'pix_ellip_sigma0', 'pix_fine']) # actual illuminated area as obtained from integrating DEM-facets (pix_area_sigma0 | pix_area_gamma0) diff.pixel_area(MLI_par=master + '.par', DEM_par=n.dem_seg_geo + '.par', DEM=n.dem_seg_geo, lookup_table=lut_final, ls_map=n.ls_map_geo, inc_map=n.inc_geo, pix_sigma0=n.pix_area_sigma0, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(master + '.par', n.pix_area_sigma0 + '.hdr') # ellipsoid-based pixel area (ellip_pix_sigma0) isp.radcal_MLI( MLI=master, MLI_par=master + '.par', OFF_par='-', CMLI=master + '_cal', refarea_flag= 1, # calculate sigma0, scale area by sin(inc_ang)/sin(ref_inc_ang) pix_area=n.pix_ellip_sigma0, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(master + '.par', n.pix_ellip_sigma0 + '.hdr') par2hdr(master + '.par', master + '_cal.hdr') # ratio of ellipsoid based pixel area and DEM-facet pixel area lat.ratio(d1=n.pix_ellip_sigma0, d2=n.pix_area_sigma0, ratio=n.pix_fine, width=master_par.range_samples, bx=1, by=1, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(master + '.par', n.pix_fine + '.hdr') for image in images: # sigma0 = MLI * ellip_pix_sigma0 / pix_area_sigma0 # gamma0 = MLI * ellip_pix_sigma0 / pix_area_gamma0 lat.product(data_1=image, data_2=n.pix_fine, product=image + '_pan', width=master_par.range_samples, bx=1, by=1, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(master + '.par', image + '_pan.hdr') diff.geocode_back(data_in=image + '_pan', width_in=master_par.range_samples, lookup_table=lut_final, data_out=image + '_pan_geo', width_out=sim_width, interp_mode=func_geoback, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(n.dem_seg_geo + '.par', image + '_pan_geo.hdr') lat.sigma2gamma(pwr1=image + '_pan_geo', inc=n.inc_geo, gamma=image + '_{}'.format(method_suffix), width=sim_width, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(n.dem_seg_geo + '.par', image + '_{}.hdr'.format(method_suffix)) products.extend([image + '_pan', image + '_pan_geo']) else: raise RuntimeError('unknown option for normalization_method') ###################################################################### print('conversion to (dB and) geotiff..') def exporter(data_in, outdir, nodata, scale='linear', dtype=2): if scale == 'db': if re.search('_geo', os.path.basename(data_in)): width = sim_width refpar = n.dem_seg_geo + '.par' else: width = master_par.range_samples refpar = master + '.par' lat.linear_to_dB(data_in=data_in, data_out=data_in + '_db', width=width, inverse_flag=0, null_value=nodata, logpath=path_log, outdir=scene.scene, shellscript=shellscript) par2hdr(refpar, data_in + '_db.hdr') data_in += '_db' if re.search('_geo', os.path.basename(data_in)): outfile = os.path.join(outdir, os.path.basename(data_in) + '.tif') disp.data2geotiff(DEM_par=n.dem_seg_geo + '.par', data=data_in, type=dtype, GeoTIFF=outfile, nodata=nodata, logpath=path_log, outdir=scene.scene, shellscript=shellscript) else: outfile = os.path.join(outdir, os.path.basename(data_in)) shutil.copyfile(data_in, outfile) shutil.copyfile(data_in + '.hdr', outfile + '.hdr') for image in images: for scale in scaling: exporter(data_in=image + '_{}'.format(method_suffix), scale=scale, dtype=2, nodata=dict(zip(('linear', 'db'), nodata))[scale], outdir=outdir) if scene.sensor in ['S1A', 'S1B']: shutil.copyfile( os.path.join(scene.scene, 'manifest.safe'), os.path.join(outdir, scene.outname_base() + '_manifest.safe')) if export_extra is not None: print('exporting extra products..') for key in export_extra: # SAR image products product_match = [x for x in products if x.endswith(key)] if len(product_match) > 0: for product in product_match: for scale in scaling: exporter(data_in=product, outdir=outdir, scale=scale, dtype=2, nodata=dict(zip(('linear', 'db'), nodata))[scale]) # ancillary (DEM) products elif n.isfile(key) and key not in ['lut_init']: filename = n[key] dtype = 5 if key == 'ls_map_geo' else 2 nodata = 0 exporter(filename, outdir, dtype=dtype, nodata=nodata) else: print('cannot not export file {}'.format(key)) shutil.copyfile(shellscript, os.path.join(outdir, os.path.basename(shellscript))) if cleanup: print('cleaning up temporary files..') shutil.rmtree(scene.scene)
def envidict(self): """ export relevant metadata to a ENVI HDR file compliant format Returns ------- dict """ out = dict(bands=1, header_offset=0, file_type='ENVI Standard', interleave='bsq', sensor_type='Unknown', byte_order=1, wavelength_units='Unknown') out['samples'] = getattr( self, union(['width', 'range_samples', 'samples'], self.keys)[0]) out['lines'] = getattr( self, union(['nlines', 'azimuth_lines', 'lines'], self.keys)[0]) dtypes_lookup = { 'FCOMPLEX': 6, 'FLOAT': 4, 'REAL*4': 4, 'INTEGER*2': 2, 'SHORT': 12 } dtype = getattr(self, union(['data_format', 'image_format'], self.keys)[0]) if dtype == 'SCOMPLEX': raise TypeError( 'unsupported data type: SCOMPLEX (2x16 bit complex)') out['data_type'] = dtypes_lookup[dtype] if out['data_type'] == 6: out['complex_function'] = 'Power' # projections = ['AEAC', 'EQA', 'LCC', 'LCC2', 'OMCH', 'PC', 'PS', 'SCH', 'TM', 'UTM'] if hasattr(self, 'DEM_projection'): if self.DEM_projection == 'UTM': hem = 'North' if float(self.false_northing) == 0 else 'South' out['map_info'] = [ 'UTM', '1.0000', '1.0000', self.corner_east, self.corner_north, str(abs(float(self.post_east))), str(abs(float(self.post_north))), self.projection_zone, hem, 'WGS-84', 'units=Meters' ] elif self.DEM_projection == 'EQA': out['map_info'] = [ 'Geographic Lat/Lon', '1.0000', '1.0000', self.corner_lon, self.corner_lat, str(abs(float(self.post_lon))), str(abs(float(self.post_lat))), 'WGS-84', 'units=Degrees' ] else: raise RuntimeError('unsupported projection') return out
def test_union(): assert anc.union([1], [1]) == [1]
def geocode(scene, dem, tempdir, outdir, targetres, scaling='linear', func_geoback=2, func_interp=0, nodata=(0, -99), sarSimCC=False, osvdir=None, allow_RES_OSV=False, cleanup=True): """ general function for geocoding SAR images with GAMMA Parameters ---------- scene: str or ~pyroSAR.drivers.ID the SAR scene to be processed dem: str the reference DEM in GAMMA format tempdir: str a temporary directory for writing intermediate files outdir: str the directory for the final GeoTiff output files targetres: int the target resolution in meters scaling: {'linear', 'db'} or list the value scaling of the backscatter values; either 'linear', 'db' or a list of both, i.e. ['linear', 'db'] func_geoback: {0, 1, 2, 3} backward geocoding interpolation mode (see GAMMA command geocode_back) * 0: nearest-neighbor * 1: bicubic spline * 2: bicubic-log spline, interpolates log(data) * 3: bicubic-sqrt spline, interpolates sqrt(data) NOTE: bicubic-log spline and bicubic-sqrt spline modes should only be used with non-negative data! func_interp: {0, 1, 2, 3} output lookup table values in regions of layover, shadow, or DEM gaps (see GAMMA command gc_map) * 0: set to (0., 0.) * 1: linear interpolation across these regions * 2: actual value * 3: nn-thinned nodata: tuple the nodata values for the output files; defined as a tuple with two values, the first for linear, the second for logarithmic scaling sarSimCC: bool perform geocoding with SAR simulation cross correlation? If False, geocoding is performed with the Range-Doppler approach using orbit state vectors osvdir: str a directory for Orbit State Vector files; this is currently only used by for Sentinel-1 where two subdirectories POEORB and RESORB are created; if set to None, a subdirectory OSV is created in the directory of the unpacked scene. allow_RES_OSV: bool also allow the less accurate RES orbit files to be used? Otherwise the function will raise an error if no POE file exists cleanup: bool should all files written to the temporary directory during function execution be deleted after processing? Returns ------- Note ---- intermediate output files (named <master_MLI>_<suffix>): * dem_seg: dem subsetted to the extent of the SAR image * lut: rough geocoding lookup table * lut_fine: fine geocoding lookup table * sim_map: simulated SAR backscatter image in DEM geometry * sim_sar: simulated SAR backscatter image in SAR geometry * u: zenith angle of surface normal vector n (angle between z and n) * v: orientation angle of n (between x and projection of n in xy plane) * inc: local incidence angle (between surface normal and look vector) * psi: projection angle (between surface normal and image plane normal) * pix: pixel area normalization factor * ls_map: layover and shadow map (in map projection) * diffpar: ISP offset/interferogram parameter file * offs: offset estimates (fcomplex) * coffs: culled range and azimuth offset estimates (fcomplex) * coffsets: culled offset estimates and cross correlation values (text format) * ccp: cross-correlation of each patch (0.0->1.0) (float) """ scene = scene if isinstance(scene, ID) else identify(scene) if scene.sensor not in ['S1A', 'S1B']: raise IOError('this method is currently only available for Sentinel-1. Please stay tuned...') if sarSimCC: raise IOError('geocoding with cross correlation offset refinement is still in the making. Please stay tuned...') for dir in [tempdir, outdir]: if not os.path.isdir(dir): os.makedirs(dir) if scene.is_processed(outdir): print('scene {} already processed'.format(scene.outname_base())) return scaling = [scaling] if isinstance(scaling, str) else scaling if isinstance(scaling, list) else [] scaling = union(scaling, ['db', 'linear']) if len(scaling) == 0: raise IOError('wrong input type for parameter scaling') if scene.compression is not None: print('unpacking scene..') try: scene.unpack(tempdir) except RuntimeError: print('scene was attempted to be processed before, exiting') return else: scene.scene = os.path.join(tempdir, os.path.basename(scene.file)) os.makedirs(scene.scene) logdir = os.path.join(scene.scene, 'logfiles') if not os.path.isdir(logdir): os.makedirs(logdir) if scene.sensor in ['S1A', 'S1B']: print('removing border noise..') scene.removeGRDBorderNoise() print('converting scene to GAMMA format..') convert2gamma(scene, scene.scene) if scene.sensor in ['S1A', 'S1B']: print('updating orbit state vectors..') if allow_RES_OSV: osvtype = ['POE', 'RES'] else: osvtype = 'POE' try: correctOSV(id=scene, osvdir=osvdir, logpath=logdir, osvType=osvtype) except RuntimeError: return calibrate(scene, scene.scene) images = [x for x in scene.getGammaImages(scene.scene) if x.endswith('_grd') or x.endswith('_slc_cal')] print('multilooking..') for image in images: multilook(image, image + '_mli', targetres) images = [x + '_mli' for x in images] master = images[0] # create output names for files to be written # appreciated files will be written # depreciated files will be set to '-' in the GAMMA function call and are thus not written n = Namespace(scene.scene, scene.outname_base()) n.appreciate(['dem_seg', 'lut_coarse', 'lut_fine', 'pix', 'ccp', 'inc', 'ls_map']) n.depreciate(['sim_map', 'u', 'v', 'psi']) # if sarSimCC: # n.appreciate(['ls_map']) ovs_lat, ovs_lon = ovs(dem + '.par', targetres) path_log = os.path.join(scene.scene, 'logfiles') if not os.path.isdir(path_log): os.makedirs(path_log) master_par = ISPPar(master + '.par') gc_map_args = [dem + '.par', dem, n.dem_seg + '.par', n.dem_seg, n.lut_coarse, ovs_lat, ovs_lon, n.sim_map, n.u, n.v, n.inc, n.psi, n.pix, n.ls_map, 8, func_interp] print('SAR image simulation from DEM..') if master_par.image_geometry == 'GROUND_RANGE': process(['gc_map_grd', master + '.par'] + gc_map_args, logpath=path_log) else: process(['gc_map', master + '.par', '-'] + gc_map_args, logpath=path_log) for item in ['dem_seg', 'sim_map', 'u', 'v', 'psi', 'pix', 'inc']: if n.isappreciated(item): par2hdr(n.dem_seg + '.par', n.get(item) + '.hdr') sim_width = ISPPar(n.dem_seg + '.par').width if sarSimCC: raise IOError('geocoding with cross correlation offset refinement is still in the making. Please stay tuned...') else: lut_final = n.lut_coarse ###################################################################### # normalization and backward geocoding approach 1 #################### ###################################################################### print('geocoding and normalization..') for image in images: process( ['geocode_back', image, master_par.range_samples, lut_final, image + '_geo', sim_width, '-', func_geoback], logpath=path_log) process(['product', image + '_geo', n.pix, image + '_geo_pan', sim_width, 1, 1, 0], logpath=path_log) process(['lin_comb', 1, image + '_geo_pan', 0, math.cos(math.radians(master_par.incidence_angle)), image + '_geo_pan_flat', sim_width], logpath=path_log) process(['sigma2gamma', image + '_geo_pan_flat', n.inc, image + '_geo_norm', sim_width], logpath=path_log) par2hdr(n.dem_seg + '.par', image + '_geo_norm.hdr') ###################################################################### # normalization and backward geocoding approach 2 #################### ###################################################################### # process(['pixel_area', master+'.par', dem_seg+'.par', dem_seg, lut_fine, ls_map, inc, pixel_area_fine], logpath=path_log) # process(['radcal_MLI', master, master+'.par', '-', master+'_cal', '-', 0, 0, 1, 0.0, '-', ellipse_pixel_area], logpath=path_log) # process(['ratio', ellipse_pixel_area, pixel_area_fine, ratio_sigma0, master_par.range_samples, 1, 1], logpath=path_log) # # for image in images: # process(['product', image, ratio_sigma0, image+'_pan', master_par.range_samples, 1, 1], logpath=path_log) # process(['geocode_back', image+'_pan', master_par.range_samples, lut_fine, image+'_pan_geo', sim_width, 0, func_geoback], logpath=path_log) # process(['lin_comb', 1, image+'_pan_geo', 0, math.cos(math.radians(master_par.incidence_angle)), image+'_pan_geo_flat', sim_width], logpath=path_log) # process(['sigma2gamma', image+'_pan_geo_flat', inc, image+'_geo_norm', sim_width], logpath=path_log) # par2hdr(dem_seg+'.par', image+'_geo_norm.hdr') ###################################################################### print('conversion to (dB and) geotiff..') for image in images: for scale in scaling: if scale == 'db': nodata_out = nodata[1] process(['linear_to_dB', image + '_geo_norm', image + '_geo_norm_db', sim_width, 0, nodata_out], logpath=path_log) par2hdr(n.dem_seg + '.par', image + '_geo_norm_db.hdr') else: nodata_out = nodata[0] suffix = {'linear': '', 'db': '_db'}[scale] infile = image + '_geo_norm{}'.format(suffix) outfile = os.path.join(outdir, os.path.basename(image) + '_geo_norm{}.tif'.format(suffix)) process(['data2geotiff', n.dem_seg + '.par', infile, 2, outfile, nodata_out], logpath=path_log) if scene.sensor in ['S1A', 'S1B']: shutil.copyfile(os.path.join(scene.scene, 'manifest.safe'), os.path.join(outdir, scene.outname_base() + '_manifest.safe')) if cleanup: print('cleaning up temporary files..') shutil.rmtree(scene.scene)
def __check_dict_keys(keys, reference): return len(union(keys, reference)) == len(keys)
def envidict(self, nodata=None): """ export relevant metadata to a ENVI HDR file compliant format Parameters ---------- nodata: int, float or None a no data value to write to the HDR file via attribute 'data ignore value' Returns ------- dict a dictionary containing attributes translated to ENVI HDR naming """ out = dict(bands=1, header_offset=0, file_type='ENVI Standard', interleave='bsq', sensor_type='Unknown', byte_order=1, wavelength_units='Unknown') if hasattr(self, 'date'): out['acquisition_time'] = self.date + 'Z' out['samples'] = getattr( self, union(['width', 'range_samples', 'samples'], self.keys)[0]) out['lines'] = getattr( self, union(['nlines', 'azimuth_lines', 'lines'], self.keys)[0]) dtypes_lookup = { 'FCOMPLEX': 6, 'FLOAT': 4, 'REAL*4': 4, 'INTEGER*2': 2, 'SHORT': 12 } dtype = getattr(self, union(['data_format', 'image_format'], self.keys)[0]) if dtype not in dtypes_lookup.keys(): raise TypeError('unsupported data type: {}'.format(dtype)) out['data_type'] = dtypes_lookup[dtype] if nodata is not None: out['data_ignore_value'] = nodata if out['data_type'] == 6: out['complex_function'] = 'Power' # projections = ['AEAC', 'EQA', 'LCC', 'LCC2', 'OMCH', 'PC', 'PS', 'SCH', 'TM', 'UTM'] # the corner coordinates are shifted by 1/2 pixel to the Northeast since GAMMA pixel # coordinates are defined for the pixel center while in ENVI it is the upper left if hasattr(self, 'DEM_projection'): if self.DEM_projection == 'UTM': hem = 'North' if float(self.false_northing) == 0 else 'South' out['map_info'] = [ 'UTM', '1.0000', '1.0000', self.corner_east - (abs(self.post_east) / 2), self.corner_north + (abs(self.post_north) / 2), str(abs(float(self.post_east))), str(abs(float(self.post_north))), self.projection_zone, hem, 'WGS-84', 'units=Meters' ] elif self.DEM_projection == 'EQA': out['map_info'] = [ 'Geographic Lat/Lon', '1.0000', '1.0000', self.corner_lon - (abs(self.post_lon) / 2), self.corner_lat + (abs(self.post_lat) / 2), str(abs(float(self.post_lon))), str(abs(float(self.post_lat))), 'WGS-84', 'units=Degrees' ] else: raise RuntimeError('unsupported projection: {}'.format( self.DEM_projection)) return out