diff --git a/opensoundscape/localization.py b/opensoundscape/localization.py index 6481fec8..5e9e4436 100644 --- a/opensoundscape/localization.py +++ b/opensoundscape/localization.py @@ -65,19 +65,47 @@ def __init__( - Estimates the tdoas using cross_correlation if not already estimated. - Estimates the location of the event using the tdoas and receiver locations. - Returns the location estimate as a tuple of cartesian coordinates (x,y) or (x,y,z) + + Editable Attributes: + These are parameters that can be set before calling estimate_location() + min_n_receivers: minimum number of receivers that must detect an event for it to be localized + cc_threshold: threshold for cross correlation + cc_filter: filter for generalized cross correlation, see + opensoundscape.signal_processing.gcc() + max_delay: only delays in +/- this range (seconds) will be considered for possible delay + (see opensoundscape.signal_processing.tdoa()); + bandpass_range: bandpass audio to [low, high] frequencies in Hz before cross correlation + speed_of_sound: speed of sound in meters per second + + Static Attributes: + receiver_files: list of audio files, one for each receiver + receiver_locations: list of [x,y] or [x,y,z] positions of each receiver in meters + start_timestamp: start time of detection as datetime.datetime + duration: length in seconds of the event + class_name: name of detection's class + Computed Attributes: + tdoas: time delay at each receiver (computed by _estimate_delays()) + cc_maxs: max of cross correlation for each time delay (computed by _estimate_delays()) + location_estimate: spatial position estimate (computed by estimate_location()) + distance_residuals: distance residuals in meters (computed by estimate_location()) + receivers_used_for_localization: list of receivers used for localization during estimate_location() + residual_rms: root mean square of distance residuals (computed by estimate_location()) """ + # editable attributes + self.min_n_receivers = min_n_receivers + self.cc_threshold = cc_threshold + self.cc_filter = cc_filter + self.max_delay = max_delay + self.bandpass_range = bandpass_range + self.speed_of_sound = speed_of_sound + + # static attributes self.receiver_files = receiver_files self.receiver_locations = np.array(receiver_locations) - self.max_delay = max_delay - self.receiver_start_time_offsets = receiver_start_time_offsets self.start_timestamp = start_timestamp - self.min_n_receivers = min_n_receivers self.duration = duration self.class_name = class_name - self.bandpass_range = bandpass_range - self.cc_threshold = cc_threshold - self.cc_filter = cc_filter - self.speed_of_sound = speed_of_sound + self.receiver_start_time_offsets = receiver_start_time_offsets # Verify that max_delay is not longer than the duration of the audio and raise a value error if it is if self.max_delay >= self.duration: @@ -85,7 +113,7 @@ def __init__( f"max_delay ({self.max_delay}) is longer than duration ({self.duration}) of audio clips." ) - # Initialize attributes + # computed attributes self.tdoas = None # time delay at each receiver self.cc_maxs = None # max of cross correlation for each time delay self.location_estimate = None # cartesian location estimate in meters diff --git a/opensoundscape/ml/cnn.py b/opensoundscape/ml/cnn.py index 725135be..4c994153 100644 --- a/opensoundscape/ml/cnn.py +++ b/opensoundscape/ml/cnn.py @@ -847,14 +847,56 @@ def __init__(self, *args, **kwargs): Args: see SpectrogramModule for arguments + + Methods: + predict: generate predictions across a set of audio files or a dataframe defining audio files and start/end clip times + train: fit the machine learning model using training data and evaluate with validation data + save: save the model to a file + load: load the model from a file + embed: generate embeddings for a set of audio files + generate_embeddings: generate embeddings for a set of audio files + generate_cams: generate gradient activation maps for a set of audio files + eval: evaluate performance by applying self.torch_metrics to predictions and labels + run_validation: test accuracy by running inference on a validation set and computing metrics + change_classes: change the classes that the model predicts + freeze_feature_extractor: freeze all layers except the classifier + freeze_layers_except: freeze all parameters of a model, optionally exluding some layers + train_dataloader: create dataloader for training + predict_dataloader: create dataloader for inference (predict/validate/test) + save_weights: save just the self.network state dict to a file + load_weights: load just the self.network state dict from a file + + Editable Attributes & Properties: + single_target: (bool) if True, predict only class with max score + device: (torch.device or str) device to use for training and inference + preprocessor: object defining preprocessing and augmentation operations, e.g. SpectrogramPreprocessor + network: pytorch model object, e.g. Resnet18 + loss_fn: callable object to use for calculating loss during training, e.g. BCEWithLogitsLoss_hot() + optimizer_params: (dict) with "class" and "kwargs" keys for class.__init__(**kwargs) + lr_scheduler_params: (dict) with "class" and "kwargs" for class.__init__(**kwargs) + use_amp: (bool) if True, uses automatic mixed precision for training + wandb_logging: (dict) settings for logging to Weights and Biases + score_metric: (str) name of the metric for overall evaluation - one of the keys in self.torch_metrics + log_file: (str) path to save output to a text file + logging_level: (int) amt of logging to log file. 0 for nothing, 1,2,3 for increasing logged info + verbose: (int) amt of logging to stdout. 0 for nothing, 1,2,3 for increasing printed output + + Other attributes: + torch_metrics: dictionary of torchmetrics name:object pairs to use for calculating metrics + - override _init_torch_metrics() method in a subclass rather than modifying directly + classes: list of class names + - set via __init__() or change_classes(), rather than modifying directly """ super().__init__(*args, **kwargs) - self.log_file = None # specify a path to save output to a text file - self.logging_level = 1 # 0 for nothing, 1,2,3 for increasing logged info - self.verbose = 1 # 0 for nothing, 1,2,3 for increasing printed output - self.scheduler = None # learning rate scheduler - self.optimizer = None # optimizer during training + self.log_file = None + """specify a path to save output to a text file""" + self.logging_level = 1 + """amount of logging to self.log_file. 0 for nothing, 1,2,3 for increasing logged info""" + self.verbose = 1 + """amount of logging to stdout. 0 for nothing, 1,2,3 for increasing printed output""" + self.scheduler = None # learning rate scheduler, initialized during configure_optimizers() call + self.optimizer = None # optimizer during training , initialized during configure_optimizers() call self.current_epoch = 0 """track number of trained epochs"""