def postprocess_batch_read_fd(template_file, plots=True): cfg_file = utils.get_parFile(parfile=template_file) ref_cfg = osrio.ConfigFile(cfg_file) num = ref_cfg.radar.n_pulses - 1 Doppler_av = np.zeros((np.size(No)*np.size(Time), np.size(inc_s), np.size(azimuth_s), num), dtype=np.complex) coh_av = np.zeros((np.size(No)*np.size(Time), np.size(inc_s), np.size(azimuth_s), num), dtype=np.complex) for iii in range(np.size(No)): path_m = ref_cfg.sim.path + os.sep + 'SKIM_12deg_rar_%d'%(No[iii]) sim_path_ref = path_m + os.sep + 'Time%d_inc_s%d_azimuth_s%d' for ind_t in range(np.size(Time)): for ind_inc in range(np.size(inc_s)): for ind_azimuth in range(np.size(azimuth_s)): # Read data path = sim_path_ref % (Time[ind_t], inc_s[ind_inc], azimuth_s[ind_azimuth]) data = np.load(os.path.join(path, 'pp_data.nc.npz')) Doppler_av[iii*np.size(Time) + ind_t, ind_inc, ind_azimuth, :] = data['dop_pp_avg'] coh_av[iii*np.size(Time)+ind_t, ind_inc, ind_azimuth, :] = data['coh'] if ref_cfg.processing.Azi_img: np.save(os.path.join(ref_cfg.sim.path, 'Doppler_coherence_data_unfocus.npy'), [Doppler_av, coh_av, num]) else: np.save(os.path.join(ref_cfg.sim.path, 'Doppler_coherence_data.npy'), [Doppler_av, coh_av, num])
def batch_sarsim(template_file): cfg_file = utils.get_parFile(parfile=template_file) ref_cfg = osrio.ConfigFile(cfg_file) step = 0 sim_path_ref = ref_cfg.sim.path + os.sep + 'sim_U%d_wdir%d_smag%d_sdir%d_inc%d_i%i' n_all = (np.size(v_wind_U) * np.size(v_wind_dir) * np.size(v_current_mag) * np.size(v_current_dir) * np.size(v_inc_angle) * n_rep) for wind_U in v_wind_U: for wind_dir in v_wind_dir: for current_mag in v_current_mag: for current_dir in v_current_dir: for inc_angle in v_inc_angle: for i_rep in np.arange(n_rep, dtype=np.int): step = step + 1 print("") print( 'CONFIGURATION AND LAUNCH OF SIMULATION %d of %d' % (step, n_all)) ### CONFIGURATION FILE ### # Load template cfg = ref_cfg # Modify template, create directory & save cfg.sim.path = sim_path_ref % ( wind_U, wind_dir, current_mag, current_dir, inc_angle, i_rep) cfg.ocean.wind_U = wind_U cfg.ocean.wind_dir = wind_dir cfg.ocean.current_mag = current_mag cfg.ocean.current_dir = current_dir cfg.sar.inc_angle = inc_angle if not os.path.exists(cfg.sim.path): os.makedirs(cfg.sim.path) # Save configuration file into an alternate file cfg.save(cfg.sim.path + os.sep + cfg_file_name) ### LAUNCH MACSAR ### subprocess.call([ sys.executable, osr_script, cfg.sim.path + os.sep + cfg_file_name ])
def sarsim(cfg_file=None): print( '-------------------------------------------------------------------', flush=True) print(time.strftime("OCEANSAR SAR Simulator [%Y-%m-%d %H:%M:%S]", time.localtime()), flush=True) # print('Copyright (c) Gerard Marull Paretas, Paco López-Dekker') print( '-------------------------------------------------------------------', flush=True) cfg_file = utils.get_parFile(parfile=cfg_file) cfg = osrio.ConfigFile(cfg_file) # Create output directory if it doesnt exist already os.makedirs(cfg.sim.path, exist_ok=True) src_path = os.path.dirname(os.path.abspath(__file__)) # RAW if cfg.sim.raw_run: print('Launching SAR RAW Generator...') args = [ cfg.sim.mpi_exec, '-np', str(cfg.sim.mpi_num_proc), sys.executable, src_path + os.sep + 'sar_raw.py', '-c', cfg.cfg_file_name, '-o', cfg.sim.path + os.sep + cfg.sim.raw_file, '-oc', cfg.sim.path + os.sep + cfg.sim.ocean_file, '-er', cfg.sim.path + os.sep + cfg.sim.errors_file ] if cfg.sim.ocean_reuse: args.append('-ro') if cfg.sim.errors_reuse: args.append('-re') returncode = subprocess.call(args) if returncode != 0: raise Exception( 'Something went wrong with SAR RAW Generator (return code %d)...' % returncode) # Processing if cfg.sim.proc_run: print('Launching SAR RAW Processor...') returncode = subprocess.call([ sys.executable, src_path + os.sep + 'sar_processor.py', '-c', cfg.cfg_file_name, '-r', cfg.sim.path + os.sep + cfg.sim.raw_file, '-o', cfg.sim.path + os.sep + cfg.sim.proc_file ]) if returncode != 0: raise Exception( 'Something went wrong with SAR RAW Processor (return code %d)...' % returncode) # ATI if cfg.sim.corar_run: print('CoRAR Processing') if cfg.sim.ati_run: print('Launching SAR ATI Processor...') returncode = subprocess.call([ sys.executable, src_path + os.sep + 'ati_processor.py', '-c', cfg.cfg_file_name, '-p', cfg.sim.path + os.sep + cfg.sim.proc_file, '-s', cfg.sim.path + os.sep + cfg.sim.ocean_file, '-o', cfg.sim.path + os.sep + cfg.sim.ati_file ]) if returncode != 0: raise Exception( 'Something went wrong with SAR ATI Processor (return code %d)...' % returncode) print('----------------------------------', flush=True) print(time.strftime("End of tasks [%Y-%m-%d %H:%M:%S]", time.localtime()), flush=True) print('----------------------------------', flush=True)
def batch_skimsim(template_file): for iii in range(np.size(No)): cfg_file = utils.get_parFile(parfile=template_file) ref_cfg = osrio.ConfigFile(cfg_file) path_m = ref_cfg.sim.path + os.sep + 'SKIM_12deg_rar_%d'%(No[iii]) sim_path_ref = path_m + os.sep + 'Time%d_inc_s%d_azimuth_s%d' for t in Time: for inc_angle in inc_s: for azimuth in azimuth_s: ### CONFIGURATION FILE ### # Load template cfg = ref_cfg # Modify template, create directory & save cfg.sim.path = sim_path_ref % (t, inc_angle, azimuth) cfg.batch_Loop.t = t cfg.radar.inc_angle = inc_angle cfg.radar.azimuth = azimuth if not os.path.exists(cfg.sim.path): os.makedirs(cfg.sim.path) # Save configuration file into an alternate file cfg.save(cfg.sim.path + os.sep + cfg_file_name) cfg_file = utils.get_parFile(parfile=template_file) ref_cfg = osrio.ConfigFile(cfg_file) step = 0 sim_path_ref = ref_cfg.sim.path + os.sep + 'Time%d_inc_s%d_azimuth_s%d_wavelength%1f' n_all = (np.size(Time) * np.size(inc_s) * np.size(azimuth_s) * np.size(wave_scale)*n_rep) for t in Time: for inc_angle in inc_s: for azimuth in azimuth_s: for wave_length in wave_scale: step = step + 1 print("") print('CONFIGURATION AND LAUNCH OF SIMULATION %d of %d' % (step, n_all)) ### CONFIGURATION FILE ### # Load template cfg = ref_cfg # Modify template, create directory & save cfg.sim.path = sim_path_ref % (t, inc_angle, azimuth, wave_length) cfg.batch_Loop.t = t cfg.radar.inc_angle = inc_angle cfg.radar.azimuth = azimuth cfg.processing.wave_scale = wave_length if not os.path.exists(cfg.sim.path): os.makedirs(cfg.sim.path) # Save configuration file into an alternate file cfg.save(cfg.sim.path + os.sep + cfg_file_name) ### LAUNCH MACSAR ### subprocess.call([sys.executable, osr_script, '-c', cfg.sim.path + os.sep + cfg_file_name])
def postprocess_batch_read(template_file, plots=True): cfg_file = utils.get_parFile(parfile=template_file) ref_cfg = osrio.ConfigFile(cfg_file) wave_scale = ref_cfg.processing.wave_scale path_m = ref_cfg.sim.path + os.sep + 'SKIM_12deg_rar_%d'%(No[0]) if ref_cfg.processing.Azi_img: sim_path_ref = path_m + os.sep + 'Time%d_inc_s%d_azimuth_s%d' + os.sep + 'wavelength%.1f_unfocus' else: sim_path_ref = path_m + os.sep + 'Time%d_inc_s%d_azimuth_s%d' + os.sep + 'wavelength%.1f' path = sim_path_ref % (Time[0], inc_s[0], azimuth_s[0], wave_scale[0]) + os.sep + 'delta_k_spectrum_plots' data = np.load(os.path.join(path, 'Angular_velocity.npy')) analyse_num = data[3] si = data[2] Angular_velocity_curves = np.zeros((np.size(No)*np.size(Time), np.size(inc_s), np.size(azimuth_s), np.size(wave_scale), int(data[2])), dtype=np.complex) Angular_velocity_av = np.zeros((np.size(No)*np.size(Time), np.size(inc_s), np.size(azimuth_s), np.size(wave_scale), 0), dtype=np.complex) Phase_velocity_curves = np.zeros((np.size(No)*np.size(Time), np.size(inc_s), np.size(azimuth_s), np.size(wave_scale), int(data[2])), dtype=np.complex) Phase_velocity_av = np.zeros((np.size(No)*np.size(Time), np.size(inc_s), np.size(azimuth_s), np.size(wave_scale), 0), dtype=np.complex) for iii in range(np.size(No)): path_m = ref_cfg.sim.path + os.sep + 'SKIM_12deg_rar_%d'%(No[iii]) if ref_cfg.processing.Azi_img: sim_path_ref = path_m + os.sep + 'Time%d_inc_s%d_azimuth_s%d' + os.sep + 'wavelength%.1f_unfocus' else: sim_path_ref = path_m + os.sep + 'Time%d_inc_s%d_azimuth_s%d' + os.sep + 'wavelength%.1f' for ind_t in range(np.size(Time)): for ind_inc in range(np.size(inc_s)): for ind_azimuth in range(np.size(azimuth_s)): for ind_wavelength in range(np.size(wave_scale)): # Read data path = sim_path_ref % (Time[ind_t], inc_s[ind_inc], azimuth_s[ind_azimuth], wave_scale[ind_wavelength]) + os.sep + 'delta_k_spectrum_plots' data = np.load(os.path.join(path, 'Angular_velocity.npy')) Angular_velocity_curves[iii*np.size(Time) + ind_t, ind_inc, ind_azimuth, ind_wavelength, :] = data[0] Angular_velocity_av[iii*np.size(Time)+ind_t, ind_inc, ind_azimuth, ind_wavelength, :] = data[1] data_p = np.load(os.path.join(path, 'Phase_velocity.npy')) Phase_velocity_curves[iii*np.size(Time)+ind_t, ind_inc, ind_azimuth, ind_wavelength, :] = data_p[0] Phase_velocity_av[iii*np.size(Time)+ind_t, ind_inc, ind_azimuth, ind_wavelength, :] = data_p[1] if ref_cfg.processing.Azi_img: np.save(os.path.join(ref_cfg.sim.path, 'Angular_velocity_data_unfocus.npy'), [Angular_velocity_curves, Angular_velocity_av, si, analyse_num]) np.save(os.path.join(ref_cfg.sim.path, 'Phase_velocity_data_unfocus.npy'), [Phase_velocity_curves, Phase_velocity_av, si, analyse_num]) else: np.save(os.path.join(ref_cfg.sim.path, 'Angular_velocity_data.npy'), [Angular_velocity_curves, Angular_velocity_av, si, analyse_num]) np.save(os.path.join(ref_cfg.sim.path, 'Phase_velocity_data.npy'), [Phase_velocity_curves, Phase_velocity_av, si, analyse_num])
def postprocess_batch_sim(template_file, plots=True): cfg_file = utils.get_parFile(parfile=template_file) ref_cfg = osrio.ConfigFile(cfg_file) if cfg.processing.Azi_img: sim_path_ref = ref_cfg.sim.path + os.sep + 'Time%d_inc_s%d_azimuth_s%d' + os.sep + 'wavelength%.1f_unfocus' else: sim_path_ref = ref_cfg.sim.path + os.sep + 'Time%d_inc_s%d_azimuth_s%d' + os.sep + 'wavelength%.1f' wave_scale = ref_cfg.processing.wave_scale sim_path_ref = ref_cfg.sim.path + os.sep + 'Time%d_inc_s%d_azimuth_s%d_wavelength%1f' n_all = (np.size(Time) * np.size(inc_s) * np.size(azimuth_s) * np.size(wave_scale) * n_rep) sim_path_ref = ref_cfg.sim.path + os.sep + 'Time%d_inc_s%d_azimuth_s%d_wavelength%1f' n_all = (np.size(Time) * np.size(inc_s) * np.size(azimuth_s) * np.size(wave_scale) * n_rep) path = sim_path_ref % (Time[0], inc_s[0], azimuth_s[0], wave_scale[0]) + os.sep + 'delta_k_spectrum_plots' # Angular velocity data = np.load(os.path.join(path, 'Angular_velocity.npy')) Angular_velocity_curves = np.zeros((np.size(Time), np.size(inc_s), np.size(azimuth_s), np.size(wave_scale), int(data[2])), dtype=np.complex) Angular_velocity_av = np.zeros((np.size(Time), np.size(inc_s), np.size(azimuth_s), np.size(wave_scale), 0), dtype=np.complex) analyse_num = data[3] # Phase velocity data_p = np.load(os.path.join(path, 'Phase_velocity.npy')) Phase_velocity_curves = np.zeros((np.size(Time), np.size(inc_s), np.size(azimuth_s), np.size(wave_scale), int(data_p[2])), dtype=np.complex) Phase_velocity_av = np.zeros((np.size(Time), np.size(inc_s), np.size(azimuth_s), np.size(wave_scale), 0), dtype=np.complex) for ind_t in range(np.size(Time)): for ind_inc in range(np.size(inc_s)): for ind_azimuth in range(np.size(azimuth_s)): for ind_wavelength in range(np.size(wave_scale)): # Read data path = sim_path_ref % (Time[ind_t], inc_s[ind_inc], azimuth_s[ind_azimuth], wave_scale[ind_wavelength]) + os.sep + 'delta_k_spectrum_plots' data = np.load(os.path.join(path, 'Angular_velocity.npy')) Angular_velocity_curves[ind_t, ind_inc, ind_azimuth, ind_wavelength, :] = data[0] Angular_velocity_av[ind_t, ind_inc, ind_azimuth, ind_wavelength, :] = data[1] data_p = np.load(os.path.join(path, 'Phase_velocity.npy')) Phase_velocity_curves[ind_t, ind_inc, ind_azimuth, ind_wavelength, :] = data_p[0] Phase_velocity_av[ind_t, ind_inc, ind_azimuth, ind_wavelength, :] = data_p[1] plot_path = sim_path_ref + os.sep + 'Averaging_through_time' for ind_inc in range(np.size(inc_s)): for ind_azimuth in range(np.size(azimuth_s)): for ind_wavelength in range(np.size(wave_scale)): value = np.mean(Angular_velocity_curves[:, ind_inc, ind_azimuth, ind_wavelength, :], axis=0) av_value = np.mean( Angular_velocity_av[ind_t, ind_inc, ind_azimuth, ind_wavelength, :],axis=0) value_p = np.mean(Phase_velocity_curves[:, ind_inc, ind_azimuth, ind_wavelength, :], axis=0) av_value_p = np.mean( Phase_velocity_av[ind_t, ind_inc, ind_azimuth, ind_wavelength, :],axis=0) print(inc_s[ind_inc],'deg') print(azimuth_s[ind_azimuth],'deg') print(wave_scale[ind_wavelength],'m') print(av_value,'rad/s') print(av_value,'m/s') if plots: plt.figure() plt.plot(analyse_num, value) plt.xlabel("Azimuth interval [Pixel]") plt.ylabel("Angular velocity (rad/s)") plt.title("Incidence angle = %d deg, Azimuth angle = %d deg, wave_length = %.1f m" % (inc_s[ind_inc], azimuth_s[ind_azimuth], wave_scale[ind_wavelength])) plt.savefig(os.path.join(ref_cfg.sim.path, 'Time_averaging_angular_velocity_%d_%d_%.1f.png' % (inc_s[ind_inc], azimuth_s[ind_azimuth], wave_scale[ind_wavelength]))) plt.close() plt.figure() plt.plot(analyse_num, value_p) plt.xlabel("Azimuth interval [Pixel]") plt.ylabel("Phase velocity (m/s)") plt.title("Incidence angle = %d deg, Azimuth angle = %d deg, wave_length = %.1f m" % (inc_s[ind_inc], azimuth_s[ind_azimuth], wave_scale[ind_wavelength])) plt.savefig(os.path.join(ref_cfg.sim.path, 'Time_averaging_angular_velocity_%d_%d_%.1f.png' % (inc_s[ind_inc], azimuth_s[ind_azimuth], wave_scale[ind_wavelength]))) plt.close()
def sarraw(cfg_file, output_file, ocean_file, reuse_ocean_file, errors_file, reuse_errors_file): ################### # INITIALIZATIONS # ################### ## MPI SETUP comm = MPI.COMM_WORLD size, rank = comm.Get_size(), comm.Get_rank() ## WELCOME if rank == 0: print( '-------------------------------------------------------------------' ) print((time.strftime("- OCEANSAR SAR RAW GENERATOR: %Y-%m-%d %H:%M:%S", time.localtime()))) print('- Copyright (c) Gerard Marull Paretas, Paco Lopez Dekker') print( '-------------------------------------------------------------------' ) ## CONFIGURATION FILE # Note: variables are 'copied' to reduce code verbosity cfg = tpio.ConfigFile(cfg_file) # RAW wh_tol = cfg.srg.wh_tol nesz = cfg.srg.nesz use_hmtf = cfg.srg.use_hmtf scat_spec_enable = cfg.srg.scat_spec_enable scat_spec_mode = cfg.srg.scat_spec_mode scat_bragg_enable = cfg.srg.scat_bragg_enable scat_bragg_model = cfg.srg.scat_bragg_model scat_bragg_d = cfg.srg.scat_bragg_d scat_bragg_spec = cfg.srg.scat_bragg_spec scat_bragg_spread = cfg.srg.scat_bragg_spread # SAR inc_angle = np.deg2rad(cfg.sar.inc_angle) f0 = cfg.sar.f0 pol = cfg.sar.pol if pol == 'DP': do_hh = True do_vv = True elif pol == 'hh': do_hh = True do_vv = False else: do_hh = False do_vv = True prf = cfg.sar.prf num_ch = int(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 sigma_n_tx = cfg.sar.sigma_n_tx phase_n_tx = np.deg2rad(cfg.sar.phase_n_tx) sigma_beta_tx = cfg.sar.sigma_beta_tx phase_beta_tx = np.deg2rad(cfg.sar.phase_beta_tx) sigma_n_rx = cfg.sar.sigma_n_rx phase_n_rx = np.deg2rad(cfg.sar.phase_n_rx) sigma_beta_rx = cfg.sar.sigma_beta_rx phase_beta_rx = np.deg2rad(cfg.sar.phase_beta_rx) # OCEAN / OTHERS ocean_dt = cfg.ocean.dt add_point_target = False use_numba = True n_sinc_samples = 8 sinc_ovs = 20 chan_sinc_vec = raw.calc_sinc_vec(n_sinc_samples, sinc_ovs, Fs=over_fs) # OCEAN SURFACE if rank == 0: print('Initializing ocean surface...') surface_full = OceanSurface() # Setup compute values compute = ['D', 'Diff', 'Diff2'] if use_hmtf: compute.append('hMTF') # Try to reuse initialized surface if reuse_ocean_file: try: surface_full.load(ocean_file, compute) except RuntimeError: pass if (not reuse_ocean_file) or (not surface_full.initialized): surface_full.init(cfg.ocean.Lx, cfg.ocean.Ly, cfg.ocean.dx, cfg.ocean.dy, cfg.ocean.cutoff_wl, cfg.ocean.spec_model, cfg.ocean.spread_model, np.deg2rad(cfg.ocean.wind_dir), cfg.ocean.wind_fetch, cfg.ocean.wind_U, cfg.ocean.current_mag, np.deg2rad(cfg.ocean.current_dir), cfg.ocean.swell_enable, cfg.ocean.swell_ampl, np.deg2rad(cfg.ocean.swell_dir), cfg.ocean.swell_wl, compute, cfg.ocean.opt_res, cfg.ocean.fft_max_prime, choppy_enable=cfg.ocean.choppy_enable) surface_full.save(ocean_file) else: surface_full = None # Initialize surface balancer surface = OceanSurfaceBalancer(surface_full, ocean_dt) # CALCULATE PARAMETERS if rank == 0: print('Initializing simulation parameters...') # SR/GR/INC Matrixes sr0 = geosar.inc_to_sr(inc_angle, alt) gr0 = geosar.inc_to_gr(inc_angle, alt) gr = surface.x + gr0 sr, inc, _ = geosar.gr_to_geo(gr, alt) sr -= np.min(sr) #inc = np.repeat(inc[np.newaxis, :], surface.Ny, axis=0) #sr = np.repeat(sr[np.newaxis, :], surface.Ny, axis=0) #gr = np.repeat(gr[np.newaxis, :], surface.Ny, axis=0) #Let's try to safe some memory and some operations inc = inc.reshape(1, inc.size) sr = sr.reshape(1, sr.size) gr = gr.reshape(1, gr.size) sin_inc = np.sin(inc) cos_inc = np.cos(inc) # lambda, K, resolution, time, etc. l0 = const.c / f0 k0 = 2. * np.pi * f0 / const.c sr_res = const.c / (2. * rg_bw) if cfg.sar.L_total: ant_L = ant_L / np.float(num_ch) d_chan = ant_L else: if np.float(cfg.sar.Spacing) != 0: d_chan = np.float(cfg.sar.Spacing) else: d_chan = ant_L if v_ground == 'auto': v_ground = geosar.orbit_to_vel(alt, ground=True) t_step = 1. / prf t_span = (1.5 * (sr0 * l0 / ant_L) + surface.Ly) / v_ground az_steps = np.int(np.floor(t_span / t_step)) # Number of RG samples max_sr = np.max(sr) + wh_tol + (np.max(surface.y_full) + (t_span / 2.) * v_ground)**2. / (2. * sr0) min_sr = np.min(sr) - wh_tol rg_samp_orig = np.int(np.ceil(((max_sr - min_sr) / sr_res) * over_fs)) rg_samp = np.int(utils.optimize_fftsize(rg_samp_orig)) # Other initializations if do_hh: proc_raw_hh = np.zeros([num_ch, az_steps, rg_samp], dtype=np.complex) if do_vv: proc_raw_vv = np.zeros([num_ch, az_steps, rg_samp], dtype=np.complex) t_last_rcs_bragg = -1. last_progress = -1 NRCS_avg_vv = np.zeros(az_steps, dtype=np.float) NRCS_avg_hh = np.zeros(az_steps, dtype=np.float) ## RCS MODELS # Specular if scat_spec_enable: if scat_spec_mode == 'kodis': rcs_spec = rcs.RCSKodis(inc, k0, surface.dx, surface.dy) elif scat_spec_mode == 'fa' or scat_spec_mode == 'spa': spec_ph0 = np.random.uniform(0., 2. * np.pi, size=[surface.Ny, surface.Nx]) rcs_spec = rcs.RCSKA(scat_spec_mode, k0, surface.x, surface.y, surface.dx, surface.dy) else: raise NotImplementedError( 'RCS mode %s for specular scattering not implemented' % scat_spec_mode) # Bragg if scat_bragg_enable: phase_bragg = np.zeros([2, surface.Ny, surface.Nx]) bragg_scats = np.zeros([2, surface.Ny, surface.Nx], dtype=np.complex) # dop_phase_p = np.random.uniform(0., 2.*np.pi, size=[surface.Ny, surface.Nx]) # dop_phase_m = np.random.uniform(0., 2.*np.pi, size=[surface.Ny, surface.Nx]) tau_c = closure.grid_coherence(cfg.ocean.wind_U, surface.dx, f0) rndscat_p = closure.randomscat_ts(tau_c, (surface.Ny, surface.Nx), prf) rndscat_m = closure.randomscat_ts(tau_c, (surface.Ny, surface.Nx), prf) # NOTE: This ignores slope, may be changed k_b = 2. * k0 * sin_inc c_b = sin_inc * np.sqrt(const.g / k_b + 0.072e-3 * k_b) if scat_bragg_model == 'romeiser97': current_dir = np.deg2rad(cfg.ocean.current_dir) current_vec = (cfg.ocean.current_mag * np.array( [np.cos(current_dir), np.sin(current_dir)])) U_dir = np.deg2rad(cfg.ocean.wind_dir) U_vec = (cfg.ocean.wind_U * np.array([np.cos(U_dir), np.sin(U_dir)])) U_eff_vec = U_vec - current_vec rcs_bragg = rcs.RCSRomeiser97( k0, inc, pol, surface.dx, surface.dy, linalg.norm(U_eff_vec), np.arctan2(U_eff_vec[1], U_eff_vec[0]), surface.wind_fetch, scat_bragg_spec, scat_bragg_spread, scat_bragg_d) else: raise NotImplementedError( 'RCS model %s for Bragg scattering not implemented' % scat_bragg_model) surface_area = surface.dx * surface.dy * surface.Nx * surface.Ny ################### # SIMULATION LOOP # ################### if rank == 0: print('Computing profiles...') for az_step in np.arange(az_steps, dtype=np.int): ## AZIMUTH & SURFACE UPDATE t_now = az_step * t_step az_now = (t_now - t_span / 2.) * v_ground # az = np.repeat((surface.y - az_now)[:, np.newaxis], surface.Nx, axis=1) az = (surface.y - az_now).reshape((surface.Ny, 1)) surface.t = t_now ## COMPUTE RCS FOR EACH MODEL # Note: SAR processing is range independent as slant range is fixed sin_az = az / sr0 az_proj_angle = np.arcsin(az / gr0) # Note: Projected displacements are added to slant range sr_surface = (sr - cos_inc * surface.Dz + az / 2 * sin_az + surface.Dx * sin_inc + surface.Dy * sin_az) if do_hh: scene_hh = np.zeros( [int(surface.Ny), int(surface.Nx)], dtype=np.complex) if do_vv: scene_vv = np.zeros( [int(surface.Ny), int(surface.Nx)], dtype=np.complex) # Point target if add_point_target and rank == 0: sr_pt = (sr[0, surface.Nx / 2] + az[surface.Ny / 2, 0] / 2 * sin_az[surface.Ny / 2, surface.Nx / 2]) pt_scat = (100. * np.exp(-1j * 2. * k0 * sr_pt)) if do_hh: scene_hh[surface.Ny / 2, surface.Nx / 2] = pt_scat if do_vv: scene_vv[surface.Ny / 2, surface.Nx / 2] = pt_scat sr_surface[surface.Ny / 2, surface.Nx / 2] = sr_pt # Specular if scat_spec_enable: if scat_spec_mode == 'kodis': Esn_sp = np.sqrt(4. * np.pi) * rcs_spec.field( az_proj_angle, sr_surface, surface.Diffx, surface.Diffy, surface.Diffxx, surface.Diffyy, surface.Diffxy) if do_hh: scene_hh += Esn_sp if do_vv: scene_vv += Esn_sp else: # FIXME if do_hh: pol_tmp = 'hh' Esn_sp = ( np.exp(-1j * (2. * k0 * sr_surface)) * (4. * np.pi)**1.5 * rcs_spec.field( 1, 1, pol_tmp[0], pol_tmp[1], inc, inc, az_proj_angle, az_proj_angle + np.pi, surface.Dz, surface.Diffx, surface.Diffy, surface.Diffxx, surface.Diffyy, surface.Diffxy)) scene_hh += Esn_sp if do_vv: pol_tmp = 'vv' Esn_sp = ( np.exp(-1j * (2. * k0 * sr_surface)) * (4. * np.pi)**1.5 * rcs_spec.field( 1, 1, pol_tmp[0], pol_tmp[1], inc, inc, az_proj_angle, az_proj_angle + np.pi, surface.Dz, surface.Diffx, surface.Diffy, surface.Diffxx, surface.Diffyy, surface.Diffxy)) scene_vv += Esn_sp NRCS_avg_hh[az_step] += (np.sum(np.abs(Esn_sp)**2) / surface_area) NRCS_avg_vv[az_step] += NRCS_avg_hh[az_step] # Bragg if scat_bragg_enable: if (t_now - t_last_rcs_bragg) > ocean_dt: if scat_bragg_model == 'romeiser97': if pol == 'DP': RCS_bragg_hh, RCS_bragg_vv = rcs_bragg.rcs( az_proj_angle, surface.Diffx, surface.Diffy) elif pol == 'hh': RCS_bragg_hh = rcs_bragg.rcs(az_proj_angle, surface.Diffx, surface.Diffy) else: RCS_bragg_vv = rcs_bragg.rcs(az_proj_angle, surface.Diffx, surface.Diffy) if use_hmtf: # Fix Bad MTF points surface.hMTF[np.where(surface.hMTF < -1)] = -1 if do_hh: RCS_bragg_hh[0] *= (1 + surface.hMTF) RCS_bragg_hh[1] *= (1 + surface.hMTF) if do_vv: RCS_bragg_vv[0] *= (1 + surface.hMTF) RCS_bragg_vv[1] *= (1 + surface.hMTF) t_last_rcs_bragg = t_now if do_hh: scat_bragg_hh = np.sqrt(RCS_bragg_hh) NRCS_bragg_hh_instant_avg = np.sum(RCS_bragg_hh) / surface_area NRCS_avg_hh[az_step] += NRCS_bragg_hh_instant_avg if do_vv: scat_bragg_vv = np.sqrt(RCS_bragg_vv) NRCS_bragg_vv_instant_avg = np.sum(RCS_bragg_vv) / surface_area NRCS_avg_vv[az_step] += NRCS_bragg_vv_instant_avg # Doppler phases (Note: Bragg radial velocity taken constant!) surf_phase = -(2 * k0) * sr_surface cap_phase = (2 * k0) * t_step * c_b * (az_step + 1) phase_bragg[0] = surf_phase - cap_phase # + dop_phase_p phase_bragg[1] = surf_phase + cap_phase # + dop_phase_m bragg_scats[0] = rndscat_m.scats(t_now) bragg_scats[1] = rndscat_p.scats(t_now) if do_hh: scene_hh += ne.evaluate( 'sum(scat_bragg_hh * exp(1j*phase_bragg) * bragg_scats, axis=0)' ) if do_vv: scene_vv += ne.evaluate( 'sum(scat_bragg_vv * exp(1j*phase_bragg) * bragg_scats, axis=0)' ) ## ANTENNA PATTERN if cfg.sar.L_total: beam_pattern = sinc_1tx_nrx(sin_az, ant_L * num_ch, f0, num_ch, field=True) else: beam_pattern = sinc_1tx_nrx(sin_az, ant_L, f0, 1, field=True) ## GENERATE CHANEL PROFILES for ch in np.arange(num_ch, dtype=np.int): if do_hh: scene_bp = scene_hh * beam_pattern # Add channel phase & compute profile scene_bp *= np.exp(-1j * k0 * d_chan * ch * sin_az) if use_numba: raw.chan_profile_numba(sr_surface.flatten(), scene_bp.flatten(), sr_res / (over_fs), min_sr, chan_sinc_vec, n_sinc_samples, sinc_ovs, proc_raw_hh[ch][az_step]) else: raw.chan_profile_weave(sr_surface.flatten(), scene_bp.flatten(), sr_res / (over_fs), min_sr, chan_sinc_vec, n_sinc_samples, sinc_ovs, proc_raw_hh[ch][az_step]) if do_vv: scene_bp = scene_vv * beam_pattern # Add channel phase & compute profile scene_bp *= np.exp(-1j * k0 * d_chan * ch * sin_az) if use_numba: raw.chan_profile_numba(sr_surface.flatten(), scene_bp.flatten(), sr_res / (over_fs), min_sr, chan_sinc_vec, n_sinc_samples, sinc_ovs, proc_raw_vv[ch][az_step]) else: raw.chan_profile_weave(sr_surface.flatten(), scene_bp.flatten(), sr_res / (over_fs), min_sr, chan_sinc_vec, n_sinc_samples, sinc_ovs, proc_raw_vv[ch][az_step]) # SHOW PROGRESS (%) current_progress = np.int((100 * az_step) / az_steps) if current_progress != last_progress: last_progress = current_progress print(('SP,%d,%d,%d' % (rank, size, current_progress))) # MERGE RESULTS if do_hh: total_raw_hh = np.empty_like(proc_raw_hh) if rank == 0 else None comm.Reduce(proc_raw_hh, total_raw_hh, op=MPI.SUM, root=0) if do_vv: total_raw_vv = np.empty_like(proc_raw_vv) if rank == 0 else None comm.Reduce(proc_raw_vv, total_raw_vv, op=MPI.SUM, root=0) ## PROCESS REDUCED RAW DATA & SAVE (ROOT) if rank == 0: print('Processing and saving results...') # Filter and decimate #range_filter = np.ones_like(total_raw) #range_filter[:, :, rg_samp/(2*2*cfg.sar.over_fs):-rg_samp/(2*2*cfg.sar.over_fs)] = 0 #total_raw = np.fft.ifft(range_filter*np.fft.fft(total_raw)) if do_hh: total_raw_hh = total_raw_hh[:, :, :rg_samp_orig] if do_vv: total_raw_vv = total_raw_vv[:, :, :rg_samp_orig] # Calibration factor (projected antenna pattern integrated in azimuth) az_axis = np.arange(-t_span / 2. * v_ground, t_span / 2. * v_ground, sr0 * const.c / (np.pi * f0 * ant_L * 10.)) if cfg.sar.L_total: pattern = sinc_1tx_nrx(az_axis / sr0, ant_L * num_ch, f0, num_ch, field=True) else: pattern = sinc_1tx_nrx(az_axis / sr0, ant_L, f0, 1, field=True) cal_factor = (1. / np.sqrt( np.trapz(np.abs(pattern)**2., az_axis) * sr_res / np.sin(inc_angle))) if do_hh: noise = (utils.db2lin(nesz, amplitude=True) / np.sqrt(2.) * (np.random.normal(size=total_raw_hh.shape) + 1j * np.random.normal(size=total_raw_hh.shape))) total_raw_hh = total_raw_hh * cal_factor + noise if do_vv: noise = (utils.db2lin(nesz, amplitude=True) / np.sqrt(2.) * (np.random.normal(size=total_raw_vv.shape) + 1j * np.random.normal(size=total_raw_vv.shape))) total_raw_vv = total_raw_vv * cal_factor + noise # Add slow-time error # if use_errors: # if do_hh: # total_raw_hh *= errors.beta_noise # if do_vv: # total_raw_vv *= errors.beta_noise # Save RAW data (and other properties, used by 3rd party software) if do_hh and do_vv: rshp = (1, ) + total_raw_hh.shape total_raw = np.concatenate( (total_raw_hh.reshape(rshp), total_raw_vv.reshape(rshp))) rshp = (1, ) + NRCS_avg_hh.shape NRCS_avg = np.concatenate( (NRCS_avg_hh.reshape(rshp), NRCS_avg_vv.reshape(rshp))) elif do_hh: rshp = (1, ) + total_raw_hh.shape total_raw = total_raw_hh.reshape(rshp) rshp = (1, ) + NRCS_avg_hh.shape NRCS_avg = NRCS_avg_hh.reshape(rshp) else: rshp = (1, ) + total_raw_vv.shape total_raw = total_raw_vv.reshape(rshp) rshp = (1, ) + NRCS_avg_vv.shape NRCS_avg = NRCS_avg_vv.reshape(rshp) raw_file = tpio.RawFile(output_file, 'w', total_raw.shape) raw_file.set('inc_angle', np.rad2deg(inc_angle)) raw_file.set('f0', f0) raw_file.set('num_ch', num_ch) raw_file.set('ant_L', ant_L) raw_file.set('prf', prf) raw_file.set('v_ground', v_ground) raw_file.set('orbit_alt', alt) raw_file.set('sr0', sr0) raw_file.set('rg_sampling', rg_bw * over_fs) raw_file.set('rg_bw', rg_bw) raw_file.set('raw_data*', total_raw) raw_file.set('NRCS_avg', NRCS_avg) raw_file.close() print((time.strftime("Finished [%Y-%m-%d %H:%M:%S]", time.localtime())))
def postprocess_batch_sim(template_file, plots=True, fontsize=14, pltsymb=['o', 'D', 's', '^', 'p']): cfg_file = utils.get_parFile(parfile=template_file) ref_cfg = osrio.ConfigFile(cfg_file) step = 0 npol = (2 if ref_cfg.sar.pol == 'DP' else 1) nch = int(ref_cfg.sar.num_ch) nim = nch * npol sim_path_ref = ref_cfg.sim.path + os.sep + 'sim_U%d_wdir%d_smag%d_sdir%d_inc%d_i%i' n_all = (np.size(v_wind_U) * np.size(v_wind_dir) * np.size(v_current_mag) * np.size(v_current_dir) * np.size(v_inc_angle) * n_rep) mean_cohs = np.zeros( (np.size(v_wind_U), np.size(v_wind_dir), np.size(v_current_mag), np.size(v_current_dir), np.size(v_inc_angle), n_rep, int((nim) * (nim - 1) / 2)), dtype=np.complex) mean_abscohs = np.zeros( (np.size(v_wind_U), np.size(v_wind_dir), np.size(v_current_mag), np.size(v_current_dir), np.size(v_inc_angle), n_rep, int((nim) * (nim - 1) / 2)), dtype=np.float) nrcs = np.zeros( (np.size(v_wind_U), np.size(v_wind_dir), np.size(v_current_mag), np.size(v_current_dir), np.size(v_inc_angle), n_rep, nch * npol), dtype=np.float) v_r_dop = np.zeros( (np.size(v_wind_U), np.size(v_wind_dir), np.size(v_current_mag), np.size(v_current_dir), np.size(v_inc_angle), n_rep, npol), dtype=np.float) for ind_w_U in range(np.size(v_wind_U)): for ind_w_dir in range(np.size(v_wind_dir)): for ind_c_mag in range(np.size(v_current_mag)): for ind_c_dir in range(np.size(v_current_dir)): for ind_inc in range(np.size(v_inc_angle)): for i_rep in range(n_rep): # Read data path = sim_path_ref % (v_wind_U[ind_w_U], v_wind_dir[ind_w_dir], v_current_mag[ind_c_mag], v_current_dir[ind_c_dir], v_inc_angle[ind_inc], i_rep) try: data_filename = os.path.join( path, 'ati_stats.npz') npzfile = np.load(data_filename) mean_cohs[ind_w_U, ind_w_dir, ind_c_mag, ind_c_dir, ind_inc, i_rep] = npzfile['coh_mean'] mean_abscohs[ind_w_U, ind_w_dir, ind_c_mag, ind_c_dir, ind_inc, i_rep] = npzfile['abscoh_mean'] nrcs[ind_w_U, ind_w_dir, ind_c_mag, ind_c_dir, ind_inc, i_rep] = npzfile['nrcs'] v_r_dop[ind_w_U, ind_w_dir, ind_c_mag, ind_c_dir, ind_inc, i_rep] = npzfile['v_r_dop'] coh_lut = npzfile['coh_lut'] except OSError: print("Issues with %s" % data_filename) mean_cohs[ind_w_U, ind_w_dir, ind_c_mag, ind_c_dir, ind_inc, i_rep] = np.NaN mean_abscohs[ind_w_U, ind_w_dir, ind_c_mag, ind_c_dir, ind_inc, i_rep] = np.NaN nrcs[ind_w_U, ind_w_dir, ind_c_mag, ind_c_dir, ind_inc, i_rep] = np.NaN v_r_dop[ind_w_U, ind_w_dir, ind_c_mag, ind_c_dir, ind_inc, i_rep] = np.NaN if plots: font = {'family': "Arial", 'weight': 'normal', 'size': fontsize} mpl.rc('font', **font) plt.figure() for ind in range(np.size(v_wind_U)): plt.plot(v_wind_dir, (mean_abscohs[ind, :, 0, 0, 0, 0, 4]), pltsymb[int(np.mod(ind, len(pltsymb)))], label=("U = %2.1f" % (v_wind_U[ind]))) plt.xlabel("Wind direction w.r.t. radar LOS [deg]") plt.ylabel("$\gamma$") plt.legend(loc=0) plt.grid(True) plt.tight_layout() plt.figure() for ind in range(np.size(v_wind_U)): plt.plot(v_wind_dir, v_r_dop[ind, :, 0, 0, 0, 0, 1], pltsymb[int(np.mod(ind, len(pltsymb)))], label=("U = %2.1f" % (v_wind_U[ind]))) plt.xlabel("Wind direction w.r.t. radar LOS [deg]") plt.ylabel("$v_{Dop} [m/s]$") plt.legend(loc=0) plt.grid(True) plt.tight_layout() plt.figure() for ind in range(np.size(v_wind_U)): plt.plot(v_wind_dir, nrcs[ind, :, 0, 0, 0, 0, 1], pltsymb[int(np.mod(ind, len(pltsymb)))], label=("U = %2.1f" % (v_wind_U[ind]))) plt.xlabel("Wind direction w.r.t. radar LOS [deg]") plt.ylabel("$NRCS [dB]$") plt.legend(loc=0) plt.grid(True) plt.tight_layout() return mean_cohs, mean_abscohs, v_r_dop, nrcs, coh_lut
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 multilooking = cfg.ati.multilooking 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(v_radial_surf, res_fact * multilooking) 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(v_horizo_surf, res_fact * multilooking) 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(np.abs(proc_data[chind])**2., multilooking) 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( proc_data[chind2] * np.conj(proc_data[chind1]), multilooking) 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]) 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]) plt.xlabel('Ground range [m]') plt.ylabel('Azimuth [m]') plt.title("Amplitude") plt.colorbar() plt.savefig(save_path) if plot_coh: 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 = [] 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) 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=%d)\n' % multilooking) 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=%d)\n' % multilooking) for pind in range(npol): output.write("%s Polarization\n" % polt[pind]) output.write('MEAN(EST. V) = %.4f\n' % np.mean(utils.smooth(v_radial_ests[pind], multilooking))) output.write('STD(EST. V) = %.4f\n' % np.std(utils.smooth(v_radial_ests[pind], multilooking))) 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: # 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() print('----------------------------------------') print((time.strftime("ATI Processing finished [%Y-%m-%d %H:%M:%S]", time.localtime()))) print('----------------------------------------')
def surface_S(cfg_file=None, inc_deg=None, ntimes=2, t_step=10e-3): """ This function generates a (short) time series of surface realizations. :param scf_file: the full path to the configuration with all OCEANSAR parameters :param inc_deg: the incident angle, in degree :param ntimes: number of time samples generated. :param t_step: spacing between time samples. This can be interpreted as the Pulse Repetition Interval :returns: a tuple with the configuration object, the surfaces, the radial velocities for each grid point, and the complex scattering coefficients """ cfg_file = utils.get_parFile(parfile=cfg_file) cfg = io.ConfigFile(cfg_file) use_hmtf = cfg.srg.use_hmtf scat_spec_enable = cfg.srg.scat_spec_enable scat_spec_mode = cfg.srg.scat_spec_mode scat_bragg_enable = cfg.srg.scat_bragg_enable scat_bragg_model = cfg.srg.scat_bragg_model scat_bragg_d = cfg.srg.scat_bragg_d scat_bragg_spec = cfg.srg.scat_bragg_spec scat_bragg_spread = cfg.srg.scat_bragg_spread # SAR inc_angle = np.deg2rad(cfg.sar.inc_angle) alt = cfg.sar.alt f0 = cfg.sar.f0 prf = cfg.sar.prf pol = cfg.sar.pol l0 = const.c / f0 k0 = 2. * np.pi * f0 / const.c if pol == 'DP': do_hh = True do_vv = True elif pol == 'hh': do_hh = True do_vv = False else: do_hh = False do_vv = True # OCEAN / OTHERS ocean_dt = cfg.ocean.dt surface = OceanSurface() compute = ['D', 'Diff', 'Diff2', 'V'] if use_hmtf: compute.append('hMTF') surface.init(cfg.ocean.Lx, cfg.ocean.Ly, cfg.ocean.dx, cfg.ocean.dy, cfg.ocean.cutoff_wl, cfg.ocean.spec_model, cfg.ocean.spread_model, np.deg2rad(cfg.ocean.wind_dir), cfg.ocean.wind_fetch, cfg.ocean.wind_U, cfg.ocean.current_mag, np.deg2rad(cfg.ocean.current_dir), cfg.ocean.swell_enable, cfg.ocean.swell_ampl, np.deg2rad(cfg.ocean.swell_dir), cfg.ocean.swell_wl, compute, cfg.ocean.opt_res, cfg.ocean.fft_max_prime, choppy_enable=cfg.ocean.choppy_enable) # Get a surface realization calculated surface.t = 0 if inc_deg is None: inc_deg = cfg.sar.inc_angle inc_angle = np.radians(inc_deg) sr0 = geosar.inc_to_sr(inc_angle, alt) gr0 = geosar.inc_to_gr(inc_angle, alt) gr = surface.x + gr0 sr, inc, _ = geosar.gr_to_geo(gr, alt) sr -= np.min(sr) inc = inc.reshape(1, inc.size) sr = sr.reshape(1, sr.size) gr = gr.reshape(1, gr.size) sin_inc = np.sin(inc) cos_inc = np.cos(inc) t_last_rcs_bragg = -1. last_progress = -1 NRCS_avg_vv = np.zeros(ntimes, dtype=np.float) NRCS_avg_hh = np.zeros(ntimes, dtype=np.float) # RCS MODELS # Specular if scat_spec_enable: if scat_spec_mode == 'kodis': rcs_spec = rcs.RCSKodis(inc, k0, surface.dx, surface.dy) elif scat_spec_mode == 'fa' or scat_spec_mode == 'spa': spec_ph0 = np.random.uniform(0., 2. * np.pi, size=[surface.Ny, surface.Nx]) rcs_spec = rcs.RCSKA(scat_spec_mode, k0, surface.x, surface.y, surface.dx, surface.dy) else: raise NotImplementedError( 'RCS mode %s for specular scattering not implemented' % scat_spec_mode) # Bragg if scat_bragg_enable: phase_bragg = np.zeros([2, surface.Ny, surface.Nx]) bragg_scats = np.zeros([2, surface.Ny, surface.Nx], dtype=np.complex) tau_c = closure.grid_coherence(cfg.ocean.wind_U, surface.dx, f0) rndscat_p = closure.randomscat_ts(tau_c, (surface.Ny, surface.Nx), prf) rndscat_m = closure.randomscat_ts(tau_c, (surface.Ny, surface.Nx), prf) # NOTE: This ignores slope, may be changed k_b = 2. * k0 * sin_inc c_b = sin_inc * np.sqrt(const.g / k_b + 0.072e-3 * k_b) if scat_bragg_model == 'romeiser97': current_dir = np.deg2rad(cfg.ocean.current_dir) current_vec = (cfg.ocean.current_mag * np.array( [np.cos(current_dir), np.sin(current_dir)])) U_dir = np.deg2rad(cfg.ocean.wind_dir) U_vec = (cfg.ocean.wind_U * np.array([np.cos(U_dir), np.sin(U_dir)])) U_eff_vec = U_vec - current_vec rcs_bragg = rcs.RCSRomeiser97( k0, inc, pol, surface.dx, surface.dy, linalg.norm(U_eff_vec), np.arctan2(U_eff_vec[1], U_eff_vec[0]), surface.wind_fetch, scat_bragg_spec, scat_bragg_spread, scat_bragg_d) else: raise NotImplementedError( 'RCS model %s for Bragg scattering not implemented' % scat_bragg_model) surface_area = surface.dx * surface.dy * surface.Nx * surface.Ny if do_hh: scene_hh = np.zeros([ntimes, surface.Ny, surface.Nx], dtype=np.complex) if do_vv: scene_vv = np.zeros([ntimes, surface.Ny, surface.Nx], dtype=np.complex) for az_step in range(ntimes): # AZIMUTH & SURFACE UPDATE t_now = az_step * t_step # az_now = (t_now - t_span/2.)*v_ground az_now = 0 # az = np.repeat((surface.y - az_now)[:, np.newaxis], surface.Nx, axis=1) az = (surface.y - az_now).reshape((surface.Ny, 1)) surface.t = t_now ## COMPUTE RCS FOR EACH MODEL # Note: SAR processing is range independent as slant range is fixed sin_az = az / sr0 az_proj_angle = np.arcsin(az / gr0) # Note: Projected displacements are added to slant range sr_surface = (sr - cos_inc * surface.Dz + az / 2 * sin_az + surface.Dx * sin_inc + surface.Dy * sin_az) # Specular if scat_spec_enable: if scat_spec_mode == 'kodis': Esn_sp = np.sqrt(4. * np.pi) * rcs_spec.field( az_proj_angle, sr_surface, surface.Diffx, surface.Diffy, surface.Diffxx, surface.Diffyy, surface.Diffxy) if do_hh: scene_hh[az_step] += Esn_sp if do_vv: scene_vv[az_step] += Esn_sp else: # FIXME if do_hh: pol_tmp = 'hh' Esn_sp = ( np.exp(-1j * (2. * k0 * sr_surface)) * (4. * np.pi)**1.5 * rcs_spec.field( 1, 1, pol_tmp[0], pol_tmp[1], inc, inc, az_proj_angle, az_proj_angle + np.pi, surface.Dz, surface.Diffx, surface.Diffy, surface.Diffxx, surface.Diffyy, surface.Diffxy)) scene_hh[az_step] += Esn_sp if do_vv: pol_tmp = 'vv' Esn_sp = ( np.exp(-1j * (2. * k0 * sr_surface)) * (4. * np.pi)**1.5 * rcs_spec.field( 1, 1, pol_tmp[0], pol_tmp[1], inc, inc, az_proj_angle, az_proj_angle + np.pi, surface.Dz, surface.Diffx, surface.Diffy, surface.Diffxx, surface.Diffyy, surface.Diffxy)) scene_vv[az_step] += Esn_sp NRCS_avg_hh[az_step] += (np.sum(np.abs(Esn_sp)**2) / surface_area) NRCS_avg_vv[az_step] += NRCS_avg_hh[az_step] # Bragg if scat_bragg_enable: if (t_now - t_last_rcs_bragg) > ocean_dt: if scat_bragg_model == 'romeiser97': if pol == 'DP': RCS_bragg_hh, RCS_bragg_vv = rcs_bragg.rcs( az_proj_angle, surface.Diffx, surface.Diffy) elif pol == 'hh': RCS_bragg_hh = rcs_bragg.rcs(az_proj_angle, surface.Diffx, surface.Diffy) else: RCS_bragg_vv = rcs_bragg.rcs(az_proj_angle, surface.Diffx, surface.Diffy) if use_hmtf: # Fix Bad MTF points surface.hMTF[np.where(surface.hMTF < -1)] = -1 if do_hh: RCS_bragg_hh[0] *= (1 + surface.hMTF) RCS_bragg_hh[1] *= (1 + surface.hMTF) if do_vv: RCS_bragg_vv[0] *= (1 + surface.hMTF) RCS_bragg_vv[1] *= (1 + surface.hMTF) t_last_rcs_bragg = t_now if do_hh: scat_bragg_hh = np.sqrt(RCS_bragg_hh) NRCS_bragg_hh_instant_avg = np.sum(RCS_bragg_hh) / surface_area NRCS_avg_hh[az_step] += NRCS_bragg_hh_instant_avg if do_vv: scat_bragg_vv = np.sqrt(RCS_bragg_vv) NRCS_bragg_vv_instant_avg = np.sum(RCS_bragg_vv) / surface_area NRCS_avg_vv[az_step] += NRCS_bragg_vv_instant_avg # Doppler phases (Note: Bragg radial velocity taken constant!) surf_phase = -(2 * k0) * sr_surface cap_phase = (2 * k0) * t_step * c_b * (az_step + 1) phase_bragg[0] = surf_phase - cap_phase # + dop_phase_p phase_bragg[1] = surf_phase + cap_phase # + dop_phase_m bragg_scats[0] = rndscat_m.scats(t_now) bragg_scats[1] = rndscat_p.scats(t_now) if do_hh: scene_hh[az_step] += ne.evaluate( 'sum(scat_bragg_hh * exp(1j*phase_bragg) * bragg_scats, axis=0)' ) if do_vv: scene_vv[az_step] += ne.evaluate( 'sum(scat_bragg_vv * exp(1j*phase_bragg) * bragg_scats, axis=0)' ) v_r = (surface.Vx * np.sin(inc) - surface.Vz * np.cos(inc)) if do_hh and do_vv: return (cfg, surface.Dz, v_r, scene_hh, scene_vv) elif do_hh: return (cfg, surface.Dz, v_r, scene_hh) else: return (cfg, surface.Dz, v_r, scene_vv)
def postprocess_batch_sim(template_file, plots=True): cfg_file = utils.get_parFile(parfile=template_file) ref_cfg = osrio.ConfigFile(cfg_file)
#wave_scale = [100, 37.5, 25, 12.5] <<<<<<< HEAD >>>>>>> parent of 60eb239... Delete oceansar_batchsarsim_skim.py ======= >>>>>>> parent of 60eb239... Delete oceansar_batchsarsim_skim.py n_rep = 1 cfg_file_name = 'config.cfg' def batch_skimsim(template_file): <<<<<<< HEAD <<<<<<< HEAD for iii in range(np.size(No)): cfg_file = utils.get_parFile(parfile=template_file) ref_cfg = osrio.ConfigFile(cfg_file) path_m = ref_cfg.sim.path + os.sep + 'SKIM_12deg_rar_%d'%(No[iii]) sim_path_ref = path_m + os.sep + 'Time%d_inc_s%d_azimuth_s%d' for t in Time: for inc_angle in inc_s: for azimuth in azimuth_s: ### CONFIGURATION FILE ### # Load template cfg = ref_cfg # Modify template, create directory & save cfg.sim.path = sim_path_ref % (t, inc_angle, azimuth) cfg.batch_Loop.t = t cfg.radar.inc_angle = inc_angle
def __init__(self, cfg_file=None, ntimes=2, t_step=10e-3, pol='DP', winddir=0, U10=None): """ This function generates a (short) time series of surface realizations. :param scf_file: the full path to the configuration with all OCEANSAR parameters :param ntimes: number of time samples generated. :param t_step: spacing between time samples. This can be interpreted as the Pulse Repetition Interval :param winddir: to force wind direction :param U10: to force wind force :returns: a tuple with the configuration object, the surfaces, the radial velocities for each grid point, and the complex scattering coefficients """ cfg_file = utils.get_parFile(parfile=cfg_file) cfg = io.ConfigFile(cfg_file) self.cfg = cfg self.use_hmtf = cfg.srg.use_hmtf self.scat_spec_enable = cfg.srg.scat_spec_enable self.scat_spec_mode = cfg.srg.scat_spec_mode self.scat_bragg_enable = cfg.srg.scat_bragg_enable self.scat_bragg_model = cfg.srg.scat_bragg_model self.scat_bragg_d = cfg.srg.scat_bragg_d self.scat_bragg_spec = cfg.srg.scat_bragg_spec self.scat_bragg_spread = cfg.srg.scat_bragg_spread # SAR self.inc_angle = np.deg2rad(cfg.sar.inc_angle) self.alt = self.cfg.sar.alt self.f0 = self.cfg.sar.f0 self.prf = cfg.sar.prf if pol is None: self.pol = cfg.sar.pol else: self.pol = pol l0 = const.c / self.f0 k0 = 2. * np.pi * self.f0 / const.c if self.pol == 'DP': self.do_hh = True self.do_vv = True elif self.pol == 'hh': self.do_hh = True self.do_vv = False else: self.do_hh = False self.do_vv = True # OCEAN / OTHERS ocean_dt = cfg.ocean.dt self.surface = OceanSurface() compute = ['D', 'Diff', 'Diff2', 'V'] print("Initializating surface") if winddir is not None: self.wind_dir = np.radians(winddir) else: self.wind_dir = np.deg2rad(cfg.ocean.wind_dir) if U10 is None: self.wind_u = cfg.ocean.wind_U else: self.wind_u = U10 if self.use_hmtf: compute.append('hMTF') self.surface.init(cfg.ocean.Lx, cfg.ocean.Ly, cfg.ocean.dx, cfg.ocean.dy, cfg.ocean.cutoff_wl, cfg.ocean.spec_model, cfg.ocean.spread_model, self.wind_dir, cfg.ocean.wind_fetch, self.wind_u, cfg.ocean.current_mag, np.deg2rad(cfg.ocean.current_dir), cfg.ocean.swell_enable, cfg.ocean.swell_ampl, np.deg2rad(cfg.ocean.swell_dir), cfg.ocean.swell_wl, compute, cfg.ocean.opt_res, cfg.ocean.fft_max_prime, choppy_enable=cfg.ocean.choppy_enable) # Get a surface realization calculated print("Computing surface realizations") self.surface.t = 0 self.ntimes = ntimes self.diffx = np.zeros((ntimes, self.surface.Ny, self.surface.Nx)) self.diffy = np.zeros((ntimes, self.surface.Ny, self.surface.Nx)) self.diffxx = np.zeros((ntimes, self.surface.Ny, self.surface.Nx)) self.diffxy = np.zeros((ntimes, self.surface.Ny, self.surface.Nx)) self.diffyy = np.zeros((ntimes, self.surface.Ny, self.surface.Nx)) self.dx = np.zeros((ntimes, self.surface.Ny, self.surface.Nx)) self.dy = np.zeros((ntimes, self.surface.Ny, self.surface.Nx)) self.dz = np.zeros((ntimes, self.surface.Ny, self.surface.Nx)) self.diffx[0, :, :] = self.surface.Diffx self.diffy[0, :, :] = self.surface.Diffy self.diffxx[0, :, :] = self.surface.Diffxx self.diffyy[0, :, :] = self.surface.Diffyy self.diffxy[0, :, :] = self.surface.Diffxy self.dx[0, :, :] = self.surface.Dx self.dy[0, :, :] = self.surface.Dy self.dz[0, :, :] = self.surface.Dz if self.use_hmtf: self.h_mtf = np.zeros((ntimes, self.surface.Ny, self.surface.Nx)) self.h_mtf[0, :, :] = self.surface.hMTF self.t_step = t_step for az_step in range(1, ntimes): t_now = az_step * t_step self.surface.t = t_now self.diffx[az_step, :, :] = self.surface.Diffx self.diffy[az_step, :, :] = self.surface.Diffy self.diffxx[az_step, :, :] = self.surface.Diffxx self.diffyy[az_step, :, :] = self.surface.Diffyy self.diffxy[az_step, :, :] = self.surface.Diffxy self.dx[az_step, :, :] = self.surface.Dx self.dy[az_step, :, :] = self.surface.Dy self.dz[az_step, :, :] = self.surface.Dz if self.use_hmtf: self.h_mtf[az_step, :, :] = self.surface.hMTF self.inc_is_set = False
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 l2_wavespectrum(cfg_file, proc_output_file, ocean_file, output_file): print( '-------------------------------------------------------------------') print( time.strftime("- OCEANSAR L2 Wavespectra: [%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'] # L2 wavespectrum rg_ml = cfg.L2_wavespectrum.rg_ml az_ml = cfg.L2_wavespectrum.az_ml krg_ml = cfg.L2_wavespectrum.krg_ml kaz_ml = cfg.L2_wavespectrum.kaz_ml ml_win = cfg.L2_wavespectrum.ml_win plot_save = cfg.L2_wavespectrum.plot_save plot_path = cfg.L2_wavespectrum.plot_path plot_format = cfg.L2_wavespectrum.plot_format plot_tex = cfg.L2_wavespectrum.plot_tex plot_surface = cfg.L2_wavespectrum.plot_surface plot_proc_ampl = cfg.L2_wavespectrum.plot_proc_ampl plot_spectrum = cfg.L2_wavespectrum.plot_spectrum n_sublook = cfg.L2_wavespectrum.n_sublook sublook_weighting = cfg.L2_wavespectrum.sublook_az_weighting ## 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) # 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 print('Starting Wavespectrum 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)) az_min = az_min + az_guard az_max = az_max - az_guard 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) ## Wave spectra computation ## Processed Doppler bandwidth proc_bw = cfg.processing.doppler_bw PRF = cfg.sar.prf fa = np.fft.fftfreq(proc_data_rshp[1], 1 / PRF) # Filters sublook_filt = [] sublook_bw = proc_bw / n_sublook for i_sbl in range(n_sublook): fa_min = -1 * proc_bw / 2 + i_sbl * sublook_bw fa_max = fa_min + sublook_bw fa_c = (fa_max + fa_min) / 2 win = np.where( np.logical_and(fa > fa_min, fa < fa_max), (sublook_weighting - (1 - sublook_weighting) * np.cos(2 * np.pi * (fa - fa_min) / sublook_bw)), 0) sublook_filt.append(win) # Apply sublooks az_downsmp = int(np.floor(az_ml / 2)) rg_downsmp = int(np.floor(rg_ml / 2)) sublooks = [] sublooks_f = [] for i_sbl in range(n_sublook): # Go to frequency domain sublook_data = np.fft.ifft(np.fft.fft(proc_data, axis=1) * sublook_filt[i_sbl].reshape( (1, proc_data_rshp[1], 1)), axis=1) # Get intensities sublook_data = np.abs(sublook_data)**2 # Multilook for chind in range(proc_data.shape[0]): sublook_data[chind] = utils.smooth(utils.smooth( sublook_data[chind], rg_ml, axis=1), az_ml, axis=0) # Keep only valid part and down sample sublook_data = sublook_data[:, az_min:az_max:az_downsmp, rg_min:rg_max:rg_downsmp] sublooks.append(sublook_data) sublooks_f.append( np.fft.fft(np.fft.fft(sublook_data - np.mean(sublook_data), axis=1), axis=2)) kaz = 2 * np.pi * np.fft.fftfreq(sublook_data.shape[1], az_downsmp * az_grid_spacing) kgrg = 2 * np.pi * np.fft.fftfreq(sublook_data.shape[2], rg_downsmp * grg_grid_spacing) xspecs = [] tind = 0 xspec_lut = np.zeros((len(sublooks), len(sublooks)), dtype=int) for ind1 in range(len(sublooks)): for ind2 in range(ind1 + 1, len(sublooks)): xspec_lut[ind1, ind2] = tind tind = tind + 1 xspec = sublooks_f[ind1] * np.conj(sublooks_f[ind2]) xspecs.append(xspec) with open(output_file, 'wb') as output: pickle.dump(xspecs, output, pickle.HIGHEST_PROTOCOL) pickle.dump([kaz, kgrg], output, pickle.HIGHEST_PROTOCOL) # 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) ## FIXME: I am plotting the cross spectrum for the first polarization and the first channel only, which is not ## very nice. To be fixed, in particular por multiple polarizations for ind1 in range(len(sublooks)): for ind2 in range(ind1 + 1, len(sublooks)): save_path_abs = os.path.join(plot_path, ('xspec_abs_%i%i.%s' % (ind1 + 1, ind2 + 1, plot_format))) save_path_pha = os.path.join(plot_path, ('xspec_pha_%i%i.%s' % (ind1 + 1, ind2 + 1, plot_format))) save_path_im = os.path.join(plot_path, ('xspec_im_%i%i.%s' % (ind1 + 1, ind2 + 1, plot_format))) ml_xspec = utils.smooth(utils.smooth(np.fft.fftshift( xspecs[xspec_lut[ind1, ind2]][0]), krg_ml, axis=1), kaz_ml, axis=0) plt.figure() plt.imshow(np.abs(ml_xspec), origin='lower', cmap='inferno_r', extent=[kgrg.min(), kgrg.max(), kaz.min(), kaz.max()], interpolation='nearest') plt.grid(True) pltax = plt.gca() pltax.set_xlim((-0.1, 0.1)) pltax.set_ylim((-0.1, 0.1)) northarr_length = 0.075 # np.min([surface_full.kx.max(), surface_full.ky.max()]) pltax.arrow(0, 0, -northarr_length * np.sin(np.radians(cfg.sar.heading)), northarr_length * np.cos(np.radians(cfg.sar.heading)), fc="k", ec="k") plt.xlabel('$k_x$ [rad/m]') plt.ylabel('$k_y$ [rad/m]') plt.colorbar() plt.savefig(save_path_abs) plt.close() plt.figure() ml_xspec_pha = np.angle(ml_xspec) ml_xspec_im = np.imag(ml_xspec) immax = np.abs(ml_xspec_im).max() whimmax = np.abs(ml_xspec_im).flatten().argmax() phmax = np.abs(ml_xspec_pha.flatten()[whimmax]) plt.imshow(ml_xspec_pha, origin='lower', cmap='bwr', extent=[kgrg.min(), kgrg.max(), kaz.min(), kaz.max()], interpolation='nearest', vmin=-2 * phmax, vmax=2 * phmax) plt.grid(True) pltax = plt.gca() pltax.set_xlim((-0.1, 0.1)) pltax.set_ylim((-0.1, 0.1)) northarr_length = 0.075 # np.min([surface_full.kx.max(), surface_full.ky.max()]) pltax.arrow(0, 0, -northarr_length * np.sin(np.radians(cfg.sar.heading)), northarr_length * np.cos(np.radians(cfg.sar.heading)), fc="k", ec="k") plt.xlabel('$k_x$ [rad/m]') plt.ylabel('$k_y$ [rad/m]') plt.colorbar() plt.savefig(save_path_pha) plt.close() plt.figure() plt.imshow(ml_xspec_im, origin='lower', cmap='bwr', extent=[kgrg.min(), kgrg.max(), kaz.min(), kaz.max()], interpolation='nearest', vmin=-2 * immax, vmax=2 * immax) plt.grid(True) pltax = plt.gca() pltax.set_xlim((-0.1, 0.1)) pltax.set_ylim((-0.1, 0.1)) northarr_length = 0.075 # np.min([surface_full.kx.max(), surface_full.ky.max()]) pltax.arrow(0, 0, -northarr_length * np.sin(np.radians(cfg.sar.heading)), northarr_length * np.cos(np.radians(cfg.sar.heading)), fc="k", ec="k") plt.xlabel('$k_x$ [rad/m]') plt.ylabel('$k_y$ [rad/m]') plt.colorbar() plt.savefig(save_path_im) plt.close()