def sar_focus(cfg_file, raw_output_file, output_file): ################### # INITIALIZATIONS # ################### print( '-------------------------------------------------------------------') print( time.strftime("- OCEANSAR SAR Processor: %Y-%m-%d %H:%M:%S", time.localtime())) print( '-------------------------------------------------------------------') ## CONFIGURATION FILE cfg = tpio.ConfigFile(cfg_file) # PROCESSING az_weighting = cfg.processing.az_weighting doppler_bw = cfg.processing.doppler_bw plot_format = cfg.processing.plot_format plot_tex = cfg.processing.plot_tex plot_save = cfg.processing.plot_save plot_path = cfg.processing.plot_path plot_raw = cfg.processing.plot_raw plot_rcmc_dopp = cfg.processing.plot_rcmc_dopp plot_rcmc_time = cfg.processing.plot_rcmc_time plot_image_valid = cfg.processing.plot_image_valid # SAR f0 = cfg.sar.f0 prf = cfg.sar.prf num_ch = cfg.sar.num_ch alt = cfg.sar.alt v_ground = cfg.sar.v_ground rg_bw = cfg.sar.rg_bw over_fs = cfg.sar.over_fs ## CALCULATE PARAMETERS l0 = const.c / f0 if v_ground == 'auto': v_ground = geo.orbit_to_vel(alt, ground=True) rg_sampling = rg_bw * over_fs ## RAW DATA raw_file = tpio.RawFile(raw_output_file, 'r') raw_data = raw_file.get('raw_data*') sr0 = raw_file.get('sr0') raw_file.close() ## OTHER INITIALIZATIONS # Create plots directory plot_path = os.path.dirname(output_file) + os.sep + plot_path if plot_save: if not os.path.exists(plot_path): os.makedirs(plot_path) slc = [] ######################## # PROCESSING MAIN LOOP # ######################## for ch in np.arange(num_ch): if plot_raw: utils.image(np.real(raw_data[0, ch]), min=-np.max(np.abs(raw_data[0, ch])), max=np.max(np.abs(raw_data[0, ch])), cmap='gray', aspect=np.float(raw_data[0, ch].shape[1]) / np.float(raw_data[0, ch].shape[0]), title='Raw Data', xlabel='Range samples', ylabel='Azimuth samples', usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'plot_raw_real_%d.%s' % (ch, plot_format), dpi=150) utils.image(np.imag(raw_data[0, ch]), min=-np.max(np.abs(raw_data[0, ch])), max=np.max(np.abs(raw_data[0, ch])), cmap='gray', aspect=np.float(raw_data[0, ch].shape[1]) / np.float(raw_data[0, ch].shape[0]), title='Raw Data', xlabel='Range samples', ylabel='Azimuth samples', usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'plot_raw_imag_%d.%s' % (ch, plot_format), dpi=150) utils.image(np.abs(raw_data[0, ch]), min=0, max=np.max(np.abs(raw_data[0, ch])), cmap='gray', aspect=np.float(raw_data[0, ch].shape[1]) / np.float(raw_data[0, ch].shape[0]), title='Raw Data', xlabel='Range samples', ylabel='Azimuth samples', usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'plot_raw_amp_%d.%s' % (ch, plot_format), dpi=150) utils.image(np.angle(raw_data[0, ch]), min=-np.pi, max=np.pi, cmap='gray', aspect=np.float(raw_data[0, ch].shape[1]) / np.float(raw_data[0, ch].shape[0]), title='Raw Data', xlabel='Range samples', ylabel='Azimuth samples', usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'plot_raw_phase_%d.%s' % (ch, plot_format), dpi=150) # Optimize matrix sizes az_size_orig, rg_size_orig = raw_data[0, ch].shape optsize = utils.optimize_fftsize(raw_data[0, ch].shape) optsize = [raw_data.shape[0], optsize[0], optsize[1]] data = np.zeros(optsize, dtype=complex) data[:, :raw_data[0, ch].shape[0], :raw_data[ 0, ch].shape[1]] = raw_data[:, ch, :, :] az_size, rg_size = data.shape[1:] # RCMC Correction print('Applying RCMC correction... [Channel %d/%d]' % (ch + 1, num_ch)) #fr = np.linspace(-rg_sampling/2., rg_sampling/2., rg_size) fr = (np.arange(rg_size) - rg_size / 2) * rg_sampling / rg_size fr = np.roll(fr, int(-rg_size / 2)) fa = (np.arange(az_size) - az_size / 2) * prf / az_size fa = np.roll(fa, int(-az_size / 2)) #fa[az_size/2:] = fa[az_size/2:] - prf rcmc_fa = sr0 / np.sqrt(1 - (fa * (l0 / 2.) / v_ground)**2.) - sr0 data = np.fft.fft2(data) # for i in np.arange(az_size): # data[i,:] *= np.exp(1j*2*np.pi*2*rcmc_fa[i]/const.c*fr) data = (data * np.exp(4j * np.pi * rcmc_fa.reshape( (1, az_size, 1)) / const.c * fr.reshape((1, 1, rg_size)))) data = np.fft.ifft(data, axis=2) if plot_rcmc_dopp: utils.image(np.abs(data[0]), min=0., max=3. * np.mean(np.abs(data)), cmap='gray', aspect=np.float(rg_size) / np.float(az_size), title='RCMC Data (Range Dopler Domain)', usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'plot_rcmc_dopp_%d.%s' % (ch, plot_format)) if plot_rcmc_time: rcmc_time = np.fft.ifft(data[0], axis=0)[:az_size_orig, :rg_size_orig] rcmc_time_max = np.max(np.abs(rcmc_time)) utils.image(np.real(rcmc_time), min=-rcmc_time_max, max=rcmc_time_max, cmap='gray', aspect=np.float(rg_size) / np.float(az_size), title='RCMC Data (Time Domain)', usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'plot_rcmc_time_real_%d.%s' % (ch, plot_format)) utils.image(np.imag(rcmc_time), min=-rcmc_time_max, max=rcmc_time_max, cmap='gray', aspect=np.float(rg_size) / np.float(az_size), title='RCMC Data (Time Domain)', usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'plot_rcmc_time_imag_%d.%s' % (ch, plot_format)) # Azimuth compression print('Applying azimuth compression... [Channel %d/%d]' % (ch + 1, num_ch)) n_samp = 2 * (np.int(doppler_bw / (fa[1] - fa[0])) / 2) weighting = az_weighting - (1. - az_weighting) * np.cos( 2 * np.pi * np.linspace(0, 1., n_samp)) # Compensate amplitude loss L_win = np.sum(np.abs(weighting)**2) / weighting.size weighting /= np.sqrt(L_win) if fa.size > n_samp: zeros = np.zeros(az_size) zeros[0:n_samp] = weighting #zeros[:n_samp/2] = weighting[:n_samp/2] #zeros[-n_samp/2:] = weighting[-n_samp/2:] weighting = np.roll(zeros, int(-n_samp / 2)) ph_ac = 4. * np.pi / l0 * sr0 * ( np.sqrt(1. - (fa * l0 / 2. / v_ground)**2.) - 1.) # for i in np.arange(rg_size): # data[:,i] *= np.exp(1j*ph_ac)*weighting data = data * (np.exp(1j * ph_ac) * weighting).reshape((1, az_size, 1)) data = np.fft.ifft(data, axis=1) print('Finishing... [Channel %d/%d]' % (ch + 1, num_ch)) # Reduce to initial dimension data = data[:, :az_size_orig, :rg_size_orig] # Removal of non valid samples n_val_az_2 = np.floor(doppler_bw / 2. / (2. * v_ground**2. / l0 / sr0) * prf / 2.) * 2. # data = raw_data[ch, n_val_az_2:(az_size_orig - n_val_az_2 - 1), :] data = data[:, n_val_az_2:(az_size_orig - n_val_az_2 - 1), :] if plot_image_valid: plt.figure() plt.imshow(np.abs(data[0]), origin='lower', vmin=0, vmax=np.max(np.abs(data)), aspect=np.float(rg_size_orig) / np.float(az_size_orig), cmap='gray') plt.xlabel("Range") plt.ylabel("Azimuth") plt.savefig( os.path.join(plot_path, ('plot_image_valid_%d.%s' % (ch, plot_format)))) slc.append(data) # Save processed data slc = np.array(slc, dtype=np.complex) print("Shape of SLC: " + str(slc.shape), flush=True) proc_file = tpio.ProcFile(output_file, 'w', slc.shape) proc_file.set('slc*', slc) proc_file.close() print('-----------------------------------------') print( time.strftime("Processing finished [%Y-%m-%d %H:%M:%S]", time.localtime())) print('-----------------------------------------')
def ati_process(cfg_file, proc_output_file, ocean_file, output_file): print('-------------------------------------------------------------------') print(time.strftime("- OCEANSAR ATI Processor: [%Y-%m-%d %H:%M:%S]", time.localtime())) print('-------------------------------------------------------------------') print('Initializing...') ## CONFIGURATION FILE cfg = tpio.ConfigFile(cfg_file) # SAR inc_angle = np.deg2rad(cfg.sar.inc_angle) f0 = cfg.sar.f0 prf = cfg.sar.prf num_ch = cfg.sar.num_ch ant_L = cfg.sar.ant_L alt = cfg.sar.alt v_ground = cfg.sar.v_ground rg_bw = cfg.sar.rg_bw over_fs = cfg.sar.over_fs pol = cfg.sar.pol if pol == 'DP': polt = ['hh', 'vv'] elif pol == 'hh': polt = ['hh'] else: polt = ['vv'] # ATI rg_ml = cfg.ati.rg_ml az_ml = cfg.ati.az_ml ml_win = cfg.ati.ml_win plot_save = cfg.ati.plot_save plot_path = cfg.ati.plot_path plot_format = cfg.ati.plot_format plot_tex = cfg.ati.plot_tex plot_surface = cfg.ati.plot_surface plot_proc_ampl = cfg.ati.plot_proc_ampl plot_coh = cfg.ati.plot_coh plot_coh_all = cfg.ati.plot_coh_all plot_ati_phase = cfg.ati.plot_ati_phase plot_ati_phase_all = cfg.ati.plot_ati_phase_all plot_vel_hist = cfg.ati.plot_vel_hist plot_vel = cfg.ati.plot_vel ## CALCULATE PARAMETERS if v_ground == 'auto': v_ground = geosar.orbit_to_vel(alt, ground=True) k0 = 2.*np.pi*f0/const.c rg_sampling = rg_bw*over_fs # PROCESSED RAW DATA proc_content = tpio.ProcFile(proc_output_file, 'r') proc_data = proc_content.get('slc*') proc_content.close() # OCEAN SURFACE surface = OceanSurface() surface.load(ocean_file, compute=['D', 'V']) surface.t = 0. # OUTPUT FILE output = open(output_file, 'w') # OTHER INITIALIZATIONS # Enable TeX if plot_tex: plt.rc('font', family='serif') plt.rc('text', usetex=True) # Create plots directory plot_path = os.path.dirname(output_file) + os.sep + plot_path if plot_save: if not os.path.exists(plot_path): os.makedirs(plot_path) # SURFACE VELOCITIES grg_grid_spacing = (const.c/2./rg_sampling/np.sin(inc_angle)) rg_res_fact = grg_grid_spacing / surface.dx az_grid_spacing = (v_ground/prf) az_res_fact = az_grid_spacing / surface.dy res_fact = np.ceil(np.sqrt(rg_res_fact*az_res_fact)) # SURFACE RADIAL VELOCITY v_radial_surf = surface.Vx*np.sin(inc_angle) - surface.Vz*np.cos(inc_angle) v_radial_surf_ml = utils.smooth(utils.smooth(v_radial_surf, res_fact * rg_ml, axis=1), res_fact * az_ml, axis=0) v_radial_surf_mean = np.mean(v_radial_surf) v_radial_surf_std = np.std(v_radial_surf) v_radial_surf_ml_std = np.std(v_radial_surf_ml) # SURFACE HORIZONTAL VELOCITY v_horizo_surf = surface.Vx v_horizo_surf_ml = utils.smooth(utils.smooth(v_horizo_surf, res_fact * rg_ml, axis=1), res_fact * az_ml, axis=0) v_horizo_surf_mean = np.mean(v_horizo_surf) v_horizo_surf_std = np.std(v_horizo_surf) v_horizo_surf_ml_std = np.std(v_horizo_surf_ml) # Expected mean azimuth shift sr0 = geosar.inc_to_sr(inc_angle, alt) avg_az_shift = - v_radial_surf_mean / v_ground * sr0 std_az_shift = v_radial_surf_std / v_ground * sr0 ################## # ATI PROCESSING # ################## print('Starting ATI processing...') # Get dimensions & calculate region of interest rg_span = surface.Lx az_span = surface.Ly rg_size = proc_data[0].shape[2] az_size = proc_data[0].shape[1] # Note: RG is projected, so plots are Ground Range rg_min = 0 rg_max = np.int(rg_span/(const.c/2./rg_sampling/np.sin(inc_angle))) az_min = np.int(az_size/2. + (-az_span/2. + avg_az_shift)/(v_ground/prf)) az_max = np.int(az_size/2. + (az_span/2. + avg_az_shift)/(v_ground/prf)) az_guard = np.int(std_az_shift / (v_ground / prf)) if (az_max - az_min) < (2 * az_guard - 10): print('Not enough edge-effect free image') return # Adaptive coregistration if cfg.sar.L_total: ant_L = ant_L/np.float(num_ch) dist_chan = ant_L/2 else: if np.float(cfg.sar.Spacing) != 0: dist_chan = np.float(cfg.sar.Spacing)/2 else: dist_chan = ant_L/2 # dist_chan = ant_L/num_ch/2. print('ATI Spacing: %f' % dist_chan) inter_chan_shift_dist = dist_chan/(v_ground/prf) # Subsample shift in azimuth for chind in range(proc_data.shape[0]): shift_dist = - chind * inter_chan_shift_dist shift_arr = np.exp(-2j * np.pi * shift_dist * np.roll(np.arange(az_size) - az_size/2, int(-az_size / 2)) / az_size) shift_arr = shift_arr.reshape((1, az_size, 1)) proc_data[chind] = np.fft.ifft(np.fft.fft(proc_data[chind], axis=1) * shift_arr, axis=1) # First dimension is number of channels, second is number of pols ch_dim = proc_data.shape[0:2] npol = ch_dim[1] proc_data_rshp = [np.prod(ch_dim), proc_data.shape[2], proc_data.shape[3]] # Compute extended covariance matrices... proc_data = proc_data.reshape(proc_data_rshp) # Intensities i_all = [] for chind in range(proc_data.shape[0]): this_i = utils.smooth(utils.smooth(np.abs(proc_data[chind])**2., rg_ml, axis=1, window=ml_win), az_ml, axis=0, window=ml_win) i_all.append(this_i[az_min:az_max, rg_min:rg_max]) i_all = np.array(i_all) # .reshape((ch_dim) + (az_max - az_min, rg_max - rg_min)) interfs = [] cohs = [] tind = 0 coh_lut = np.zeros((proc_data.shape[0], proc_data.shape[0]), dtype=int) for chind1 in range(proc_data.shape[0]): for chind2 in range(chind1 + 1, proc_data.shape[0]): coh_lut[chind1, chind2] = tind tind = tind + 1 t_interf = utils.smooth(utils.smooth(proc_data[chind2] * np.conj(proc_data[chind1]), rg_ml, axis=1, window=ml_win), az_ml, axis=0, window=ml_win) interfs.append(t_interf[az_min:az_max, rg_min:rg_max]) cohs.append(t_interf[az_min:az_max, rg_min:rg_max] / np.sqrt(i_all[chind1] * i_all[chind2])) print('Generating plots and estimating values...') # SURFACE HEIGHT if plot_surface: plt.figure() plt.imshow(surface.Dz, cmap="ocean", extent=[0, surface.Lx, 0, surface.Ly], origin='lower') plt.title('Surface Height') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') cbar = plt.colorbar() cbar.ax.set_xlabel('[m]') if plot_save: plt.savefig(plot_path + os.sep + 'plot_surface.' + plot_format, bbox_inches='tight') plt.close() else: plt.show() # PROCESSED AMPLITUDE if plot_proc_ampl: for pind in range(npol): save_path = (plot_path + os.sep + 'amp_dB_' + polt[pind]+ '.' + plot_format) plt.figure() plt.imshow(utils.db(i_all[pind]), aspect='equal', origin='lower', vmin=utils.db(np.max(i_all[pind]))-20, extent=[0., rg_span, 0., az_span], interpolation='nearest', cmap='viridis') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("Amplitude") plt.colorbar() plt.savefig(save_path) save_path = (plot_path + os.sep + 'amp_' + polt[pind]+ '.' + plot_format) int_img = (i_all[pind])**0.5 vmin = np.mean(int_img) - 3 * np.std(int_img) vmax = np.mean(int_img) + 3 * np.std(int_img) plt.figure() plt.imshow(int_img, aspect='equal', origin='lower', vmin=vmin, vmax=vmax, extent=[0., rg_span, 0., az_span], interpolation='nearest', cmap='viridis') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("Amplitude") plt.colorbar() plt.savefig(save_path) if plot_coh and ch_dim[0] > 1: for pind in range(npol): save_path = (plot_path + os.sep + 'ATI_coh_' + polt[pind] + polt[pind] + '.' + plot_format) coh_ind = coh_lut[(pind, pind + npol)] plt.figure() plt.imshow(np.abs(cohs[coh_ind]), aspect='equal', origin='lower', vmin=0, vmax=1, extent=[0., rg_span, 0., az_span], cmap='bone') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("ATI Coherence") # plt.colorbar() plt.savefig(save_path) # ATI PHASE tau_ati = dist_chan/v_ground ati_phases = [] # Hack to avoid interferogram computation if there are no interferometric channels if num_ch > 1: npol_ = npol else: npol_ = 0 for pind in range(npol_): save_path = (plot_path + os.sep + 'ATI_pha_' + polt[pind] + polt[pind] + '.' + plot_format) coh_ind = coh_lut[(pind, pind + npol)] ati_phase = uwphase(cohs[coh_ind]) ati_phases.append(ati_phase) v_radial_est = -ati_phase / tau_ati / (k0 * 2.) if plot_ati_phase: phase_mean = np.mean(ati_phase) phase_std = np.std(ati_phase) vmin = np.max([-np.abs(phase_mean) - 4*phase_std, -np.abs(ati_phase).max()]) vmax = np.min([np.abs(phase_mean) + 4*phase_std, np.abs(ati_phase).max()]) plt.figure() plt.imshow(ati_phase, aspect='equal', origin='lower', vmin=vmin, vmax=vmax, extent=[0., rg_span, 0., az_span], cmap='hsv') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("ATI Phase") plt.colorbar() plt.savefig(save_path) save_path = (plot_path + os.sep + 'ATI_rvel_' + polt[pind] + polt[pind] + '.' + plot_format) vmin = -np.abs(v_radial_surf_mean) - 4. * v_radial_surf_std vmax = np.abs(v_radial_surf_mean) + 4. * v_radial_surf_std plt.figure() plt.imshow(v_radial_est, aspect='equal', origin='lower', vmin=vmin, vmax=vmax, extent=[0., rg_span, 0., az_span], cmap='bwr') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("Estimated Radial Velocity " + polt[pind]) plt.colorbar() plt.savefig(save_path) if npol_ == 4: # Bypass this for now # Cross pol interferogram coh_ind = coh_lut[(0, 1)] save_path = (plot_path + os.sep + 'POL_coh_' + polt[0] + polt[1] + '.' + plot_format) utils.image(np.abs(cohs[coh_ind]), max=1, min=0, aspect='equal', cmap='gray', extent=[0., rg_span, 0., az_span], xlabel='Ground range [m]', ylabel='Azimuth [m]', title='XPOL Coherence', usetex=plot_tex, save=plot_save, save_path=save_path) save_path = (plot_path + os.sep + 'POL_pha_' + polt[0] + polt[1] + '.' + plot_format) ati_phase = uwphase(cohs[coh_ind]) phase_mean = np.mean(ati_phase) phase_std = np.std(ati_phase) vmin = np.max([-np.abs(phase_mean) - 4*phase_std, -np.pi]) vmax = np.min([np.abs(phase_mean) + 4*phase_std, np.pi]) utils.image(ati_phase, aspect='equal', min=vmin, max=vmax, cmap=utils.bwr_cmap, extent=[0., rg_span, 0., az_span], xlabel='Ground range [m]', ylabel='Azimuth [m]', title='XPOL Phase', cbar_xlabel='[rad]', usetex=plot_tex, save=plot_save, save_path=save_path) if num_ch > 1: ati_phases = np.array(ati_phases) output.write('--------------------------------------------\n') output.write('SURFACE RADIAL VELOCITY - NO SMOOTHING\n') output.write('MEAN(SURF. V) = %.4f\n' % v_radial_surf_mean) output.write('STD(SURF. V) = %.4f\n' % v_radial_surf_std) output.write('--------------------------------------------\n\n') output.write('--------------------------------------------\n') output.write('SURFACE RADIAL VELOCITY - SMOOTHING (WIN. SIZE=%dx%d)\n' % (az_ml, rg_ml)) output.write('MEAN(SURF. V) = %.4f\n' % v_radial_surf_mean) output.write('STD(SURF. V) = %.4f\n' % v_radial_surf_ml_std) output.write('--------------------------------------------\n\n') output.write('--------------------------------------------\n') output.write('SURFACE HORIZONTAL VELOCITY - NO SMOOTHING\n') output.write('MEAN(SURF. V) = %.4f\n' % v_horizo_surf_mean) output.write('STD(SURF. V) = %.4f\n' % v_horizo_surf_std) output.write('--------------------------------------------\n\n') if plot_vel_hist: # PLOT RADIAL VELOCITY plt.figure() plt.hist(v_radial_surf.flatten(), 200, normed=True, histtype='step') #plt.hist(v_radial_surf_ml.flatten(), 500, normed=True, histtype='step') plt.grid(True) plt.xlim([-np.abs(v_radial_surf_mean) - 4.*v_radial_surf_std, np.abs(v_radial_surf_mean) + 4.* v_radial_surf_std]) plt.xlabel('Radial velocity [m/s]') plt.ylabel('PDF') plt.title('Surface velocity') if plot_save: plt.savefig(plot_path + os.sep + 'TRUE_radial_vel_hist.' + plot_format) plt.close() else: plt.show() plt.figure() plt.hist(v_radial_surf_ml.flatten(), 200, normed=True, histtype='step') #plt.hist(v_radial_surf_ml.flatten(), 500, normed=True, histtype='step') plt.grid(True) plt.xlim([-np.abs(v_radial_surf_mean) - 4.*v_radial_surf_std, np.abs(v_radial_surf_mean) + 4.* v_radial_surf_std]) plt.xlabel('Radial velocity [m/s]') plt.ylabel('PDF') plt.title('Surface velocity (low pass filtered)') if plot_save: plt.savefig(plot_path + os.sep + 'TRUE_radial_vel_ml_hist.' + plot_format) plt.close() else: plt.show() if plot_vel: utils.image(v_radial_surf, aspect='equal', cmap=utils.bwr_cmap, extent=[0., rg_span, 0., az_span], xlabel='Ground range [m]', ylabel='Azimuth [m]', title='Surface Radial Velocity', cbar_xlabel='[m/s]', min=-np.abs(v_radial_surf_mean) - 4.*v_radial_surf_std, max=np.abs(v_radial_surf_mean) + 4.*v_radial_surf_std, usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'TRUE_radial_vel.' + plot_format) utils.image(v_radial_surf_ml, aspect='equal', cmap=utils.bwr_cmap, extent=[0., rg_span, 0., az_span], xlabel='Ground range [m]', ylabel='Azimuth [m]', title='Surface Radial Velocity', cbar_xlabel='[m/s]', min=-np.abs(v_radial_surf_mean) - 4.*v_radial_surf_std, max=np.abs(v_radial_surf_mean) + 4.*v_radial_surf_std, usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'TRUE_radial_vel_ml.' + plot_format) ## ESTIMATED VELOCITIES # Note: plot limits are taken from surface calculations to keep the same ranges # ESTIMATE RADIAL VELOCITY v_radial_ests = -ati_phases/tau_ati/(k0*2.) # ESTIMATE HORIZONTAL VELOCITY v_horizo_ests = -ati_phases/tau_ati/(k0*2.)/np.sin(inc_angle) #Trim edges v_radial_ests = v_radial_ests[:, az_guard:-az_guard, 5:-5] v_horizo_ests = v_horizo_ests[:, az_guard:-az_guard, 5:-5] output.write('--------------------------------------------\n') output.write('ESTIMATED RADIAL VELOCITY - NO SMOOTHING\n') for pind in range(npol): output.write("%s Polarization\n" % polt[pind]) output.write('MEAN(EST. V) = %.4f\n' % np.mean(v_radial_ests[pind])) output.write('STD(EST. V) = %.4f\n' % np.std(v_radial_ests[pind])) output.write('--------------------------------------------\n\n') output.write('--------------------------------------------\n') output.write('ESTIMATED RADIAL VELOCITY - SMOOTHING (WIN. SIZE=%dx%d)\n' % (az_ml, rg_ml)) for pind in range(npol): output.write("%s Polarization\n" % polt[pind]) output.write('MEAN(EST. V) = %.4f\n' % np.mean(utils.smooth(utils.smooth(v_radial_ests[pind], rg_ml, axis=1), az_ml, axis=0))) output.write('STD(EST. V) = %.4f\n' % np.std(utils.smooth(utils.smooth(v_radial_ests[pind], rg_ml, axis=1), az_ml, axis=0))) output.write('--------------------------------------------\n\n') output.write('--------------------------------------------\n') output.write('ESTIMATED HORIZONTAL VELOCITY - NO SMOOTHING\n') for pind in range(npol): output.write("%s Polarization\n" % polt[pind]) output.write('MEAN(EST. V) = %.4f\n' % np.mean(v_horizo_ests[pind])) output.write('STD(EST. V) = %.4f\n' % np.std(v_horizo_ests[pind])) output.write('--------------------------------------------\n\n') # Processed NRCS NRCS_est_avg = 10*np.log10(np.mean(np.mean(i_all[:, az_guard:-az_guard, 5:-5], axis=-1), axis=-1)) output.write('--------------------------------------------\n') for pind in range(npol): output.write("%s Polarization\n" % polt[pind]) output.write('Estimated mean NRCS = %5.2f\n' % NRCS_est_avg[pind]) output.write('--------------------------------------------\n\n') # Some bookkeeping information output.write('--------------------------------------------\n') output.write('GROUND RANGE GRID SPACING = %.4f\n' % grg_grid_spacing) output.write('AZIMUTH GRID SPACING = %.4f\n' % az_grid_spacing) output.write('--------------------------------------------\n\n') output.close() if plot_vel_hist and num_ch > 1: # PLOT RADIAL VELOCITY plt.figure() plt.hist(v_radial_surf.flatten(), 200, normed=True, histtype='step', label='True') for pind in range(npol): plt.hist(v_radial_ests[pind].flatten(), 200, normed=True, histtype='step', label=polt[pind]) plt.grid(True) plt.xlim([-np.abs(v_radial_surf_mean) - 4.*v_radial_surf_std, np.abs(v_radial_surf_mean) + 4.*v_radial_surf_std]) plt.xlabel('Radial velocity [m/s]') plt.ylabel('PDF') plt.title('Estimated velocity') plt.legend() if plot_save: plt.savefig(plot_path + os.sep + 'ATI_radial_vel_hist.' + plot_format) plt.close() else: plt.show() # Save some statistics to npz file # if num_ch > 1: filenpz = os.path.join(os.path.dirname(output_file), 'ati_stats.npz') # Mean coh cohs = np.array(cohs)[:, az_guard:-az_guard, 5:-5] np.savez(filenpz, nrcs=NRCS_est_avg, v_r_dop=np.mean(np.mean(v_radial_ests, axis=-1), axis=-1), v_r_surf = v_radial_surf_mean, v_r_surf_std = v_radial_surf_std, coh_mean= np.mean(np.mean(cohs, axis=-1), axis=-1), abscoh_mean=np.mean(np.mean(np.abs(cohs), axis=-1), axis=-1), coh_lut=coh_lut, pols=polt) print('----------------------------------------') print(time.strftime("ATI Processing finished [%Y-%m-%d %H:%M:%S]", time.localtime())) print('----------------------------------------')
def ati_process(cfg_file, insar_output_file, ocean_file, output_file): print( '-------------------------------------------------------------------') print( time.strftime("- OCEANSAR ATI Processor: [%Y-%m-%d %H:%M:%S]", time.localtime())) print( '-------------------------------------------------------------------') print('Initializing...') ## CONFIGURATION FILE cfg = tpio.ConfigFile(cfg_file) # SAR pol = cfg.sar.pol if pol == 'DP': polt = ['hh', 'vv'] elif pol == 'hh': polt = ['hh'] else: polt = ['vv'] # ATI ml_win = cfg.ati.ml_win plot_save = cfg.ati.plot_save plot_path = cfg.ati.plot_path plot_format = cfg.ati.plot_format plot_tex = cfg.ati.plot_tex plot_surface = cfg.ati.plot_surface plot_proc_ampl = cfg.ati.plot_proc_ampl plot_coh = cfg.ati.plot_coh plot_coh_all = cfg.ati.plot_coh_all plot_ati_phase = cfg.ati.plot_ati_phase plot_ati_phase_all = cfg.ati.plot_ati_phase_all plot_vel_hist = cfg.ati.plot_vel_hist plot_vel = cfg.ati.plot_vel # PROCESSED InSAR L1b DATA insar_data = tpio.L1bFile(insar_output_file, 'r') i_all = insar_data.get('ml_intensity') cohs = insar_data.get('ml_coherence') * np.exp( 1j * insar_data.get('ml_phase')) coh_lut = insar_data.get('coh_lut') sr0 = insar_data.get('sr0') inc_angle = insar_data.get('inc_angle') b_ati = insar_data.get('b_ati') b_xti = insar_data.get('b_xti') f0 = insar_data.get('f0') az_sampling = insar_data.get('az_sampling') num_ch = insar_data.get('num_ch') rg_sampling = insar_data.get('rg_sampling') v_ground = insar_data.get('v_ground') alt = insar_data.get('orbit_alt') inc_angle = np.deg2rad(insar_data.get('inc_angle')) rg_ml = insar_data.get('rg_ml') az_ml = insar_data.get('az_ml') insar_data.close() # CALCULATE PARAMETERS k0 = 2. * np.pi * f0 / const.c # OCEAN SURFACE surface = OceanSurface() surface.load(ocean_file, compute=['D', 'V']) surface.t = 0. # OUTPUT FILE output = open(output_file, 'w') # OTHER INITIALIZATIONS # Enable TeX if plot_tex: plt.rc('font', family='serif') plt.rc('text', usetex=True) # Create plots directory plot_path = os.path.dirname(output_file) + os.sep + plot_path if plot_save: if not os.path.exists(plot_path): os.makedirs(plot_path) # SURFACE VELOCITIES grg_grid_spacing = (const.c / 2. / rg_sampling / np.sin(inc_angle)) rg_res_fact = grg_grid_spacing / surface.dx az_grid_spacing = (v_ground / az_sampling) az_res_fact = az_grid_spacing / surface.dy res_fact = np.ceil(np.sqrt(rg_res_fact * az_res_fact)) # SURFACE RADIAL VELOCITY v_radial_surf = surface.Vx * np.sin(inc_angle) - surface.Vz * np.cos( inc_angle) v_radial_surf_ml = utils.smooth(utils.smooth(v_radial_surf, res_fact * rg_ml, axis=1), res_fact * az_ml, axis=0) v_radial_surf_mean = np.mean(v_radial_surf) v_radial_surf_std = np.std(v_radial_surf) v_radial_surf_ml_std = np.std(v_radial_surf_ml) # SURFACE HORIZONTAL VELOCITY v_horizo_surf = surface.Vx v_horizo_surf_ml = utils.smooth(utils.smooth(v_horizo_surf, res_fact * rg_ml, axis=1), res_fact * az_ml, axis=0) v_horizo_surf_mean = np.mean(v_horizo_surf) v_horizo_surf_std = np.std(v_horizo_surf) v_horizo_surf_ml_std = np.std(v_horizo_surf_ml) # Expected mean azimuth shift sr0 = geosar.inc_to_sr(inc_angle, alt) avg_az_shift = -v_radial_surf_mean / v_ground * sr0 std_az_shift = v_radial_surf_std / v_ground * sr0 az_guard = np.int(std_az_shift / (v_ground / az_sampling)) ################## # ATI PROCESSING # ################## print('Starting ATI processing...') # Get dimensions & calculate region of interest rg_span = surface.Lx az_span = surface.Ly # First dimension is number of channels, second is number of pols ch_dim = i_all.shape[0:2] npol = ch_dim[1] print('Generating plots and estimating values...') # SURFACE HEIGHT if plot_surface: plt.figure() plt.imshow(surface.Dz, cmap="ocean", extent=[0, surface.Lx, 0, surface.Ly], origin='lower') plt.title('Surface Height') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') cbar = plt.colorbar() cbar.ax.set_xlabel('[m]') if plot_save: plt.savefig(plot_path + os.sep + 'plot_surface.' + plot_format, bbox_inches='tight') plt.close() else: plt.show() # PROCESSED AMPLITUDE if plot_proc_ampl: for pind in range(npol): save_path = (plot_path + os.sep + 'amp_dB_' + polt[pind] + '.' + plot_format) plt.figure() plt.imshow(utils.db(i_all[0, pind]), aspect='equal', origin='lower', vmin=utils.db(np.max(i_all[pind])) - 20, extent=[0., rg_span, 0., az_span], interpolation='nearest', cmap='viridis') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("Amplitude") plt.colorbar() plt.savefig(save_path) plt.close() save_path = (plot_path + os.sep + 'amp_' + polt[pind] + '.' + plot_format) int_img = (i_all[0, pind])**0.5 vmin = np.mean(int_img) - 3 * np.std(int_img) vmax = np.mean(int_img) + 3 * np.std(int_img) plt.figure() plt.imshow(int_img, aspect='equal', origin='lower', vmin=vmin, vmax=vmax, extent=[0., rg_span, 0., az_span], interpolation='nearest', cmap='viridis') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("Amplitude") plt.colorbar() plt.savefig(save_path) plt.close() if plot_coh and ch_dim[0] > 1: for pind in range(npol): save_path = (plot_path + os.sep + 'ATI_coh_' + polt[pind] + polt[pind] + '.' + plot_format) coh_ind = coh_lut[0, pind, 1, pind] plt.figure() plt.imshow(np.abs(cohs[coh_ind]), aspect='equal', origin='lower', vmin=0, vmax=1, extent=[0., rg_span, 0., az_span], cmap='bone') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("ATI Coherence") # plt.colorbar() plt.savefig(save_path) # ATI PHASE tau_ati = b_ati / v_ground ati_phases = [] # Hack to avoid interferogram computation if there are no interferometric channels if num_ch > 1: npol_ = npol else: npol_ = 0 for pind in range(npol_): save_path = (plot_path + os.sep + 'ATI_pha_' + polt[pind] + polt[pind] + '.' + plot_format) coh_ind = coh_lut[(0, pind, 1, pind)] ati_phase = uwphase(cohs[coh_ind]) ati_phases.append(ati_phase) v_radial_est = -ati_phase / tau_ati[1] / (k0 * 2.) if plot_ati_phase: phase_mean = np.mean(ati_phase) phase_std = np.std(ati_phase) vmin = np.max([ -np.abs(phase_mean) - 4 * phase_std, -np.abs(ati_phase).max() ]) vmax = np.min( [np.abs(phase_mean) + 4 * phase_std, np.abs(ati_phase).max()]) plt.figure() plt.imshow(ati_phase, aspect='equal', origin='lower', vmin=vmin, vmax=vmax, extent=[0., rg_span, 0., az_span], cmap='hsv') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("ATI Phase") plt.colorbar() plt.savefig(save_path) save_path = (plot_path + os.sep + 'ATI_rvel_' + polt[pind] + polt[pind] + '.' + plot_format) vmin = -np.abs(v_radial_surf_mean) - 4. * v_radial_surf_std vmax = np.abs(v_radial_surf_mean) + 4. * v_radial_surf_std plt.figure() plt.imshow(v_radial_est, aspect='equal', origin='lower', vmin=vmin, vmax=vmax, extent=[0., rg_span, 0., az_span], cmap='bwr') plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("Estimated Radial Velocity " + polt[pind]) plt.colorbar() plt.savefig(save_path) if npol_ == 4: # Bypass this for now # Cross pol interferogram coh_ind = coh_lut[(0, 1)] save_path = (plot_path + os.sep + 'POL_coh_' + polt[0] + polt[1] + '.' + plot_format) utils.image(np.abs(cohs[coh_ind]), max=1, min=0, aspect='equal', cmap='gray', extent=[0., rg_span, 0., az_span], xlabel='Ground range [m]', ylabel='Azimuth [m]', title='XPOL Coherence', usetex=plot_tex, save=plot_save, save_path=save_path) save_path = (plot_path + os.sep + 'POL_pha_' + polt[0] + polt[1] + '.' + plot_format) ati_phase = uwphase(cohs[coh_ind]) phase_mean = np.mean(ati_phase) phase_std = np.std(ati_phase) vmin = np.max([-np.abs(phase_mean) - 4 * phase_std, -np.pi]) vmax = np.min([np.abs(phase_mean) + 4 * phase_std, np.pi]) utils.image(ati_phase, aspect='equal', min=vmin, max=vmax, cmap=utils.bwr_cmap, extent=[0., rg_span, 0., az_span], xlabel='Ground range [m]', ylabel='Azimuth [m]', title='XPOL Phase', cbar_xlabel='[rad]', usetex=plot_tex, save=plot_save, save_path=save_path) if num_ch > 1: ati_phases = np.array(ati_phases) output.write('--------------------------------------------\n') output.write('SURFACE RADIAL VELOCITY - NO SMOOTHING\n') output.write('MEAN(SURF. V) = %.4f\n' % v_radial_surf_mean) output.write('STD(SURF. V) = %.4f\n' % v_radial_surf_std) output.write('--------------------------------------------\n\n') output.write('--------------------------------------------\n') output.write( 'SURFACE RADIAL VELOCITY - SMOOTHING (WIN. SIZE=%dx%d)\n' % (az_ml, rg_ml)) output.write('MEAN(SURF. V) = %.4f\n' % v_radial_surf_mean) output.write('STD(SURF. V) = %.4f\n' % v_radial_surf_ml_std) output.write('--------------------------------------------\n\n') output.write('--------------------------------------------\n') output.write('SURFACE HORIZONTAL VELOCITY - NO SMOOTHING\n') output.write('MEAN(SURF. V) = %.4f\n' % v_horizo_surf_mean) output.write('STD(SURF. V) = %.4f\n' % v_horizo_surf_std) output.write('--------------------------------------------\n\n') if plot_vel_hist: # PLOT RADIAL VELOCITY plt.figure() plt.hist(v_radial_surf.flatten(), 200, density=True, histtype='step') #plt.hist(v_radial_surf_ml.flatten(), 500, density=True, histtype='step') plt.grid(True) plt.xlim([ -np.abs(v_radial_surf_mean) - 4. * v_radial_surf_std, np.abs(v_radial_surf_mean) + 4. * v_radial_surf_std ]) plt.xlabel('Radial velocity [m/s]') plt.ylabel('PDF') plt.title('Surface velocity') if plot_save: plt.savefig(plot_path + os.sep + 'TRUE_radial_vel_hist.' + plot_format) plt.close() else: plt.show() plt.figure() plt.hist(v_radial_surf_ml.flatten(), 200, density=True, histtype='step') #plt.hist(v_radial_surf_ml.flatten(), 500, density=True, histtype='step') plt.grid(True) plt.xlim([ -np.abs(v_radial_surf_mean) - 4. * v_radial_surf_std, np.abs(v_radial_surf_mean) + 4. * v_radial_surf_std ]) plt.xlabel('Radial velocity [m/s]') plt.ylabel('PDF') plt.title('Surface velocity (low pass filtered)') if plot_save: plt.savefig(plot_path + os.sep + 'TRUE_radial_vel_ml_hist.' + plot_format) plt.close() else: plt.show() if plot_vel: utils.image( v_radial_surf, aspect='equal', cmap=utils.bwr_cmap, extent=[0., rg_span, 0., az_span], xlabel='Ground range [m]', ylabel='Azimuth [m]', title='Surface Radial Velocity', cbar_xlabel='[m/s]', min=-np.abs(v_radial_surf_mean) - 4. * v_radial_surf_std, max=np.abs(v_radial_surf_mean) + 4. * v_radial_surf_std, usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'TRUE_radial_vel.' + plot_format) utils.image( v_radial_surf_ml, aspect='equal', cmap=utils.bwr_cmap, extent=[0., rg_span, 0., az_span], xlabel='Ground range [m]', ylabel='Azimuth [m]', title='Surface Radial Velocity', cbar_xlabel='[m/s]', min=-np.abs(v_radial_surf_mean) - 4. * v_radial_surf_std, max=np.abs(v_radial_surf_mean) + 4. * v_radial_surf_std, usetex=plot_tex, save=plot_save, save_path=plot_path + os.sep + 'TRUE_radial_vel_ml.' + plot_format) ## ESTIMATED VELOCITIES # Note: plot limits are taken from surface calculations to keep the same ranges # ESTIMATE RADIAL VELOCITY v_radial_ests = -ati_phases / tau_ati[1] / (k0 * 2.) # ESTIMATE HORIZONTAL VELOCITY v_horizo_ests = -ati_phases / tau_ati[1] / (k0 * 2.) / np.sin(inc_angle) #Trim edges v_radial_ests = v_radial_ests[:, az_guard:-az_guard, 5:-5] v_horizo_ests = v_horizo_ests[:, az_guard:-az_guard, 5:-5] output.write('--------------------------------------------\n') output.write('ESTIMATED RADIAL VELOCITY - NO SMOOTHING\n') for pind in range(npol): output.write("%s Polarization\n" % polt[pind]) output.write('MEAN(EST. V) = %.4f\n' % np.mean(v_radial_ests[pind])) output.write('STD(EST. V) = %.4f\n' % np.std(v_radial_ests[pind])) output.write('--------------------------------------------\n\n') output.write('--------------------------------------------\n') output.write( 'ESTIMATED RADIAL VELOCITY - SMOOTHING (WIN. SIZE=%dx%d)\n' % (az_ml, rg_ml)) for pind in range(npol): output.write("%s Polarization\n" % polt[pind]) output.write('MEAN(EST. V) = %.4f\n' % np.mean( utils.smooth(utils.smooth(v_radial_ests[pind], rg_ml, axis=1), az_ml, axis=0))) output.write('STD(EST. V) = %.4f\n' % np.std( utils.smooth(utils.smooth(v_radial_ests[pind], rg_ml, axis=1), az_ml, axis=0))) output.write('--------------------------------------------\n\n') output.write('--------------------------------------------\n') output.write('ESTIMATED HORIZONTAL VELOCITY - NO SMOOTHING\n') for pind in range(npol): output.write("%s Polarization\n" % polt[pind]) output.write('MEAN(EST. V) = %.4f\n' % np.mean(v_horizo_ests[pind])) output.write('STD(EST. V) = %.4f\n' % np.std(v_horizo_ests[pind])) output.write('--------------------------------------------\n\n') # Processed NRCS NRCS_est_avg = 10 * np.log10( np.mean(np.mean(i_all[:, :, az_guard:-az_guard, 5:-5], axis=-1), axis=-1)) output.write('--------------------------------------------\n') for pind in range(npol): output.write("%s Polarization\n" % polt[pind]) output.write('Estimated mean NRCS = %5.2f\n' % NRCS_est_avg[0, pind]) output.write('--------------------------------------------\n\n') # Some bookkeeping information output.write('--------------------------------------------\n') output.write('GROUND RANGE GRID SPACING = %.4f\n' % grg_grid_spacing) output.write('AZIMUTH GRID SPACING = %.4f\n' % az_grid_spacing) output.write('--------------------------------------------\n\n') output.close() if plot_vel_hist and num_ch > 1: # PLOT RADIAL VELOCITY plt.figure() plt.hist(v_radial_surf.flatten(), 200, density=True, histtype='step', label='True') for pind in range(npol): plt.hist(v_radial_ests[pind].flatten(), 200, density=True, histtype='step', label=polt[pind]) plt.grid(True) plt.xlim([ -np.abs(v_radial_surf_mean) - 4. * v_radial_surf_std, np.abs(v_radial_surf_mean) + 4. * v_radial_surf_std ]) plt.xlabel('Radial velocity [m/s]') plt.ylabel('PDF') plt.title('Estimated velocity') plt.legend() if plot_save: plt.savefig(plot_path + os.sep + 'ATI_radial_vel_hist.' + plot_format) plt.close() else: plt.show() # Save some statistics to npz file # if num_ch > 1: filenpz = os.path.join(os.path.dirname(output_file), 'ati_stats.npz') # Mean coh cohs = np.array(cohs)[:, az_guard:-az_guard, 5:-5] np.savez(filenpz, nrcs=NRCS_est_avg, v_r_dop=np.mean(np.mean(v_radial_ests, axis=-1), axis=-1), v_r_surf=v_radial_surf_mean, v_r_surf_std=v_radial_surf_std, coh_mean=np.mean(np.mean(cohs, axis=-1), axis=-1), abscoh_mean=np.mean(np.mean(np.abs(cohs), axis=-1), axis=-1), coh_lut=coh_lut, pols=polt) print('----------------------------------------') print( time.strftime("ATI Processing finished [%Y-%m-%d %H:%M:%S]", time.localtime())) print('----------------------------------------')