def _stft(data, sampling_rate): """ Take the specified short time fourier transform of the provided data. Parameters ---------- data : numpy.ndarray Must be one-dimensional sampling_rate : float The sampling rate. Returns ------- numpy.ndarray """ if not (isinstance(data, numpy.ndarray) and data.ndim == 1): raise ValueError( 'This short time fourier transform function only applies to a ' 'one-dimensional numpy array') nfft = 2**int(numpy.ceil(numpy.log2(numpy.sqrt(data.shape[0]))) + 2) nperseg = int(0.97 * nfft) window = kaiser(nperseg, 5) noverlap = int(0.9 * nfft) frequencies, times, trans_data = spectrogram(data, sampling_rate, window=window, nperseg=nperseg, noverlap=noverlap, nfft=nfft, return_onesided=False) return times, fftshift(frequencies, axes=0), fftshift(trans_data, axes=0)
def _deweight_array(input_data, weight_array, oversample_rate, dimension): """ Uniformly weight complex SAR data along the given dimension. Parameters ---------- input_data : numpy.ndarray weight_array : numpy.ndarray oversample_rate : int|float dimension : int Returns ------- numpy.ndarray """ if weight_array is None: # nothing to be done return input_data weight_size = round(input_data.shape[dimension]/oversample_rate) if weight_array.ndim != 1: raise ValueError('weight_array must be one dimensional.') if weight_array.size != weight_size: weight_array = scipy.signal.resample(weight_array, weight_size) weight_ind_start = int_func(numpy.floor(0.5*(input_data.shape[dimension] - weight_size))) weight_ind_end = weight_ind_start + weight_size output_data = fftshift(fft(input_data, axis=dimension), axes=dimension) if dimension == 0: output_data[weight_ind_start:weight_ind_end, :] /= weight_array[:, numpy.newaxis] else: output_data[:, weight_ind_start:weight_ind_end] /= weight_array return ifft(ifftshift(output_data, axes=dimension), axis=dimension)
def subaperture_processing_array(array, aperture_indices, output_resolution, dimension=0): """ Perform the sub-aperture processing on the given complex array data. Parameters ---------- array : numpy.ndarray The complex array data. Dimension other than 2 is not supported. aperture_indices : Tuple[int, int] The start/stop indices for the subaperture processing. output_resolution : int The output resolution parameter. dimension : int The dimension along which to perform the sub-aperture processing. Must be one of 0 or 1. Returns ------- numpy.ndarray """ array = _validate_input(array) dimension = _validate_dimension(dimension) return subaperture_processing_phase_history(fftshift(fft(array, axis=dimension), axes=dimension), aperture_indices, output_resolution, dimension=dimension)
def apply_weight_array(input_data, weight_array, oversample_rate, dimension, inverse=False): """ Apply the weight array along the given dimension. Parameters ---------- input_data : numpy.ndarray The complex data array to weight. weight_array : numpy.ndarray The weight array. oversample_rate : int|float The oversample rate. dimension : int Along which dimension to apply the weighting? Must be one of `{0, 1}`. inverse : bool If `True`, this divides the weight (i.e. de-weight), otherwise it multiplies. Returns ------- numpy.ndarray """ if not (isinstance(input_data, numpy.ndarray) and input_data.ndim == 2): raise ValueError('The data array must be two-dimensional') if weight_array is None: # nothing to be done return input_data weight_array, weight_ind_start, weight_ind_end = determine_weight_array( input_data.shape, weight_array, oversample_rate, dimension) if inverse and numpy.any(weight_array == 0): raise ValueError( 'inverse=True and the weight array contains some zero entries.') output_data = fftshift(fft(input_data, axis=dimension), axes=dimension) if dimension == 0: if inverse: output_data[weight_ind_start: weight_ind_end, :] /= weight_array[:, numpy.newaxis] else: output_data[weight_ind_start: weight_ind_end, :] *= weight_array[:, numpy.newaxis] else: if inverse: output_data[:, weight_ind_start:weight_ind_end] /= weight_array else: output_data[:, weight_ind_start:weight_ind_end] *= weight_array return ifft(ifftshift(output_data, axes=dimension), axis=dimension)
def _get_fft_complex_data(self, cdata): """ Transform the complex image data to phase history data. Parameters ---------- cdata : numpy.ndarray Returns ------- numpy.ndarray """ return fftshift(fft2_sicd(cdata, self.sicd))
def create_deskewed_transform(reader, dimension=0, suffix='.sarpy.cache'): """ Performs the Fourier transform of the deskewed entirety of the given ComplexImageReader contents. Parameters ---------- reader : SICDTypeCanvasImageReader The reader object. dimension : int One of [0, 1], which dimension to deskew along. suffix : None|str The suffix for the created file name (created using the tempfile module). Returns ------- (str, numpy.ndarray, numpy.ndarray) A file name, numpy memmap of the given object, and mean along the given dimension. Care should be taken to ensure that the file is deleted when the usage is complete. """ # set up a true file for the memmap # NB: it should be noted that the tempfile usage which clean themselves up # cannot (as of 2021-04-23) be opened multiple times on Windows, which # means that such a "file" cannot be used in conjunction with a numpy # memmap. data_size = reader.data_size sicd = reader.get_sicd() _, file_name = mkstemp(suffix=suffix, text=False) logger.debug('Creating temp file % s' % file_name) # set up the memmap memmap = numpy.memmap(file_name, dtype='complex64', mode='r+', offset=0, shape=data_size) calculator = DeskewCalculator( reader.base_reader, dimension=dimension, index=reader.index, apply_deskew=True, apply_deweighting=False, apply_off_axis=False) mean_value = numpy.zeros((data_size[0], ), dtype='float64') if dimension == 0 else \ numpy.zeros((data_size[1],), dtype='float64') # we'll proceed in blocks of approximately this number of pixels pixels_threshold = 2**20 # is our whole reader sufficiently small to just do it all in one fell-swoop? if data_size[0]*data_size[1] <= 4*pixels_threshold: data = fftshift(fft2_sicd(calculator[:, :], sicd)) memmap[:, :] = data mean_value[:] = numpy.mean(numpy.abs(data), axis=1-dimension) return file_name, memmap, mean_value # fetch full rows, and transform then shift along the row direction block_size = int(numpy.ceil(pixels_threshold/data_size[1])) start_col = 0 while start_col < data_size[1]: end_col = min(start_col+block_size, data_size[1]) data = fftshift(fft_sicd(calculator[:, start_col:end_col], 0, sicd), axes=0) memmap[:, start_col:end_col] = data if dimension == 0: mean_value += numpy.sum(numpy.abs(data), axis=1) start_col = end_col # fetch full columns, and transform then shift along the column direction block_size = int(numpy.ceil(pixels_threshold/data_size[0])) start_row = 0 while start_row < data_size[0]: end_row = min(start_row+block_size, data_size[0]) data = fftshift(fft_sicd(memmap[start_row:end_row, :], 1, sicd), axes=1) memmap[start_row:end_row, :] = data if dimension == 1: mean_value += numpy.sum(numpy.abs(data), axis=0) start_row = end_row if dimension == 0: mean_value /= data_size[1] else: mean_value /= data_size[0] return file_name, memmap, mean_value
def do_dimension(dimension): if dimension == 0: dir_params = sicd.Grid.Row aperture_in = row_aperture weighting_in = row_weighting dimension_limits = row_limits else: dir_params = sicd.Grid.Col aperture_in = column_aperture weighting_in = column_weighting dimension_limits = column_limits not_skewed = is_not_skewed(sicd, dimension) uniform_weight = is_uniform_weight(sicd, dimension) delta_kcoa = dir_params.DeltaKCOAPoly.get_array(dtype='float64') st_beam_comp = sicd.ImageFormation.STBeamComp if sicd.ImageFormation is not None else None if dimension == 1 and (not uniform_weight or weighting_in is not None): if st_beam_comp is None: logger.warning( 'Processing along the column direction requires modification\n\t' 'of the original weighting scheme, and the value for\n\t' 'ImageFormation.STBeamComp is not populated.\n\t' 'It is unclear how imperfect the de-weighting effort along the column may be.' ) elif st_beam_comp == 'NO': logger.warning( 'Processing along the column direction requires modification\n\t' 'of the original weighting scheme, and the value for\n\t' 'ImageFormation.STBeamComp is populated as `NO`.\n\t' 'It is likely that the de-weighting effort along the column is imperfect.' ) if aperture_in is None and weighting_in is None: # nothing to be done in this dimension return noise_adjustment_multiplier new_weight = None if weighting_in is None else weighting_in['WgtFunct'] dimension_limits, cur_aperture_limits, cur_weight_function, \ new_aperture_limits, new_weight_function = aperture_dimension_params( old_sicd, dimension, dimension_limits=dimension_limits, aperture_limits=aperture_in, new_weight_function=new_weight) index_count = dimension_limits[1] - dimension_limits[0] cur_center_index = 0.5 * (cur_aperture_limits[0] + cur_aperture_limits[1]) new_center_index = 0.5 * (new_aperture_limits[0] + new_aperture_limits[1]) noise_multiplier = noise_scaling(cur_aperture_limits, cur_weight_function, new_aperture_limits, new_weight_function) # perform deskew, if necessary if not not_skewed: if dimension == 0: row_array = get_direction_array_meters(0, 0, out_data_shape[0]) for (_start_ind, _stop_ind) in col_iterations: col_array = get_direction_array_meters( 1, _start_ind, _stop_ind) working_data[:, _start_ind:_stop_ind] = apply_skew_poly( working_data[:, _start_ind:_stop_ind], delta_kcoa, row_array, col_array, dir_params.Sgn, 0, forward=False) else: col_array = get_direction_array_meters(1, 0, out_data_shape[1]) for (_start_ind, _stop_ind) in row_iterations: row_array = get_direction_array_meters( 0, _start_ind, _stop_ind) working_data[_start_ind:_stop_ind, :] = apply_skew_poly( working_data[_start_ind:_stop_ind, :], delta_kcoa, row_array, col_array, dir_params.Sgn, 1, forward=False) # perform fourier transform along the given dimension if dimension == 0: for (_start_ind, _stop_ind) in col_iterations: working_data[:, _start_ind:_stop_ind] = fftshift( fft_sicd(working_data[:, _start_ind:_stop_ind], dimension, sicd), axes=dimension) else: for (_start_ind, _stop_ind) in row_iterations: working_data[_start_ind:_stop_ind, :] = fftshift( fft_sicd(working_data[_start_ind:_stop_ind, :], dimension, sicd), axes=dimension) # perform deweight, if necessary if not uniform_weight: if dimension == 0: working_data[cur_aperture_limits[0]:cur_aperture_limits[ 1], :] /= cur_weight_function[:, numpy.newaxis] else: working_data[:, cur_aperture_limits[0]: cur_aperture_limits[1]] /= cur_weight_function # do sub-aperture, if necessary if aperture_in is not None: if dimension == 0: working_data[:new_aperture_limits[0], :] = 0 working_data[new_aperture_limits[1]:, :] = 0 else: working_data[:, :new_aperture_limits[0]] = 0 working_data[:, new_aperture_limits[1]:] = 0 the_ratio = float(new_aperture_limits[1] - new_aperture_limits[0]) / \ float(cur_aperture_limits[1] - cur_aperture_limits[0]) # modify the ImpRespBW value (derived ImpRespWid handled at the end) dir_params.ImpRespBW *= the_ratio # perform reweight, if necessary if weighting_in is not None: if dimension == 0: working_data[new_aperture_limits[0]:new_aperture_limits[ 1], :] *= new_weight_function[:, numpy.newaxis] else: working_data[:, new_aperture_limits[0]: new_aperture_limits[1]] *= new_weight_function # modify the weight definition dir_params.WgtType = WgtTypeType( WindowName=weighting_in['WindowName'], Parameters=weighting_in.get('Parameters', None)) dir_params.WgtFunct = weighting_in['WgtFunct'].copy() elif not uniform_weight: if dimension == 0: working_data[new_aperture_limits[0]:new_aperture_limits[ 1], :] *= new_weight_function[:, numpy.newaxis] else: working_data[:, new_aperture_limits[0]: new_aperture_limits[1]] *= new_weight_function # perform inverse fourier transform along the given dimension if dimension == 0: for (_start_ind, _stop_ind) in col_iterations: working_data[:, _start_ind:_stop_ind] = ifft_sicd( ifftshift(working_data[:, _start_ind:_stop_ind], axes=dimension), dimension, sicd) else: for (_start_ind, _stop_ind) in row_iterations: working_data[_start_ind:_stop_ind, :] = ifft_sicd( ifftshift(working_data[_start_ind:_stop_ind, :], axes=dimension), dimension, sicd) # perform the (original) reskew, if necessary if not numpy.all(delta_kcoa == 0): if dimension == 0: row_array = get_direction_array_meters(0, 0, out_data_shape[0]) for (_start_ind, _stop_ind) in col_iterations: col_array = get_direction_array_meters( 1, _start_ind, _stop_ind) working_data[:, _start_ind:_stop_ind] = apply_skew_poly( working_data[:, _start_ind:_stop_ind], delta_kcoa, row_array, col_array, dir_params.Sgn, 0, forward=True) else: col_array = get_direction_array_meters(1, 0, out_data_shape[1]) for (_start_ind, _stop_ind) in row_iterations: row_array = get_direction_array_meters( 0, _start_ind, _stop_ind) working_data[_start_ind:_stop_ind, :] = apply_skew_poly( working_data[_start_ind:_stop_ind, :], delta_kcoa, row_array, col_array, dir_params.Sgn, 1, forward=True) # modify the delta_kcoa_poly - introduce the shift necessary for additional offset if new_center_index != cur_center_index: additional_shift = dir_params.Sgn * ( cur_center_index - new_center_index) / float( index_count * dir_params.SS) delta_kcoa[0, 0] += additional_shift dir_params.DeltaKCOAPoly = delta_kcoa return noise_adjustment_multiplier * noise_multiplier
def csi_array(array, dimension=0, platform_direction='R', fill=1, filter_map=None): """ Creates a color subaperture array from a complex array. .. Note: this ignores any potential sign issues for the fft and ifft, because the results would be identical - fft followed by ifft versus ifft followed by fft. Parameters ---------- array : numpy.ndarray The complex valued SAR data, assumed to be in the "image" domain. Required to be two-dimensional. dimension : int The dimension over which to split the sub-aperture. platform_direction : str The (case insensitive) platform direction, required to be one of `('R', 'L')`. fill : float The fill factor. This will be ignored if `filter_map` is provided. filter_map : None|numpy.ndarray The RGB filter mapping. This is assumed constructed using :func:`filter_map_construction`. Returns ------- numpy.ndarray """ if not (isinstance(array, numpy.ndarray) and len(array.shape) == 2 and numpy.iscomplexobj(array)): raise ValueError('array must be a two-dimensional numpy array of complex dtype') dimension = int_func(dimension) if dimension not in [0, 1]: raise ValueError('dimension must be 0 or 1, got {}'.format(dimension)) if dimension == 0: array = array.T pdir_func = platform_direction.upper()[0] if pdir_func not in ['R', 'L']: raise ValueError('It is expected that pdir is one of "R" or "L". Got {}'.format(platform_direction)) # get our filter construction data if filter_map is None: fill = max(1.0, float(fill)) filter_map = filter_map_construction(array.shape[1]/fill) if not (isinstance(filter_map, numpy.ndarray) and filter_map.dtype.name in ['float32', 'float64'] and filter_map.ndim == 2 and filter_map.shape[1] == 3): raise ValueError('filter_map must be a N x 3 numpy array of float dtype.') # move to phase history domain ph_indices = int(numpy.floor(0.5*(array.shape[1] - filter_map.shape[0]))) + \ numpy.arange(filter_map.shape[0], dtype=numpy.int32) ph0 = fftshift(ifft(numpy.cast[numpy.complex128](array), axis=1), axes=1)[:, ph_indices] # construct the filtered workspace # NB: processing is more efficient with color band in the first dimension ph0_RGB = numpy.zeros((3, array.shape[0], filter_map.shape[0]), dtype=numpy.complex128) for i in range(3): ph0_RGB[i, :, :] = ph0*filter_map[:, i] del ph0 # Shift phase history to avoid having zeropad in middle of filter, to alleviate # the purple sidelobe artifact. filter_shift = int(numpy.ceil(0.25*filter_map.shape[0])) ph0_RGB[0, :] = numpy.roll(ph0_RGB[0, :], -filter_shift) ph0_RGB[2, :] = numpy.roll(ph0_RGB[2, :], filter_shift) # NB: the green band is already centered # FFT back to the image domain im0_RGB = fft(fftshift(ph0_RGB, axes=2), n=array.shape[1], axis=2) del ph0_RGB # Replace the intensity with the original image intensity to main full resolution # (in intensity, but not in color). scale_factor = numpy.abs(array)/numpy.abs(im0_RGB).max(axis=0) im0_RGB = numpy.abs(im0_RGB)*scale_factor # reorient image so that the color segment is in the final dimension if dimension == 0: im0_RGB = im0_RGB.transpose([2, 1, 0]) else: im0_RGB = im0_RGB.transpose([1, 2, 0]) if pdir_func == 'R': # reverse the color band order im0_RGB = im0_RGB[:, :, ::-1] return im0_RGB
def do_dimension(dimension): if dimension == 0: dir_params = sicd.Grid.Row aperture_in = row_aperture weighting_in = row_weighting index_count = sicd.ImageData.NumRows else: dir_params = sicd.Grid.Col aperture_in = column_aperture weighting_in = column_weighting index_count = sicd.ImageData.NumCols not_skewed = is_not_skewed(sicd, dimension) uniform_weight = is_uniform_weight(sicd, dimension) delta_kcoa = dir_params.DeltaKCOAPoly.get_array(dtype='float64') st_beam_comp = sicd.ImageFormation.STBeamComp if sicd.ImageFormation is not None else None if dimension == 1 and (not uniform_weight or weighting_in is not None): if st_beam_comp is None: logger.warning( 'Processing along the column direction requires modification\n\t' 'of the original weighting scheme, and the value for\n\t' 'ImageFormation.STBeamComp is not populated.\n\t' 'It is unclear how imperfect the de-weighting effort along the column may be.' ) elif st_beam_comp == 'NO': logger.warning( 'Processing along the column direction requires modification\n\t' 'of the original weighting scheme, and the value for\n\t' 'ImageFormation.STBeamComp is populated as `NO`.\n\t' 'It is likely that the de-weighting effort along the column is imperfect.' ) if aperture_in is None and weighting_in is None: # nothing to be done in this dimension return oversample = max(1., 1. / (dir_params.SS * dir_params.ImpRespBW)) old_weight, start_index, end_index = determine_weight_array( out_data_shape, dir_params.WgtFunct.copy(), oversample, dimension) center_index = 0.5 * (start_index + end_index) # perform deskew, if necessary if not not_skewed: if dimension == 0: row_array = get_direction_array_meters(0, 0, out_data_shape[0]) for (_start_ind, _stop_ind) in col_iterations: col_array = get_direction_array_meters( 1, _start_ind, _stop_ind) working_data[:, _start_ind:_stop_ind] = apply_skew_poly( working_data[:, _start_ind:_stop_ind], delta_kcoa, row_array, col_array, dir_params.Sgn, 0, forward=False) else: col_array = get_direction_array_meters(1, 0, out_data_shape[1]) for (_start_ind, _stop_ind) in row_iterations: row_array = get_direction_array_meters( 0, _start_ind, _stop_ind) working_data[_start_ind:_stop_ind, :] = apply_skew_poly( working_data[_start_ind:_stop_ind, :], delta_kcoa, row_array, col_array, dir_params.Sgn, 1, forward=False) # perform fourier transform along the given dimension if dimension == 0: for (_start_ind, _stop_ind) in col_iterations: working_data[:, _start_ind:_stop_ind] = fftshift( fft_sicd(working_data[:, _start_ind:_stop_ind], dimension, sicd), axes=dimension) else: for (_start_ind, _stop_ind) in row_iterations: working_data[_start_ind:_stop_ind, :] = fftshift( fft_sicd(working_data[_start_ind:_stop_ind, :], dimension, sicd), axes=dimension) # perform deweight, if necessary if not uniform_weight: if dimension == 0: working_data[ start_index:end_index, :] /= old_weight[:, numpy.newaxis] else: working_data[:, start_index:end_index] /= old_weight # do sub-aperture, if necessary if aperture_in is not None: new_start_index = max(int(aperture_in[0]), start_index) new_end_index = min(int(aperture_in[1]), end_index) new_center_index = 0.5 * (new_start_index + new_end_index) if dimension == 0: working_data[:new_start_index, :] = 0 working_data[new_end_index:, :] = 0 else: working_data[:, :new_start_index] = 0 working_data[:, new_end_index:] = 0 new_oversample = oversample * float( end_index - start_index) / float(new_end_index - new_start_index) the_ratio = new_oversample / oversample # modify the ImpRespBW value (derived ImpRespWid handled at the end) dir_params.ImpRespBW /= the_ratio else: new_center_index = center_index new_oversample = oversample # perform reweight, if necessary if weighting_in is not None: new_weight, start_index, end_index = determine_weight_array( out_data_shape, weighting_in['WgtFunction'].copy(), new_oversample, dimension) start_index += int(new_center_index - center_index) end_index += int(new_center_index - center_index) if dimension == 0: working_data[ start_index:end_index, :] *= new_weight[:, numpy.newaxis] else: working_data[:, start_index:end_index] *= new_weight # modify the weight definition dir_params.WgtType = WgtTypeType( WindowName=weighting_in['WindowName'], Parameters=weighting_in.get('Parameters', None)) dir_params.WgtFunct = weighting_in['WgtFunction'].copy() elif not uniform_weight: # weight remained the same, and it's not uniform new_weight, start_index, end_index = determine_weight_array( out_data_shape, dir_params.WgtFunct.copy(), new_oversample, dimension) if dimension == 0: working_data[ start_index:end_index, :] *= new_weight[:, numpy.newaxis] else: working_data[:, start_index:end_index] *= new_weight # perform inverse fourier transform along the given dimension if dimension == 0: for (_start_ind, _stop_ind) in col_iterations: working_data[:, _start_ind:_stop_ind] = ifft_sicd( ifftshift(working_data[:, _start_ind:_stop_ind], axes=dimension), dimension, sicd) else: for (_start_ind, _stop_ind) in row_iterations: working_data[_start_ind:_stop_ind, :] = ifft_sicd( ifftshift(working_data[_start_ind:_stop_ind, :], axes=dimension), dimension, sicd) # perform the (original) reskew, if necessary if not numpy.all(delta_kcoa == 0): if dimension == 0: row_array = get_direction_array_meters(0, 0, out_data_shape[0]) for (_start_ind, _stop_ind) in col_iterations: col_array = get_direction_array_meters( 1, _start_ind, _stop_ind) working_data[:, _start_ind:_stop_ind] = apply_skew_poly( working_data[:, _start_ind:_stop_ind], delta_kcoa, row_array, col_array, dir_params.Sgn, 0, forward=True) else: col_array = get_direction_array_meters(1, 0, out_data_shape[1]) for (_start_ind, _stop_ind) in row_iterations: row_array = get_direction_array_meters( 0, _start_ind, _stop_ind) working_data[_start_ind:_stop_ind, :] = apply_skew_poly( working_data[_start_ind:_stop_ind, :], delta_kcoa, row_array, col_array, dir_params.Sgn, 1, forward=True) # modify the delta_kcoa_poly - introduce the shift necessary for additional offset if center_index != new_center_index: additional_shift = dir_params.Sgn * ( center_index - new_center_index) / float( index_count * dir_params.SS) delta_kcoa[0, 0] += additional_shift dir_params.DeltaKCOAPoly = delta_kcoa # re-derive the various ImpResp parameters sicd.Grid.derive_direction_params(sicd.ImageData, populate=True)
def update_displayed_selection(self): def get_extent(coords): return min(coords[0::2]), max(coords[0::2]), min(coords[1::2]), max(coords[1::2]) def draw_row_delta_lines(): deltak1 = (row_count - 1)*(0.5 + the_sicd.Grid.Row.SS*the_sicd.Grid.Row.DeltaK1) + 1 deltak2 = (row_count - 1)*(0.5 + the_sicd.Grid.Row.SS*the_sicd.Grid.Row.DeltaK2) + 1 self.frequency_panel.canvas.modify_existing_shape_using_image_coords( self.variables.row_deltak1, (deltak1, 0, deltak1, col_count)) self.frequency_panel.canvas.modify_existing_shape_using_image_coords( self.variables.row_deltak2, (deltak2, 0, deltak2, col_count)) def draw_col_delta_lines(): deltak1 = (col_count - 1)*(0.5 + the_sicd.Grid.Col.SS*the_sicd.Grid.Col.DeltaK1) + 1 deltak2 = (col_count - 1)*(0.5 + the_sicd.Grid.Col.SS*the_sicd.Grid.Col.DeltaK2) + 1 self.frequency_panel.canvas.modify_existing_shape_using_image_coords( self.variables.col_deltak1, (0, deltak1, row_count, deltak1)) self.frequency_panel.canvas.modify_existing_shape_using_image_coords( self.variables.col_deltak2, (0, deltak2, row_count, deltak2)) def draw_row_bandwidth_lines(): try: delta_kcoa_center = the_sicd.Grid.Row.DeltaKCOAPoly(row_phys, col_phys) except Exception: delta_kcoa_center = 0.0 row_bw_low = (row_count - 1)*( 0.5 + the_sicd.Grid.Row.SS*(delta_kcoa_center - 0.5*the_sicd.Grid.Row.ImpRespBW)) + 1 row_bw_high = (row_count - 1)*( 0.5 + the_sicd.Grid.Row.SS*(delta_kcoa_center + 0.5*the_sicd.Grid.Row.ImpRespBW)) + 1 row_bw_low = (row_bw_low % row_count) row_bw_high = (row_bw_high % row_count) self.frequency_panel.canvas.modify_existing_shape_using_image_coords( self.variables.row_line_low, (row_bw_low, 0, row_bw_low, col_count)) self.frequency_panel.canvas.modify_existing_shape_using_image_coords( self.variables.row_line_high, (row_bw_high, 0, row_bw_high, col_count)) def draw_col_bandwidth_lines(): try: delta_kcoa_center = the_sicd.Grid.Col.DeltaKCOAPoly(row_phys, col_phys) except Exception: delta_kcoa_center = 0.0 col_bw_low = (col_count - 1) * ( 0.5 + the_sicd.Grid.Col.SS*(delta_kcoa_center - 0.5*the_sicd.Grid.Col.ImpRespBW)) + 1 col_bw_high = (col_count - 1) * ( 0.5 + the_sicd.Grid.Col.SS*(delta_kcoa_center + 0.5*the_sicd.Grid.Col.ImpRespBW)) + 1 col_bw_low = (col_bw_low % col_count) col_bw_high = (col_bw_high % col_count) self.frequency_panel.canvas.modify_existing_shape_using_image_coords( self.variables.col_line_low, (0, col_bw_low, row_count, col_bw_low)) self.frequency_panel.canvas.modify_existing_shape_using_image_coords( self.variables.col_line_high, (0, col_bw_high, row_count, col_bw_high)) threshold = self.image_panel.canvas.variables.config.select_size_threshold select_id = self.image_panel.canvas.variables.select_rect.uid rect_coords = self.image_panel.canvas.get_shape_image_coords(select_id) extent = get_extent(rect_coords) # left, right, bottom, top row_count = extent[1] - extent[0] col_count = extent[3] - extent[2] the_sicd = self.variables.image_reader.get_sicd() row_phys, col_phys = get_physical_coordinates( the_sicd, 0.5*(extent[0]+extent[1]), 0.5*(extent[2]+extent[3])) if row_count < threshold or col_count < threshold: junk_data = numpy.zeros((100, 100), dtype='uint8') self.frequency_panel.set_image_reader(NumpyImageReader(junk_data)) self._initialize_bandwidth_lines() else: image_data = self.variables.image_reader.base_reader[extent[0]:extent[1], extent[2]:extent[3]] if image_data is not None: self.frequency_panel.set_image_reader( NumpyImageReader(remap.density(fftshift(fft2_sicd(image_data, the_sicd))))) self._initialize_bandwidth_lines() draw_row_delta_lines() draw_col_delta_lines() draw_row_bandwidth_lines() draw_col_bandwidth_lines() else: junk_data = numpy.zeros((100, 100), dtype='uint8') self.frequency_panel.set_image_reader(NumpyImageReader(junk_data)) self._initialize_bandwidth_lines()
def subaperture_generator(self, row_range, col_range, frames=None): # type: (tuple, tuple, Union[None, int, list, tuple, numpy.ndarray]) -> Generator[numpy.ndarray] """ Supplies a generator for the given row and column ranges and frames collection. **Note that this IGNORES the block_size parameter in fetching, and fetches the entire required block.** The full resolution data in the processing dimension is required, even if down-sampled by the row_range or col_range parameter. Parameters ---------- row_range : Tuple[int, int, int] The row range. col_range : Tuple[int, int, int] The column range. frames : None|int|list|tuple|numpy.ndarray The frame or frame collection. Returns ------- Generator[numpy.ndarray] """ def get_dimension_details(the_range): the_snip = -1 if the_range[2] < 0 else 1 t_full_range = (the_range[0], the_range[1], the_snip) t_full_size = the_range[1] - the_range[0] t_step = abs(the_range[2]) return t_full_range, t_full_size, t_step if self._fill is None: raise ValueError( 'Unable to proceed unless the index and dimension are set.') frames = self._parse_frame_argument(frames) if isinstance(frames, integer_types): frames = [ frames, ] if self.dimension == 0: # determine the full resolution block of data to fetch this_row_range, full_size, step = get_dimension_details(row_range) # fetch the necessary data block data = self.reader[ this_row_range[0]:this_row_range[1]:this_row_range[2], col_range[0]:col_range[1]:col_range[2], self.index] else: # determine the full resolution block of data to fetch this_col_range, full_size, step = get_dimension_details(col_range) # fetch the necessary data block, and transform to phase space data = self.reader[ row_range[0]:row_range[1]:row_range[2], this_col_range[0]:this_col_range[1]:this_col_range[2], self.index] # handle any nonsense data as 0 data[~numpy.isfinite(data)] = 0 # transform the data to phase space data = fftshift(fft(data, axis=self.dimension), axes=self.dimension) # define our frame collection frame_collection, output_resolution = frame_definition( full_size, frame_count=self.frame_count, aperture_fraction=self.aperture_fraction, fill=self.fill, method=self.method) # iterate over frames and generate the results for frame_index in frames: frame_def = frame_collection[int_func(frame_index)] this_subap_data = subaperture_processing_phase_history( data, frame_def, output_resolution=output_resolution, dimension=self.dimension) if step == 1: yield this_subap_data elif self.dimension == 0: yield this_subap_data[::step, :] else: yield this_subap_data[:, ::step]