def read_geometry(inps): ts_obj = timeseries(inps.timeseries_file) ts_obj.open(print_msg=False) # 2D / 3D geometry if inps.geom_file: geom_obj = geometry(inps.geom_file) geom_obj.open() if 'incidenceAngle' not in geom_obj.datasetNames: inps.incAngle = ut.incidence_angle(ts_obj.metadata, dimension=0) inps.rangeDist = ut.range_distance(ts_obj.metadata, dimension=0) else: print(('read 2D incidenceAngle,slantRangeDistance from {} file:' ' {}').format(geom_obj.name, os.path.basename(geom_obj.file))) inps.incAngle = geom_obj.read(datasetName='incidenceAngle', print_msg=False).flatten() inps.rangeDist = geom_obj.read(datasetName='slantRangeDistance', print_msg=False).flatten() if 'bperp' in geom_obj.datasetNames: print('read 3D bperp from {} file: {} ...'.format(geom_obj.name, os.path.basename(geom_obj.file))) dset_list = ['bperp-{}'.format(d) for d in ts_obj.dateList] inps.pbase = geom_obj.read(datasetName=dset_list, print_msg=False).reshape((ts_obj.numDate, -1)) inps.pbase -= np.tile(inps.pbase[ts_obj.refIndex, :].reshape(1, -1), (ts_obj.numDate, 1)) else: print('read mean bperp from {} file'.format(ts_obj.name)) inps.pbase = ts_obj.pbase.reshape((-1, 1)) # 0D geometry else: print('read mean incidenceAngle,slantRangeDistance,bperp value from {} file'.format(ts_obj.name)) inps.incAngle = ut.incidence_angle(ts_obj.metadata, dimension=0) inps.rangeDist = ut.range_distance(ts_obj.metadata, dimension=0) inps.pbase = ts_obj.pbase.reshape((-1, 1)) inps.sinIncAngle = np.sin(inps.incAngle * np.pi / 180.) return inps
def read_geometry(ts_file, geom_file=None, box=None): """Read the following geometry info in 0/2/3D Parameters: ts_file - str, path of time-series file geom_file - str, path of geometry file box - tuple of 4 int for (x0, y0, x1, y1) of the area of interest Returns: sin_inc_angle - 0/2D array, sin(inc_angle) range_dist - 0/2D array, slant range distance in meter pbase - 0/3D array, perp baseline in meter """ ts_obj = timeseries(ts_file) ts_obj.open(print_msg=False) # 0/2/3D geometry if geom_file: geom_obj = geometry(geom_file) geom_obj.open() # 0/2D incidence angle / slant range distance if 'incidenceAngle' not in geom_obj.datasetNames: inc_angle = ut.incidence_angle(ts_obj.metadata, dimension=0) range_dist = ut.range_distance(ts_obj.metadata, dimension=0) else: print( 'read 2D incidenceAngle, slantRangeDistance from {} file: {}'. format(geom_obj.name, os.path.basename(geom_obj.file))) inc_angle = geom_obj.read(datasetName='incidenceAngle', box=box, print_msg=False).flatten() range_dist = geom_obj.read(datasetName='slantRangeDistance', box=box, print_msg=False).flatten() # 0/3D perp baseline if 'bperp' in geom_obj.datasetNames: print('read 3D bperp from {} file: {} ...'.format( geom_obj.name, os.path.basename(geom_obj.file))) dset_list = ['bperp-{}'.format(d) for d in ts_obj.dateList] pbase = geom_obj.read(datasetName=dset_list, box=box, print_msg=False).reshape( (ts_obj.numDate, -1)) pbase -= np.tile(pbase[ts_obj.refIndex, :].reshape(1, -1), (ts_obj.numDate, 1)) else: print('read mean bperp from {} file'.format(ts_obj.name)) pbase = ts_obj.pbase.reshape((-1, 1)) # 0D geometry else: print( 'read mean incidenceAngle, slantRangeDistance, bperp value from {} file' .format(ts_obj.name)) inc_angle = ut.incidence_angle(ts_obj.metadata, dimension=0) range_dist = ut.range_distance(ts_obj.metadata, dimension=0) pbase = ts_obj.pbase.reshape((-1, 1)) sin_inc_angle = np.sin(inc_angle * np.pi / 180.) return sin_inc_angle, range_dist, pbase
def main(iargs=None): inps = cmd_line_parse(iargs) # Calculate look angle atr = readfile.read_attribute(inps.file) dem = None if inps.dem_file: dem = readfile.read(inps.dem_file, datasetName='height')[0] angle = ut.incidence_angle(atr, dem=dem, dimension=2) # Geo coord if 'Y_FIRST' in atr.keys(): print( 'Input file is geocoded, only center incident angle is calculated: ' ) print(angle) length = int(atr['LENGTH']) width = int(atr['WIDTH']) angle_mat = np.zeros((length, width), np.float32) angle_mat[:] = angle angle = angle_mat atr['FILE_TYPE'] = 'mask' atr['UNIT'] = 'degree' if 'REF_DATE' in atr.keys(): atr.pop('REF_DATE') if not inps.outfile: inps.outfile = 'incidenceAngle.h5' writefile.write(angle, out_file=inps.outfile, metadata=atr) return inps.outfile
def get_design_matrix(atr1, atr2, az_angle=90): """Get the design matrix A to convert asc/desc to hz/up. Only asc + desc -> hz + up is implemented for now. Project displacement from LOS to Horizontal and Vertical components math for 3D: cos(theta)*Uz - cos(alpha)*sin(theta)*Ux + sin(alpha)*sin(theta)*Uy = Ulos math for 2D: cos(theta)*Uv - sin(alpha-az)*sin(theta)*Uh = Ulos #Uh_perp = 0.0 This could be easily modified to support multiple view geometry (e.g. two adjcent tracks from asc & desc) to resolve 3D Parameters: atr1/2 : dict, metadata of input LOS files Returns: A : 2D matrix in size of (2,2) """ atr_list = [atr1, atr2] A = np.zeros((2, 2)) for i in range(len(atr_list)): atr = atr_list[i] # incidence angle inc_angle = float(ut.incidence_angle(atr, dimension=0, print_msg=False)) print('incidence angle: '+str(inc_angle)) inc_angle *= np.pi/180. # heading angle head_angle = float(atr['HEADING']) if head_angle < 0.: head_angle += 360. print('heading angle: '+str(head_angle)) head_angle *= np.pi/180. # construct design matrix A[i, 0] = np.cos(inc_angle) A[i, 1] = np.sin(inc_angle) * np.sin(head_angle - az_angle) return A
def get_los_geometry(self, geom_obj, print_msg=False): lat, lon = self.get_stat_lat_lon(print_msg=print_msg) # get LOS geometry if isinstance(geom_obj, str): # geometry file atr = readfile.read_attribute(geom_obj) coord = ut.coordinate(atr, lookup_file=geom_obj) y, x = coord.geo2radar(lat, lon, print_msg=print_msg)[0:2] box = (x, y, x + 1, y + 1) inc_angle = readfile.read(geom_obj, datasetName='incidenceAngle', box=box, print_msg=print_msg)[0][0, 0] az_angle = readfile.read(geom_obj, datasetName='azimuthAngle', box=box, print_msg=print_msg)[0][0, 0] head_angle = ut.azimuth2heading_angle(az_angle) elif isinstance(geom_obj, dict): # use mean inc/head_angle from metadata inc_angle = ut.incidence_angle(geom_obj, dimension=0, print_msg=print_msg) head_angle = float(geom_obj['HEADING']) # for old reading of los.rdr band2 data into headingAngle directly if (head_angle + 180.) > 45.: head_angle = ut.azimuth2heading_angle(head_angle) else: raise ValueError( 'input geom_obj is neight str nor dict: {}'.format(geom_obj)) return inc_angle, head_angle
def get_incidence_angle(self, box=None): if not self.extraMetadata or 'Y_FIRST' in self.extraMetadata.keys(): return None if 'height' in self.dsNames: dem = readfile.read(self.datasetDict['height'], datasetName='height')[0] else: dem = None data = ut.incidence_angle(self.extraMetadata, dem=dem, dimension=2, print_msg=False) if box is not None: data = data[box[1]:box[3], box[0]:box[2]] return data
def get_design_matrix(atr1, atr2, az_angle=90): """Get the design matrix A to convert asc/desc to hz/up. Only asc + desc -> hz + up is implemented for now. Project displacement from LOS to Horizontal and Vertical components: Math for 3D: Ulos = sin(inc_angle) * cos(head_angle) * Ux * -1 + sin(inc_angle) * sin(head_angle) * Uy + cos(inc_angle) * Uz Math for 2D: Ulos = sin(inc_angle) * sin(head_angle - az) * Uhorz * -1 + cos(inc_angle) * Uvert with Uhorz_perp = 0.0 This could be easily modified to support multiple view geometry (e.g. two adjcent tracks from asc & desc) to resolve 3D Parameters: atr1/2 : dict, metadata of input LOS files az_angle : float, azimuth angle for the horizontal direction of interest in degrees. Default is 90 (for east-west direction) Returns: A : 2D matrix in size of (2, 2) """ # degree to radian az_angle *= np.pi / 180. atr_list = [atr1, atr2] A = np.zeros((2, 2)) for i in range(len(atr_list)): atr = atr_list[i] # incidence angle inc_angle = float(ut.incidence_angle(atr, dimension=0, print_msg=False)) print('incidence angle: ' + str(inc_angle)) inc_angle *= np.pi / 180. # heading angle head_angle = float(atr['HEADING']) if head_angle < 0.: head_angle += 360. print('heading angle: ' + str(head_angle)) head_angle *= np.pi / 180. # construct design matrix A[i, 0] = np.cos(inc_angle) A[i, 1] = np.sin(inc_angle) * np.sin(head_angle - az_angle) return A
def get_design_matrix(atr1, atr2, azimuth=-90): """Get the design matrix A to convert asc/desc to hz/up. Only asc + desc -> hz + up is implemented for now. Project displacement from LOS to Horizontal and Vertical components: Math for 3D: dLOS = dE * sin(inc_angle) * sin(az_angle) * -1 + dN * sin(inc_angle) * cos(az_angle) + dU * cos(inc_angle) Math for 2D: dLOS = dH * sin(inc_angle) * cos(az_angle - az) + dV * cos(inc_angle) with dH_perp = 0.0 This could be easily modified to support multiple view geometry (e.g. two adjcent tracks from asc & desc) to resolve 3D Parameters: atr1/2 - dict, metadata of input LOS files azimuth - float, azimuth angle for the horizontal direction of interest in degrees. Measured from the north with anti-clockwise direction as positive. Returns: A - 2D matrix in size of (2, 2) """ # degree to radian azimuth *= np.pi / 180. atr_list = [atr1, atr2] A = np.zeros((2, 2)) for i in range(len(atr_list)): atr = atr_list[i] # LOS incidence angle los_inc_angle = float( ut.incidence_angle(atr, dimension=0, print_msg=False)) print('LOS incidence angle: {} deg'.format(los_inc_angle)) los_inc_angle *= np.pi / 180. # LOS azimuth angle los_az_angle = ut.heading2azimuth_angle(float(atr['HEADING'])) print('LOS azimuth angle: {} deg'.format(los_az_angle)) los_az_angle *= np.pi / 180. # construct design matrix A[i, 0] = np.cos(los_inc_angle) A[i, 1] = np.sin(los_inc_angle) * np.cos(los_az_angle - azimuth) return A
def get_los_geometry(self, insar_obj, print_msg=False): lat, lon = self.get_stat_lat_lon(print_msg=print_msg) # get LOS geometry if isinstance(insar_obj, str): # geometry file atr = readfile.read_attribute(insar_obj) coord = ut.coordinate(atr, lookup_file=insar_obj) y, x = coord.geo2radar(lat, lon, print_msg=print_msg)[0:2] box = (x, y, x+1, y+1) inc_angle = readfile.read(insar_obj, datasetName='incidenceAngle', box=box, print_msg=print_msg)[0][0,0] az_angle = readfile.read(insar_obj, datasetName='azimuthAngle', box=box, print_msg=print_msg)[0][0,0] head_angle = ut.azimuth2heading_angle(az_angle) elif isinstance(insar_obj, dict): # use mean inc/head_angle from metadata inc_angle = ut.incidence_angle(insar_obj, dimension=0, print_msg=print_msg) head_angle = float(insar_obj['HEADING']) # for old reading of los.rdr band2 data into headingAngle directly if (head_angle + 180.) > 45.: head_angle = ut.azimuth2heading_angle(head_angle) else: raise ValueError('input insar_obj is neight str nor dict: {}'.format(insar_obj)) return inc_angle, head_angle
def check_inputs(inps): parser = create_parser() # output directories/files atr = dict() mintpy_dir = None if inps.timeseries_file: atr = readfile.read_attribute(inps.timeseries_file) mintpy_dir = os.path.dirname(inps.timeseries_file) if not inps.outfile: fbase = os.path.splitext(inps.timeseries_file)[0] inps.outfile = '{}_{}.h5'.format(fbase, inps.trop_model) elif inps.geom_file: atr = readfile.read_attribute(inps.geom_file) mintpy_dir = os.path.join(os.path.dirname(inps.geom_file), '..') else: mintpy_dir = os.path.abspath(os.getcwd()) # trop_file inps.trop_file = os.path.join(mintpy_dir, 'inputs/{}.h5'.format(inps.trop_model)) print('output tropospheric delay file: {}'.format(inps.trop_file)) # hour if not inps.hour: if 'CENTER_LINE_UTC' in atr.keys(): inps.hour = ptime.closest_weather_product_time(atr['CENTER_LINE_UTC'], inps.trop_model) else: parser.print_usage() raise Exception('no input for hour') print('time of cloest available product: {}:00 UTC'.format(inps.hour)) # date list if inps.timeseries_file: print('read date list from timeseries file: {}'.format(inps.timeseries_file)) ts_obj = timeseries(inps.timeseries_file) ts_obj.open(print_msg=False) inps.date_list = ts_obj.dateList elif len(inps.date_list) == 1: if os.path.isfile(inps.date_list[0]): print('read date list from text file: {}'.format(inps.date_list[0])) inps.date_list = ptime.yyyymmdd(np.loadtxt(inps.date_list[0], dtype=bytes, usecols=(0,)).astype(str).tolist()) else: parser.print_usage() raise Exception('ERROR: input date list < 2') # Grib data directory inps.grib_dir = os.path.join(inps.weather_dir, inps.trop_model) if not os.path.isdir(inps.grib_dir): os.makedirs(inps.grib_dir) print('making directory: '+inps.grib_dir) # Date list to grib file list inps.grib_file_list = date_list2grib_file(inps.date_list, inps.hour, inps.trop_model, inps.grib_dir) if 'REF_Y' in atr.keys(): inps.ref_yx = [int(atr['REF_Y']), int(atr['REF_X'])] print('reference pixel: {}'.format(inps.ref_yx)) # Coordinate system: geocoded or not inps.geocoded = False if 'Y_FIRST' in atr.keys(): inps.geocoded = True print('geocoded: {}'.format(inps.geocoded)) # Prepare DEM, inc_angle, lat/lon file for PyAPS to read if inps.geom_file: geom_obj = geometry(inps.geom_file) geom_obj.open() print('converting DEM/incAngle for PyAPS to read') # DEM dem = readfile.read(inps.geom_file, datasetName='height', print_msg=False)[0] inps.dem_file = 'pyapsDem.hgt' writefile.write(dem, inps.dem_file, metadata=atr) # inc_angle if 'incidenceAngle' in geom_obj.datasetNames: inps.inc_angle = readfile.read(inps.geom_file, datasetName='incidenceAngle', print_msg=False)[0] else: atr = readfile.read_attribute(inps.timeseries_file) inps.inc_angle = ut.incidence_angle(atr, dem=dem, dimension=0) inps.inc_angle = np.ones(dem.shape, dtype=np.float32) * inps.inc_angle inps.inc_angle_file = 'pyapsIncAngle.flt' writefile.write(inps.inc_angle, inps.inc_angle_file, metadata=atr) # latitude if 'latitude' in geom_obj.datasetNames: data = readfile.read(inps.geom_file, datasetName='latitude', print_msg=False)[0] print('converting lat for PyAPS to read') inps.lat_file = 'pyapsLat.flt' writefile.write(data, inps.lat_file, metadata=atr) else: inps.lat_file = None # longitude if 'longitude' in geom_obj.datasetNames: data = readfile.read(inps.geom_file, datasetName='longitude', print_msg=False)[0] print('converting lon for PyAPS to read') inps.lon_file = 'pyapsLon.flt' writefile.write(data, inps.lon_file, metadata=atr) else: inps.lon_file = None return inps, atr
def run_asc_desc2horz_vert(inps): """Decompose asc / desc LOS files into horz / vert file(s). Parameters: inps - namespace, input parameters Returns: inps.outfile - str(s) output file(s) """ ## 1. calculate the overlaping area in lat/lon atr_list = [ readfile.read_attribute(fname, datasetName=inps.ds_name) for fname in inps.file ] S, N, W, E = get_overlap_lalo(atr_list) lat_step = float(atr_list[0]['Y_STEP']) lon_step = float(atr_list[0]['X_STEP']) length = int(round((S - N) / lat_step)) width = int(round((E - W) / lon_step)) print('overlaping area in SNWE: {}'.format((S, N, W, E))) ## 2. read LOS data and geometry num_file = len(inps.file) num_pixel = length * width dlos = np.zeros((num_file, length, width), dtype=np.float32) if inps.geom_file: los_inc_angle = np.zeros((num_file, length, width), dtype=np.float32) los_az_angle = np.zeros((num_file, length, width), dtype=np.float32) else: los_inc_angle = np.zeros(num_file, dtype=np.float32) los_az_angle = np.zeros(num_file, dtype=np.float32) for i, (atr, fname) in enumerate(zip(atr_list, inps.file)): # overlap SNWE --> box to read for each specific file coord = ut.coordinate(atr) x0 = coord.lalo2yx(W, coord_type='lon') y0 = coord.lalo2yx(N, coord_type='lat') box = (x0, y0, x0 + width, y0 + length) # read data dlos[i, :] = readfile.read(fname, box=box, datasetName=inps.ds_name)[0] msg = f'{inps.ds_name} ' if inps.ds_name else '' print(f'read {msg} from file: {fname}') # read geometry if inps.geom_file: los_inc_angle[i, :] = readfile.read( inps.geom_file[i], box=box, datasetName='incidenceAngle')[0] los_az_angle[i, :] = readfile.read(inps.geom_file[i], box=box, datasetName='azimuthAngle')[0] print( f'read 2D LOS incidence / azimuth angles from file: {inps.geom_file[i]}' ) else: los_inc_angle[i] = ut.incidence_angle(atr, dimension=0, print_msg=False) los_az_angle[i] = ut.heading2azimuth_angle(float(atr['HEADING'])) print( 'calculate the constant LOS incidence / azimuth angles from metadata as:' ) print(f'LOS incidence angle: {los_inc_angle[i]:.1f} deg') print(f'LOS azimuth angle: {los_az_angle[i]:.1f} deg') ## 3. decompose LOS displacements into horizontal / Vertical displacements print('---------------------') dhorz, dvert = asc_desc2horz_vert(dlos, los_inc_angle, los_az_angle, inps.horz_az_angle) ## 4. write outputs print('---------------------') # Update attributes atr = atr_list[0].copy() if inps.ds_name and atr['FILE_TYPE'] in [ 'ifgramStack', 'timeseries', 'HDFEOS' ]: atr['FILE_TYPE'] = 'displacement' atr['WIDTH'] = str(width) atr['LENGTH'] = str(length) atr['X_STEP'] = str(lon_step) atr['Y_STEP'] = str(lat_step) atr['X_FIRST'] = str(W) atr['Y_FIRST'] = str(N) # update REF_X/Y ref_lat, ref_lon = float(atr['REF_LAT']), float(atr['REF_LON']) [ref_y, ref_x] = ut.coordinate(atr).geo2radar(ref_lat, ref_lon)[0:2] atr['REF_Y'] = int(ref_y) atr['REF_X'] = int(ref_x) # use ref_file for time-series file writing ref_file = inps.file[0] if atr_list[0][ 'FILE_TYPE'] == 'timeseries' else None if inps.one_outfile: print('write asc/desc/horz/vert datasets into {}'.format( inps.one_outfile)) dsDict = {} for i, atr in enumerate(atr_list): # dataset name for LOS data track_num = atr.get('trackNumber', None) proj_name = atr.get('PROJECT_NAME', None) if proj_name in ['none', 'None', None]: proj_name = atr.get('FILE_PATH', None) proj_name = sensor.project_name2sensor_name(proj_name)[0] ds_name = proj_name if proj_name else '' ds_name += 'A' if atr['ORBIT_DIRECTION'].lower().startswith( 'asc') else 'D' ds_name += f'T{track_num}' if track_num else '' ds_name += '_{}'.format(atr['DATE12']) # assign dataset value dsDict[ds_name] = dlos[i] dsDict['horizontal'] = dhorz dsDict['vertical'] = dvert writefile.write(dsDict, out_file=inps.one_outfile, metadata=atr, ref_file=ref_file) else: print('writing horizontal component to file: ' + inps.outfile[0]) writefile.write(dhorz, out_file=inps.outfile[0], metadata=atr, ref_file=ref_file) print('writing vertical component to file: ' + inps.outfile[1]) writefile.write(dvert, out_file=inps.outfile[1], metadata=atr, ref_file=ref_file) return inps.outfile
def main(iargs=None): inps = cmd_line_parse(iargs) # 1. Extract the common area of two input files # Basic info atr1 = readfile.read_attribute(inps.file[0]) atr2 = readfile.read_attribute(inps.file[1]) # check coordinates if any('X_FIRST' not in i for i in [atr1, atr2]): raise Exception('Not all input files are geocoded.') # check spatial resolution if any(atr1[i] != atr2[i] for i in ['X_STEP','Y_STEP']): msg = 'file1: {}\n'.format(inps.file[0]) msg += 'Y_STEP: {} m, X_STEP: {} m\n'.format(atr1['Y_STEP'], atr1['X_STEP']) msg += 'file2: {}\n'.format(inps.file[1]) msg += 'Y_STEP: {} m, X_STEP: {} m'.format(atr2['Y_STEP'], atr2['X_STEP']) raise ValueError('input files do not have the same spatial resolution\n{}'.format(msg)) k1 = atr1['FILE_TYPE'] print('Input 1st file is '+k1) # Common AOI in lalo west, east, south, north = get_overlap_lalo(atr1, atr2) lon_step = float(atr1['X_STEP']) lat_step = float(atr1['Y_STEP']) width = int(round((east - west) / lon_step)) length = int(round((south - north) / lat_step)) # Read data in common AOI: LOS displacement, heading angle, incident angle u_los = np.zeros((2, width*length)) heading = [] incidence = [] for i in range(len(inps.file)): fname = inps.file[i] print('---------------------') print('reading '+fname) atr = readfile.read_attribute(fname) coord = ut.coordinate(atr) [x0, x1] = coord.lalo2yx([west, east], coord_type='lon') [y0, y1] = coord.lalo2yx([north, south], coord_type='lat') V = readfile.read(fname, box=(x0, y0, x1, y1))[0] u_los[i, :] = V.flatten(0) heading_angle = float(atr['HEADING']) if heading_angle < 0.: heading_angle += 360. print('heading angle: '+str(heading_angle)) heading_angle *= np.pi/180. heading.append(heading_angle) inc_angle = float(ut.incidence_angle(atr, dimension=0)) inc_angle *= np.pi/180. incidence.append(inc_angle) # 2. Project displacement from LOS to Horizontal and Vertical components # math for 3D: cos(theta)*Uz - cos(alpha)*sin(theta)*Ux + sin(alpha)*sin(theta)*Uy = Ulos # math for 2D: cos(theta)*Uv - sin(alpha-az)*sin(theta)*Uh = Ulos #Uh_perp = 0.0 # This could be easily modified to support multiple view geometry # (e.g. two adjcent tracks from asc & desc) to resolve 3D # Design matrix A = np.zeros((2, 2)) for i in range(len(inps.file)): A[i, 0] = np.cos(incidence[i]) A[i, 1] = np.sin(incidence[i]) * np.sin(heading[i]-inps.azimuth) A_inv = np.linalg.pinv(A) u_vh = np.dot(A_inv, u_los) u_v = np.reshape(u_vh[0, :], (length, width)) u_h = np.reshape(u_vh[1, :], (length, width)) # 3. Output # Attributes atr = atr1.copy() atr['WIDTH'] = str(width) atr['LENGTH'] = str(length) atr['X_FIRST'] = str(west) atr['Y_FIRST'] = str(north) atr['X_STEP'] = str(lon_step) atr['Y_STEP'] = str(lat_step) print('---------------------') horz_file = inps.outfile[0] print('writing horizontal component to file: '+horz_file) writefile.write(u_h, out_file=horz_file, metadata=atr) vert_file = inps.outfile[1] print('writing vertical component to file: '+vert_file) writefile.write(u_v, out_file=vert_file, metadata=atr) print('Done.') return inps.outfile
def main(iargs=None): inps = cmd_line_parse(iargs) # 1. Extract the common area of two input files # Basic info atr1 = readfile.read_attribute(inps.file[0]) atr2 = readfile.read_attribute(inps.file[1]) if any('X_FIRST' not in i for i in [atr1, atr2]): raise Exception('ERROR: Not all input files are geocoded.') k1 = atr1['FILE_TYPE'] print('Input 1st file is '+k1) # Common AOI in lalo west, east, south, north = get_overlap_lalo(atr1, atr2) lon_step = float(atr1['X_STEP']) lat_step = float(atr1['Y_STEP']) width = int(round((east - west) / lon_step)) length = int(round((south - north) / lat_step)) # Read data in common AOI: LOS displacement, heading angle, incident angle u_los = np.zeros((2, width*length)) heading = [] incidence = [] for i in range(len(inps.file)): fname = inps.file[i] print('---------------------') print('reading '+fname) atr = readfile.read_attribute(fname) coord = ut.coordinate(atr) [x0, x1] = coord.lalo2yx([west, east], coord_type='lon') [y0, y1] = coord.lalo2yx([north, south], coord_type='lat') V = readfile.read(fname, box=(x0, y0, x1, y1))[0] u_los[i, :] = V.flatten(0) heading_angle = float(atr['HEADING']) if heading_angle < 0.: heading_angle += 360. print('heading angle: '+str(heading_angle)) heading_angle *= np.pi/180. heading.append(heading_angle) inc_angle = float(ut.incidence_angle(atr, dimension=0)) inc_angle *= np.pi/180. incidence.append(inc_angle) # 2. Project displacement from LOS to Horizontal and Vertical components # math for 3D: cos(theta)*Uz - cos(alpha)*sin(theta)*Ux + sin(alpha)*sin(theta)*Uy = Ulos # math for 2D: cos(theta)*Uv - sin(alpha-az)*sin(theta)*Uh = Ulos #Uh_perp = 0.0 # This could be easily modified to support multiple view geometry # (e.g. two adjcent tracks from asc & desc) to resolve 3D # Design matrix A = np.zeros((2, 2)) for i in range(len(inps.file)): A[i, 0] = np.cos(incidence[i]) A[i, 1] = np.sin(incidence[i]) * np.sin(heading[i]-inps.azimuth) A_inv = np.linalg.pinv(A) u_vh = np.dot(A_inv, u_los) u_v = np.reshape(u_vh[0, :], (length, width)) u_h = np.reshape(u_vh[1, :], (length, width)) # 3. Output # Attributes atr = atr1.copy() atr['WIDTH'] = str(width) atr['LENGTH'] = str(length) atr['X_FIRST'] = str(west) atr['Y_FIRST'] = str(north) atr['X_STEP'] = str(lon_step) atr['Y_STEP'] = str(lat_step) print('---------------------') outname = inps.outfile[0] print('writing vertical component to file: '+outname) writefile.write(u_v, out_file=outname, metadata=atr) outname = inps.outfile[1] print('writing horizontal component to file: '+outname) writefile.write(u_h, out_file=outname, metadata=atr) print('Done.') return