def test_check_radar_images_5d_good(self): """Ensures correct output from check_radar_images. In this case the input matrix is 5-D (good). """ dl_utils.check_radar_images(radar_image_matrix=RADAR_IMAGE_MATRIX_5D)
def test_check_radar_images_2d(self): """Ensures correct output from check_radar_images. In this case the input matrix is 2-D (bad). """ with self.assertRaises(ValueError): dl_utils.check_radar_images( radar_image_matrix=RADAR_IMAGE_MATRIX_2D)
def test_check_radar_images_5d_bad(self): """Ensures correct output from check_radar_images. In this case, the input matrix is 5-D but a 3-D or 4-D matrix is expected. """ with self.assertRaises(ValueError): dl_utils.check_radar_images( radar_image_matrix=RADAR_IMAGE_MATRIX_5D, max_num_dimensions=4)
def flip_radar_images_y(radar_image_matrix): """Flips radar images in the y-direction. :param radar_image_matrix: See doc for `deep_learning_utils.check_radar_images`. :return: flipped_image_matrix: Flipped version of input (same dimensions). """ dl_utils.check_radar_images(radar_image_matrix=radar_image_matrix, min_num_dimensions=3, max_num_dimensions=5) return numpy.flip(radar_image_matrix, axis=1)
def noise_radar_images(radar_image_matrix, standard_deviation): """Adds Gaussian noise to each radar image. This method assumes that images are normalized (as by `deep_learning_utils.normalize_radar_images`), so the standard deviation is unitless and the same standard deviation applies to all channels. :param radar_image_matrix: See doc for `deep_learning_utils.check_radar_images`. :param standard_deviation: Standard deviation of Gaussian noise. :return: noised_image_matrix: Same as `radar_image_matrix`, but after noising. The shapes of the two numpy arrays are the same. """ dl_utils.check_radar_images(radar_image_matrix=radar_image_matrix, min_num_dimensions=3, max_num_dimensions=5) error_checking.assert_is_greater(standard_deviation, 0.) noise_matrix = numpy.random.normal(loc=0., scale=standard_deviation, size=radar_image_matrix.shape) return radar_image_matrix + noise_matrix
def rotate_radar_images(radar_image_matrix, ccw_rotation_angle_deg): """Rotates each radar image in the xy-plane. :param radar_image_matrix: See doc for `deep_learning_utils.check_radar_images`. :param ccw_rotation_angle_deg: Each image will be rotated counterclockwise by this angle (degrees). :return: rotated_image_matrix: Same as `radar_image_matrix`, but after rotation. The shapes of the two numpy arrays are the same. """ dl_utils.check_radar_images(radar_image_matrix=radar_image_matrix, min_num_dimensions=3, max_num_dimensions=5) error_checking.assert_is_geq(ccw_rotation_angle_deg, -180.) error_checking.assert_is_leq(ccw_rotation_angle_deg, 180.) return scipy_rotate(input=radar_image_matrix, angle=-ccw_rotation_angle_deg, axes=(1, 2), reshape=False, order=1, mode='constant', cval=PADDING_VALUE)
def apply_2d3d_cnn(model_object, reflectivity_matrix_dbz, azimuthal_shear_matrix_s01, sounding_matrix=None, num_examples_per_batch=100, verbose=False, return_features=False, feature_layer_name=None): """Applies CNN to both 2-D and 3-D radar images (and possibly soundings). M = number of rows in each reflectivity image N = number of columns in each reflectivity image :param model_object: Trained instance of `keras.models.Model` or `keras.models.Sequential`. :param reflectivity_matrix_dbz: numpy array (E x M x N x H_r x 1) of storm-centered reflectivity images. :param azimuthal_shear_matrix_s01: numpy array (E x 2M x 2N x C) of storm-centered azimuthal-shear images. :param sounding_matrix: See doc for `apply_2d_or_3d_cnn`. :param num_examples_per_batch: Same. :param verbose: Same. :param return_features: Same. :param feature_layer_name: Same. If return_features = True... :return: feature_matrix: See doc for `apply_2d_or_3d_cnn`. If return_features = False... :return: class_probability_matrix: See doc for `apply_2d_or_3d_cnn`. """ dl_utils.check_radar_images(radar_image_matrix=reflectivity_matrix_dbz, min_num_dimensions=5, max_num_dimensions=5) dl_utils.check_radar_images(radar_image_matrix=azimuthal_shear_matrix_s01, min_num_dimensions=4, max_num_dimensions=4) if sounding_matrix is not None: dl_utils.check_soundings(sounding_matrix=sounding_matrix, num_examples=reflectivity_matrix_dbz.shape[0]) dl_utils.check_soundings( sounding_matrix=sounding_matrix, num_examples=azimuthal_shear_matrix_s01.shape[0]) num_examples = reflectivity_matrix_dbz.shape[0] if num_examples_per_batch is None: num_examples_per_batch = num_examples + 0 else: error_checking.assert_is_integer(num_examples_per_batch) error_checking.assert_is_greater(num_examples_per_batch, 0) num_examples_per_batch = min([num_examples_per_batch, num_examples]) error_checking.assert_is_boolean(verbose) error_checking.assert_is_boolean(return_features) if return_features: model_object_to_use = model_to_feature_generator( model_object=model_object, feature_layer_name=feature_layer_name) else: model_object_to_use = model_object output_matrix = None for i in range(0, num_examples, num_examples_per_batch): this_first_index = i this_last_index = min( [i + num_examples_per_batch - 1, num_examples - 1]) these_indices = numpy.linspace(this_first_index, this_last_index, num=this_last_index - this_first_index + 1, dtype=int) if verbose: print('Applying model to examples {0:d}-{1:d} of {2:d}...').format( this_first_index + 1, this_last_index + 1, num_examples) if sounding_matrix is None: these_outputs = model_object_to_use.predict( [ reflectivity_matrix_dbz[these_indices, ...], azimuthal_shear_matrix_s01[these_indices, ...] ], batch_size=len(these_indices)) else: these_outputs = model_object_to_use.predict( [ reflectivity_matrix_dbz[these_indices, ...], azimuthal_shear_matrix_s01[these_indices, ...], sounding_matrix[these_indices, ...] ], batch_size=len(these_indices)) if output_matrix is None: output_matrix = these_outputs + 0. else: output_matrix = numpy.concatenate((output_matrix, these_outputs), axis=0) if verbose: print 'Have applied model to all {0:d} examples!'.format(num_examples) if return_features: return output_matrix return _binary_probabilities_to_matrix(output_matrix)
def apply_2d_or_3d_cnn(model_object, radar_image_matrix, sounding_matrix=None, num_examples_per_batch=100, verbose=False, return_features=False, feature_layer_name=None): """Applies CNN to either 2-D or 3-D radar images (and possibly soundings). :param model_object: Trained instance of `keras.models.Model` or `keras.models.Sequential`. :param radar_image_matrix: E-by-M-by-N-by-C numpy array of storm-centered radar images. :param sounding_matrix: [may be None] numpy array (E x H_s x F_s) of storm-centered sounding. :param num_examples_per_batch: Number of examples per batch. Will apply CNN to this many examples at once. If `num_examples_per_batch is None`, will apply CNN to all examples at once. :param verbose: Boolean flag. If True, will print progress messages. :param return_features: Boolean flag. If True, this method will return features (activations of an intermediate layer). If False, this method will return probabilistic predictions. :param feature_layer_name: [used only if return_features = True] Name of layer for which features will be returned. If return_features = True... :return: feature_matrix: E-by-Z numpy array of features, where Z = number of outputs from the given layer. If return_features = False... :return: class_probability_matrix: E-by-K numpy array of class probabilities. class_probability_matrix[i, k] is the forecast probability that the [i]th storm object belongs to the [k]th class. Classes are mutually exclusive and collectively exhaustive, so the sum across each row is 1. """ dl_utils.check_radar_images(radar_image_matrix=radar_image_matrix, min_num_dimensions=4, max_num_dimensions=5) num_examples = radar_image_matrix.shape[0] if sounding_matrix is not None: dl_utils.check_soundings(sounding_matrix=sounding_matrix, num_examples=num_examples) if num_examples_per_batch is None: num_examples_per_batch = num_examples + 0 else: error_checking.assert_is_integer(num_examples_per_batch) error_checking.assert_is_greater(num_examples_per_batch, 0) num_examples_per_batch = min([num_examples_per_batch, num_examples]) error_checking.assert_is_boolean(verbose) error_checking.assert_is_boolean(return_features) if return_features: model_object_to_use = model_to_feature_generator( model_object=model_object, feature_layer_name=feature_layer_name) else: model_object_to_use = model_object output_matrix = None for i in range(0, num_examples, num_examples_per_batch): this_first_index = i this_last_index = min( [i + num_examples_per_batch - 1, num_examples - 1]) these_indices = numpy.linspace(this_first_index, this_last_index, num=this_last_index - this_first_index + 1, dtype=int) if verbose: print('Applying model to examples {0:d}-{1:d} of {2:d}...').format( this_first_index + 1, this_last_index + 1, num_examples) if sounding_matrix is None: these_outputs = model_object_to_use.predict( radar_image_matrix[these_indices, ...], batch_size=len(these_indices)) else: these_outputs = model_object_to_use.predict( [ radar_image_matrix[these_indices, ...], sounding_matrix[these_indices, ...] ], batch_size=len(these_indices)) if output_matrix is None: output_matrix = these_outputs + 0. else: output_matrix = numpy.concatenate((output_matrix, these_outputs), axis=0) if verbose: print 'Have applied model to all {0:d} examples!'.format(num_examples) if return_features: return output_matrix return _binary_probabilities_to_matrix(output_matrix)
def shift_radar_images(radar_image_matrix, x_offset_pixels, y_offset_pixels): """Shifts each radar image in the x- and y-dimensions. :param radar_image_matrix: See doc for `deep_learning_utils.check_radar_images`. :param x_offset_pixels: Each image will be shifted this many pixels in the +x-direction. :param y_offset_pixels: Each image will be shifted this many pixels in the +y-direction. :return: shifted_image_matrix: Same as `radar_image_matrix`, but after shifting. The shapes of the two numpy arrays are the same. """ dl_utils.check_radar_images(radar_image_matrix=radar_image_matrix, min_num_dimensions=3, max_num_dimensions=5) num_grid_rows = radar_image_matrix.shape[1] half_num_grid_rows = int(numpy.floor(float(num_grid_rows) / 2)) error_checking.assert_is_integer(y_offset_pixels) error_checking.assert_is_geq(y_offset_pixels, -half_num_grid_rows) error_checking.assert_is_leq(y_offset_pixels, half_num_grid_rows) num_grid_columns = radar_image_matrix.shape[2] half_num_grid_columns = int(numpy.floor(float(num_grid_columns) / 2)) error_checking.assert_is_integer(x_offset_pixels) error_checking.assert_is_geq(x_offset_pixels, -half_num_grid_columns) error_checking.assert_is_leq(x_offset_pixels, half_num_grid_columns) if x_offset_pixels == y_offset_pixels == 0: return radar_image_matrix + 0. num_padding_columns_at_left = max([x_offset_pixels, 0]) num_padding_columns_at_right = max([-x_offset_pixels, 0]) num_padding_rows_at_top = max([y_offset_pixels, 0]) num_padding_rows_at_bottom = max([-y_offset_pixels, 0]) pad_width_input_arg = ((0, 0), (num_padding_rows_at_top, num_padding_rows_at_bottom), (num_padding_columns_at_left, num_padding_columns_at_right)) num_dimensions = len(radar_image_matrix.shape) for _ in range(3, num_dimensions): pad_width_input_arg += ((0, 0), ) shifted_image_matrix = numpy.pad(radar_image_matrix, pad_width=pad_width_input_arg, mode='constant', constant_values=PADDING_VALUE) if x_offset_pixels >= 0: shifted_image_matrix = shifted_image_matrix[:, :, :num_grid_columns, ...] else: shifted_image_matrix = shifted_image_matrix[:, :, -num_grid_columns:, ...] if y_offset_pixels >= 0: shifted_image_matrix = shifted_image_matrix[:, :num_grid_rows, ...] else: shifted_image_matrix = shifted_image_matrix[:, -num_grid_rows:, ...] return shifted_image_matrix