diff --git a/MindEarth/applications/climate-prediction/ensoforecast/src/utils.py b/MindEarth/applications/climate-prediction/ensoforecast/src/utils.py index d3c4f0cdbb4e8efb030777d9056ed87d442236d6..e1c669d0738185323e5c50d623e5959045a4befe 100644 --- a/MindEarth/applications/climate-prediction/ensoforecast/src/utils.py +++ b/MindEarth/applications/climate-prediction/ensoforecast/src/utils.py @@ -59,8 +59,10 @@ def init_dataloader(config): data_params = config.get('data') train_type = data_params.get('train_dataset') valid_type = data_params.get('valid_dataset') - assert train_type in ['CMIP5', 'Reanalysis'], 'Unexpected Data Type %s.' % train_type - assert valid_type in ['CMIP5', 'Reanalysis'], 'Unexpected Data Type %s.' % valid_type + if train_type not in ['CMIP5', 'Reanalysis']: + raise ValueError(f"Unexpected Data Type {train_type}.") + if valid_type not in ['CMIP5', 'Reanalysis']: + raise ValueError(f"Unexpected Data Type {valid_type}.") if train_type == 'CMIP5': train_dataset = CMIP5Data(data_params.get('root_dir'), data_params.get('train_period'), data_params.get('obs_time'), data_params.get('pred_time')) diff --git a/MindEarth/applications/earthquake/G-TEAM/src/models.py b/MindEarth/applications/earthquake/G-TEAM/src/models.py index 1c91673a673d2c80b0fbf448eb096240fcf393ed..57a23019794223ba2af95741a36521a98d19d706 100644 --- a/MindEarth/applications/earthquake/G-TEAM/src/models.py +++ b/MindEarth/applications/earthquake/G-TEAM/src/models.py @@ -236,7 +236,8 @@ class PositionEmbedding(nn.Cell): min_lat, max_lat = wavelengths[0] min_lon, max_lon = wavelengths[1] min_depth, max_depth = wavelengths[2] - assert emb_dim % 10 == 0 + if emb_dim % 10 != 0: + raise ValueError(f"emb_dim must be divisible by 10, but got {emb_dim}") lat_dim = emb_dim // 5 lon_dim = emb_dim // 5 depth_dim = emb_dim // 10 diff --git a/MindEarth/applications/medium-range/koopman_vit/src/callback.py b/MindEarth/applications/medium-range/koopman_vit/src/callback.py index f8802248e95e06d5de6ed611f5435e96bc72d9e0..66b4f932030b01012a799567348236142998f661 100644 --- a/MindEarth/applications/medium-range/koopman_vit/src/callback.py +++ b/MindEarth/applications/medium-range/koopman_vit/src/callback.py @@ -184,8 +184,8 @@ class Lploss(nn.LossBase): def __init__(self, p=2, size_average=True, reduction=True): super(Lploss, self).__init__() # Dimension and Lp-norm type are positive - assert p > 0 - + if p <= 0: + raise ValueError(f"p must be positive, but got {p}") self.p = p self.reduction = reduction self.size_average = size_average diff --git a/MindEarth/applications/nowcasting/PreDiff/configs/diffusion.yaml b/MindEarth/applications/nowcasting/PreDiff/configs/diffusion.yaml deleted file mode 100644 index 408dfe6f013d21af1b9292c6fc461622bfef82b6..0000000000000000000000000000000000000000 --- a/MindEarth/applications/nowcasting/PreDiff/configs/diffusion.yaml +++ /dev/null @@ -1,193 +0,0 @@ -data: - dataset_name: "sevirlr" - seq_in: 13 - plot_stride: 1 - interval_real_time: 10 - raw_seq_len: 25 - sample_mode: "sequent" - stride: 6 - layout: "NTHWC" - start_date: null - train_val_split_date: [2019, 3, 19] - train_test_split_date: [2019, 6, 1] - end_date: null - val_ratio: 0.1 - metrics_mode: "0" - metrics_list: ['csi', 'pod', 'sucr', 'bias'] - threshold_list: [16, 74, 133, 160, 181, 219] - aug_mode: "0" - root_dir: "./dataset/sevir_lr" -layout: - t_in: 7 - t_out: 6 - data_channels: 1 - layout: "NTHWC" -optim: - total_batch_size: 64 - micro_batch_size: 2 - seed: 0 - float32_matmul_precision: "high" - method: "adamw" - lr: 1.0e-5 - betas: [0.9, 0.999] - gradient_clip_val: 1.0 - max_epochs: 2000 - loss_type: "l2" - warmup_percentage: 0.1 - lr_scheduler_mode: "cosine" - min_lr_ratio: 1.0e-3 - warmup_min_lr_ratio: 0.1 - monitor: "val/loss" - early_stop: false - early_stop_mode: "min" - early_stop_patience: 100 - save_top_k: 3 -logging: - logging_prefix: "PreDiff" - monitor_lr: true - monitor_device: false - track_grad_norm: -1 - use_wandb: false - profiler: null -trainer: - check_val_every_n_epoch: 50 - log_step_ratio: 0.001 - precision: 32 - find_unused_parameters: false -eval: - train_example_data_idx_list: [0, ] - val_example_data_idx_list: [0, 16, 32, 48, 64, 72, 96, 108, 128] - test_example_data_idx_list: [0, 16, 32, 48, 64, 72, 96, 108, 128] - eval_example_only: true - eval_aligned: true - eval_unaligned: true - num_samples_per_context: 1 - fs: 20 - label_offset: [-0.5, 0.5] - label_avg_int: false - fvd_features: 400 -model: - diffusion: - data_shape: [6, 128, 128, 1] - timesteps: 1000 - beta_schedule: "linear" - log_every_t: 100 - clip_denoised: false - linear_start: 1e-4 - linear_end: 2e-2 - cosine_s: 8e-3 - given_betas: null - original_elbo_weight: 0. - v_posterior: 0. - l_simple_weight: 1. - learn_logvar: false - logvar_init: 0. - latent_shape: [6, 16, 16, 64] - cond_stage_forward: null - scale_by_std: false - scale_factor: 1.0 - latent_cond_shape: [7, 16, 16, 64] - align: - alignment_type: "avg_x" - guide_scale: 50.0 - model_type: "cuboid" - model_args: - input_shape: [6, 16, 16, 64] - out_channels: 1 - base_units: 128 - scale_alpha: 1.0 - depth: [1, 1] - downsample: 2 - downsample_type: "patch_merge" - use_attn_pattern: true - num_heads: 4 - attn_drop: 0.1 - proj_drop: 0.1 - ffn_drop: 0.1 - ffn_activation: "gelu" - gated_ffn: false - norm_layer: "layer_norm" - use_inter_ffn: true - hierarchical_pos_embed: false - padding_type: "zeros" - use_relative_pos: true - self_attn_use_final_proj: true - num_global_vectors: 0 - use_global_vector_ffn: true - use_global_self_attn: false - separate_global_qkv: false - global_dim_ratio: 1 - attn_linear_init_mode: "0" - ffn_linear_init_mode: "0" - ffn2_linear_init_mode: "2" - attn_proj_linear_init_mode: "2" - conv_init_mode: "0" - down_linear_init_mode: "0" - global_proj_linear_init_mode: "2" - norm_init_mode: "0" - time_embed_channels_mult: 4 - time_embed_use_scale_shift_norm: false - time_embed_dropout: 0.0 - pool: "attention" - readout_seq: true - t_out: 6 - model_ckpt_path: "./ckpt/align.ckpt" - latent_model: - input_shape: [7, 16, 16, 64] - target_shape: [6, 16, 16, 64] - base_units: 256 - block_units: Null - scale_alpha: 1.0 - num_heads: 4 - attn_drop: 0.1 - proj_drop: 0.1 - ffn_drop: 0.1 - downsample: 2 - downsample_type: "patch_merge" - upsample_type: "upsample" - upsample_kernel_size: 3 - depth: [4, 4] - use_attn_pattern: true - num_global_vectors: 0 - use_global_vector_ffn: false - use_global_self_attn: true - separate_global_qkv: true - global_dim_ratio: 1 - ffn_activation: "gelu" - gated_ffn: false - norm_layer: "layer_norm" - padding_type: "zeros" - use_relative_pos: true - self_attn_use_final_proj: true - attn_linear_init_mode: "0" - ffn_linear_init_mode: "0" - ffn2_linear_init_mode: "2" - attn_proj_linear_init_mode: "2" - conv_init_mode: "0" - down_linear_init_mode: "0" - global_proj_linear_init_mode: "2" - norm_init_mode: "0" - time_embed_channels_mult: 4 - time_embed_use_scale_shift_norm: false - time_embed_dropout: 0.0 - unet_res_connect: true - vae: - pretrained_ckpt_path: "./ckpt/vae.ckpt" - data_channels: 1 - down_block_types: ['DownEncoderBlock2D', 'DownEncoderBlock2D', 'DownEncoderBlock2D', 'DownEncoderBlock2D'] - in_channels: 1 - block_out_channels: [128, 256, 512, 512] - act_fn: 'silu' - latent_channels: 64 - up_block_types: ['UpDecoderBlock2D', 'UpDecoderBlock2D', 'UpDecoderBlock2D', 'UpDecoderBlock2D'] - norm_num_groups: 32 - layers_per_block: 2 - out_channels: 1 -summary: - summary_dir: "./summary/prediff" - eval_interval: 10 - save_ckpt_epochs: 1 - keep_ckpt_max: 100 - ckpt_path: "./ckpt/diffusion.ckpt" - load_ckpt: false - diff --git a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/cuboid_transformer.py b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/cuboid_transformer.py index b51fb72cd72e32e2b799ba51156782ea9359eca9..97e3e952bf51c43b3b7df15e7420c91f109707fc 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/cuboid_transformer.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/cuboid_transformer.py @@ -335,7 +335,11 @@ class Upsample3DLayer(nn.Cell): def construct(self, x): """Forward pass of the 3D Upsampling layer.""" b, t, h, w, c = x.shape - assert self.target_size[0] == t + if self.target_size[0] != t: + raise ValueError( + f"Target size mismatch: expected first dimension to be {self.target_size[0]}, " + f"but got {t}. Please ensure consistent dimensions." + ) x = x.reshape(b * t, h, w, c).permute(0, 3, 1, 2) x = self.up(x) return ( @@ -645,7 +649,11 @@ class CuboidSelfAttentionLayer(nn.Cell): self.ffn_linear_init_mode = ffn_linear_init_mode self.norm_init_mode = norm_init_mode - assert dim % num_heads == 0 + if dim % num_heads != 0: + raise ValueError( + f"Dimension {dim} must be divisible by number of heads {num_heads}. " + f"Got dim={dim}, num_heads={num_heads}" + ) self.num_heads = num_heads self.dim = dim self.cuboid_size = cuboid_size @@ -659,7 +667,11 @@ class CuboidSelfAttentionLayer(nn.Cell): self.use_global_self_attn = use_global_self_attn self.separate_global_qkv = separate_global_qkv self.global_dim_ratio = global_dim_ratio - assert self.padding_type in ["ignore", "zeros", "nearest"] + if self.padding_type not in ["ignore", "zeros", "nearest"]: + raise ValueError( + f"Invalid padding_type: '{self.padding_type}'. " + f"Expected one of: ['ignore', 'zeros', 'nearest']" + ) head_dim = dim // num_heads self.scale = qk_scale or head_dim**-0.5 @@ -767,7 +779,11 @@ class CuboidSelfAttentionLayer(nn.Cell): """ x = self.norm(x) batch, time, height, width, channels = x.shape - assert channels == self.dim + if channels != self.dim: + raise ValueError( + f"Channel dimension mismatch: expected {self.dim}, got {channels}. " + f"Please ensure input channels match the layer's expected dimension." + ) cuboid_size, shift_size = update_cuboid_size_shift_size( (time, height, width), self.cuboid_size, self.shift_size, self.strategy ) diff --git a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/cuboid_transformer_unet.py b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/cuboid_transformer_unet.py index ae3292ceb0fffed8c4e78e663b53addf3cb44b0b..67929ae0c9bf7a1f848b3a07026e8a87eb339567 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/cuboid_transformer_unet.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/cuboid_transformer_unet.py @@ -117,16 +117,29 @@ class CuboidTransformerUNet(nn.Cell): for i in range(self.num_blocks) ] else: - assert len(block_units) == self.num_blocks and block_units[0] == base_units + if len(block_units) != self.num_blocks: + raise ValueError( + f"Length of block_units ({len(block_units)}) does not match " + f"num_blocks ({self.num_blocks}). They must be equal." + ) + if block_units[0] != base_units: + raise ValueError( + f"First block_units value ({block_units[0]}) does not match " + f"base_units ({base_units}). The first unit must equal base_units." + ) self.block_units = block_units self.hierarchical_pos_embed = hierarchical_pos_embed self.num_global_vectors = num_global_vectors use_global_vector = num_global_vectors > 0 self.use_global_vector = use_global_vector if global_dim_ratio != 1: - assert ( - separate_global_qkv is True - ), f"Setting global_dim_ratio != 1 requires separate_global_qkv == True." + if not separate_global_qkv: + raise ValueError( + "Configuration conflict: When global_dim_ratio != 1, " + "separate_global_qkv must be set to True. " + f"Current values: global_dim_ratio={global_dim_ratio}, " + f"separate_global_qkv={separate_global_qkv}" + ) self.global_dim_ratio = global_dim_ratio self.use_global_vector_ffn = use_global_vector_ffn @@ -143,7 +156,19 @@ class CuboidTransformerUNet(nn.Cell): t_in, h_in, w_in, c_in = input_shape t_out, h_out, w_out, c_out = target_shape - assert h_in == h_out and w_in == w_out and c_in == c_out + if h_in != h_out or w_in != w_out or c_in != c_out: + mismatched_dims = [] + if h_in != h_out: + mismatched_dims.append(f"height ({h_in} vs {h_out})") + if w_in != w_out: + mismatched_dims.append(f"width ({w_in} vs {w_out})") + if c_in != c_out: + mismatched_dims.append(f"channels ({c_in} vs {c_out})") + raise ValueError( + f"Input and output dimensions mismatch. " + f"Mismatched dimensions: {', '.join(mismatched_dims)}. " + f"All dimensions must match for this operation." + ) self.t_in = t_in self.t_out = t_out self.first_proj = TimeEmbedResBlock( @@ -263,27 +288,37 @@ class CuboidTransformerUNet(nn.Cell): if not isinstance(block_cuboid_size[0][0], (list, tuple)): block_cuboid_size = [block_cuboid_size for _ in range(self.num_blocks)] else: - assert ( - len(block_cuboid_size) == self.num_blocks - ), f"Incorrect input format! Received block_cuboid_size={block_cuboid_size}" - + if len(block_cuboid_size) != self.num_blocks: + raise ValueError( + f"Block cuboid size dimension mismatch. Expected {self.num_blocks} blocks, " + f"but got {len(block_cuboid_size)}. Received block_cuboid_size={block_cuboid_size}. " + f"Please ensure the input matches the expected number of blocks." + ) if not isinstance(block_cuboid_strategy[0][0], (list, tuple)): block_cuboid_strategy = [ block_cuboid_strategy for _ in range(self.num_blocks) ] else: - assert ( - len(block_cuboid_strategy) == self.num_blocks - ), f"Incorrect input format! Received block_strategy={block_cuboid_strategy}" + if len(block_cuboid_strategy) != self.num_blocks: + raise ValueError( + f"Configuration error: Expected {self.num_blocks} block strategies, " + f"but got {len(block_cuboid_strategy)}. " + f"Received block_cuboid_strategy={block_cuboid_strategy}. " + f"Please ensure the strategy list matches the number of blocks." + ) if not isinstance(block_cuboid_shift_size[0][0], (list, tuple)): block_cuboid_shift_size = [ block_cuboid_shift_size for _ in range(self.num_blocks) ] else: - assert ( - len(block_cuboid_shift_size) == self.num_blocks - ), f"Incorrect input format! Received block_shift_size={block_cuboid_shift_size}" + if len(block_cuboid_shift_size) != self.num_blocks: + raise ValueError( + f"Block shift size configuration error: Expected {self.num_blocks} shift sizes, " + f"but received {len(block_cuboid_shift_size)}. " + f"Invalid configuration: block_cuboid_shift_size={block_cuboid_shift_size}. " + f"Please provide exactly {self.num_blocks} shift sizes in the list." + ) self.block_cuboid_size = block_cuboid_size self.block_cuboid_strategy = block_cuboid_strategy self.block_cuboid_shift_size = block_cuboid_shift_size @@ -442,7 +477,20 @@ class CuboidTransformerUNet(nn.Cell): if not hasattr(self, "_data_shape"): t_in, h_in, w_in, c_in = self.input_shape t_out, h_out, w_out, c_out = self.target_shape - assert h_in == h_out and w_in == w_out and c_in == c_out + if not (h_in == h_out and w_in == w_out and c_in == c_out): + mismatches = [] + if h_in != h_out: + mismatches.append(f"height ({h_in} vs {h_out})") + if w_in != w_out: + mismatches.append(f"width ({w_in} vs {w_out})") + if c_in != c_out: + mismatches.append(f"channels ({c_in} vs {c_out})") + raise ValueError( + f"Input-output dimension mismatch. Mismatched dimensions: {', '.join(mismatches)}. " + f"All dimensions must match for this operation. " + f"Input shape: (h={h_in}, w={w_in}, c={c_in}), " + f"Output shape: (h={h_out}, w={w_out}, c={c_out})" + ) self._data_shape = ( t_in + t_out, h_in, diff --git a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/latent_diffusion.py b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/latent_diffusion.py index 657dd45c4d56f0c1d60a46a5e0b87fde7d859f2d..040afb9cb3f2310d48f654c93cd14f18fd52a035 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/latent_diffusion.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/latent_diffusion.py @@ -211,9 +211,12 @@ class LatentDiffusion(nn.Cell): self.num_timesteps = int(timesteps) self.linear_start = linear_start self.linear_end = linear_end - assert ( - alphas_cumprod.shape[0] == self.num_timesteps - ), "alphas have to be defined for each timestep" + if alphas_cumprod.shape[0] != self.num_timesteps: + raise ValueError( + f"Timestep dimension mismatch: alphas_cumprod has {alphas_cumprod.shape[0]} timesteps, " + f"but expected {self.num_timesteps}. " + "The alpha values must be defined for each diffusion timestep." + ) to_mindspore = partial(Tensor, dtype=ms.float32) self.betas = Parameter(to_mindspore(betas), name="betas", requires_grad=False) @@ -287,7 +290,12 @@ class LatentDiffusion(nn.Cell): self.lvlb_weights = Parameter( lvlb_weights, name="lvlb_weights", requires_grad=False ) - assert not ops.isnan(self.lvlb_weights).all() + if ops.isnan(self.lvlb_weights).all(): + raise ValueError( + "All lvlb_weights are NaN (Not a Number). " + "This indicates a numerical instability or uninitialized weights. " + "Please check the weight initialization or training process." + ) def instantiate_first_stage(self, first_stage_model): """ @@ -298,8 +306,16 @@ class LatentDiffusion(nn.Cell): if isinstance(first_stage_model, nn.Cell): model = first_stage_model else: - assert first_stage_model is None - raise NotImplementedError("No default first_stage_model supported yet!") + if first_stage_model is not None: + raise ValueError( + "Custom first_stage_model is not currently supported. " + f"Received: {type(first_stage_model).__name__}. " + "This functionality is planned for future implementation." + ) + raise NotImplementedError( + "Automatic first_stage_model initialization is not yet implemented. " + "Please check for framework updates or consider contributing." + ) self.first_stage_model = model.set_train(False) self.first_stage_model.train = disabled_train for param in self.first_stage_model.trainable_params(): @@ -356,7 +372,14 @@ class LatentDiffusion(nn.Cell): def einops_spatial_layout(self): """Generates spatial Einops pattern for 2D/3D data handling.""" if not hasattr(self, "_einops_spatial_layout"): - assert len(self.layout) == 4 or len(self.layout) == 5 + if len(self.layout) not in (4, 5): + raise ValueError( + f"Invalid layout dimension: expected 4 or 5 dimensions, but got {len(self.layout)}. " + f"Current layout: {self.layout}\n" + "Possible solutions:\n" + "1. For 2D data: use [batch, channel, height, width]\n" + "2. For 3D data: use [batch, channel, depth, height, width]" + ) self._einops_spatial_layout = ( "(N T) C H W" if self.layout.find("T") else "N C H W" ) @@ -718,8 +741,19 @@ class LatentDiffusion(nn.Cell): ) if mask is not None: - assert x0 is not None - assert x0.shape[2:3] == mask.shape[2:3] # spatial size has to match + if x0 is None: + raise ValueError( + "Missing required input: x0 cannot be None. " + "Please provide valid input data." + ) + + if x0.shape[2:3] != mask.shape[2:3]: + raise ValueError( + f"Spatial dimension mismatch between input and mask. " + f"Input spatial size: {x0.shape[2:3]}, " + f"Mask spatial size: {mask.shape[2:3]}. " + "The height and width dimensions must match exactly." + ) for i in iterator: ts = ops.full((batch_size,), i, dtype=ms.int64) img = self.p_sample( @@ -781,7 +815,11 @@ class LatentDiffusion(nn.Cell): if shape is None: shape = self.get_batch_latent_shape(batch_size=batch_size) if self.cond_stage_model is not None: - assert cond is not None + if cond is None: + raise ValueError( + "Required condition is None. " + "This parameter must be provided with a valid value." + ) cond_tensor_slice = [ slice(None, None), ] * len(self.data_shape) diff --git a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/solver.py b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/solver.py index 103cf70643de7aa19105dacb28116e31938d750a..bdbb5d4f85002b5943f4b5c290cf7c9d650dedaf 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/solver.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/solver.py @@ -79,7 +79,11 @@ class DiffusionTrainer(nn.Cell): epoch_start = time.time() iterator = self.traindataset.create_dict_iterator() - assert iterator, "dataset is empty" + if not iterator: + raise ValueError( + "Empty dataset error: The provided dataset iterator contains no data. " + "Please verify your data loading pipeline and ensure the dataset is properly populated." + ) batch_idx = 0 for batch_idx, batch in enumerate(iterator): processed_data = self.datasetprocessing.process_data(batch["vil"]) diff --git a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/time_embed.py b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/time_embed.py index 1642d0c295c14a7d002fc9b2023802a764109b27..f052dc189b0f0c214c45d7b1017cc7e9c5ac560e 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/diffusion/time_embed.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/diffusion/time_embed.py @@ -40,7 +40,13 @@ class Upsample(nn.Cell): def construct(self, x): '''upsample forward''' - assert x.shape[1] == self.channels + if x.shape[1] != self.channels: + raise ValueError( + f"Channel dimension mismatch: input has {x.shape[1]} channels, " + f"but layer expects {self.channels} channels. " + f"Input shape: {x.shape}, expected channels dimension: {self.channels}. " + "Please adjust your input data or layer configuration." + ) if self.dims == 3: x = ops.interpolate( x, (x.shape[2], x.shape[3] * 2, x.shape[4] * 2), mode="nearest" @@ -78,11 +84,22 @@ class Downsample(nn.Cell): padding=padding, ) else: - assert self.channels == self.out_channels + if self.channels != self.out_channels: + raise ValueError( + f"Channel configuration mismatch: input channels ({self.channels}) " + f"must match output channels ({self.out_channels}) for this operation. " + "Please adjust either the input channels or the layer configuration." + ) self.op = avg_pool_nd(dims, kernel_size=stride, stride=stride) def construct(self, x): - assert x.shape[1] == self.channels + if x.shape[1] != self.channels: + raise ValueError( + f"Input channel mismatch: Expected {self.channels} channels, " + f"but received input with {x.shape[1]} channels. " + f"Full input shape: {x.shape}. " + "Please ensure your input data matches the layer's channel requirements." + ) return self.op(x) @@ -163,7 +180,12 @@ class TimeEmbedResBlock(nn.Cell): self.dropout = dropout self.use_embed = use_embed if use_embed: - assert isinstance(emb_channels, int) + if not isinstance(emb_channels, int): + raise TypeError( + f"Invalid type for emb_channels: expected integer, got {type(emb_channels).__name__}. " + f"Received value: {emb_channels}. " + "Please provide an integer value for the embedding channels." + ) self.emb_channels = emb_channels self.out_channels = out_channels or channels self.use_conv = use_conv diff --git a/MindEarth/applications/nowcasting/PreDiff/src/knowledge_alignment/alignment.py b/MindEarth/applications/nowcasting/PreDiff/src/knowledge_alignment/alignment.py index f1a6785b3b2b6a7ecdeb3a53d94cfdaff3ac47a9..ec4b7f1608bcfbee9891e0879d2d6b7e237c97d5 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/knowledge_alignment/alignment.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/knowledge_alignment/alignment.py @@ -53,7 +53,13 @@ class QKVAttention(nn.Cell): :return: an [N x (H * C) x T] tensor after attention. """ bs, width, length = qkv.shape - assert width % (3 * self.n_heads) == 0 + if width % (3 * self.n_heads) != 0: + raise ValueError( + f"Dimension mismatch: width ({width}) must be divisible by {3 * self.n_heads} " + f"(3 * n_heads), but got remainder {width % (3 * self.n_heads)}. " + f"Current configuration: n_heads={self.n_heads}. " + "Please adjust either the input width or the number of attention heads." + ) ch = width // (3 * self.n_heads) q, k, v = qkv.chunk(3, dim=1) scale = 1 / math.sqrt(math.sqrt(ch)) @@ -220,7 +226,17 @@ class NoisyCuboidTransformerEncoder(nn.Cell): for i in range(self.num_blocks) ] else: - assert len(block_units) == self.num_blocks and block_units[0] == base_units + if len(block_units) != self.num_blocks: + raise ValueError( + f"Block configuration mismatch: Expected {self.num_blocks} blocks, " + f"but got {len(block_units)}. Received block_units: {block_units}" + ) + + if block_units[0] != base_units: + raise ValueError( + f"First block units mismatch: Expected {base_units}, " + f"but got {block_units[0]}. The first block must match base_units." + ) self.block_units = block_units self.hierarchical_pos_embed = hierarchical_pos_embed self.num_global_vectors = num_global_vectors @@ -321,27 +337,39 @@ class NoisyCuboidTransformerEncoder(nn.Cell): if not isinstance(block_cuboid_size[0][0], (list, tuple)): block_cuboid_size = [block_cuboid_size for _ in range(self.num_blocks)] else: - assert ( - len(block_cuboid_size) == self.num_blocks - ), f"Incorrect input format! Received block_cuboid_size={block_cuboid_size}" + if len(block_cuboid_size) != self.num_blocks: + raise ValueError( + f"Block cuboid configuration error: Expected {self.num_blocks} blocks, " + f"but received {len(block_cuboid_size)} block configurations. " + f"Received block_cuboid_size: {block_cuboid_size}\n" + "Please ensure the number of block configurations matches num_blocks." + ) if not isinstance(block_cuboid_strategy[0][0], (list, tuple)): block_cuboid_strategy = [ block_cuboid_strategy for _ in range(self.num_blocks) ] else: - assert ( - len(block_cuboid_strategy) == self.num_blocks - ), f"Incorrect input format! Received block_strategy={block_cuboid_strategy}" + if len(block_cuboid_strategy) != self.num_blocks: + raise ValueError( + f"Block strategy configuration error: Expected {self.num_blocks} strategies (one per block), " + f"but received {len(block_cuboid_strategy)}. " + f"Received strategies: {block_cuboid_strategy}\n" + "Each cuboid block must have a corresponding processing strategy." + ) if not isinstance(block_cuboid_shift_size[0][0], (list, tuple)): block_cuboid_shift_size = [ block_cuboid_shift_size for _ in range(self.num_blocks) ] else: - assert ( - len(block_cuboid_shift_size) == self.num_blocks - ), f"Incorrect input format! Received block_shift_size={block_cuboid_shift_size}" + if len(block_cuboid_shift_size) != self.num_blocks: + raise ValueError( + f"Block shift configuration error: Expected {self.num_blocks} shift sizes (one per block), " + f"but received {len(block_cuboid_shift_size)}. " + f"Received shift sizes: {block_cuboid_shift_size}\n" + "Each cuboid block must have a corresponding shift size configuration." + ) self.block_cuboid_size = block_cuboid_size self.block_cuboid_strategy = block_cuboid_strategy self.block_cuboid_shift_size = block_cuboid_shift_size diff --git a/MindEarth/applications/nowcasting/PreDiff/src/sevir_dataset.py b/MindEarth/applications/nowcasting/PreDiff/src/sevir_dataset.py index d0fca3d1c9ce714a11e1a203e22fa6e4bfec2048..5b9c48128820cf64ad0b23b4fe3f7258061e373d 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/sevir_dataset.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/sevir_dataset.py @@ -414,14 +414,22 @@ class SEVIRDataLoader: self.data_shape = SEVIR_DATA_SHAPE self.raw_seq_in = raw_seq_in - assert ( - seq_in <= self.raw_seq_in - ), f"seq_in must not be larger than raw_seq_in = {raw_seq_in}, got {seq_in}." + if seq_in > self.raw_seq_in: + raise ValueError( + f"Sequence length violation: Input sequence length ({seq_in}) " + f"exceeds maximum allowed length ({self.raw_seq_in}).\n" + f"Technical constraints: Processed sequence length must be ≤ original length.\n" + "Please check your sequence trimming/padding operations." + ) self.seq_in = seq_in - assert sample_mode in [ - "random", - "sequent", - ], f"Invalid sample_mode = {sample_mode}, must be 'random' or 'sequent'." + if sample_mode not in ["random", "sequent"]: + raise ValueError( + f"Invalid sampling mode: '{sample_mode}'. " + f"Allowed options are: {['random', 'sequent']}\n" + "Please specify either:\n" + "- 'random' for stochastic sampling\n" + "- 'sequent' for sequential sampling" + ) self.sample_mode = sample_mode self.stride = stride self.batch_size = batch_size @@ -921,7 +929,13 @@ class SEVIRDataset: if data_types is None: data_types = SEVIR_DATA_TYPES else: - assert set(data_types).issubset(SEVIR_DATA_TYPES) + if not set(data_types).issubset(SEVIR_DATA_TYPES): + invalid_types = set(data_types) - set(SEVIR_DATA_TYPES) + raise ValueError( + f"Invalid data type(s) detected: {sorted(invalid_types)}\n" + f"Allowed SEVIR data types are: {sorted(SEVIR_DATA_TYPES)}\n" + "Please remove or replace the unsupported data types." + ) self.layout = layout self.data_types = data_types diff --git a/MindEarth/applications/nowcasting/PreDiff/src/utils.py b/MindEarth/applications/nowcasting/PreDiff/src/utils.py index 5727573a783b017ac215f4f3a5dcb53484505590..1908b6a13b9e8b4b2da3935003a4af8cee1d40d2 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/utils.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/utils.py @@ -179,7 +179,13 @@ class SEVIRSkillScore(Metric): ): super().__init__() self.layout = layout - assert preprocess_type == "sevir" or preprocess_type.startswith("sevir_pool") + if not (preprocess_type == "sevir" or preprocess_type.startswith("sevir_pool")): + raise ValueError( + f"Invalid preprocessing type: '{preprocess_type}'\n" + "Allowed options:\n" + "- 'sevir' for standard processing\n" + "- 'sevir_pool*' for pooled variants (e.g. 'sevir_pool4')" + ) self.preprocess_type = preprocess_type self.threshold_list = threshold_list self.metrics_list = metrics_list @@ -191,9 +197,11 @@ class SEVIRSkillScore(Metric): state_shape = (len(self.threshold_list),) elif mode in ("1", "2"): self.keep_seq_in_dim = True - assert isinstance( - self.seq_in, int - ), "seq_in must be provided when we need to keep seq_in dim." + if not isinstance(self.seq_in, int): + raise TypeError( + f"Invalid type for seq_in: expected integer, got {type(self.seq_in).__name__}. " + "This parameter is required when preserving the sequence dimension." + ) state_shape = (len(self.threshold_list), self.seq_in) else: @@ -572,8 +580,17 @@ def get_norm_layer( """ if isinstance(norm_type, str): if norm_type == "layer_norm": - assert in_channels > 0 - assert axis == -1 + if in_channels <= 0: + raise ValueError( + f"Invalid number of input channels: {in_channels}. " + "in_channels must be a positive integer." + ) + + if axis != -1: + raise ValueError( + f"Invalid axis specification: {axis}. " + "This operation only supports axis=-1 (last dimension)." + ) norm_layer = nn.LayerNorm( normalized_shape=[in_channels], epsilon=epsilon, **kwargs ) @@ -606,7 +623,15 @@ def generalize_padding(x, pad_t, pad_h, pad_w, padding_type, t_pad_left=False): if pad_t == 0 and pad_h == 0 and pad_w == 0: return x - assert padding_type in ["zeros", "ignore", "nearest"] + if padding_type not in ["zeros", "ignore", "nearest"]: + raise ValueError( + f"Invalid padding type: '{padding_type}'. " + f"Allowed options are: {['zeros', 'ignore', 'nearest']}\n" + "Please specify one of:\n" + "- 'zeros': pad with zero values\n" + "- 'ignore': maintain original values\n" + "- 'nearest': replicate edge values" + ) _, t, h, w, _ = x.shape if padding_type == "nearest": @@ -634,7 +659,11 @@ def generalize_unpadding(x, pad_t, pad_h, pad_w, padding_type): Raises: AssertionError: If invalid padding_type is provided. """ - assert padding_type in ["zeros", "ignore", "nearest"] + if padding_type not in ["zeros", "ignore", "nearest"]: + raise ValueError( + f"Invalid padding_type: '{padding_type}'. " + f"Supported padding types are: 'zeros', 'ignore', 'nearest'" + ) _, t, h, w, _ = x.shape if pad_t == 0 and pad_h == 0 and pad_w == 0: return x diff --git a/MindEarth/applications/nowcasting/PreDiff/src/vae/resnet.py b/MindEarth/applications/nowcasting/PreDiff/src/vae/resnet.py index 6a20d3b5fdb1ad343105c33e6649708d4745810f..b954f9d4595df4e71880b317557987f254d77112 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/vae/resnet.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/vae/resnet.py @@ -120,7 +120,11 @@ class Upsample1D(nn.Cell): def construct(self, x): """forward""" - assert x.shape[1] == self.channels + if x.shape[1] != self.channels: + raise ValueError( + f"Input channels mismatch. Expected {self.channels} channels, " + f"but got {x.shape[1]} channels in dimension 1 of input tensor." + ) if self.use_conv_transpose: return self.conv(x) @@ -165,11 +169,14 @@ class Downsample1D(nn.Cell): has_bias=True, ) else: - assert self.channels == self.out_channels + if self.channels != self.out_channels: + raise RuntimeError( + f"Channels mismatch. Expected channels and out_channels to be equal, " + f"but got channels={self.channels}, out_channels={self.out_channels}." + ) self.conv = AvgPool1d(kernel_size=stride, stride=stride) def construct(self, x): - assert x.shape[1] == self.channels return self.conv(x) @@ -226,7 +233,14 @@ class Upsample2D(nn.Cell): def construct(self, hidden_states, output_size=None): """forward""" - assert hidden_states.shape[1] == self.channels + if hidden_states.shape[1] != self.channels: + raise ValueError( + f"Channel dimension mismatch in hidden states. " + f"Expected {self.channels} channels at dimension 1, " + f"but received {hidden_states.shape[1]} channels. " + f"Full shape: {tuple(hidden_states.shape)}" + ) + if self.use_conv_transpose: return self.conv(hidden_states) @@ -292,7 +306,13 @@ class Downsample2D(nn.Cell): has_bias=True, ) else: - assert self.channels == self.out_channels + if self.channels != self.out_channels: + raise RuntimeError( + f"Layer configuration conflict. channels ({self.channels}) " + f"must equal out_channels ({self.out_channels}). " + f"Check layer initialization parameters." + ) + conv = mint.nn.AvgPool2d(kernel_size=stride, stride=stride) if name == "conv": self.conv2d_0 = conv @@ -304,12 +324,28 @@ class Downsample2D(nn.Cell): def construct(self, hidden_states): """forward""" - assert hidden_states.shape[1] == self.channels + if hidden_states.shape[1] != self.channels: + raise ValueError( + f"Channel dimension mismatch in hidden states. Expected {self.channels} channels at dimension 1, " + f"but received tensor with {hidden_states.shape[1]} channels. " + f"Full shape: {tuple(hidden_states.shape)}" + ) + if self.use_conv and self.padding == 0: pad = (0, 1, 0, 1) hidden_states = ops.pad(hidden_states, pad, mode="constant", value=None) - assert hidden_states.shape[1] == self.channels + if hidden_states.shape[1] != self.channels: + raise ValueError( + f"Channel dimension mismatch in hidden states. " + f"Layer expects {self.channels} channels at dimension 1, " + f"but received {hidden_states.shape[1]} channels. " + f"Full tensor shape: {tuple(hidden_states.shape)}\n" + f"Possible solutions:\n" + f"1. Check input data pipeline\n" + f"2. Verify layer configuration (current channels: {self.channels})\n" + f"3. Inspect preceding layer's output channels" + ) hidden_states = self.conv(hidden_states) return hidden_states @@ -356,7 +392,17 @@ class FirUpsample2D(nn.Cell): Core upsampling operation with optional convolution and FIR filtering. """ - assert isinstance(factor, int) and factor >= 1 + if not isinstance(factor, int): + raise TypeError( + f"Invalid type for 'factor'. Expected integer, " + f"but got {type(factor).__name__}." + ) + + if factor < 1: + raise ValueError( + f"Invalid value for 'factor'. Must be >= 1, " + f"but got {factor}." + ) # Setup filter kernel. if kernel is None: @@ -387,7 +433,25 @@ class FirUpsample2D(nn.Cell): output_shape[0] - (hidden_states.shape[2] - 1) * stride[0] - convh, output_shape[1] - (hidden_states.shape[3] - 1) * stride[1] - convw, ) - assert output_padding[0] >= 0 and output_padding[1] >= 0 + if len(output_padding) < 2: + raise IndexError( + f"output_padding must have at least 2 elements, " + f"but got {len(output_padding)} elements" + ) + + errors = [] + if output_padding[0] < 0: + errors.append(f"output_padding[0] = {output_padding[0]} < 0") + if output_padding[1] < 0: + errors.append(f"output_padding[1] = {output_padding[1]} < 0") + + if errors: + raise ValueError( + f"Invalid output padding values:\n" + + "\n".join(errors) + + f"\nAll output padding values must be >= 0. " + f"Full output_padding: {output_padding}" + ) num_groups = hidden_states.shape[1] // in_c # Transpose weights. @@ -477,7 +541,17 @@ class FirDownsample2D(nn.Cell): """ Core downsampling operation with optional convolution and FIR filtering. """ - assert isinstance(factor, int) and factor >= 1 + if not isinstance(factor, int): + raise TypeError( + f"Invalid type for 'factor'. Expected integer, " + f"but got {type(factor).__name__} with value {repr(factor)}." + ) + + if factor < 1: + raise ValueError( + f"Invalid value for 'factor'. Must be a positive integer >= 1, " + f"but got {factor}." + ) if kernel is None: kernel = [1] * factor @@ -819,7 +893,17 @@ class ResidualTemporalBlock1D(nn.Cell): def upsample_2d(hidden_states, kernel=None, factor=2, gain=1): """Upsample2D a batch of 2D images with the given filter.""" - assert isinstance(factor, int) and factor >= 1 + if not isinstance(factor, int): + raise TypeError( + f"Invalid type for 'factor'. Expected integer, " + f"but got {type(factor).__name__} with value {repr(factor)}." + ) + + if factor < 1: + raise ValueError( + f"Invalid value for 'factor'. Must be a positive integer >= 1, " + f"but got {factor}." + ) if kernel is None: kernel = [1] * factor @@ -840,7 +924,12 @@ def upsample_2d(hidden_states, kernel=None, factor=2, gain=1): def downsample_2d(hidden_states, kernel=None, factor=2, gain=1): """Downsample2D a batch of 2D images with the given filter.""" - assert isinstance(factor, int) and factor >= 1 + if not isinstance(factor, int): + raise TypeError(f"factor must be an integer, got {type(factor).__name__}") + + if factor < 1: + raise ValueError(f"factor must be >= 1, got {factor}") + if kernel is None: kernel = [1] * factor diff --git a/MindEarth/applications/nowcasting/PreDiff/src/visual.py b/MindEarth/applications/nowcasting/PreDiff/src/visual.py index 343f3e17edfa1c455ba6e2cf4ee90f12a0adc8ef..65d27e6265b14b4f8573daa566707bd1005b411c 100644 --- a/MindEarth/applications/nowcasting/PreDiff/src/visual.py +++ b/MindEarth/applications/nowcasting/PreDiff/src/visual.py @@ -117,13 +117,30 @@ def vis_sevir_seq( if isinstance(seq, Sequence): seq_list = [ele.astype(np.float32) for ele in seq] - assert isinstance(label, Sequence) and len(label) == len(seq) + if not isinstance(label, Sequence): + raise TypeError( + f"label must be a Sequence (list, tuple, etc.), " + f"got {type(label).__name__}" + ) + + if len(label) != len(seq): + raise ValueError( + f"Length mismatch: label and seq must have same length\n" + f"• len(label) = {len(label)}\n" + f"• len(seq) = {len(seq)}" + ) label_list = label elif isinstance(seq, np.ndarray): seq_list = [ seq.astype(np.float32), ] - assert isinstance(label, str) + if not isinstance(label, str): + raise TypeError( + f"Invalid label type. Expected string, " + f"but got {type(label).__name__}. " + f"Value: {repr(label)}" + ) + label_list = [ label, ]