diff --git a/Evaluation/evaluate.py b/Evaluation/evaluate.py index 101d39e..529c0f4 100644 --- a/Evaluation/evaluate.py +++ b/Evaluation/evaluate.py @@ -50,8 +50,7 @@ def forward(self, y_pred, y_true): y_true_f = torch.flatten(y_true) intersection = torch.sum(y_true_f * y_pred_f) union = torch.sum(y_true_f + y_pred_f) - intersection - score = (intersection + self.smooth) / (union + self.smooth) - return score + return (intersection + self.smooth) / (union + self.smooth) class FocalTverskyLoss(nn.Module): @@ -81,10 +80,16 @@ def nan_hook(self, module, inp, output): torch.save(inp, os.path.join(self.output_dir, 'nan_floss_ip.pt')) module_params = module.named_parameters() for name, param in module_params: - torch.save(param, os.path.join(self.output_dir, 'nan_floss_{}_param.pt'.format(name))) - raise RuntimeError(" classname " + self.__class__.__name__ + "i " + str( - i) + f" module: {module} classname {self.__class__.__name__} Found NAN in output {i} at indices: ", - nan_mask.nonzero(), "where:", out[nan_mask.nonzero()[:, 0].unique(sorted=True)]) + torch.save(param, os.path.join(self.output_dir, f'nan_floss_{name}_param.pt')) + raise RuntimeError( + ( + f" classname {self.__class__.__name__}i {str(i)}" + + f" module: {module} classname {self.__class__.__name__} Found NAN in output {i} at indices: " + ), + nan_mask.nonzero(), + "where:", + out[nan_mask.nonzero()[:, 0].unique(sorted=True)], + ) class FocalTverskyLoss_detailed(nn.Module): @@ -100,7 +105,9 @@ def forward(self, logger, y_pred, y_true): true_pos = torch.sum(y_true_pos * y_pred_pos) false_neg = torch.sum(y_true_pos * (1 - y_pred_pos)) false_pos = torch.sum((1 - y_true_pos) * y_pred_pos) - logger.info("True Positive:" + str(true_pos) + " False_Negative:" + str(false_neg) + " False_Positive:" + str(false_pos)) + logger.info( + f"True Positive:{str(true_pos)} False_Negative:{str(false_neg)} False_Positive:{str(false_pos)}" + ) pt_1 = (true_pos + self.smooth) / ( true_pos + self.alpha * false_neg + (1 - self.alpha) * false_pos + self.smooth) return pow((1 - pt_1), self.gamma) @@ -159,6 +166,8 @@ def getLosses(logger, true_pos, false_neg, false_pos, intersection, union): pt_1 = (true_pos + smooth) / (true_pos + alpha * false_neg + (1 - alpha) * false_pos + smooth) floss = pow((1 - pt_1), gamma) - logger.info("True Positive:" + str(true_pos) + " False_Negative:" + str(false_neg) + " False_Positive:" + str(false_pos)) - logger.info("Floss:" + str(floss) + " diceloss:" + str(dice_loss) + " iou:" + str(iou)) + logger.info( + f"True Positive:{str(true_pos)} False_Negative:{str(false_neg)} False_Positive:{str(false_pos)}" + ) + logger.info(f"Floss:{str(floss)} diceloss:{str(dice_loss)} iou:{str(iou)}") return floss, dice_loss, iou diff --git a/Models/unet3d.py b/Models/unet3d.py index de551db..35b29bb 100644 --- a/Models/unet3d.py +++ b/Models/unet3d.py @@ -226,9 +226,15 @@ def nan_hook(self, module, inp, output): torch.save(inp, os.path.join(self.output_dir, 'nan_values_ip.pt')) module_params = module.named_parameters() for name, param in module_params: - torch.save(param, os.path.join(self.output_dir, 'nan_{}_param.pt'.format(name))) + torch.save(param, os.path.join(self.output_dir, f'nan_{name}_param.pt')) torch.save(self.input_to_net, os.path.join(self.output_dir, 'nan_ip_batch.pt')) - raise RuntimeError(" classname "+self.__class__.__name__+"i "+str(i)+f" module: {module} classname {self.__class__.__name__} Found NAN in output {i} at indices: ", nan_mask.nonzero(), "where:", out[nan_mask.nonzero()[:, 0].unique(sorted=True)]) + raise RuntimeError( + f" classname {self.__class__.__name__}i {str(i)}" + + f" module: {module} classname {self.__class__.__name__} Found NAN in output {i} at indices: ", + nan_mask.nonzero(), + "where:", + out[nan_mask.nonzero()[:, 0].unique(sorted=True)], + ) def forward(self, x): # print("unet") diff --git a/Utils/customutils.py b/Utils/customutils.py index ffb4817..908f696 100644 --- a/Utils/customutils.py +++ b/Utils/customutils.py @@ -79,8 +79,7 @@ def performUndersampling(fullImgVol, mask=None, maskmatpath=None, zeropad=True): # path will only be used in mask not supplied fullKSPVol = fft2c(fullImgVol) underKSPVol = performUndersamplingKSP(fullKSPVol, mask, maskmatpath, zeropad) - underImgVol = ifft2c(underKSPVol) - return underImgVol + return ifft2c(underKSPVol) def performUndersamplingKSP(fullKSPVol, mask=None, maskmatpath=None, zeropad=True): @@ -89,18 +88,16 @@ def performUndersamplingKSP(fullKSPVol, mask=None, maskmatpath=None, zeropad=Tru if mask is None: mask = sio.loadmat(maskmatpath)['mask'] if zeropad: - underKSPVol = np.multiply(fullKSPVol.transpose((2, 0, 1)), mask).transpose((1, 2, 0)) - else: - temp = [] - for i in range(mask.shape[0]): - maskline = mask[i, :] - if maskline.any(): - temp.append(fullKSPVol[i, ...]) - temp = np.array(temp) - underKSPVol = [] - for i in range(mask.shape[1]): - maskline = mask[:, i] - if maskline.any(): - underKSPVol.append(temp[:, i, ...]) - underKSPVol = np.array(underKSPVol).swapaxes(0, 1) - return underKSPVol + return np.multiply(fullKSPVol.transpose((2, 0, 1)), mask).transpose((1, 2, 0)) + temp = [] + for i in range(mask.shape[0]): + maskline = mask[i, :] + if maskline.any(): + temp.append(fullKSPVol[i, ...]) + temp = np.array(temp) + underKSPVol = [] + for i in range(mask.shape[1]): + maskline = mask[:, i] + if maskline.any(): + underKSPVol.append(temp[:, i, ...]) + return np.array(underKSPVol).swapaxes(0, 1) diff --git a/Utils/madam.py b/Utils/madam.py index f7cfa5a..c8b7452 100644 --- a/Utils/madam.py +++ b/Utils/madam.py @@ -17,10 +17,7 @@ def step(self, closure=None): closure (callable, optional): A closure that reevaluates the model and returns the loss. """ - loss = None - if closure is not None: - loss = closure() - + loss = closure() if closure is not None else None for group in self.param_groups: for p in group['params']: if p.grad is None: @@ -35,11 +32,11 @@ def step(self, closure=None): state['step'] += 1 bias_correction = 1 - 0.999 ** state['step'] state['exp_avg_sq'] = 0.999 * state['exp_avg_sq'] + 0.001 * p.grad.data**2 - + g_normed = p.grad.data / (state['exp_avg_sq']/bias_correction).sqrt() g_normed[torch.isnan(g_normed)] = 0 g_normed.clamp_(-self.g_bound, self.g_bound) - + p.data *= torch.exp( -group['lr']*g_normed*torch.sign(p.data) ) p.data.clamp_(-state['max'], state['max']) diff --git a/Utils/vessel_utils.py b/Utils/vessel_utils.py index 4b73c79..68048e5 100644 --- a/Utils/vessel_utils.py +++ b/Utils/vessel_utils.py @@ -118,13 +118,13 @@ def convert_and_save_tif(image3D, output_path, filename='output.tif', isColored= image = transforms.ToPILImage(mode='RGB')(tensor_image) image_list.append(image) - print('convert_and_save_tif:size of image:'+ str(len(image_list))) + print(f'convert_and_save_tif:size of image:{len(image_list)}') with TiffImagePlugin.AppendingTiffWriter(output_path + filename, True) as tifWriter: for im in image_list: # with open(DATASET_FOLDER+tiff_in) as tiff_in: im.save(tifWriter) tifWriter.newFrame() - print("Conversion to tiff completed, image saved as {}".format(filename)) + print(f"Conversion to tiff completed, image saved as {filename}") def convert_and_save_tif_greyscale(image3D, output_path, filename='output.tif'): """ @@ -137,13 +137,13 @@ def convert_and_save_tif_greyscale(image3D, output_path, filename='output.tif'): image = transforms.ToPILImage(mode='F')(tensor_image) image_list.append(image) - print('convert_and_save_tif:size of image:' + str(len(image_list))) + print(f'convert_and_save_tif:size of image:{len(image_list)}') with TiffImagePlugin.AppendingTiffWriter(output_path + filename, True) as tifWriter: for im in image_list: # with open(DATASET_FOLDER+tiff_in) as tiff_in: im.save(tifWriter) tifWriter.newFrame() - print("Conversion to tiff completed, image saved as {}".format(filename)) + print(f"Conversion to tiff completed, image saved as {filename}") def create_mask(predicted, logger): diff --git a/main_executor.py b/main_executor.py index b704feb..566bb3e 100644 --- a/main_executor.py +++ b/main_executor.py @@ -2,6 +2,7 @@ """ """ + import argparse import random import os @@ -181,15 +182,21 @@ OUTPUT_PATH = args.output_path LOAD_PATH = args.load_path - CHECKPOINT_PATH = OUTPUT_PATH + "/" + MODEL_NAME + '/checkpoint/' - TENSORBOARD_PATH_TRAINING = OUTPUT_PATH + "/" + MODEL_NAME + '/tensorboard/tensorboard_training/' - TENSORBOARD_PATH_VALIDATION = OUTPUT_PATH + "/" + MODEL_NAME + '/tensorboard/tensorboard_validation/' - TENSORBOARD_PATH_TESTING = OUTPUT_PATH + "/" + MODEL_NAME + '/tensorboard/tensorboard_testing/' + CHECKPOINT_PATH = f"{OUTPUT_PATH}/{MODEL_NAME}/checkpoint/" + TENSORBOARD_PATH_TRAINING = ( + f"{OUTPUT_PATH}/{MODEL_NAME}/tensorboard/tensorboard_training/" + ) + TENSORBOARD_PATH_VALIDATION = ( + f"{OUTPUT_PATH}/{MODEL_NAME}/tensorboard/tensorboard_validation/" + ) + TENSORBOARD_PATH_TESTING = ( + f"{OUTPUT_PATH}/{MODEL_NAME}/tensorboard/tensorboard_testing/" + ) - LOGGER_PATH = OUTPUT_PATH + "/" + MODEL_NAME + '.log' + LOGGER_PATH = f"{OUTPUT_PATH}/{MODEL_NAME}.log" logger = Logger(MODEL_NAME, LOGGER_PATH).get_logger() - test_logger = Logger(MODEL_NAME + '_test', LOGGER_PATH).get_logger() + test_logger = Logger(f'{MODEL_NAME}_test', LOGGER_PATH).get_logger() wandb = None if str(args.wandb).lower() == "true": import wandb @@ -207,7 +214,9 @@ # Model - model = torch.nn.DataParallel(getModel(args.model, OUTPUT_PATH + "/" + MODEL_NAME)) + model = torch.nn.DataParallel( + getModel(args.model, f"{OUTPUT_PATH}/{MODEL_NAME}") + ) model.cuda() writer_training = SummaryWriter(TENSORBOARD_PATH_TRAINING) diff --git a/pipeline.py b/pipeline.py index 40d9e05..4c18ff2 100644 --- a/pipeline.py +++ b/pipeline.py @@ -51,7 +51,7 @@ def __init__(self, cmd_args, model, logger, dir_path, checkpoint_path, writer_tr self.MODEL_NAME = cmd_args.model_name self.model_type = cmd_args.model self.lr_1 = cmd_args.learning_rate - self.logger.info("learning rate " + str(self.lr_1)) + self.logger.info(f"learning rate {str(self.lr_1)}") # self.optimizer = torch.optim.Adam(model.parameters(), lr=cmd_args.learning_rate) self.optimizer = Madam(model.parameters(), lr=cmd_args.learning_rate) self.num_epochs = cmd_args.num_epochs @@ -117,30 +117,25 @@ def create_TIOSubDS(self, vol_path, label_path, crossvalidation_set=None, is_tra get_subjects_only=False, transforms=None): if is_train: - trainDS = SRDataset(logger=self.logger, patch_size=self.patch_size, - dir_path=vol_path, - label_dir_path=label_path, - # TODO: implement non-iso patch-size, now only using the first element - stride_depth=self.stride_depth, stride_length=self.stride_length, - stride_width=self.stride_width, Size=None, fly_under_percent=None, - # TODO: implement fly_under_percent, if needed - patch_size_us=self.patch_size, pre_interpolate=None, norm_data=False, - pre_load=True, - return_coords=True, - files_us=crossvalidation_set) # TODO implement patch_size_us if required - patch_size//scaling_factor - if get_subjects_only: - return trainDS - # sampler = tio.data.UniformSampler(self.patch_size) - # patches_queue = tio.Queue( - # trainDS, - # max_length=(self.samples_per_epoch // len(trainDS.pre_loaded_data['pre_loaded_img'])) * 2, - # samples_per_volume=1, - # sampler=sampler, - # num_workers=0, - # start_background=True - # ) - # return patches_queue - return trainDS + return SRDataset( + logger=self.logger, + patch_size=self.patch_size, + dir_path=vol_path, + label_dir_path=label_path, + # TODO: implement non-iso patch-size, now only using the first element + stride_depth=self.stride_depth, + stride_length=self.stride_length, + stride_width=self.stride_width, + Size=None, + fly_under_percent=None, + # TODO: implement fly_under_percent, if needed + patch_size_us=self.patch_size, + pre_interpolate=None, + norm_data=False, + pre_load=True, + return_coords=True, + files_us=crossvalidation_set, + ) elif is_validate: validationDS = SRDataset(logger=self.logger, patch_size=self.patch_size, dir_path=vol_path, @@ -186,12 +181,8 @@ def create_TIOSubDS(self, vol_path, label_path, crossvalidation_set=None, is_tra overlap = np.subtract(self.patch_size, (self.stride_length, self.stride_width, self.stride_depth)) grid_samplers = [] - for i in range(len(subjects)): - grid_sampler = tio.inference.GridSampler( - subjects[i], - self.patch_size, - overlap, - ) + for subject_ in subjects: + grid_sampler = tio.inference.GridSampler(subject_, self.patch_size, overlap) grid_samplers.append(grid_sampler) return torch.utils.data.ConcatDataset(grid_samplers)