From c7b50ea0935af80b785ca700585ad3a43c678591 Mon Sep 17 00:00:00 2001 From: Ashesh Date: Mon, 25 Mar 2024 15:04:24 +0100 Subject: [PATCH] added code --- .../__pycache__/config_utils.cpython-39.pyc | Bin 0 -> 1626 bytes denoisplit/__pycache__/losses.cpython-39.pyc | Bin 0 -> 5700 bytes .../__pycache__/training.cpython-39.pyc | Bin 0 -> 10878 bytes .../__pycache__/training_utils.cpython-39.pyc | Bin 0 -> 1963 bytes denoisplit/__pycache__/utils.cpython-39.pyc | Bin 0 -> 15218 bytes .../pred_frame_creator.cpython-39.pyc | Bin 0 -> 2735 bytes denoisplit/analysis/checkpoint_utils.py | 9 + denoisplit/analysis/critic_notebook_utils.py | 110 + .../analysis/denoiser_splitter_utils.py | 35 + denoisplit/analysis/double_dip_utils.py | 69 + denoisplit/analysis/grad_viewer.py | 114 + denoisplit/analysis/lvae_utils.py | 29 + denoisplit/analysis/mmse_prediction.py | 231 ++ denoisplit/analysis/padding_utils.py | 24 + denoisplit/analysis/paper_plots.py | 289 ++ denoisplit/analysis/plot_error_utils.py | 82 + denoisplit/analysis/plot_utils.py | 364 +++ denoisplit/analysis/pred_frame_creator.py | 57 + .../analysis/quantifying_uncertainty.py | 213 ++ denoisplit/analysis/results_handler.py | 94 + denoisplit/analysis/stitch_prediction.py | 266 ++ denoisplit/config_utils.py | 50 + .../__pycache__/default_config.cpython-39.pyc | Bin 0 -> 1022 bytes .../__pycache__/pavia3_config.cpython-39.pyc | Bin 0 -> 3191 bytes denoisplit/configs/allencell_config.py | 99 + denoisplit/configs/biosr_config.py | 129 + denoisplit/configs/biosr_new_config.py | 128 + .../configs/biosr_reconstructive_config.py | 136 + .../biosr_sparsely_supervised_config.py | 160 ++ denoisplit/configs/biosr_supervised_config.py | 146 + denoisplit/configs/biosr_usplit_config.py | 127 + denoisplit/configs/bravenet_config.py | 62 + .../configs/customdata3curve_lvae_config.py | 105 + denoisplit/configs/customdata_lvae_config.py | 102 + denoisplit/configs/dao3ch_config.py | 128 + denoisplit/configs/deepencoder_lvae_config.py | 124 + denoisplit/configs/default_config.py | 38 + .../configs/denoiser_splitting_config.py | 146 + .../denoiser_usplit_separate_config.py | 134 + denoisplit/configs/exp_microscopyv2_config.py | 128 + denoisplit/configs/hagen_usplit_config.py | 125 + .../configs/hdn_biosr_denoiser_config.py | 125 + denoisplit/configs/hdn_denoiser_config.py | 122 + .../configs/hdn_hagen_restricted_config.py | 122 + .../configs/hdn_paviaatn_denoiser_config.py | 120 + denoisplit/configs/ht_iba1_ki64_config.py | 123 + .../configs/ht_iba1_ki64_multidata_config.py | 132 + denoisplit/configs/lvae_with_stitch_config.py | 107 + .../microscopy_mc_lvae_twindecoder_config.py | 71 + ...oscopy_multi_channel_lvae_critic_config.py | 75 + denoisplit/configs/multi_encoder_config.py | 84 + denoisplit/configs/notmnist_lvae_config.py | 55 + denoisplit/configs/pavia2Vanilla_config.py | 106 + denoisplit/configs/pavia2_config.py | 107 + denoisplit/configs/pavia3_config.py | 129 + denoisplit/configs/pavia_atn_config.py | 128 + denoisplit/configs/pavia_atn_usplit_config.py | 128 + .../pavia_deterministic_lvae_config.py | 96 + denoisplit/configs/pembl_config.py | 94 + denoisplit/configs/places_lvae_config.py | 53 + .../configs/places_lvae_twindecoder_config.py | 53 + denoisplit/configs/semi_supervised_config.py | 106 + denoisplit/configs/shroff_config.py | 100 + denoisplit/configs/sox2golgi_config.py | 127 + denoisplit/configs/sox2golgi_v2_config.py | 128 + .../configs/splitter_denoiser_config.py | 131 + denoisplit/configs/twodset_config.py | 141 + .../configs/twodset_finetuning_config.py | 154 ++ .../configs/twodset_sox2golgi_v2_config.py | 142 + denoisplit/configs/twotiff_bravenet_config.py | 65 + denoisplit/configs/twotiff_config.py | 125 + .../configs/twotiff_deterministic_config.py | 98 + denoisplit/configs/twotiff_unet_config.py | 61 + denoisplit/configs/unet_config.py | 59 + denoisplit/core/__init__.py | 0 .../core/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 154 bytes .../__pycache__/custom_enum.cpython-39.pyc | Bin 0 -> 909 bytes .../data_split_type.cpython-39.pyc | Bin 0 -> 2595 bytes .../core/__pycache__/data_type.cpython-39.pyc | Bin 0 -> 1053 bytes .../__pycache__/data_utils.cpython-39.pyc | Bin 0 -> 6468 bytes .../empty_patch_fetcher.cpython-39.pyc | Bin 0 -> 2023 bytes .../__pycache__/likelihoods.cpython-39.pyc | Bin 0 -> 7158 bytes .../core/__pycache__/loss_type.cpython-39.pyc | Bin 0 -> 598 bytes .../__pycache__/metric_monitor.cpython-39.pyc | Bin 0 -> 709 bytes .../mixed_input_type.cpython-39.pyc | Bin 0 -> 498 bytes .../__pycache__/model_type.cpython-39.pyc | Bin 0 -> 1231 bytes .../__pycache__/nn_submodules.cpython-39.pyc | Bin 0 -> 4310 bytes .../__pycache__/non_stochastic.cpython-39.pyc | Bin 0 -> 5199 bytes .../numpy_decorator.cpython-39.pyc | Bin 0 -> 771 bytes .../core/__pycache__/psnr.cpython-39.pyc | Bin 0 -> 2189 bytes .../__pycache__/sampler_type.cpython-39.pyc | Bin 0 -> 576 bytes .../stable_dist_params.cpython-39.pyc | Bin 0 -> 2181 bytes .../__pycache__/stable_exp.cpython-39.pyc | Bin 0 -> 2891 bytes .../__pycache__/stochastic.cpython-39.pyc | Bin 0 -> 7344 bytes .../__pycache__/tiff_reader.cpython-39.pyc | Bin 0 -> 886 bytes denoisplit/core/custom_enum.py | 20 + denoisplit/core/data_split_type.py | 101 + denoisplit/core/data_type.py | 31 + denoisplit/core/data_utils.py | 207 ++ denoisplit/core/dloader_type.py | 6 + denoisplit/core/empty_patch_fetcher.py | 54 + denoisplit/core/filename_utils.py | 22 + denoisplit/core/likelihoods.py | 241 ++ denoisplit/core/loss_type.py | 12 + denoisplit/core/metric_callback.py | 17 + denoisplit/core/metric_monitor.py | 12 + denoisplit/core/mixed_input_type.py | 10 + denoisplit/core/model_type.py | 33 + denoisplit/core/nn_submodules.py | 124 + denoisplit/core/non_stochastic.py | 158 ++ denoisplit/core/numpy_decorator.py | 22 + denoisplit/core/psnr.py | 63 + denoisplit/core/sampler_type.py | 11 + denoisplit/core/sampler_utils.py | 11 + denoisplit/core/seamless_stitch_base.py | 95 + denoisplit/core/stable_dist_params.py | 54 + denoisplit/core/stable_exp.py | 63 + denoisplit/core/stochastic.py | 285 ++ denoisplit/core/tiff_reader.py | 19 + .../allencell_rawdata_loader.cpython-39.pyc | Bin 0 -> 3684 bytes .../base_data_loader.cpython-39.pyc | Bin 0 -> 847 bytes .../dao_3ch_rawdata_loader.cpython-39.pyc | Bin 0 -> 1550 bytes ...embl_semisup_rawdata_loader.cpython-39.pyc | Bin 0 -> 1624 bytes ...microscopyv2_rawdata_loader.cpython-39.pyc | Bin 0 -> 1861 bytes .../ht_iba1_ki67_dloader.cpython-39.pyc | Bin 0 -> 1481 bytes ...ht_iba1_ki67_rawdata_loader.cpython-39.pyc | Bin 0 -> 2994 bytes ...intensity_augm_tiff_dloader.cpython-39.pyc | Bin 0 -> 7200 bytes .../lc_multich_dloader.cpython-39.pyc | Bin 0 -> 7661 bytes ...tich_explicit_input_dloader.cpython-39.pyc | Bin 0 -> 2373 bytes ...erm_tiff_dloader_randomized.cpython-39.pyc | Bin 0 -> 1170 bytes ...ulti_channel_train_val_data.cpython-39.pyc | Bin 0 -> 1522 bytes .../__pycache__/multifile_dset.cpython-39.pyc | Bin 0 -> 7392 bytes .../multifile_raw_dloader.cpython-39.pyc | Bin 0 -> 6769 bytes .../notmnist_dloader.cpython-39.pyc | Bin 0 -> 3600 bytes .../patch_index_manager.cpython-39.pyc | Bin 0 -> 6193 bytes .../pavia2_3ch_dloader.cpython-39.pyc | Bin 0 -> 2380 bytes .../__pycache__/pavia2_dloader.cpython-39.pyc | Bin 0 -> 7953 bytes .../__pycache__/pavia2_enums.cpython-39.pyc | Bin 0 -> 1089 bytes .../pavia2_rawdata_loader.cpython-39.pyc | Bin 0 -> 4308 bytes .../pavia3_rawdata_loader.cpython-39.pyc | Bin 0 -> 3211 bytes .../__pycache__/places_dloader.cpython-39.pyc | Bin 0 -> 3480 bytes .../raw_mrc_dloader.cpython-39.pyc | Bin 0 -> 2133 bytes .../__pycache__/read_mrc.cpython-39.pyc | Bin 0 -> 2204 bytes .../schroff_rawdata_loader.cpython-39.pyc | Bin 0 -> 3834 bytes .../semi_supervised_dloader.cpython-39.pyc | Bin 0 -> 2262 bytes .../sinosoid_dloader.cpython-39.pyc | Bin 0 -> 12952 bytes ...sinosoid_threecurve_dloader.cpython-39.pyc | Bin 0 -> 14126 bytes .../sox2golgi_rawdata_loader.cpython-39.pyc | Bin 0 -> 3000 bytes ...sox2golgi_v2_rawdata_loader.cpython-39.pyc | Bin 0 -> 3530 bytes .../target_index_switcher.cpython-39.pyc | Bin 0 -> 5662 bytes .../__pycache__/train_val_data.cpython-39.pyc | Bin 0 -> 4124 bytes .../two_dset_dloader.cpython-39.pyc | Bin 0 -> 5277 bytes .../two_tiff_rawdata_loader.cpython-39.pyc | Bin 0 -> 2163 bytes .../vanilla_dloader.cpython-39.pyc | Bin 0 -> 22810 bytes .../data_loader/allencell_rawdata_loader.py | 59 + denoisplit/data_loader/base_data_loader.py | 10 + .../data_loader/cngb_mito_actin_dloader.py | 34 + denoisplit/data_loader/crop_synchronizer.py | 68 + .../data_loader/dao_3ch_rawdata_loader.py | 39 + denoisplit/data_loader/doubledip_input.py | 17 + .../embl_semisup_rawdata_loader.py | 46 + .../exp_microscopyv2_rawdata_loader.py | 54 + .../data_loader/ht_iba1_ki67_dloader.py | 37 + .../ht_iba1_ki67_rawdata_loader.py | 76 + .../intensity_augm_tiff_dloader.py | 222 ++ denoisplit/data_loader/lc_multich_dloader.py | 225 ++ .../lc_multich_explicit_input_dloader.py | 47 + .../data_loader/mcdt_twinindex_dloader.py | 26 + ..._channel_determ_tiff_dloader_randomized.py | 28 + .../multi_channel_train_val_data.py | 44 + denoisplit/data_loader/multifile_dset.py | 265 ++ .../data_loader/multifile_raw_dloader.py | 189 ++ denoisplit/data_loader/notmnist_dloader.py | 87 + denoisplit/data_loader/patch_index_manager.py | 199 ++ denoisplit/data_loader/pavia2_3ch_dloader.py | 59 + denoisplit/data_loader/pavia2_dloader.py | 300 ++ denoisplit/data_loader/pavia2_enums.py | 23 + .../data_loader/pavia2_rawdata_loader.py | 121 + .../data_loader/pavia3_rawdata_loader.py | 92 + denoisplit/data_loader/places_dloader.py | 85 + denoisplit/data_loader/raw_mrc_dloader.py | 64 + denoisplit/data_loader/read_mrc.py | 154 ++ .../data_loader/schroff_rawdata_loader.py | 63 + .../data_loader/semi_supervised_dloader.py | 78 + .../data_loader/single_channel/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 176 bytes .../multi_dataset_dloader.cpython-39.pyc | Bin 0 -> 5979 bytes .../single_channel_dloader.cpython-39.pyc | Bin 0 -> 2516 bytes .../single_channel_mc_dloader.cpython-39.pyc | Bin 0 -> 4718 bytes .../single_channel/multi_dataset_dloader.py | 186 ++ .../single_channel/single_channel_dloader.py | 59 + .../single_channel_mc_dloader.py | 158 ++ denoisplit/data_loader/sinosoid_dloader.py | 440 +++ .../sinosoid_threecurve_dloader.py | 522 ++++ .../data_loader/sox2golgi_rawdata_loader.py | 66 + .../sox2golgi_v2_rawdata_loader.py | 124 + .../data_loader/target_index_switcher.py | 176 ++ denoisplit/data_loader/tiff_dloader.py | 137 + denoisplit/data_loader/train_val_data.py | 138 + denoisplit/data_loader/two_dset_dloader.py | 242 ++ .../data_loader/two_tiff_rawdata_loader.py | 69 + denoisplit/data_loader/vanilla_dloader.py | 688 +++++ .../__pycache__/exclusive_loss.cpython-39.pyc | Bin 0 -> 1666 bytes .../nbr_consistency_loss.cpython-39.pyc | Bin 0 -> 7666 bytes ...tricted_reconstruction_loss.cpython-39.pyc | Bin 0 -> 10237 bytes denoisplit/loss/exclusive_loss.py | 50 + denoisplit/loss/nbr_consistency_loss.py | 214 ++ .../loss/restricted_reconstruction_loss.py | 384 +++ denoisplit/losses.py | 163 ++ .../__pycache__/running_psnr.cpython-39.pyc | Bin 0 -> 1375 bytes denoisplit/metrics/calibration.py | 114 + denoisplit/metrics/running_psnr.py | 35 + .../nets/__pycache__/brave_net.cpython-39.pyc | Bin 0 -> 4907 bytes .../__pycache__/brave_net_raw.cpython-39.pyc | Bin 0 -> 5258 bytes .../context_transfer_module.cpython-39.pyc | Bin 0 -> 4511 bytes .../denoiser_splitter.cpython-39.pyc | Bin 0 -> 9247 bytes .../__pycache__/discriminator.cpython-39.pyc | Bin 0 -> 7526 bytes .../gmm_nnbased_noise_model.cpython-39.pyc | Bin 0 -> 4343 bytes .../gmm_noise_model.cpython-39.pyc | Bin 0 -> 9892 bytes .../hist_gmm_noise_model.cpython-39.pyc | Bin 0 -> 3343 bytes .../hist_noise_model.cpython-39.pyc | Bin 0 -> 4723 bytes .../nets/__pycache__/lvae.cpython-39.pyc | Bin 0 -> 30769 bytes .../lvae_bleedthrough.cpython-39.pyc | Bin 0 -> 8061 bytes .../lvae_deepencoder.cpython-39.pyc | Bin 0 -> 4088 bytes .../__pycache__/lvae_denoiser.cpython-39.pyc | Bin 0 -> 3621 bytes .../__pycache__/lvae_layers.cpython-39.pyc | Bin 0 -> 20328 bytes ...tidset_multi_input_branches.cpython-39.pyc | Bin 0 -> 7176 bytes .../lvae_multidset_multi_optim.cpython-39.pyc | Bin 0 -> 5511 bytes ...multiple_encoder_single_opt.cpython-39.pyc | Bin 0 -> 2892 bytes .../lvae_multiple_encoders.cpython-39.pyc | Bin 0 -> 7686 bytes .../lvae_multires_target.cpython-39.pyc | Bin 0 -> 4061 bytes ...e_restricted_reconstruction.cpython-39.pyc | Bin 0 -> 4123 bytes .../lvae_semi_supervised.cpython-39.pyc | Bin 0 -> 7476 bytes .../lvae_twindecoder.cpython-39.pyc | Bin 0 -> 8249 bytes .../__pycache__/lvae_twodset.cpython-39.pyc | Bin 0 -> 9029 bytes .../lvae_twodset_finetuning.cpython-39.pyc | Bin 0 -> 9954 bytes ...ae_twodset_restrictedrecons.cpython-39.pyc | Bin 0 -> 10195 bytes .../lvae_with_critic.cpython-39.pyc | Bin 0 -> 5106 bytes .../lvae_with_stitch.cpython-39.pyc | Bin 0 -> 8110 bytes .../lvae_with_stitch_2stage.cpython-39.pyc | Bin 0 -> 2620 bytes .../__pycache__/model_utils.cpython-39.pyc | Bin 0 -> 5191 bytes .../__pycache__/noise_model.cpython-39.pyc | Bin 0 -> 4326 bytes .../splitter_denoiser.cpython-39.pyc | Bin 0 -> 3268 bytes .../nets/__pycache__/unet.cpython-39.pyc | Bin 0 -> 8698 bytes .../__pycache__/unet_parts.cpython-39.pyc | Bin 0 -> 2927 bytes denoisplit/nets/brave_net.py | 114 + denoisplit/nets/brave_net_raw.py | 226 ++ denoisplit/nets/cellpose_segmentation.py | 51 + denoisplit/nets/context_transfer_module.py | 122 + denoisplit/nets/denoiser_splitter.py | 313 +++ denoisplit/nets/discriminator.py | 214 ++ denoisplit/nets/gmm_nnbased_noise_model.py | 129 + denoisplit/nets/gmm_noise_model.py | 345 +++ denoisplit/nets/hist_gmm_noise_model.py | 112 + denoisplit/nets/hist_gmm_noise_model2.py | 112 + denoisplit/nets/hist_noise_model.py | 289 ++ denoisplit/nets/lvae.py | 1209 ++++++++ denoisplit/nets/lvae_bleedthrough.py | 253 ++ denoisplit/nets/lvae_deepencoder.py | 126 + denoisplit/nets/lvae_denoiser.py | 104 + denoisplit/nets/lvae_layers.py | 722 +++++ .../lvae_multidset_multi_input_branches.py | 259 ++ denoisplit/nets/lvae_multidset_multi_optim.py | 166 ++ .../nets/lvae_multiple_encoder_single_opt.py | 87 + denoisplit/nets/lvae_multiple_encoders.py | 286 ++ denoisplit/nets/lvae_multires_target.py | 117 + .../nets/lvae_restricted_reconstruction.py | 114 + denoisplit/nets/lvae_semi_supervised.py | 230 ++ denoisplit/nets/lvae_twindecoder.py | 287 ++ denoisplit/nets/lvae_twodset.py | 371 +++ denoisplit/nets/lvae_twodset_finetuning.py | 388 +++ .../nets/lvae_twodset_restrictedrecons.py | 400 +++ denoisplit/nets/lvae_with_critic.py | 146 + denoisplit/nets/lvae_with_stitch.py | 255 ++ denoisplit/nets/lvae_with_stitch_2stage.py | 66 + denoisplit/nets/model_utils.py | 133 + denoisplit/nets/noise_model.py | 156 ++ denoisplit/nets/seamless_stich.py | 174 ++ denoisplit/nets/seamless_stich_grad1.py | 148 + denoisplit/nets/splitter_denoiser.py | 81 + denoisplit/nets/unet.py | 295 ++ denoisplit/nets/unet_parts.py | 73 + denoisplit/notebooks/Denoiser.ipynb | 992 +++++++ denoisplit/notebooks/Denoiser_Splitter.ipynb | 2175 +++++++++++++++ .../ECCV24/denoiser_performance.ipynb | 159 ++ denoisplit/notebooks/EvalFineTuning.ipynb | 2380 ++++++++++++++++ denoisplit/notebooks/EvalNoiseModel.ipynb | 332 +++ .../notebooks/EvalOnMultiFileDataset.ipynb | 2144 +++++++++++++++ denoisplit/notebooks/EvalOnWholeFrames.ipynb | 2431 +++++++++++++++++ .../notebooks/ExpansionMicroscopyV2.ipynb | 104 + .../InspectingBackgroundSource.ipynb | 2161 +++++++++++++++ denoisplit/notebooks/WeightEvolution.ipynb | 1782 ++++++++++++ denoisplit/notebooks/biosr_data.ipynb | 224 ++ .../datasets/dao_3channel_filteringdata.ipynb | 156 ++ .../notebooks/datasets/nicola_dataset.ipynb | 145 + .../notebooks/denoiser_psnr_comparison.ipynb | 434 +++ denoisplit/notebooks/full_image_plots.ipynb | 831 ++++++ denoisplit/notebooks/intro_figure.ipynb | 149 + .../config_loader-checkpoint.ipynb | 134 + .../disentangle_imports-checkpoint.ipynb | 79 + .../disentangle_setup-checkpoint.ipynb | 213 ++ .../root_dirs-checkpoint.ipynb | 106 + denoisplit/notebooks/nb_core/__init__.py | 0 .../notebooks/nb_core/config_loader.ipynb | 138 + .../nb_core/disentangle_imports.ipynb | 90 + .../notebooks/nb_core/disentangle_setup.ipynb | 299 ++ denoisplit/notebooks/nb_core/root_dirs.ipynb | 109 + ...erf_comparison_diff_noise_model_ways.ipynb | 232 ++ denoisplit/notebooks/sampling_video.avi | Bin 0 -> 5686 bytes denoisplit/notebooks/sox2golgi_dloader.ipynb | 194 ++ denoisplit/notebooks/taverna_sox2_golgi.ipynb | 538 ++++ denoisplit/notebooks/tiff_viewer.ipynb | 297 ++ denoisplit/notebooks/training_data_size.ipynb | 238 ++ .../__pycache__/base_sampler.cpython-39.pyc | Bin 0 -> 1390 bytes .../default_grid_sampler.cpython-39.pyc | Bin 0 -> 901 bytes .../intensity_aug_sampler.cpython-39.pyc | Bin 0 -> 4776 bytes .../__pycache__/nbr_sampler.cpython-39.pyc | Bin 0 -> 3726 bytes .../__pycache__/random_sampler.cpython-39.pyc | Bin 0 -> 828 bytes .../singleimg_sampler.cpython-39.pyc | Bin 0 -> 1361 bytes denoisplit/sampler/base_sampler.py | 31 + denoisplit/sampler/default_grid_sampler.py | 18 + denoisplit/sampler/intensity_aug_sampler.py | 140 + denoisplit/sampler/nbr_sampler.py | 87 + denoisplit/sampler/random_sampler.py | 16 + denoisplit/sampler/singleimg_sampler.py | 33 + denoisplit/sampler/twin_index_sampler.py | 65 + .../scripts/combine_sequential_results.py | 44 + denoisplit/scripts/compare_configs.py | 153 ++ .../scripts/compare_pyconfig_pklconfig.py | 49 + denoisplit/scripts/evaluate.py | 845 ++++++ denoisplit/scripts/evaluate_sequentially.py | 25 + denoisplit/scripts/print_configs.py | 21 + denoisplit/scripts/print_paperstats.py | 101 + denoisplit/scripts/run.py | 303 ++ denoisplit/scripts/some_runs.sh | 7 + .../analysis/test_quantifying_uncertainty.py | 61 + .../tests/analysis/test_stitch_prediction.py | 116 + denoisplit/tests/core/test_psnr.py | 84 + denoisplit/tests/core/test_stable_exp.py | 27 + .../test_multi_channel_tiff_dloader.py | 24 + .../data_loader/test_multifile_raw_dloader.py | 154 ++ .../data_loader/test_patch_index_manager.py | 20 + denoisplit/tests/nets/test_lvae_layers.py | 102 + .../sampler/test_default_grid_sampler.py | 57 + .../tests/sampler/test_random_sampler.py | 63 + .../tests/sampler/test_twin_index_sampler.py | 30 + denoisplit/training.py | 575 ++++ denoisplit/training_utils.py | 55 + denoisplit/utils.py | 545 ++++ installation.sh | 21 + 350 files changed, 47778 insertions(+) create mode 100644 denoisplit/__pycache__/config_utils.cpython-39.pyc create mode 100644 denoisplit/__pycache__/losses.cpython-39.pyc create mode 100644 denoisplit/__pycache__/training.cpython-39.pyc create mode 100644 denoisplit/__pycache__/training_utils.cpython-39.pyc create mode 100644 denoisplit/__pycache__/utils.cpython-39.pyc create mode 100644 denoisplit/analysis/__pycache__/pred_frame_creator.cpython-39.pyc create mode 100644 denoisplit/analysis/checkpoint_utils.py create mode 100644 denoisplit/analysis/critic_notebook_utils.py create mode 100644 denoisplit/analysis/denoiser_splitter_utils.py create mode 100644 denoisplit/analysis/double_dip_utils.py create mode 100644 denoisplit/analysis/grad_viewer.py create mode 100644 denoisplit/analysis/lvae_utils.py create mode 100644 denoisplit/analysis/mmse_prediction.py create mode 100644 denoisplit/analysis/padding_utils.py create mode 100644 denoisplit/analysis/paper_plots.py create mode 100644 denoisplit/analysis/plot_error_utils.py create mode 100644 denoisplit/analysis/plot_utils.py create mode 100644 denoisplit/analysis/pred_frame_creator.py create mode 100644 denoisplit/analysis/quantifying_uncertainty.py create mode 100644 denoisplit/analysis/results_handler.py create mode 100644 denoisplit/analysis/stitch_prediction.py create mode 100644 denoisplit/config_utils.py create mode 100644 denoisplit/configs/__pycache__/default_config.cpython-39.pyc create mode 100644 denoisplit/configs/__pycache__/pavia3_config.cpython-39.pyc create mode 100644 denoisplit/configs/allencell_config.py create mode 100644 denoisplit/configs/biosr_config.py create mode 100644 denoisplit/configs/biosr_new_config.py create mode 100644 denoisplit/configs/biosr_reconstructive_config.py create mode 100644 denoisplit/configs/biosr_sparsely_supervised_config.py create mode 100644 denoisplit/configs/biosr_supervised_config.py create mode 100644 denoisplit/configs/biosr_usplit_config.py create mode 100644 denoisplit/configs/bravenet_config.py create mode 100644 denoisplit/configs/customdata3curve_lvae_config.py create mode 100644 denoisplit/configs/customdata_lvae_config.py create mode 100644 denoisplit/configs/dao3ch_config.py create mode 100644 denoisplit/configs/deepencoder_lvae_config.py create mode 100644 denoisplit/configs/default_config.py create mode 100644 denoisplit/configs/denoiser_splitting_config.py create mode 100644 denoisplit/configs/denoiser_usplit_separate_config.py create mode 100644 denoisplit/configs/exp_microscopyv2_config.py create mode 100644 denoisplit/configs/hagen_usplit_config.py create mode 100644 denoisplit/configs/hdn_biosr_denoiser_config.py create mode 100644 denoisplit/configs/hdn_denoiser_config.py create mode 100644 denoisplit/configs/hdn_hagen_restricted_config.py create mode 100644 denoisplit/configs/hdn_paviaatn_denoiser_config.py create mode 100644 denoisplit/configs/ht_iba1_ki64_config.py create mode 100644 denoisplit/configs/ht_iba1_ki64_multidata_config.py create mode 100644 denoisplit/configs/lvae_with_stitch_config.py create mode 100644 denoisplit/configs/microscopy_mc_lvae_twindecoder_config.py create mode 100644 denoisplit/configs/microscopy_multi_channel_lvae_critic_config.py create mode 100644 denoisplit/configs/multi_encoder_config.py create mode 100644 denoisplit/configs/notmnist_lvae_config.py create mode 100644 denoisplit/configs/pavia2Vanilla_config.py create mode 100644 denoisplit/configs/pavia2_config.py create mode 100644 denoisplit/configs/pavia3_config.py create mode 100644 denoisplit/configs/pavia_atn_config.py create mode 100644 denoisplit/configs/pavia_atn_usplit_config.py create mode 100644 denoisplit/configs/pavia_deterministic_lvae_config.py create mode 100644 denoisplit/configs/pembl_config.py create mode 100644 denoisplit/configs/places_lvae_config.py create mode 100644 denoisplit/configs/places_lvae_twindecoder_config.py create mode 100644 denoisplit/configs/semi_supervised_config.py create mode 100644 denoisplit/configs/shroff_config.py create mode 100644 denoisplit/configs/sox2golgi_config.py create mode 100644 denoisplit/configs/sox2golgi_v2_config.py create mode 100644 denoisplit/configs/splitter_denoiser_config.py create mode 100644 denoisplit/configs/twodset_config.py create mode 100644 denoisplit/configs/twodset_finetuning_config.py create mode 100644 denoisplit/configs/twodset_sox2golgi_v2_config.py create mode 100644 denoisplit/configs/twotiff_bravenet_config.py create mode 100644 denoisplit/configs/twotiff_config.py create mode 100644 denoisplit/configs/twotiff_deterministic_config.py create mode 100644 denoisplit/configs/twotiff_unet_config.py create mode 100644 denoisplit/configs/unet_config.py create mode 100644 denoisplit/core/__init__.py create mode 100644 denoisplit/core/__pycache__/__init__.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/custom_enum.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/data_split_type.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/data_type.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/data_utils.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/empty_patch_fetcher.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/likelihoods.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/loss_type.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/metric_monitor.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/mixed_input_type.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/model_type.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/nn_submodules.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/non_stochastic.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/numpy_decorator.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/psnr.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/sampler_type.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/stable_dist_params.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/stable_exp.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/stochastic.cpython-39.pyc create mode 100644 denoisplit/core/__pycache__/tiff_reader.cpython-39.pyc create mode 100644 denoisplit/core/custom_enum.py create mode 100644 denoisplit/core/data_split_type.py create mode 100644 denoisplit/core/data_type.py create mode 100644 denoisplit/core/data_utils.py create mode 100644 denoisplit/core/dloader_type.py create mode 100644 denoisplit/core/empty_patch_fetcher.py create mode 100644 denoisplit/core/filename_utils.py create mode 100644 denoisplit/core/likelihoods.py create mode 100644 denoisplit/core/loss_type.py create mode 100644 denoisplit/core/metric_callback.py create mode 100644 denoisplit/core/metric_monitor.py create mode 100644 denoisplit/core/mixed_input_type.py create mode 100644 denoisplit/core/model_type.py create mode 100644 denoisplit/core/nn_submodules.py create mode 100644 denoisplit/core/non_stochastic.py create mode 100644 denoisplit/core/numpy_decorator.py create mode 100644 denoisplit/core/psnr.py create mode 100644 denoisplit/core/sampler_type.py create mode 100644 denoisplit/core/sampler_utils.py create mode 100644 denoisplit/core/seamless_stitch_base.py create mode 100644 denoisplit/core/stable_dist_params.py create mode 100644 denoisplit/core/stable_exp.py create mode 100644 denoisplit/core/stochastic.py create mode 100644 denoisplit/core/tiff_reader.py create mode 100644 denoisplit/data_loader/__pycache__/allencell_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/base_data_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/dao_3ch_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/embl_semisup_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/exp_microscopyv2_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/ht_iba1_ki67_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/ht_iba1_ki67_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/intensity_augm_tiff_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/lc_multich_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/lc_multich_explicit_input_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/multi_channel_determ_tiff_dloader_randomized.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/multi_channel_train_val_data.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/multifile_dset.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/multifile_raw_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/notmnist_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/patch_index_manager.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/pavia2_3ch_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/pavia2_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/pavia2_enums.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/pavia2_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/pavia3_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/places_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/raw_mrc_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/read_mrc.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/schroff_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/semi_supervised_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/sinosoid_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/sinosoid_threecurve_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/sox2golgi_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/sox2golgi_v2_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/target_index_switcher.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/train_val_data.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/two_dset_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/two_tiff_rawdata_loader.cpython-39.pyc create mode 100644 denoisplit/data_loader/__pycache__/vanilla_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/allencell_rawdata_loader.py create mode 100644 denoisplit/data_loader/base_data_loader.py create mode 100644 denoisplit/data_loader/cngb_mito_actin_dloader.py create mode 100644 denoisplit/data_loader/crop_synchronizer.py create mode 100644 denoisplit/data_loader/dao_3ch_rawdata_loader.py create mode 100644 denoisplit/data_loader/doubledip_input.py create mode 100644 denoisplit/data_loader/embl_semisup_rawdata_loader.py create mode 100644 denoisplit/data_loader/exp_microscopyv2_rawdata_loader.py create mode 100644 denoisplit/data_loader/ht_iba1_ki67_dloader.py create mode 100644 denoisplit/data_loader/ht_iba1_ki67_rawdata_loader.py create mode 100644 denoisplit/data_loader/intensity_augm_tiff_dloader.py create mode 100644 denoisplit/data_loader/lc_multich_dloader.py create mode 100644 denoisplit/data_loader/lc_multich_explicit_input_dloader.py create mode 100644 denoisplit/data_loader/mcdt_twinindex_dloader.py create mode 100644 denoisplit/data_loader/multi_channel_determ_tiff_dloader_randomized.py create mode 100644 denoisplit/data_loader/multi_channel_train_val_data.py create mode 100644 denoisplit/data_loader/multifile_dset.py create mode 100644 denoisplit/data_loader/multifile_raw_dloader.py create mode 100644 denoisplit/data_loader/notmnist_dloader.py create mode 100644 denoisplit/data_loader/patch_index_manager.py create mode 100644 denoisplit/data_loader/pavia2_3ch_dloader.py create mode 100644 denoisplit/data_loader/pavia2_dloader.py create mode 100644 denoisplit/data_loader/pavia2_enums.py create mode 100644 denoisplit/data_loader/pavia2_rawdata_loader.py create mode 100644 denoisplit/data_loader/pavia3_rawdata_loader.py create mode 100644 denoisplit/data_loader/places_dloader.py create mode 100644 denoisplit/data_loader/raw_mrc_dloader.py create mode 100644 denoisplit/data_loader/read_mrc.py create mode 100644 denoisplit/data_loader/schroff_rawdata_loader.py create mode 100644 denoisplit/data_loader/semi_supervised_dloader.py create mode 100644 denoisplit/data_loader/single_channel/__init__.py create mode 100644 denoisplit/data_loader/single_channel/__pycache__/__init__.cpython-39.pyc create mode 100644 denoisplit/data_loader/single_channel/__pycache__/multi_dataset_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/single_channel/__pycache__/single_channel_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/single_channel/__pycache__/single_channel_mc_dloader.cpython-39.pyc create mode 100644 denoisplit/data_loader/single_channel/multi_dataset_dloader.py create mode 100644 denoisplit/data_loader/single_channel/single_channel_dloader.py create mode 100644 denoisplit/data_loader/single_channel/single_channel_mc_dloader.py create mode 100644 denoisplit/data_loader/sinosoid_dloader.py create mode 100644 denoisplit/data_loader/sinosoid_threecurve_dloader.py create mode 100644 denoisplit/data_loader/sox2golgi_rawdata_loader.py create mode 100644 denoisplit/data_loader/sox2golgi_v2_rawdata_loader.py create mode 100644 denoisplit/data_loader/target_index_switcher.py create mode 100644 denoisplit/data_loader/tiff_dloader.py create mode 100644 denoisplit/data_loader/train_val_data.py create mode 100644 denoisplit/data_loader/two_dset_dloader.py create mode 100644 denoisplit/data_loader/two_tiff_rawdata_loader.py create mode 100644 denoisplit/data_loader/vanilla_dloader.py create mode 100644 denoisplit/loss/__pycache__/exclusive_loss.cpython-39.pyc create mode 100644 denoisplit/loss/__pycache__/nbr_consistency_loss.cpython-39.pyc create mode 100644 denoisplit/loss/__pycache__/restricted_reconstruction_loss.cpython-39.pyc create mode 100644 denoisplit/loss/exclusive_loss.py create mode 100644 denoisplit/loss/nbr_consistency_loss.py create mode 100644 denoisplit/loss/restricted_reconstruction_loss.py create mode 100644 denoisplit/losses.py create mode 100644 denoisplit/metrics/__pycache__/running_psnr.cpython-39.pyc create mode 100644 denoisplit/metrics/calibration.py create mode 100644 denoisplit/metrics/running_psnr.py create mode 100644 denoisplit/nets/__pycache__/brave_net.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/brave_net_raw.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/context_transfer_module.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/denoiser_splitter.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/discriminator.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/gmm_nnbased_noise_model.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/gmm_noise_model.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/hist_gmm_noise_model.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/hist_noise_model.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_bleedthrough.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_deepencoder.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_denoiser.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_layers.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_multidset_multi_input_branches.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_multidset_multi_optim.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_multiple_encoder_single_opt.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_multiple_encoders.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_multires_target.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_restricted_reconstruction.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_semi_supervised.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_twindecoder.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_twodset.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_twodset_finetuning.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_twodset_restrictedrecons.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_with_critic.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_with_stitch.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/lvae_with_stitch_2stage.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/model_utils.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/noise_model.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/splitter_denoiser.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/unet.cpython-39.pyc create mode 100644 denoisplit/nets/__pycache__/unet_parts.cpython-39.pyc create mode 100644 denoisplit/nets/brave_net.py create mode 100644 denoisplit/nets/brave_net_raw.py create mode 100644 denoisplit/nets/cellpose_segmentation.py create mode 100644 denoisplit/nets/context_transfer_module.py create mode 100644 denoisplit/nets/denoiser_splitter.py create mode 100644 denoisplit/nets/discriminator.py create mode 100644 denoisplit/nets/gmm_nnbased_noise_model.py create mode 100644 denoisplit/nets/gmm_noise_model.py create mode 100644 denoisplit/nets/hist_gmm_noise_model.py create mode 100644 denoisplit/nets/hist_gmm_noise_model2.py create mode 100644 denoisplit/nets/hist_noise_model.py create mode 100644 denoisplit/nets/lvae.py create mode 100644 denoisplit/nets/lvae_bleedthrough.py create mode 100644 denoisplit/nets/lvae_deepencoder.py create mode 100644 denoisplit/nets/lvae_denoiser.py create mode 100644 denoisplit/nets/lvae_layers.py create mode 100644 denoisplit/nets/lvae_multidset_multi_input_branches.py create mode 100644 denoisplit/nets/lvae_multidset_multi_optim.py create mode 100644 denoisplit/nets/lvae_multiple_encoder_single_opt.py create mode 100644 denoisplit/nets/lvae_multiple_encoders.py create mode 100644 denoisplit/nets/lvae_multires_target.py create mode 100644 denoisplit/nets/lvae_restricted_reconstruction.py create mode 100644 denoisplit/nets/lvae_semi_supervised.py create mode 100644 denoisplit/nets/lvae_twindecoder.py create mode 100644 denoisplit/nets/lvae_twodset.py create mode 100644 denoisplit/nets/lvae_twodset_finetuning.py create mode 100644 denoisplit/nets/lvae_twodset_restrictedrecons.py create mode 100644 denoisplit/nets/lvae_with_critic.py create mode 100644 denoisplit/nets/lvae_with_stitch.py create mode 100644 denoisplit/nets/lvae_with_stitch_2stage.py create mode 100644 denoisplit/nets/model_utils.py create mode 100644 denoisplit/nets/noise_model.py create mode 100644 denoisplit/nets/seamless_stich.py create mode 100644 denoisplit/nets/seamless_stich_grad1.py create mode 100644 denoisplit/nets/splitter_denoiser.py create mode 100644 denoisplit/nets/unet.py create mode 100644 denoisplit/nets/unet_parts.py create mode 100644 denoisplit/notebooks/Denoiser.ipynb create mode 100644 denoisplit/notebooks/Denoiser_Splitter.ipynb create mode 100644 denoisplit/notebooks/ECCV24/denoiser_performance.ipynb create mode 100644 denoisplit/notebooks/EvalFineTuning.ipynb create mode 100644 denoisplit/notebooks/EvalNoiseModel.ipynb create mode 100644 denoisplit/notebooks/EvalOnMultiFileDataset.ipynb create mode 100644 denoisplit/notebooks/EvalOnWholeFrames.ipynb create mode 100644 denoisplit/notebooks/ExpansionMicroscopyV2.ipynb create mode 100644 denoisplit/notebooks/InspectingBackgroundSource.ipynb create mode 100644 denoisplit/notebooks/WeightEvolution.ipynb create mode 100644 denoisplit/notebooks/biosr_data.ipynb create mode 100644 denoisplit/notebooks/datasets/dao_3channel_filteringdata.ipynb create mode 100644 denoisplit/notebooks/datasets/nicola_dataset.ipynb create mode 100644 denoisplit/notebooks/denoiser_psnr_comparison.ipynb create mode 100644 denoisplit/notebooks/full_image_plots.ipynb create mode 100644 denoisplit/notebooks/intro_figure.ipynb create mode 100644 denoisplit/notebooks/nb_core/.ipynb_checkpoints/config_loader-checkpoint.ipynb create mode 100644 denoisplit/notebooks/nb_core/.ipynb_checkpoints/disentangle_imports-checkpoint.ipynb create mode 100644 denoisplit/notebooks/nb_core/.ipynb_checkpoints/disentangle_setup-checkpoint.ipynb create mode 100644 denoisplit/notebooks/nb_core/.ipynb_checkpoints/root_dirs-checkpoint.ipynb create mode 100644 denoisplit/notebooks/nb_core/__init__.py create mode 100644 denoisplit/notebooks/nb_core/config_loader.ipynb create mode 100644 denoisplit/notebooks/nb_core/disentangle_imports.ipynb create mode 100644 denoisplit/notebooks/nb_core/disentangle_setup.ipynb create mode 100644 denoisplit/notebooks/nb_core/root_dirs.ipynb create mode 100644 denoisplit/notebooks/perf_comparison_diff_noise_model_ways.ipynb create mode 100644 denoisplit/notebooks/sampling_video.avi create mode 100644 denoisplit/notebooks/sox2golgi_dloader.ipynb create mode 100644 denoisplit/notebooks/taverna_sox2_golgi.ipynb create mode 100644 denoisplit/notebooks/tiff_viewer.ipynb create mode 100644 denoisplit/notebooks/training_data_size.ipynb create mode 100644 denoisplit/sampler/__pycache__/base_sampler.cpython-39.pyc create mode 100644 denoisplit/sampler/__pycache__/default_grid_sampler.cpython-39.pyc create mode 100644 denoisplit/sampler/__pycache__/intensity_aug_sampler.cpython-39.pyc create mode 100644 denoisplit/sampler/__pycache__/nbr_sampler.cpython-39.pyc create mode 100644 denoisplit/sampler/__pycache__/random_sampler.cpython-39.pyc create mode 100644 denoisplit/sampler/__pycache__/singleimg_sampler.cpython-39.pyc create mode 100644 denoisplit/sampler/base_sampler.py create mode 100644 denoisplit/sampler/default_grid_sampler.py create mode 100644 denoisplit/sampler/intensity_aug_sampler.py create mode 100644 denoisplit/sampler/nbr_sampler.py create mode 100644 denoisplit/sampler/random_sampler.py create mode 100644 denoisplit/sampler/singleimg_sampler.py create mode 100644 denoisplit/sampler/twin_index_sampler.py create mode 100644 denoisplit/scripts/combine_sequential_results.py create mode 100644 denoisplit/scripts/compare_configs.py create mode 100644 denoisplit/scripts/compare_pyconfig_pklconfig.py create mode 100644 denoisplit/scripts/evaluate.py create mode 100644 denoisplit/scripts/evaluate_sequentially.py create mode 100644 denoisplit/scripts/print_configs.py create mode 100644 denoisplit/scripts/print_paperstats.py create mode 100644 denoisplit/scripts/run.py create mode 100755 denoisplit/scripts/some_runs.sh create mode 100644 denoisplit/tests/analysis/test_quantifying_uncertainty.py create mode 100644 denoisplit/tests/analysis/test_stitch_prediction.py create mode 100644 denoisplit/tests/core/test_psnr.py create mode 100644 denoisplit/tests/core/test_stable_exp.py create mode 100644 denoisplit/tests/data_loader/test_multi_channel_tiff_dloader.py create mode 100644 denoisplit/tests/data_loader/test_multifile_raw_dloader.py create mode 100644 denoisplit/tests/data_loader/test_patch_index_manager.py create mode 100644 denoisplit/tests/nets/test_lvae_layers.py create mode 100644 denoisplit/tests/sampler/test_default_grid_sampler.py create mode 100644 denoisplit/tests/sampler/test_random_sampler.py create mode 100644 denoisplit/tests/sampler/test_twin_index_sampler.py create mode 100644 denoisplit/training.py create mode 100644 denoisplit/training_utils.py create mode 100644 denoisplit/utils.py create mode 100644 installation.sh diff --git a/denoisplit/__pycache__/config_utils.cpython-39.pyc b/denoisplit/__pycache__/config_utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24b20885af1a095a78234aa84d02769445fb7427 GIT binary patch literal 1626 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 O;?MdmKkyg)cmE5zkVCBi literal 0 HcmV?d00001 diff --git a/denoisplit/__pycache__/training.cpython-39.pyc b/denoisplit/__pycache__/training.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee7320aa09b6e2ed6311467aba7f6ad8b9106823 GIT binary patch literal 10878 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 literal 0 HcmV?d00001 diff --git a/denoisplit/analysis/__pycache__/pred_frame_creator.cpython-39.pyc b/denoisplit/analysis/__pycache__/pred_frame_creator.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eda6a1149cfc6f8fbd3cc8dea676ec3249894da9 GIT binary patch literal 2735 zcmbVOTW=dh6rP#Ac8rK!B>MQW3NWqDrkmvVuli&p2Mkx6H0- zW373h<*~n@RI=abUz#_>Q~yF=;5)N%noIk_toF=({muElbH?%FVuhjn{Tpv>MU4GJ zoukD==LX*N3XEb6rnnMa-r%kl4G*=~^?N}h;Osl5d=)%qDtIIsp%QmlJskg3xuuQ1 zTzjBvt)!c2Q;Ykm*6fb%*RsKm&e|A(sSS-*Ni)-`HjJ}oTc?<=wFahlVzy=Cp5Cau z03Nng=QgWbnx+Nxc?1I*tNo|{I;*}xE<(CBPr`b`2bFYqj* z{!P5;Uobh(nPfTZuqmIhZGYlVf=M_jWuoKdr98;PmWQ^l_!EJZ!5hZIoMub82ODMO zP6c0#lu+Ii!CBFtE+~J7L!TH6j*L~YYq7KRl&KJ{(o^=#d&D`|#vx12#VXq$>U%g` zq#q_}CI`EQ;}kE*jLS7giOjyPpRwoUj!BeE`bs~Py|@o*j9miFQpH&;({?=6R`iE9 z7;7^~ZIJY{t5cpUU(q8^$vG!!`Y>lJf>dJ6{upA7n`EkQ6zQ>TsUV3Z9< za|Q5(1Oh2p-nRUK<(U=f*fCO=cj!wcIT}J;dJUbF9LnIo6<*^SgHz~Kx z3$+8h&V|HB&ZZQlh_4Qxc||ll=Ua7QKE|wBgsFS(B<6h@_<#&a_hCBgF1f-lv{EP3^_K$>%ffB z01!xb#M7nk+3!5#9Wh0IoI>7|^DrAA(|OOlnV9e_oR%;Wk@RPL3h~d7`Ht*yx$_Ns z5Hzp$xNr!zTwZJt1u~N_{f%LN$CLmHs$WKB&caw9H(cBLok7w!=V+9|!_Yx&nL;Ku zCf+y1De_kQs|L$1WP%puvy&=YaCxg>^dsy^-Hi_Euk-VG$Cpky@yLdz(-!-#9Q~>am-b$G@p^7BhJBwSV5tGoMd<2PqA!H@!O}+ z9j5eS*a+8Qj#KEIq#1o&o)g96XChp^EqcmXNBjb1^c8|E@kXG|KO?&}U4-Tl* z!$GrczQT|V=Qmi3baBFA)+e^eyNA54BDG!OOc#0V6KZXeAyUkjWZY4%Q|lFXu0`3_P~eloQX)GN%ZpJIdG0Aio|~R-S;99@v8S97G8uQ literal 0 HcmV?d00001 diff --git a/denoisplit/analysis/checkpoint_utils.py b/denoisplit/analysis/checkpoint_utils.py new file mode 100644 index 0000000..1df27f0 --- /dev/null +++ b/denoisplit/analysis/checkpoint_utils.py @@ -0,0 +1,9 @@ +import glob + + +def get_best_checkpoint(ckpt_dir): + output = [] + for filename in glob.glob(ckpt_dir + "/*_best.ckpt"): + output.append(filename) + assert len(output) == 1, '\n'.join(output) + return output[0] diff --git a/denoisplit/analysis/critic_notebook_utils.py b/denoisplit/analysis/critic_notebook_utils.py new file mode 100644 index 0000000..39b01f8 --- /dev/null +++ b/denoisplit/analysis/critic_notebook_utils.py @@ -0,0 +1,110 @@ +""" +Functions used in Critic notebooks +""" +import numpy as np +import torch + +from denoisplit.core.model_type import ModelType +from denoisplit.core.psnr import PSNR, RangeInvariantPsnr + + +def _get_critic_prediction(pred: torch.Tensor, tar: torch.Tensor, D) -> dict: + """ + Given a predicted image and a target image, here we return a per sample prediction of + the critic regarding whether they belong to real or predicted images. + Args: + pred: predicted image + tar: target image + D: discriminator model + """ + pred_label = D(pred) + tar_label = D(tar) + pred_label = torch.sigmoid(pred_label) + tar_label = torch.sigmoid(tar_label) + N = len(pred_label) + pred_label = pred_label.view(N, -1) + tar_label = tar_label.view(N, -1) + return { + 'generated': { + 'mu': pred_label.mean(dim=1), + 'std': pred_label.std(dim=1) + }, + 'target': { + 'mu': tar_label.mean(dim=1), + 'std': tar_label.std(dim=1) + } + } + + +def get_critic_prediction(model, pred_normalized, target_normalized): + pred1, pred2 = pred_normalized.chunk(2, dim=1) + tar1, tar2 = target_normalized.chunk(2, dim=1) + cpred_1 = _get_critic_prediction(pred1, tar1, model.D1) + cpred_2 = _get_critic_prediction(pred2, tar2, model.D2) + return cpred_1, cpred_2 + + +def get_mmse_dict(model, x_normalized, target_normalized, mmse_count, model_type, psnr_type='range_invariant', + compute_kl_loss=False): + assert psnr_type in ['simple', 'range_invariant'] + if psnr_type == 'simple': + psnr_fn = PSNR + else: + psnr_fn = RangeInvariantPsnr + + img_mmse = 0 + avg_logvar = None + assert mmse_count >= 1 + for _ in range(mmse_count): + recon_normalized, td_data = model(x_normalized) + ll, dic = model.likelihood(recon_normalized, target_normalized) + recon_img = dic['mean'] + img_mmse += recon_img / mmse_count + if model.predict_logvar: + if avg_logvar is None: + avg_logvar = 0 + avg_logvar += dic['logvar'] / mmse_count + + ll, dic = model.likelihood(recon_normalized, target_normalized) + mse = (img_mmse - target_normalized) ** 2 + # batch and the two channels + N = np.prod(mse.shape[:2]) + rmse = torch.sqrt(torch.mean(mse.view(N, -1), dim=1)) + rmse = rmse.view(mse.shape[:2]) + loss_mmse = model.likelihood.log_likelihood(target_normalized, {'mean': img_mmse, 'logvar': avg_logvar}) + kl_loss = None + kl_loss_channelwise = None + if compute_kl_loss: + kl_loss = model.get_kl_divergence_loss(td_data).cpu().numpy() + resN = len(td_data['kl_channelwise']) + kl_loss_channelwise = [td_data['kl_channelwise'][i].detach().cpu().numpy() for i in range(resN)] + + psnrl1 = psnr_fn(target_normalized[:, 0], img_mmse[:, 0]).cpu().numpy() + psnrl2 = psnr_fn(target_normalized[:, 1], img_mmse[:, 1]).cpu().numpy() + + output = { + 'mmse_img': img_mmse, + 'mmse_rec_loss': loss_mmse, + 'img': recon_img, + 'rec_loss': ll, + 'rmse': rmse, + 'psnr_l1': psnrl1, + 'psnr_l2': psnrl2, + 'kl_loss': kl_loss, + 'kl_loss_channelwise': kl_loss_channelwise, + } + if model_type == ModelType.LadderVAECritic: + D_loss = model.get_critic_loss_stats(recon_img, target_normalized)['loss'].cpu().item() + cpred_1, cpred_2 = get_critic_prediction(model, recon_img, target_normalized) + critic = { + 'label1': cpred_1, + 'label2': cpred_2, + 'D_loss': D_loss, + } + output['critic'] = critic + return output + + +def get_label_separated_loss(loss_tensor): + assert loss_tensor.shape[1] == 2 + return -1 * loss_tensor[:, 0].mean(dim=(1, 2)).cpu().numpy(), -1 * loss_tensor[:, 1].mean(dim=(1, 2)).cpu().numpy() diff --git a/denoisplit/analysis/denoiser_splitter_utils.py b/denoisplit/analysis/denoiser_splitter_utils.py new file mode 100644 index 0000000..82f8b86 --- /dev/null +++ b/denoisplit/analysis/denoiser_splitter_utils.py @@ -0,0 +1,35 @@ +""" +This is specific to the HDN => uSplit pipeline. +""" +import os + +from denoisplit.config_utils import get_configdir_from_saved_predictionfile, load_config + + +def get_source_channel(pred_fname): + den_config_dir1 = get_configdir_from_saved_predictionfile(pred_fname) + config_temp = load_config(den_config_dir1) + print(pred_fname, config_temp.model.denoise_channel, config_temp.data.ch1_fname, config_temp.data.ch2_fname) + if config_temp.model.denoise_channel == 'Ch1': + ch1 = config_temp.data.ch1_fname + elif config_temp.model.denoise_channel == 'Ch2': + ch1 = config_temp.data.ch2_fname + else: + raise ValueError('Unhandled channel', config_temp.model.denoise_channel) + return ch1 + + +def whether_to_flip(ch1_fname, ch2_fname, reference_config): + """ + When one wants to get the highsnr data, then one does not know if the order of the channels is same as what uSplit predicts. + If not, then one needs to flip the channels. + """ + ch1 = get_source_channel(ch1_fname) + ch2 = get_source_channel(ch2_fname) + channels = [reference_config.data.ch1_fname, reference_config.data.ch2_fname] + assert ch1 in channels, f'{ch1} not in {channels}' + assert ch2 in channels, f'{ch2} not in {channels}' + assert ch1 != ch2, f'{ch1} and {ch2} are same' + if ch1 == reference_config.data.ch2_fname: + return True + return False diff --git a/denoisplit/analysis/double_dip_utils.py b/denoisplit/analysis/double_dip_utils.py new file mode 100644 index 0000000..f50b337 --- /dev/null +++ b/denoisplit/analysis/double_dip_utils.py @@ -0,0 +1,69 @@ +import os + +import matplotlib.pyplot as plt +import numpy as np + +from denoisplit.analysis.plot_utils import clean_ax +from denoisplit.core.psnr import RangeInvariantPsnr + + +def get_psnr(gt, pred): + """ + Order in the prediction is not fixed. So, we compute the psnr of each ground truth with both predictions + and then pick the correct ordering based on the psnr value. + """ + psnr0_0 = RangeInvariantPsnr(gt[0], pred[0]) + psnr0_1 = RangeInvariantPsnr(gt[0], pred[1]) + + psnr1_0 = RangeInvariantPsnr(gt[1], pred[0]) + psnr1_1 = RangeInvariantPsnr(gt[1], pred[1]) + if psnr0_0 + psnr1_1 > psnr0_1 + psnr1_0: + return psnr0_0, psnr1_1 + else: + return psnr0_1, psnr1_0 + + +def step_num(fname: str) -> int: + """ + sum1_499.jpg => 499 + """ + return int(fname.split('.')[0].split('_')[-1]) + + +def get_fpath_sequence(prefix, rootdir, extension=None): + """ + Args: + prefix: file name should start with prefix + rootdir: + extension:str + """ + output = [] + for fname in os.listdir(rootdir): + if prefix == fname[:len(prefix)]: + if extension is not None: + if fname[-1 * len(extension):] != extension: + continue + + output.append(os.path.join(rootdir, fname)) + + return sorted(output, key=lambda x: step_num(os.path.basename(x))) + + +def show_imgs_from_np_fpaths(fpath_list, ncols=4, img_sz=5, title_list=None, preprocessing_fn=None): + nrows = int(np.ceil(len(fpath_list) / ncols)) + _, ax = plt.subplots(figsize=(img_sz * ncols, nrows * img_sz), ncols=ncols, nrows=nrows) + clean_ax(ax) + if len(ax.shape) == 1: + ax = ax.reshape(1, -1) + for ridx in range(nrows): + for cidx in range(ncols): + fpath_idx = ridx * nrows + cidx + fpath = fpath_list[fpath_idx] + img = np.load(fpath) + if preprocessing_fn is not None: + img = preprocessing_fn(img) + + ax[ridx, cidx].imshow(img[0]) + if isinstance(title_list, list): + title = title_list[fpath_idx] + ax[ridx, cidx].set_title(title) diff --git a/denoisplit/analysis/grad_viewer.py b/denoisplit/analysis/grad_viewer.py new file mode 100644 index 0000000..575c9ef --- /dev/null +++ b/denoisplit/analysis/grad_viewer.py @@ -0,0 +1,114 @@ +""" +This module computes the gradients and stores them so that next access is fast. +This can be used to compute gradients of arbitrary order on images. +Last two dimensions of the data are assumed to be x & y dimension. + +grads = GradientFetcher(imgs) +To get d/dx2y3, +grad_x2_y3 = grads[2,3] + +""" +import numpy as np +from typing import List, Tuple +import seaborn as sns + + +class GradientFetcher: + def __init__(self, data) -> None: + self._data = data + + self._grad_data = {0: {0: self._data}} + + @staticmethod + def apply_x_grad(data): + grad = np.empty(data.shape) + grad[:] = np.nan + grad[..., :, 1:] = data[..., :, 1:] - data[..., :, :-1] + return grad + + @staticmethod + def apply_y_grad(data): + grad = np.empty(data.shape) + grad[:] = np.nan + grad[..., 1:, :] = data[..., 1:, :] - data[..., :-1, :] + return grad + + def __getitem__(self, order): + order_x, order_y = order + if order_x in self._grad_data and order_y in self._grad_data[order_x]: + return self._grad_data[order_x][order_y] + + self.compute(order_x, order_y) + return self._grad_data[order_x][order_y] + + def compute(self, order_x, order_y): + assert order_y >= 0 and order_x >= 0 + if order_x in self._grad_data: + if order_y in self._grad_data[order_x]: + return self._grad_data[order_x][order_y] + if order_y - 1 not in self._grad_data[order_x]: + self.compute(order_x, order_y - 1) + + self._grad_data[order_x][order_y] = self.apply_y_grad(self._grad_data[order_x][order_y - 1]) + return self._grad_data[order_x][order_y] + + self._grad_data[order_x] = {} + self.compute(order_x - 1, order_y) + self._grad_data[order_x][order_y] = self.apply_x_grad(self._grad_data[order_x - 1][order_y]) + return self._grad_data[order_x][order_y] + + +class GradientViewer: + def __init__(self, data) -> None: + self._data = data + self._grad = GradientFetcher(data) + + def plot(self, + ax, + gradorder_list: List[Tuple[int, int]], + x_start=0, + x_end=None, + y_start=0, + y_end=None, + subsample=1, + reduce_x=False, + reduce_y=False): + if x_end is None: + x_end = self._data.shape[-1] + + if y_end is None: + y_end = self._data.shape[-2] + + if isinstance(reduce_x, bool): + reduce_x = [reduce_x] * len(gradorder_list) + if isinstance(reduce_y, bool): + reduce_y = [reduce_y] * len(gradorder_list) + + all_plots_data = [] + for idx, order in enumerate(gradorder_list): + grad_data = self._grad[order] + grad_data = grad_data[y_start:y_end:subsample, x_start:x_end:subsample] + if reduce_x[idx]: + grad_data = grad_data.mean(axis=1) + sns.lineplot(data=grad_data, ax=ax[idx]) + all_plots_data.append(grad_data) + elif reduce_y[idx]: + grad_data = grad_data.mean(axis=0) + sns.lineplot(data=grad_data, ax=ax[idx]) + all_plots_data.append(grad_data) + else: + sns.heatmap(grad_data, ax=ax[idx]) + all_plots_data.append(grad_data) + return all_plots_data + + +if __name__ == '__main__': + import matplotlib.pyplot as plt + imgs = np.arange(1024).reshape(1, 1, 32, 32) + plt.imshow(imgs[0, 0]) + grads = GradientFetcher(imgs) + gradx = grads[1, 0] + print('next') + grady = grads[0, 1] + print('next') + gradxy = grads[1, 1] diff --git a/denoisplit/analysis/lvae_utils.py b/denoisplit/analysis/lvae_utils.py new file mode 100644 index 0000000..40ea2f1 --- /dev/null +++ b/denoisplit/analysis/lvae_utils.py @@ -0,0 +1,29 @@ +import numpy as np +import torch + +from denoisplit.core.data_utils import crop_img_tensor + + +def get_img_from_forward_output(out, model): + recons_img = model.likelihood.get_mean_lv(out)[0] + recons_img = recons_img * model.data_std + model.data_mean + return recons_img + + +def get_z(img, model): + with torch.no_grad(): + img = torch.Tensor(img[None]).cuda() + x_normalized = model.normalize(img) + recons_img_latent, td_data = model(x_normalized) + q_mu = td_data['q_mu'] + recons_img = get_img_from_forward_output(recons_img_latent, model) + return recons_img, q_mu + + +def get_recons_with_latent(img_shape, z, model): + # Top-down inference/generation + out, td_data = model.topdown_pass(None, forced_latent=z, n_img_prior=1) + # Restore original image size + out = crop_img_tensor(out, img_shape) + + return get_img_from_forward_output(out, model) diff --git a/denoisplit/analysis/mmse_prediction.py b/denoisplit/analysis/mmse_prediction.py new file mode 100644 index 0000000..3cfd341 --- /dev/null +++ b/denoisplit/analysis/mmse_prediction.py @@ -0,0 +1,231 @@ +from typing import Tuple + +import numpy as np +import torch +from torch.utils.data import DataLoader +from tqdm import tqdm + +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.metrics.running_psnr import RunningPSNR + + +def get_mmse_prediction(model, dset, inp_idx, mmse_count, padded_size: int, prediction_size: int, batch_size=16, + track_progress: bool = True) -> \ + Tuple[ + torch.Tensor, torch.Tensor]: + """ + The work here is to simply get the MMSE prediction for a specific input. + Args: + model: + dset: the dataset. + inp_idx: Input index of the dataset for which MMSE prediction needs to be computed. + mmse_count: Averaging over how many times? + padded_size: After padding what should be size of the input to the model. + prediction_size: How much should be kept for prediction. Ex: padded_size=96 and prediction_size=64. 16 pixesls + are padded on all sides in this case. + batch_size: Used for speeding up the computation. + + Returns: + MMSE prediction and the target. Both are in normalized state. + + """ + assert padded_size >= prediction_size + old_img_sz = dset.get_img_sz() + dset.set_img_sz(padded_size) + + padN = (padded_size - prediction_size) // 2 + + with torch.no_grad(): + inp, tar = dset[inp_idx] + inp = torch.Tensor(inp[None]) + tar = torch.Tensor(tar[None]) + inp = inp.repeat(batch_size, 1, 1, 1) + tar = tar.repeat(batch_size, 1, 1, 1) + inp = inp.cuda() + tar = tar.cuda() + recon_img_list = [] + range_mmse = range(0, mmse_count, batch_size) + if track_progress: + range_mmse = tqdm(range_mmse) + + for i in range_mmse: + end = min(i + batch_size, mmse_count) - i + x_normalized = model.normalize_input(inp[:end]) + tar_normalized = model.normalize_target(tar[:end]) + recon_normalized, td_data = model(x_normalized) + recon_img = model.likelihood.get_mean_lv(recon_normalized)[0] + if padN > 0: + tar_normalized = tar_normalized[:, :, padN:-padN, padN:-padN] + recon_normalized = recon_normalized[:, :, padN:-padN, padN:-padN] + recon_img = recon_img[:, :, padN:-padN, padN:-padN] + + assert tar_normalized.shape[-1] == prediction_size + assert tar_normalized.shape[-2] == prediction_size + assert tar_normalized.shape[-2:] == recon_normalized.shape[-2:] + recon_img_list.append(recon_img.cpu()) + mmse_img = torch.mean(torch.cat(recon_img_list, dim=0), dim=0)[None] + + dset.set_img_sz(old_img_sz) + return mmse_img, tar_normalized.cpu() + + +def get_dset_predictions(model, dset, batch_size, model_type=None, mmse_count=1, num_workers=4): + dloader = DataLoader(dset, pin_memory=False, num_workers=num_workers, shuffle=False, batch_size=batch_size) + predictions = [] + predictions_std = [] + losses = [] + logvar_arr = [] + patch_psnr_channels = [RunningPSNR() for _ in range(dset[0][1].shape[0])] + with torch.no_grad(): + for batch in tqdm(dloader): + inp, tar = batch[:2] + inp = inp.cuda() + tar = tar.cuda() + + recon_img_list = [] + for mmse_idx in range(mmse_count): + if model_type in [ModelType.UNet, ModelType.BraveNet]: + x_normalized = model.normalize_input(inp) + tar_normalized = model.normalize_target(tar) + + recon_normalized = model(x_normalized) + if model_type == ModelType.BraveNet: + recon_normalized = recon_normalized[0] + + imgs = recon_normalized + rec_loss = model.get_reconstruction_loss(recon_normalized, tar_normalized) + + if mmse_idx == 0: + logvar_arr.append(np.array([-1])) + losses.append(rec_loss.cpu().numpy()) + + else: + if model_type == ModelType.LadderVaeStitch: + x_normalized = model.normalize_input(inp) + tar_normalized = model.normalize_target(tar) + + recon_normalized, td_data = model(x_normalized) + offset = model.compute_offset(td_data['z']) + rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, + tar_normalized, + offset, + return_predicted_img=True) + elif model_type == ModelType.LadderVaeSemiSupervised: + x_normalized = model.normalize_input(inp, torch.zeros_like(tar[:, 0, 0, 0], dtype=torch.int64)) + tar_normalized = model.normalize_target(tar, torch.zeros_like(tar[:, 0, 0, 0], + dtype=torch.int64)) + + recon_normalized, td_data = model(x_normalized) + rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, + x_normalized, + tar_normalized, + return_predicted_img=True) + + elif model_type == ModelType.LadderVaeMixedRecons: + x_normalized = model.normalize_input(inp) + tar_normalized = model.normalize_target(tar) + + recon_normalized, td_data = model(x_normalized) + rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, + x_normalized, + tar_normalized, + return_predicted_img=True) + elif model_type in [ + ModelType.LadderVaeTwoDataSet, ModelType.LadderVaeTwoDatasetMultiBranch, + ModelType.LadderVaeTwoDatasetMultiOptim + ]: + dset_idx, loss_idx = batch[2:] + dset_idx = dset_idx.cuda() + loss_idx = loss_idx.cuda() + + x_normalized = model.normalize_input(inp) + tar_normalized = model.normalize_target(tar, dset_idx) + if model_type in [ + ModelType.LadderVaeTwoDatasetMultiBranch, ModelType.LadderVaeTwoDatasetMultiOptim + ]: + mask_mixrecons = loss_idx == LossType.ElboMixedReconstruction + mask_2ch = loss_idx == LossType.Elbo + assert mask_2ch.sum() in [0, len(x_normalized)] + assert mask_mixrecons.sum() in [0, len(x_normalized)] + loss_idx_type = LossType.Elbo if mask_2ch.sum() == len( + x_normalized) else LossType.ElboMixedReconstruction + recon_normalized, _ = model(x_normalized, loss_idx_type) + else: + recon_normalized, _ = model(x_normalized) + rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, + tar_normalized, + dset_idx, + loss_idx, + return_predicted_img=True) + + elif model_type == ModelType.LVaeDeepEncoderIntensityAug: + x_normalized = model.normalize_input(inp) + alpha = torch.Tensor([0.5] * len(x_normalized)).to(x_normalized.device) + tar_normalized = model.normalize_target(tar, batch=(None, None, alpha)) + out_l1, out_l2, td_data = model(x_normalized) + + rec_loss, imgs = model.get_reconstruction_loss(out_l1, + out_l2, + tar_normalized, + return_predicted_img=True) + imgs = torch.cat(imgs, dim=1) + rec_loss = {'loss': rec_loss} + elif model_type == ModelType.Denoiser: + assert model.denoise_channel in [ + 'Ch1', 'Ch2', 'input' + ], '"all" denoise channel not supported for evaluation. Pick one of "Ch1", "Ch2", "input"' + + x_normalized_new, tar_new = model.get_new_input_target((inp, tar, *batch[2:])) + tar_normalized = model.normalize_target(tar_new) + recon_normalized, _ = model(x_normalized_new) + rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, + tar_normalized, + x_normalized_new, + return_predicted_img=True) + elif model_type == ModelType.DenoiserSplitter: + x_normalized, tar_normalized = model.get_normalized_input_target((inp, tar, *batch[2:])) + recon_normalized, _ = model(x_normalized) + rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, + tar_normalized, + x_normalized, + return_predicted_img=True) + + else: + x_normalized = model.normalize_input(inp) + tar_normalized = model.normalize_target(tar) + recon_normalized, _ = model(x_normalized) + rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, + tar_normalized, + inp, + return_predicted_img=True) + + if mmse_idx == 0: + q_dic = model.likelihood.distr_params(recon_normalized) if model.likelihood is not None else { + 'logvar': None + } + if q_dic['logvar'] is not None: + logvar_arr.append(q_dic['logvar'].cpu().numpy()) + else: + logvar_arr.append(np.array([-1])) + + try: + losses.append(rec_loss['loss'].cpu().numpy()) + except: + losses.append(rec_loss['loss']) + + for i in range(imgs.shape[1]): + patch_psnr_channels[i].update(imgs[:, i], tar_normalized[:, i]) + + recon_img_list.append(imgs.cpu()[None]) + + samples = torch.cat(recon_img_list, dim=0) + mmse_imgs = torch.mean(samples, dim=0) + mmse_std = torch.std(samples, dim=0) + predictions.append(mmse_imgs.cpu().numpy()) + predictions_std.append(mmse_std.cpu().numpy()) + + psnr = [x.get() for x in patch_psnr_channels] + return np.concatenate(predictions, + axis=0), np.array(losses), np.concatenate(logvar_arr), psnr, np.concatenate(predictions_std, + axis=0) diff --git a/denoisplit/analysis/padding_utils.py b/denoisplit/analysis/padding_utils.py new file mode 100644 index 0000000..5066a84 --- /dev/null +++ b/denoisplit/analysis/padding_utils.py @@ -0,0 +1,24 @@ +import numpy as np + + +def select_boundary(inp: np.ndarray, width: int): + """ + Returns the boundary pixels. + Args: + inp:numpy.ndarray + width: + + Returns: + + """ + bnd_pixels = inp.clone() + bnd_pixels[..., width:-width, width:-width] = np.nan + filtr = bnd_pixels.isnan() + bnd_pixels = bnd_pixels[~filtr] + + # checking the sanity. assumption square image. + pSz = inp.shape[-1] + pixelcount = 4 * width * pSz - 4 * width * width + assert pixelcount == np.prod(bnd_pixels.shape) + + return bnd_pixels diff --git a/denoisplit/analysis/paper_plots.py b/denoisplit/analysis/paper_plots.py new file mode 100644 index 0000000..cccee15 --- /dev/null +++ b/denoisplit/analysis/paper_plots.py @@ -0,0 +1,289 @@ +import os +from typing import List + +import matplotlib.pyplot as plt +import numpy as np +import torch +from matplotlib.gridspec import GridSpec +from matplotlib.patches import Rectangle + +from denoisplit.analysis.plot_utils import add_left_arrow, add_pixel_kde, add_right_arrow, clean_ax +from denoisplit.core.psnr import RangeInvariantPsnr + + +def get_plotoutput_dir(ckpt_dir, patch_size, mmse_count=50): + plotsrootdir = f'/group/jug/ashesh/data/paper_figures/patch_{patch_size}_mmse_{mmse_count}' + rdate, rconfig, rid = ckpt_dir.split("/")[-3:] + fname_prefix = rdate + '-' + rconfig.replace('-', '')[:-2] + '-' + rid + plotsdir = os.path.join(plotsrootdir, fname_prefix) + os.makedirs(plotsdir, exist_ok=True) + print(plotsdir) + return plotsdir + + +def get_last_index(bin_count, quantile): + cumsum = np.cumsum(bin_count) + normalized_cumsum = cumsum / cumsum[-1] + for i in range(1, len(normalized_cumsum)): + if normalized_cumsum[-i] < quantile: + return i - 1 + return None + + +def get_first_index(bin_count, quantile): + cumsum = np.cumsum(bin_count) + normalized_cumsum = cumsum / cumsum[-1] + for i in range(len(normalized_cumsum)): + if normalized_cumsum[i] > quantile: + return i + return None + + +def plot_calibration(ax, calibration_stats): + first_idx = get_first_index(calibration_stats[0]['bin_count'], 0.001) + last_idx = get_last_index(calibration_stats[0]['bin_count'], 0.999) + ax.plot(calibration_stats[0]['rmv'][first_idx:-last_idx], + calibration_stats[0]['rmse'][first_idx:-last_idx], + 'o', + label='$\hat{C}_0$') + + first_idx = get_first_index(calibration_stats[1]['bin_count'], 0.001) + last_idx = get_last_index(calibration_stats[1]['bin_count'], 0.999) + ax.plot(calibration_stats[1]['rmv'][first_idx:-last_idx], + calibration_stats[1]['rmse'][first_idx:-last_idx], + 'o', + label='$\hat{C}_1$') + + ax.set_xlabel('RMV') + ax.set_ylabel('RMSE') + ax.legend() + + +# add_left_arrow(axes_list[3], (155,80), arrow_length=50) +def get_psnr_str(tar_hsnr, pred, col_idx): + return f'{RangeInvariantPsnr(tar_hsnr[col_idx][None], pred[col_idx][None]).item():.1f}' + + +def add_psnr_str(ax_, psnr): + """ + Add psnr string to the axes + """ + textstr = f'PSNR\n{psnr}' + props = dict(boxstyle='round', facecolor='gray', alpha=0.5) + # place a text box in upper left in axes coords + ax_.text(0.05, + 0.95, + textstr, + transform=ax_.transAxes, + fontsize=11, + verticalalignment='top', + bbox=props, + color='white') + + +def get_predictions(idx, val_dset, model, mmse_count=50, patch_size=256): + print(f'Predicting for {idx}') + val_dset.set_img_sz(patch_size, 64) + + with torch.no_grad(): + # val_dset.enable_noise() + inp, tar = val_dset[idx] + # val_dset.disable_noise() + + inp = torch.Tensor(inp[None]) + tar = torch.Tensor(tar[None]) + inp = inp.cuda() + x_normalized = model.normalize_input(inp) + tar = tar.cuda() + tar_normalized = model.normalize_target(tar) + + recon_img_list = [] + for _ in range(mmse_count): + recon_normalized, td_data = model(x_normalized) + rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, + x_normalized, + tar_normalized, + return_predicted_img=True) + imgs = model.unnormalize_target(imgs) + recon_img_list.append(imgs.cpu().numpy()[0]) + + recon_img_list = np.array(recon_img_list) + return inp, tar, recon_img_list + + +def show_for_one(idx, + val_dset, + highsnr_val_dset, + model, + calibration_stats, + mmse_count=5, + patch_size=256, + num_samples=2, + baseline_preds=None): + highsnr_val_dset.set_img_sz(patch_size, 64) + highsnr_val_dset.disable_noise() + _, tar_hsnr = highsnr_val_dset[idx] + inp, tar, recon_img_list = get_predictions(idx, val_dset, model, mmse_count=mmse_count, patch_size=patch_size) + plot_crops(inp, + tar, + tar_hsnr, + recon_img_list, + calibration_stats, + num_samples=num_samples, + baseline_preds=baseline_preds) + + +def plot_crops(inp, tar, tar_hsnr, recon_img_list, calibration_stats, num_samples=2, baseline_preds=None): + if baseline_preds is None: + baseline_preds = [] + if len(baseline_preds) > 0: + for i in range(len(baseline_preds)): + if baseline_preds[i].shape != tar_hsnr.shape: + print( + f'Baseline prediction {i} shape {baseline_preds[i].shape} does not match target shape {tar_hsnr.shape}' + ) + print('This happens when we want to predict the edges of the image.') + return + color_ch_list = ['goldenrod', 'cyan'] + color_pred = 'red' + insetplot_xmax_value = 10000 + insetplot_xmin_value = -1000 + inset_min_labelsize = 10 + inset_rect = [0.05, 0.05, 0.4, 0.2] + + img_sz = 3 + ncols = num_samples + len(baseline_preds) + 1 + 1 + 1 + 1 + 1 * (num_samples > 1) + grid_factor = 5 + grid_img_sz = img_sz * grid_factor + example_spacing = 1 + c0_extra = 1 + nimgs = 1 + fig_w = ncols * img_sz + 2 * c0_extra / grid_factor + fig_h = int(img_sz * ncols + (example_spacing * (nimgs - 1)) / grid_factor) + fig = plt.figure(figsize=(fig_w, fig_h)) + gs = GridSpec(nrows=int(grid_factor * fig_h), ncols=int(grid_factor * fig_w), hspace=0.2, wspace=0.2) + params = {'mathtext.default': 'regular'} + plt.rcParams.update(params) + # plot baselines + for i in range(2, 2 + len(baseline_preds)): + for col_idx in range(baseline_preds[0].shape[0]): + ax_temp = fig.add_subplot(gs[col_idx * grid_img_sz:grid_img_sz * (col_idx + 1), + i * grid_img_sz + c0_extra:(i + 1) * grid_img_sz + c0_extra]) + print(tar_hsnr.shape, baseline_preds[i - 2].shape) + psnr = get_psnr_str(tar_hsnr, baseline_preds[i - 2], col_idx) + ax_temp.imshow(baseline_preds[i - 2][col_idx], cmap='magma') + add_psnr_str(ax_temp, psnr) + clean_ax(ax_temp) + + # plot samples + sample_start_idx = 2 + len(baseline_preds) + for i in range(sample_start_idx, ncols - 3): + for col_idx in range(recon_img_list.shape[1]): + ax_temp = fig.add_subplot(gs[col_idx * grid_img_sz:grid_img_sz * (col_idx + 1), + i * grid_img_sz + c0_extra:(i + 1) * grid_img_sz + c0_extra]) + psnr = get_psnr_str(tar_hsnr, recon_img_list[i - sample_start_idx], col_idx) + ax_temp.imshow(recon_img_list[i - sample_start_idx][col_idx], cmap='magma') + add_psnr_str(ax_temp, psnr) + clean_ax(ax_temp) + # inset_ax = add_pixel_kde(ax_temp, + # inset_rect, + # [tar_hsnr[col_idx], + # recon_img_list[i - sample_start_idx][col_idx]], + # inset_min_labelsize, + # label_list=['', ''], + # color_list=[color_ch_list[col_idx], color_pred], + # plot_xmax_value=insetplot_xmax_value, + # plot_xmin_value=insetplot_xmin_value) + + # inset_ax.set_xticks([]) + # inset_ax.set_yticks([]) + + # difference image + if num_samples > 1: + for col_idx in range(recon_img_list.shape[1]): + ax_temp = fig.add_subplot(gs[col_idx * grid_img_sz:grid_img_sz * (col_idx + 1), + (ncols - 3) * grid_img_sz + c0_extra:(ncols - 2) * grid_img_sz + c0_extra]) + ax_temp.imshow(recon_img_list[1][col_idx] - recon_img_list[0][col_idx], cmap='coolwarm') + clean_ax(ax_temp) + + for col_idx in range(recon_img_list.shape[1]): + # print(recon_img_list.shape) + ax_temp = fig.add_subplot(gs[col_idx * grid_img_sz:grid_img_sz * (col_idx + 1), + c0_extra + (ncols - 2) * grid_img_sz:(ncols - 1) * grid_img_sz + c0_extra]) + psnr = get_psnr_str(tar_hsnr, recon_img_list.mean(axis=0), col_idx) + ax_temp.imshow(recon_img_list.mean(axis=0)[col_idx], cmap='magma') + add_psnr_str(ax_temp, psnr) + # inset_ax = add_pixel_kde(ax_temp, + # inset_rect, + # [tar_hsnr[col_idx], + # recon_img_list.mean(axis=0)[col_idx]], + # inset_min_labelsize, + # label_list=['', ''], + # color_list=[color_ch_list[col_idx], color_pred], + # plot_xmax_value=insetplot_xmax_value, + # plot_xmin_value=insetplot_xmin_value) + # inset_ax.set_xticks([]) + # inset_ax.set_yticks([]) + + clean_ax(ax_temp) + + ax_temp = fig.add_subplot(gs[col_idx * grid_img_sz:grid_img_sz * (col_idx + 1), + (ncols - 1) * grid_img_sz + 2 * c0_extra:(ncols) * grid_img_sz + 2 * c0_extra]) + ax_temp.imshow(tar_hsnr[col_idx], cmap='magma') + if col_idx == 0: + legend_ch1_ax = ax_temp + if col_idx == 1: + legend_ch2_ax = ax_temp + + # inset_ax = add_pixel_kde(ax_temp, + # inset_rect, + # [tar_hsnr[col_idx], + # ], + # inset_min_labelsize, + # label_list=[''], + # color_list=[color_ch_list[col_idx]], + # plot_xmax_value=insetplot_xmax_value, + # plot_xmin_value=insetplot_xmin_value) + # inset_ax.set_xticks([]) + # inset_ax.set_yticks([]) + + clean_ax(ax_temp) + + ax_temp = fig.add_subplot(gs[col_idx * grid_img_sz:grid_img_sz * (col_idx + 1), grid_img_sz:2 * grid_img_sz]) + ax_temp.imshow(tar[0, col_idx].cpu().numpy(), cmap='magma') + # inset_ax = add_pixel_kde(ax_temp, + # inset_rect, + # [tar[0,col_idx].cpu().numpy(), + # ], + # inset_min_labelsize, + # label_list=[''], + # color_list=[color_ch_list[col_idx]], + # plot_kwargs_list=[{'linestyle':'--'}], + # plot_xmax_value=insetplot_xmax_value, + # plot_xmin_value=insetplot_xmin_value) + + # inset_ax.set_xticks([]) + # inset_ax.set_yticks([]) + + clean_ax(ax_temp) + + ax_temp = fig.add_subplot(gs[0:grid_img_sz, 0:grid_img_sz]) + ax_temp.imshow(inp[0, 0].cpu().numpy(), cmap='magma') + clean_ax(ax_temp) + import matplotlib.lines as mlines + + # line_ch1 = mlines.Line2D([0, 1], [0, 1], color=color_ch_list[0], linestyle='-', label='$C_1$') + # line_ch2 = mlines.Line2D([0, 1], [0, 1], color=color_ch_list[1], linestyle='-', label='$C_2$') + # line_pred = mlines.Line2D([0, 1], [0, 1], color=color_pred, linestyle='-', label='Pred') + # line_noisych1 = mlines.Line2D([0, 1], [0, 1], color=color_ch_list[0], linestyle='--', label='$C^N_1$') + # line_noisych2 = mlines.Line2D([0, 1], [0, 1], color=color_ch_list[1], linestyle='--', label='$C^N_2$') + # legend_ch1 = legend_ch1_ax.legend(handles=[line_ch1, line_noisych1, line_pred], loc='upper right', frameon=False, labelcolor='white', + # prop={'size': 11}) + # legend_ch2 = legend_ch2_ax.legend(handles=[line_ch2, line_noisych2, line_pred], loc='upper right', frameon=False, labelcolor='white', + # prop={'size': 11}) + + if calibration_stats is not None: + smaller_offset = 4 + ax_temp = fig.add_subplot(gs[grid_img_sz + 1:2 * grid_img_sz - smaller_offset + 1, + smaller_offset - 1:grid_img_sz - 1]) + plot_calibration(ax_temp, calibration_stats) diff --git a/denoisplit/analysis/plot_error_utils.py b/denoisplit/analysis/plot_error_utils.py new file mode 100644 index 0000000..f32f434 --- /dev/null +++ b/denoisplit/analysis/plot_error_utils.py @@ -0,0 +1,82 @@ +import matplotlib +import matplotlib.pyplot as plt +import numpy as np + +from mpl_toolkits.axes_grid1 import AxesGrid + + +def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name='shiftedcmap'): + ''' + Adapted from https://stackoverflow.com/questions/7404116/defining-the-midpoint-of-a-colormap-in-matplotlib + + Function to offset the "center" of a colormap. Useful for + data with a negative min and positive max and you want the + middle of the colormap's dynamic range to be at zero. + + Input + ----- + cmap : The matplotlib colormap to be altered + start : Offset from lowest point in the colormap's range. + Defaults to 0.0 (no lower offset). Should be between + 0.0 and `midpoint`. + midpoint : The new center of the colormap. Defaults to + 0.5 (no shift). Should be between 0.0 and 1.0. In + general, this should be 1 - vmax / (vmax + abs(vmin)) + For example if your data range from -15.0 to +5.0 and + you want the center of the colormap at 0.0, `midpoint` + should be set to 1 - 5/(5 + 15)) or 0.75 + stop : Offset from highest point in the colormap's range. + Defaults to 1.0 (no upper offset). Should be between + `midpoint` and 1.0. + ''' + cdict = {'red': [], 'green': [], 'blue': [], 'alpha': []} + + # regular index to compute the colors + reg_index = np.linspace(start, stop, 257) + mid_idx = len(reg_index) // 2 + # shifted index to match the data + shift_index = np.hstack( + [np.linspace(0.0, midpoint, 128, endpoint=False), + np.linspace(midpoint, 1.0, 129, endpoint=True)]) + + for ri, si in zip(reg_index, shift_index): + r, g, b, a = cmap(ri) + a = np.abs(ri - reg_index[mid_idx]) / reg_index[mid_idx] + # print(a) + cdict['red'].append((si, r, r)) + cdict['green'].append((si, g, g)) + cdict['blue'].append((si, b, b)) + cdict['alpha'].append((si, a, a)) + + newcmap = matplotlib.colors.LinearSegmentedColormap(name, cdict) + matplotlib.colormaps.register(cmap=newcmap, force=True) + + return newcmap + + +def get_fractional_change(target, prediction, max_val=None): + if max_val is None: + max_val = target.max() + return (target - prediction) / max_val + + +def get_zero_centered_midval(error): + """ + When done this way, the midval ensures that the colorbar is centered at 0. (Don't know how, but it works ;)) + """ + vmax = error.max() + vmin = error.min() + midval = 1 - vmax / (vmax + abs(vmin)) + return midval + + +def plot_error(target, prediction, cmap=matplotlib.cm.coolwarm, ax=None, max_val=None): + if ax is None: + _, ax = plt.subplots(figsize=(6, 6)) + + z2 = get_fractional_change(target, prediction, max_val=max_val) + midval = get_zero_centered_midval(z2) + shifted_cmap = shiftedColorMap(cmap, start=0, midpoint=midval, stop=1.0, name='shiftedcmap') + ax.imshow(prediction, cmap='gray') + img_err = ax.imshow(z2, cmap=shifted_cmap, alpha=1) + plt.colorbar(img_err, ax=ax) diff --git a/denoisplit/analysis/plot_utils.py b/denoisplit/analysis/plot_utils.py new file mode 100644 index 0000000..196d6fa --- /dev/null +++ b/denoisplit/analysis/plot_utils.py @@ -0,0 +1,364 @@ +from typing import List, Union + +import matplotlib.pyplot as plt +import numpy as np +import seaborn as sns +import torch + +from denoisplit.analysis.critic_notebook_utils import get_label_separated_loss, get_mmse_dict +from denoisplit.analysis.lvae_utils import get_img_from_forward_output +from denoisplit.analysis.quantifying_uncertainty import get_regionwise_metric + + +def clean_ax(ax): + # 2D or 1D axes are of type np.ndarray + if isinstance(ax, np.ndarray): + for one_ax in ax: + clean_ax(one_ax) + return + + ax.set_yticklabels([]) + ax.set_xticklabels([]) + ax.tick_params(left=False, right=False, top=False, bottom=False) + + +def add_text(ax, text, img_shape, place='TOP_LEFT'): + """ + Adding text on image + """ + assert place in ['TOP_LEFT', 'BOTTOM_RIGHT'] + if place == 'TOP_LEFT': + ax.text(img_shape[1] * 20 / 500, img_shape[0] * 35 / 500, text, bbox=dict(facecolor='white', alpha=0.9)) + elif place == 'BOTTOM_RIGHT': + s0 = img_shape[1] + s1 = img_shape[0] + ax.text(s0 - s0 * 150 / 500, s1 - s1 * 35 / 500, text, bbox=dict(facecolor='white', alpha=0.9)) + + +def plot_one_batch_twinnoise(imgs, plot_width=20): + batch_size = len(imgs) + ncols = batch_size // 2 + img_sz = plot_width // ncols + _, ax = plt.subplots(figsize=(ncols * img_sz, 2 * img_sz), ncols=ncols, nrows=2) + for i in range(ncols): + ax[0, i].imshow(imgs[i, 0]) + ax[1, i].imshow(imgs[i + batch_size // 2, 0]) + + ax[1, i].set_title(f'{i + 1 + batch_size // 2}.') + ax[0, i].set_title(f'{i + 1}.') + + ax[0, i].tick_params(left=False, right=False, top=False, bottom=False) + ax[0, i].axis('off') + ax[1, i].tick_params(left=False, right=False, top=False, bottom=False) + ax[1, i].axis('off') + + +def get_k_largest_indices(arr: np.ndarray, K: int): + """ + Returns the index for K largest elements, in the order small->large. + """ + ind = np.argpartition(arr, -1 * K)[-1 * K:] + return ind[np.argsort(arr[ind])] + + +def add_subplot_axes(ax, rect: List[float], facecolor: str = 'w', min_labelsize: int = 5): + """ + Add an axes inside an axes. This can be used to create an inset plot. + Adapted from https://stackoverflow.com/questions/17458580/embedding-small-plots-inside-subplots-in-matplotlib + Args: + ax: matplotblib.axes + rect: Array with 4 elements describing where to position the new axes inside the current axes ax. + eg: [0.1,0.1,0.4,0.2] + facecolor: what should be the background color of the new axes + min_labelsize: what should be the minimum labelsize in the new axes + """ + fig = plt.gcf() + box = ax.get_position() + width = box.width + height = box.height + # transAxes: co-ordinate system of the axes: 0,0 is bottomleft and 1,1 is top right. + # With below command, we want to get to a position which would be the position of new plot in the axes coordinate + # system + inax_position = ax.transAxes.transform(rect[0:2]) + transFigure = fig.transFigure.inverted() + # with below command, we now have a position of the new plot in the figure coordinate system. we need this because + # we can create a new axes in the figure coordinate system. so we want to get everything in that system. + infig_position = transFigure.transform(inax_position) + x = infig_position[0] + y = infig_position[1] + width *= rect[2] + height *= rect[3] # <= Typo was here + # subax = fig.add_axes([x,y,width,height],facecolor=facecolor) # matplotlib 2.0+ + subax = fig.add_axes([x, y, width, height], facecolor=facecolor) + x_labelsize = subax.get_xticklabels()[0].get_size() + y_labelsize = subax.get_yticklabels()[0].get_size() + x_labelsize *= rect[2]**0.5 + y_labelsize *= rect[3]**0.5 + subax.xaxis.set_tick_params(labelsize=max(min_labelsize, x_labelsize)) + subax.yaxis.set_tick_params(labelsize=max(min_labelsize, y_labelsize)) + return subax + + +def clean_for_xaxis_plot(inset_ax): + """ + For an xaxis plot, the y axis values don't matter. Neither the axes borders save the bottom one. + """ + # Removing y-axes ticks and text + inset_ax.set_yticklabels([]) + inset_ax.tick_params(left=False, right=False) + inset_ax.set_ylabel('') + + # removing the axes border lines. + inset_ax.spines['top'].set_visible(False) + inset_ax.spines['right'].set_visible(False) + inset_ax.spines['left'].set_visible(False) + + +def add_pixel_kde(ax, + rect: List[float], + data_list: List[np.ndarray], + min_labelsize: int, + plot_xmax_value: int = None, + plot_xmin_value: int = None, + plot_kwargs_list=None, + color_list=None, + label_list=None, + color_xtick='white'): + """ + Adds KDE (density plot) of data1(eg: target) and data2(ex: predicted) image pixel values as an inset + """ + if plot_kwargs_list is None: + plot_kwargs_list = [{} for _ in range(len(data_list))] + + inset_ax = add_subplot_axes(ax, rect, facecolor="None", min_labelsize=min_labelsize) + + inset_ax.tick_params(axis='x', colors=color_xtick) + # xmin, xmax = inset_ax.get_xlim() + + if plot_xmax_value is not None: + xmax_data = plot_xmax_value + else: + xmax_data = [int(datak.max()) for datak in data_list] + if len(xmax_data) > 1: + xmax_data = max(*xmax_data) + 1 + else: + xmax_data = xmax_data[0] + 1 + + xmin_data = 0 + if plot_xmin_value is not None: + xmin_data = plot_xmin_value + else: + xmin_data = [int(datak.min()) for datak in data_list] + if len(xmin_data) > 1: + xmin_data = min(*xmin_data) - 1 + else: + xmin_data = xmin_data[0] - 1 + + for datak, colork, labelk, plot_kwargsk in zip(data_list, color_list, label_list, plot_kwargs_list): + sns.kdeplot(data=datak.reshape(-1, ), + ax=inset_ax, + color=colork, + label=labelk, + clip=(xmin_data, None), + **plot_kwargsk) + + inset_ax.set_aspect('auto') + inset_ax.set_xlim([xmin_data, xmax_data]) #xmin=0,xmax= xmax_data + inset_ax.set_xbound(lower=xmin_data, upper=xmax_data) + + xticks = inset_ax.get_xticks() + inset_ax.set_xticks([xticks[0], xticks[-1]]) + clean_for_xaxis_plot(inset_ax) + return inset_ax + + +def plot_imgs_from_idx(idx_list, + val_dset, + model, + model_type, + psnr_type='range_invariant', + inset_pixel_kde=False, + inset_rect=None, + inset_min_labelsize=None, + color_ch1='red', + color_ch2='black', + color_generated='pink'): + """ + Plots images and their disentangled predictions. Input is a list of idx for which this is done. + """ + ncols = 5 + nrows = len(idx_list) + img_sz = 20 / ncols + _, ax = plt.subplots(figsize=(ncols * img_sz, nrows * img_sz), ncols=ncols, nrows=nrows) + + with torch.no_grad(): + for ax_idx, img_idx in enumerate(idx_list): + inp, tar = val_dset[img_idx] + inp = torch.Tensor(inp[None]).cuda() + tar = torch.Tensor(tar[None]).cuda() + + x_normalized = model.normalize_input(inp) + target_normalized = model.normalize_target(tar) + + recon_normalized, td_data = model(x_normalized) + imgs = get_img_from_forward_output(recon_normalized, model) + loss_dic = get_mmse_dict(model, x_normalized, target_normalized, 1, model_type, psnr_type=psnr_type) + ll1, ll2 = get_label_separated_loss(loss_dic['mmse_rec_loss']) + + inp = inp.cpu().numpy() + tar = tar.cpu().numpy() + imgs = imgs.cpu().numpy() + + psnr1 = loss_dic['psnr_l1'][0] + psnr2 = loss_dic['psnr_l2'][0] + + ax[ax_idx, 0].imshow(inp[0, 0]) + if inset_pixel_kde: + # distribution of both labels + add_pixel_kde(ax[ax_idx, 0], + inset_rect, + tar[0, 0], + tar[0, 1], + inset_min_labelsize, + label1='Ch1', + label2='Ch2', + color1=color_ch1, + color2=color_ch2) + + # max and min values for label 1 + l1_max = max(tar[0, 0].max(), imgs[0, 0].max()) + l1_min = min(tar[0, 0].min(), imgs[0, 0].min()) + + ax[ax_idx, 1].imshow(tar[0, 0], vmin=l1_min, vmax=l1_max) + ax[ax_idx, 2].imshow(imgs[0, 0], vmin=l1_min, vmax=l1_max) + add_text(ax[ax_idx, 2], f'PSNR:{psnr1:.1f}', inp.shape[-2:]) + txt = f'{int(l1_min)}-{int(l1_max)}' + add_text(ax[ax_idx, 2], txt, inp.shape[-2:], place='BOTTOM_RIGHT') + add_text(ax[ax_idx, 1], txt, inp.shape[-2:], place='BOTTOM_RIGHT') + if inset_pixel_kde: + # distribution of label 1 and its prediction + add_pixel_kde(ax[ax_idx, 2], + inset_rect, + tar[0, 0], + imgs[0, 0], + inset_min_labelsize, + label1='Ch1', + label2='Gen', + color1=color_ch1, + color2=color_generated) + + # max and min values for label 2 + l2_max = max(tar[0, 1].max(), imgs[0, 1].max()) + l2_min = min(tar[0, 1].min(), imgs[0, 1].min()) + ax[ax_idx, 3].imshow(tar[0, 1], vmin=l2_min, vmax=l2_max) + ax[ax_idx, 4].imshow(imgs[0, 1], vmin=l2_min, vmax=l2_max) + txt = f'{int(l2_min)}-{int(l2_max)}' + add_text(ax[ax_idx, 4], f'PSNR:{psnr2:.1f}', inp.shape[-2:]) + add_text(ax[ax_idx, 4], txt, inp.shape[-2:], place='BOTTOM_RIGHT') + add_text(ax[ax_idx, 3], txt, inp.shape[-2:], place='BOTTOM_RIGHT') + if inset_pixel_kde: + # distribution of label 2 and its prediction + add_pixel_kde(ax[ax_idx, 4], + inset_rect, + tar[0, 1], + imgs[0, 1], + inset_min_labelsize, + label1='Ch2', + label2='Gen', + color1=color_ch2, + color2=color_generated) + + ax[ax_idx, 2].set_title(f'Error: {ll1[0]:.3f}') + ax[ax_idx, 4].set_title(f'Error: {ll2[0]:.3f}') + ax[ax_idx, 0].set_title(f'Id:{img_idx}') + ax[ax_idx, 1].set_title('Image 1') + ax[ax_idx, 3].set_title('Image 2') + + +def plot_regionwise_metric(model, + dset, + idx_list: List[int], + metric_types: List[str], + regionsize: int = 64, + sample_count: int = 5, + normalize_type=None): + metric_dict, target = get_regionwise_metric(model, + dset, + idx_list, + metric_types, + regionsize=regionsize, + sample_count=sample_count, + normalize_type=normalize_type) + + img_sz = 3.5 + nrows = len(idx_list) + sample_count = 20 + inset_rect = [0.1, 0.1, 0.4, 0.2] + inset_min_labelsize = 8 + _, ax = plt.subplots(figsize=(img_sz * 4, nrows * img_sz), ncols=4, nrows=nrows) + for i, img_idx in enumerate(idx_list): + ax[i, 0].imshow(target[img_idx][0]) + ax[i, 2].imshow(target[img_idx][1]) + + add_pixel_kde( + ax[i, 0], + inset_rect, + target[img_idx][0], + target[img_idx][1], + inset_min_labelsize, + color1='r', + color2='black', + ) + add_pixel_kde( + ax[i, 2], + inset_rect, + target[img_idx][1], + target[img_idx][0], + inset_min_labelsize, + color1='r', + color2='black', + ) + + max_val = metric_dict[sample_count][img_idx]['RMSE'].max() + min_val = metric_dict[sample_count][img_idx]['RMSE'].min() + sns.heatmap(metric_dict[sample_count][img_idx]['RMSE'][0], ax=ax[i, 1], vmax=max_val, vmin=min_val) + sns.heatmap(metric_dict[sample_count][img_idx]['RMSE'][1], ax=ax[i, 3], vmax=max_val, vmin=min_val) + + +# Adding arrows. +def add_left_arrow(ax, xy_location, arrow_length=20, color='red', arrowstyle='->'): + xy_start = (xy_location[0] + arrow_length, xy_location[1]) + return add_arrow(ax, xy_start, xy_location, color='red', arrowstyle=arrowstyle) + + +def add_right_arrow(ax, xy_location, arrow_length=20, color='red', arrowstyle='->'): + xy_start = (xy_location[0] - arrow_length, xy_location[1]) + return add_arrow(ax, xy_start, xy_location, color='red', arrowstyle=arrowstyle) + + +def add_top_arrow(ax, xy_location, arrow_length=20, color='red', arrowstyle='->'): + xy_start = (xy_location[0], xy_location[1] + arrow_length) + return add_arrow(ax, xy_start, xy_location, color='red', arrowstyle=arrowstyle) + + +def add_bottom_arrow(ax, xy_location, arrow_length=20, color='red', arrowstyle='->'): + xy_start = (xy_location[0], xy_location[1] - arrow_length) + return add_arrow(ax, xy_start, xy_location, color='red', arrowstyle=arrowstyle) + + +def get_start_vector(xy_start, xy_end, arrow_length): + """ + Given an arrow_length, return a xy_start such that xy_start => xy_end vector has this length. + """ + direction = (xy_end[0] - xy_start[0], xy_end[1] - xy_start[1]) + norm = np.linalg.norm(direction) + direction = (direction[0] / norm, direction[1] / norm) + direction = (direction[0] * arrow_length, direction[1] * arrow_length) + xy_start = (xy_end[0] - direction[0], xy_end[1] - direction[1]) + return xy_start + + +def add_arrow(ax, xy_start, xy_end, arrow_length=None, color='red', arrowstyle="->"): + if arrow_length is not None: + xy_start = get_start_vector(xy_start, xy_end, arrow_length) + ax.annotate("", xy=xy_end, xytext=xy_start, arrowprops=dict(arrowstyle=arrowstyle, color=color, linewidth=1)) diff --git a/denoisplit/analysis/pred_frame_creator.py b/denoisplit/analysis/pred_frame_creator.py new file mode 100644 index 0000000..ffd2ec6 --- /dev/null +++ b/denoisplit/analysis/pred_frame_creator.py @@ -0,0 +1,57 @@ +""" +Here, we filter and club together the predicted patches to form the predicted frame. +""" +import os + +import numpy as np +from PIL import Image + + +class PredFrameCreator: + + def __init__(self, grid_index_manager, frame_t, dump_dir=None) -> None: + self._grid_index_manager = grid_index_manager + _, H, W, C = self._grid_index_manager.get_data_shape() + self.frame = np.zeros((C, H, W), dtype=np.int32) + self.target_frame = np.zeros((C, H, W), dtype=np.int32) + self._frame_t = frame_t + self._dump_dir = dump_dir + os.makedirs(self._dump_dir, exist_ok=True) + os.makedirs(self.ch_subdir(0), exist_ok=True) + os.makedirs(self.ch_subdir(1), exist_ok=True) + + print(f'{self.__class__.__name__} frame_t:{self._frame_t}') + + def _update(self, predictions, indices, output_frame): + for i, index in enumerate(indices): + h, w, t = self._grid_index_manager.hwt_from_idx(index) + if t != self._frame_t: + continue + sz = predictions[i].shape[-1] + output_frame[:, h:h + sz, w:w + sz] = predictions[i] + + def update(self, predictions, indices): + self._update(predictions, indices, self.frame) + + def update_target(self, target, indices): + self._update(target, indices, self.target_frame) + + def reset(self): + self.frame = np.zeros_like(self.frame) + + def dump_target(self): + assert self._dump_dir is not None + fname = os.path.join(self.ch_subdir(0), f"tar_t_{self._frame_t}.png") + Image.fromarray(self.target_frame[0]).save(fname) + fname = os.path.join(self.ch_subdir(1), f"tar_t_{self._frame_t}.png") + Image.fromarray(self.target_frame[1]).save(fname) + + def ch_subdir(self, ch_idx): + return os.path.join(self._dump_dir, f"ch_{ch_idx}") + + def dump(self, epoch): + assert self._dump_dir is not None + for ch_idx in range(self.frame.shape[0]): + subdir = self.ch_subdir(ch_idx) + fpath = os.path.join(subdir, f"{epoch}_t_{self._frame_t}.png") + Image.fromarray(self.frame[ch_idx]).save(fpath) diff --git a/denoisplit/analysis/quantifying_uncertainty.py b/denoisplit/analysis/quantifying_uncertainty.py new file mode 100644 index 0000000..909dc39 --- /dev/null +++ b/denoisplit/analysis/quantifying_uncertainty.py @@ -0,0 +1,213 @@ +""" +Here, we have functions which can be used to quantify uncertainty in the predictions. +""" +from typing import Dict, List + +import matplotlib.pyplot as plt +import numpy as np +import seaborn as sns +import torch + +from denoisplit.analysis.lvae_utils import get_img_from_forward_output +from denoisplit.core.psnr import PSNR, RangeInvariantPsnr + + +def sample_images(model, dset, idx_list, sample_count: int = 5): + output = {} + with torch.no_grad(): + for img_idx in idx_list: + inp, tar = dset[img_idx] + output[img_idx] = {'rec': [], 'tar': tar} + inp = torch.Tensor(inp[None]).cuda() + x_normalized = model.normalize_input(inp) + for _ in range(sample_count): + recon_normalized, _ = model(x_normalized) + imgs = get_img_from_forward_output(recon_normalized, model) + output[img_idx]['rec'].append(imgs[0].cpu().numpy()) + + return output + + +def compute_regionwise_metric_pairwise_one_pair(data1, data2, metric_types: List[str], regionsize: int): + # ensure that we are working with a square + assert data1.shape[-1] == data1.shape[-2] + assert data1.shape == data2.shape + Nc = data1.shape[-3] + Nh = data1.shape[-2] // regionsize + Nw = data1.shape[-1] // regionsize + output = {mtype: np.zeros((Nc, Nh, Nw)) for mtype in metric_types} + for hidx in range(Nh): + for widx in range(Nw): + h = hidx * regionsize + w = widx * regionsize + d1 = data1[..., h:h + regionsize, w:w + regionsize] + d2 = data2[..., h:h + regionsize, w:w + regionsize] + met_dic = _compute_metrics(d1, d2, metric_types) + for mtype in metric_types: + output[mtype][..., hidx, widx] = met_dic[mtype] + + return output + + +def _compute_metrics(data1, data2, metric_types: List[str]): + data1 = data1.reshape(len(data1), -1) + data2 = data2.reshape(len(data2), -1) + + output = {} + # import pdb;pdb.set_trace() + for metric_type in metric_types: + assert metric_type in ['PSNR', 'RangeInvariantPsnr', 'RMSE'] + + if metric_type == 'RMSE': + metric = np.sqrt(np.mean((data1 - data2) ** 2, axis=1)) + elif metric_type == 'PSNR': + metric = np.array([PSNR(data1[0], data2[0]), PSNR(data1[1], data2[1])]) + elif metric_type == 'RangeInvariantPsnr': + metric = np.array([RangeInvariantPsnr(data1[0], data2[0]), + RangeInvariantPsnr(data1[1], data2[1])]) + output[metric_type] = metric + return output + + +def compute_regionwise_metric_pairwise(model, dset, idx_list: List[int], metric_types, regionsize: int = 64, + sample_count: int = 5) -> Dict[int, dict]: + """ + This will get the prediction multiple times for each of the idx. It would then compute the pairswise metric + between the predictions, that too on small regions. So, if the model is not sure about a certain region, it would simply + predict very different things every time and we should get a low PSNR in that region. + Args: + model: model + dset: the dataset + idx_list: list of idx for which we want to compute this metric + Returns: + nested dictionary with following structure img_idx => [pairwise_metric,rec,tar] + pairwise_metric => idx1 => idx2 => metric_type => value + samples => List of sampled reconstructions + + """ + output = {} + sample_dict = sample_images(model, dset, idx_list, sample_count=sample_count) + for img_idx in idx_list: + assert len(sample_dict[img_idx]['rec']) == sample_count + rec_list = sample_dict[img_idx]['rec'] + output[img_idx] = {'tar': sample_dict[img_idx]['tar'], 'samples': rec_list, 'pairwise_metric': {}} + + for idx1 in range(sample_count): + output[img_idx]['pairwise_metric'][idx1] = {} + # NOTE: we need to iterate starting from 0 and not from idx1 + 1 since not every metric is symmetric. + # PSNR is definitely not. + for idx2 in range(sample_count): + + if idx1 == idx2: + continue + output[img_idx]['pairwise_metric'][idx1][idx2] = compute_regionwise_metric_pairwise_one_pair( + rec_list[idx1], + rec_list[idx2], + metric_types, + regionsize) + return output + + +def upscale_regionwise_metric(metric_dict: dict, regionsize: int): + """ + This expands the regionwise metric to take the same shape as the input image. This ensures that one could simply + use the heatmap. + """ + output_dict = {} + for img_idx in metric_dict.keys(): + output_dict[img_idx] = {} + for mtype in metric_dict[img_idx].keys(): + metric = metric_dict[img_idx][mtype] + repeat = np.array([1] * len(metric.shape)) + # The last 2 dimensions are the spatial dimensions. expand it to fit regionsize times the + # current dimensions. + repeat[-2:] = regionsize + metric = np.kron(metric, np.ones(tuple(repeat))) + output_dict[img_idx][mtype] = metric + return output_dict + + +def aggregate_metric(metric_dict): + """ + Take the average metric over all pairs. + Args: + metric_dict: nested dictionary with the following structure. + img_idx => pairwise_metric => idx1 => idx2 => metric_type + Returns: + aggregated_dict with following structure :img_idx => metric_type + """ + output_dict = {} + for img_idx in metric_dict.keys(): + output_dict[img_idx] = {} + pair_count = 0 + metric_types = [] + for idx1 in metric_dict[img_idx]['pairwise_metric'].keys(): + for idx2 in metric_dict[img_idx]['pairwise_metric'][idx1].keys(): + pair_count += 1 + for metric_type in metric_dict[img_idx]['pairwise_metric'][idx1][idx2]: + if metric_type not in output_dict[img_idx]: + output_dict[img_idx][metric_type] = 0 + metric_types.append(metric_type) + else: + assert metric_type in metric_types + + output_dict[img_idx][metric_type] += metric_dict[img_idx]['pairwise_metric'][idx1][idx2][ + metric_type] + for metric_type in metric_types: + output_dict[img_idx][metric_type] = output_dict[img_idx][metric_type] / pair_count + return output_dict + + +def normalize_metric_single_target(metric_dict: Dict[str, dict], normalize_type: str, target: np.ndarray) -> Dict[ + str, np.ndarray]: + """ + Args: + metric_dict: dictionary with the following structure + metric_type => metric + + """ + assert normalize_type in ['pixelwise_norm'] + normalized_metric = {} + if normalize_type == 'pixelwise_norm': + for metric_type in metric_dict: + metric_mat = metric_dict[metric_type] + normalized_metric[metric_type] = metric_mat / target + return normalized_metric + + +def normalize_metric(metric_dict: Dict[int, dict], normalize_type: str, target_dict: Dict[int, np.ndarray]) -> Dict[ + int, dict]: + """ + Args: + metric_dict: nested dictionary with following structure. + 'img_idx' => 'metric_type' => metric_value + normalize_type: str + target_dict: dictionary with following structure. + 'img_idx' => target image. + """ + normalized_metric_dict = {} + for img_idx in metric_dict.keys(): + normalized_metric_dict[img_idx] = normalize_metric_single_target(metric_dict[img_idx], normalize_type, + target_dict[img_idx]) + return normalized_metric_dict + + +def get_regionwise_metric(model, dset, idx_list: List[int], metric_types, regionsize: int = 64, + sample_count: int = 5, normalize_type='pixelwise_norm'): + """ + Here, we intend to get regionwise metric. One applies aggregation, upscaling and optionally normalization on top + of it. + """ + metric = compute_regionwise_metric_pairwise(model, dset, idx_list, metric_types, regionsize=regionsize, + sample_count=sample_count) + agg_metric = aggregate_metric(metric) + target_dict = {img_idx: metric[img_idx]['tar'] for img_idx in metric.keys()} + upscale_metric = upscale_regionwise_metric(agg_metric, regionsize) + + if normalize_type is not None: + upscale_metric = normalize_metric(upscale_metric, + normalize_type, + target_dict) + + target = {img_id: metric[img_id]['tar'] for img_id in metric.keys()} + return upscale_metric, target diff --git a/denoisplit/analysis/results_handler.py b/denoisplit/analysis/results_handler.py new file mode 100644 index 0000000..44a7711 --- /dev/null +++ b/denoisplit/analysis/results_handler.py @@ -0,0 +1,94 @@ +import json +import os +import pickle + +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.core.tiff_reader import save_tiff + + +class PaperResultsHandler: + + def __init__( + self, + output_dir, + eval_datasplit_type, + patch_size, + grid_size, + mmse_count, + skip_last_pixels, + predict_kth_frame=None, + ): + self._dtype = eval_datasplit_type + self._outdir = output_dir + self._patchN = patch_size + self._gridN = grid_size + self._mmseN = mmse_count + self._skiplN = skip_last_pixels + self._predict_kth_frame = predict_kth_frame + + def dirpath(self): + return os.path.join( + self._outdir, + f'{DataSplitType.name(self._dtype)}_P{self._patchN}_G{self._gridN}_M{self._mmseN}_Sk{self._skiplN}') + + @staticmethod + def get_fname(ckpt_fpath): + assert ckpt_fpath[-1] != '/' + basename = '_'.join(ckpt_fpath.split("/")[4:]) + '.pkl' + basename = 'stats_' + basename + return basename + + @staticmethod + def get_pred_fname(ckpt_fpath): + assert ckpt_fpath[-1] != '/' + basename = '_'.join(ckpt_fpath.split("/")[4:]) + '.tif' + basename = 'pred_' + basename + return basename + + def get_output_dir(self): + outdir = self.dirpath() + if self._predict_kth_frame is not None: + outdir = os.path.join(outdir, f'kth_{self._predict_kth_frame}') + + if not os.path.isdir(outdir): + os.mkdir(outdir) + return outdir + + def get_output_fpath(self, ckpt_fpath): + outdir = self.get_output_dir() + output_fpath = os.path.join(outdir, self.get_fname(ckpt_fpath)) + return output_fpath + + def save(self, ckpt_fpath, ckpt_stats): + output_fpath = self.get_output_fpath(ckpt_fpath) + with open(output_fpath, 'wb') as f: + pickle.dump(ckpt_stats, f) + print(f'[{self.__class__.__name__}] Saved to {output_fpath}') + return output_fpath + + def dump_predictions(self, ckpt_fpath, predictions, hparam_dict): + fname = self.get_pred_fname(ckpt_fpath) + fpath = os.path.join(self.get_output_dir(), fname) + save_tiff(fpath, predictions) + print(f'Written {predictions.shape} to {fpath}') + hparam_fpath = fpath.replace('.tif', '.json') + with open(hparam_fpath, 'w') as f: + json.dump(hparam_dict, f) + + def load(self, output_fpath): + assert os.path.exists(output_fpath) + with open(output_fpath, 'rb') as f: + return pickle.load(f) + + +if __name__ == '__main__': + output_dir = '.' + patch_size = 23 + grid_size = 16 + mmse_count = 1 + skip_last_pixels = 0 + + saver = PaperResultsHandler(output_dir, 1, patch_size, grid_size, mmse_count, skip_last_pixels) + fpath = saver.save('/home/ashesh.ashesh/training/disentangle/2210/D7-M3-S0-L0/82', {'a': [1, 2], 'b': [3]}) + + print(saver.load(fpath)) diff --git a/denoisplit/analysis/stitch_prediction.py b/denoisplit/analysis/stitch_prediction.py new file mode 100644 index 0000000..c394b2c --- /dev/null +++ b/denoisplit/analysis/stitch_prediction.py @@ -0,0 +1,266 @@ +import numpy as np + +from denoisplit.data_loader.multifile_dset import MultiFileDset + + +class PatchLocation: + """ + Encapsulates t_idx and spatial location. + """ + + def __init__(self, h_idx_range, w_idx_range, t_idx): + self.t = t_idx + self.h_start, self.h_end = h_idx_range + self.w_start, self.w_end = w_idx_range + + def __str__(self): + msg = f'T:{self.t} [{self.h_start}-{self.h_end}) [{self.w_start}-{self.w_end}) ' + return msg + + +def _get_location(extra_padding, hwt, pred_h, pred_w): + h_start, w_start, t_idx = hwt + h_start -= extra_padding + h_end = h_start + pred_h + w_start -= extra_padding + w_end = w_start + pred_w + return PatchLocation((h_start, h_end), (w_start, w_end), t_idx) + + +def get_location_from_idx(dset, dset_input_idx, pred_h, pred_w): + """ + For a given idx of the dataset, it returns where exactly in the dataset, does this prediction lies. + Note that this prediction also has padded pixels and so a subset of it will be used in the final prediction. + Which time frame, which spatial location (h_start, h_end, w_start,w_end) + Args: + dset: + dset_input_idx: + pred_h: + pred_w: + + Returns: + """ + extra_padding = dset.per_side_overlap_pixelcount() + htw = dset.get_idx_manager().hwt_from_idx(dset_input_idx, grid_size=dset.get_grid_size()) + return _get_location(extra_padding, htw, pred_h, pred_w) + + +def set_skip_boundary_pixels_mask(mask, loc, skip_count): + if skip_count == 0: + return mask + assert skip_count > 0 + assert loc.h_end - skip_count >= 0 + assert loc.w_end - skip_count >= 0 + mask[loc.t, :, loc.h_start:loc.h_start + skip_count, loc.w_start:loc.w_end] = False + mask[loc.t, :, loc.h_end - skip_count:loc.h_end, loc.w_start:loc.w_end] = False + mask[loc.t, :, loc.h_start:loc.h_end, loc.w_start:loc.w_start + skip_count] = False + mask[loc.t, :, loc.h_start:loc.h_end, loc.w_end - skip_count:loc.w_end] = False + + +def set_skip_central_pixels_mask(mask, loc, skip_count): + if skip_count == 0: + return mask + assert skip_count > 0 + h_mid = (loc.h_start + loc.h_end) // 2 + w_mid = (loc.w_start + loc.w_end) // 2 + l_skip = skip_count // 2 + r_skip = skip_count - l_skip + mask[loc.t, :, h_mid - l_skip:h_mid + r_skip, w_mid - l_skip:w_mid + r_skip] = False + + +def stitched_prediction_mask(dset, padded_patch_shape, skip_boundary_pixel_count, skip_central_pixel_count): + """ + Returns the boolean matrix. It will be 0 if it lies either in skipped boundaries or skipped central pixels + Args: + dset: + padded_patch_shape: + skip_boundary_pixel_count: + skip_central_pixel_count: + + Returns: + """ + N, H, W, C = dset.get_data_shape() + mask = np.full((N, C, H, W), True) + hN, wN = padded_patch_shape + for dset_input_idx in range(len(dset)): + loc = get_location_from_idx(dset, dset_input_idx, hN, wN) + set_skip_boundary_pixels_mask(mask, loc, skip_boundary_pixel_count) + set_skip_central_pixels_mask(mask, loc, skip_central_pixel_count) + + old_img_sz = dset.get_img_sz() + dset.set_img_sz(dset._img_sz_for_hw) + mask = stitch_predictions(mask, dset) + dset.set_img_sz(old_img_sz) + return mask + + +def _get_smoothing_mask(cropped_pred_shape, smoothening_pixelcount, loc, frame_size): + """ + It returns a mask. If the mask is multipled with all predictions and predictions are then added to + the overall frame at their corect location, it would simulate following scenario: + take all patches belonging to a row. join these patches by smoothening their vertical boundaries. + Then take all these combined and smoothened rows. join them vertically by smoothening the horizontal boundaries. + For this to happen, one needs *= operation as used here. + """ + mask = np.ones(cropped_pred_shape) + on_leftb = loc.w_start == 0 + on_rightb = loc.w_end >= frame_size + on_topb = loc.h_start == 0 + on_bottomb = loc.h_end >= frame_size + + if smoothening_pixelcount == 0: + return mask + + assert 2 * smoothening_pixelcount <= min(cropped_pred_shape) + if (not on_leftb) and (not on_rightb) and (not on_topb) and (not on_bottomb): + assert 4 * smoothening_pixelcount <= min(cropped_pred_shape) + + w_levels = np.arange(1, 0, step=-1 * 1 / (2 * smoothening_pixelcount + 1))[1:].reshape((1, -1)) + if not on_rightb: + mask[:, -2 * smoothening_pixelcount:] *= w_levels + if not on_leftb: + mask[:, :2 * smoothening_pixelcount] *= w_levels[:, ::-1] + + if not on_bottomb: + mask[-2 * smoothening_pixelcount:, :] *= w_levels.T + + if not on_topb: + mask[:2 * smoothening_pixelcount, :] *= w_levels[:, ::-1].T + + return mask + + +def remove_pad(pred, loc, extra_padding, smoothening_pixelcount, frame_shape): + assert smoothening_pixelcount == 0 + if extra_padding - smoothening_pixelcount > 0: + h_s = extra_padding - smoothening_pixelcount + + # rows + h_N = frame_shape[0] + if loc.h_end > h_N: + assert loc.h_end - extra_padding + smoothening_pixelcount <= h_N + h_e = extra_padding - smoothening_pixelcount + + w_s = extra_padding - smoothening_pixelcount + + # columns + w_N = frame_shape[1] + if loc.w_end > w_N: + assert loc.w_end - extra_padding + smoothening_pixelcount <= w_N + + w_e = extra_padding - smoothening_pixelcount + + return pred[h_s:-h_e, w_s:-w_e] + + return pred + + +def update_loc_for_final_insertion(loc, extra_padding, smoothening_pixelcount): + extra_padding = extra_padding - smoothening_pixelcount + loc.h_start += extra_padding + loc.w_start += extra_padding + loc.h_end -= extra_padding + loc.w_end -= extra_padding + return loc + + +def stitch_predictions(predictions, dset, smoothening_pixelcount=0): + """ + Args: + smoothening_pixelcount: number of pixels which can be interpolated + """ + assert smoothening_pixelcount >= 0 and isinstance(smoothening_pixelcount, int) + if isinstance(dset, MultiFileDset): + cum_count = 0 + output = [] + for dset in dset.dsets: + cnt = dset.idx_manager.grid_count() + output.append(stitch_predictions(predictions[cum_count:cum_count + cnt], dset, smoothening_pixelcount)) + cum_count += cnt + return output + + else: + extra_padding = dset.per_side_overlap_pixelcount() + # if there are more channels, use all of them. + shape = list(dset.get_data_shape()) + shape[-1] = max(shape[-1], predictions.shape[1]) + + output = np.zeros(shape, dtype=predictions.dtype) + frame_shape = dset.get_data_shape()[1:3] + for dset_input_idx in range(predictions.shape[0]): + loc = get_location_from_idx(dset, dset_input_idx, predictions.shape[-2], predictions.shape[-1]) + + mask = None + cropped_pred_list = [] + for ch_idx in range(predictions.shape[1]): + # class i + cropped_pred_i = remove_pad(predictions[dset_input_idx, ch_idx], loc, extra_padding, + smoothening_pixelcount, frame_shape) + + if mask is None: + # NOTE: don't need to compute it for every patch. + assert smoothening_pixelcount == 0, "For smoothing,enable the get_smoothing_mask. It is disabled since I don't use it and it needs modification to work with non-square images" + mask = 1 + # mask = _get_smoothing_mask(cropped_pred_i.shape, smoothening_pixelcount, loc, frame_size) + + cropped_pred_list.append(cropped_pred_i) + + loc = update_loc_for_final_insertion(loc, extra_padding, smoothening_pixelcount) + for ch_idx in range(predictions.shape[1]): + output[loc.t, loc.h_start:loc.h_end, loc.w_start:loc.w_end, ch_idx] += cropped_pred_list[ch_idx] * mask + + return output + + +if __name__ == '__main__': + from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager + grid_size = 32 + patch_size = 64 + data_shape = (1, 1550, 1920, 2) + N = data_shape[0] * (data_shape[1] // grid_size) * (data_shape[2] // grid_size) + predictions = np.zeros((N, 2, patch_size, patch_size)) + # data_shape, grid_size, patch_size, grid_alignement + idx_manager = GridIndexManager(data_shape, grid_size, patch_size, GridAlignement.Center) + + class TestDataSet: + + def __init__(self) -> None: + self.idx_manager = idx_manager + + def per_side_overlap_pixelcount(self): + return (patch_size - grid_size) // 2 + + def get_data_shape(self): + return data_shape + + def get_grid_size(self): + return grid_size + + dset = TestDataSet() + # import pdb;pdb.set_trace() + stitch_predictions = stitch_predictions(predictions, dset, smoothening_pixelcount=0) + # loc = PatchLocation((0, 32), (0, 32), 5) + # extra_padding = 16 + # smoothening_pixelcount = 4 + # frame_size = 2720 + # out = remove_pad(np.ones((64, 64)), loc, extra_padding, smoothening_pixelcount, frame_size) + # mask = _get_smoothing_mask(out.shape, smoothening_pixelcount, loc, frame_size) + # print(loc) + # loc = update_loc_for_final_insertion(loc, extra_padding, smoothening_pixelcount, frame_size) + # print(loc, mask.shape, out.shape) + + # import matplotlib.pyplot as plt + # plt.imshow(mask, cmap='hot') + # plt.show() + # extra_padding = 0 + # hwt1 = (0, 0, 0) + # pred_h = 4 + # pred_w = 4 + # hwt2 = (pred_h, pred_w, 2) + # loc1 = _get_location(extra_padding, hwt1, pred_h, pred_w) + # loc2 = _get_location(extra_padding, hwt2, pred_h, pred_w) + # mask = np.full((10, 8, 8), 1) + # set_skip_boundary_pixels_mask(mask, loc1, 1) + # set_skip_boundary_pixels_mask(mask, loc2, 1) + # print(mask[hwt1[-1]]) + # print(mask[hwt2[-1]]) diff --git a/denoisplit/config_utils.py b/denoisplit/config_utils.py new file mode 100644 index 0000000..643b5e2 --- /dev/null +++ b/denoisplit/config_utils.py @@ -0,0 +1,50 @@ +""" +Utility files for configs + 1. Take the diff between two configs. +""" +import os +import pickle + +import ml_collections +from denoisplit.core.loss_type import LossType + + +def load_config(config_fpath): + if os.path.isdir(config_fpath): + config_fpath = os.path.join(config_fpath, 'config.pkl') + else: + assert config_fpath[-4:] == '.pkl', f'{config_fpath} is not a pickle file. Aborting' + with open(config_fpath, 'rb') as f: + config = pickle.load(f) + return get_updated_config(config) + + +def get_updated_config(config): + """ + It makes sure that older versions of the config also run with current settings. + """ + frozen_dict = isinstance(config, ml_collections.FrozenConfigDict) + if frozen_dict: + config = ml_collections.ConfigDict(config) + + with config.unlocked(): + pass + + if frozen_dict: + return ml_collections.FrozenConfigDict(config) + else: + return config + + +def get_configdir_from_saved_predictionfile(pref_file_name, train_dir='/home/ashesh.ashesh/training/disentangle'): + """ + Example input: 'pred_disentangle_2402_D16-M23-S0-L0_14.tif' + Returns: '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/14' + """ + fname = pref_file_name + assert fname[-4:] == '.tif' + fname = fname[:-4] + *_, ym, modelcfg, modelid = fname.split('_') + subdir = '/'.join([ym, modelcfg, modelid]) + datacfg_dir = os.path.join(train_dir, subdir) + return datacfg_dir diff --git a/denoisplit/configs/__pycache__/default_config.cpython-39.pyc b/denoisplit/configs/__pycache__/default_config.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..370a73931b1fe181c73d2efbdb7316d9696c4f1b GIT binary patch literal 1022 zcmY*Y&2AGh5cY2VHfhpAT3UX3s3@0Q5(#lcfYeg8qAF5b2`LxLwVhqJ-u23M0#v52>3j{+f zl4$I8ETcRg#}Q&RR{x5|H5Q$qLE{E?p`$_MmQF}sO0G{YOHRG>c0>St(H&UEfw1UX z^c{Vk>uZE#TRX2`qw^Rysu=j1ECNpxw{AUvlLg#nv5%j(ap%^Hm+nxP)gao%J?86n z@iJ=!y~3J7-ju7RZK*>E2wpKMl8{uLbtrjCuAz^oNL!L73tUl>#mV2#^ty-H5|_%P->yHYw?1D z9{}SOSfZ+!J!kk#5aa4n8RHVGi6}&oy3QG~G{Z(*akrLg!Z4Mh#D&s16oppYhW83y z*eXI~so+OqVI9cU6WVJpjeZhq94LI^3$&|4L$+=7Tr!pXT zoK5H$==_27Q=swh{wPy99}$yrlMO31^4yFVFO)bbrLYw=0an=tT!DQ!-B%lym#&|3 zi~n~w-~{sm1d5Wl6LnxEQ5Pm4kK+XFFhit5&8V9C8RQM>x&_K@hTDWI45`w5xcIfh eg9zJ0PYYt(=O!=VF-#?Y<$pf|KRSX-)cygWh$rm; literal 0 HcmV?d00001 diff --git a/denoisplit/configs/__pycache__/pavia3_config.cpython-39.pyc b/denoisplit/configs/__pycache__/pavia3_config.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f2bd747c6597a751abbd5c34c1a2ba416e63245f GIT binary patch literal 3191 zcmZuzOLJUD6~1>~nx`b|;a6-2^A^N2lI#Qqg5}sw6oMo~FJbqc)4XmD zTPJz48hEVnTOZsSPRI|}$z6D6$9ss}jxV!WH@?E=-1se6xAJd0{q{t^J<)GZ^xGuU zZ<9>F?euZ-uuZ;$i1OsSY##Jgb_w)*))u+%=!RQ;z!o5R%}E|Q`pBM39y|IvTLk}x z)7)fB;NNue?>o)6*fJzPaFQ){8T>Z8a#}bkfZK8Ohi+{bacr^te(s~3!rE|?c_YvA zZ+XA)oyL!ltG7>!?CMF8?6GU0PuO+Pci0P{@3I@9KZX}Y@}8qVL9U9VP4GWE z@qqGMJL3lc*Vv-$jQ|ACKR3qz!xMb4^!v@fAOCve$=HX~%t+oByr+#fw)Zo5^ACUi z_}_m!zQ0l!e~7u9e})7f|HeLl+8E~{H+e2brYyM%*@y~L?$RE!|M3!5$DiUjQ$C=A z2;3x-52EP!gVrF4c#En5SA%9Yw6vsQ9L7N_PC~^=WbayQ{od-`*4o{6Yjb;h$I9Im zBoD)6@9jH;yh84gMo1dc(w!vcWG9i)D(NPPRxqD7vnf{V|)wlg&!gQaoIXru;ecwD?gVuWv0N;223@KXuydIkGXW=HqLLhZ4;(q zwTMQyF!gv8k=}sDF&9c&qo%aYSvZPJEwx>M2-^naj9n=|q=Lph&PPy%=J(O zl5*MOu?__{OOret+FHIpqM3AdgqbZ&G$KmFkPC~@Q9xv(spe);(wHTYGkumyb0tE5 z4xRTv(IH$zvmV9T)KkhBFyqi-8fP=0ZN$w@O{MMcil(dqxdm9;`DsNtJog>BLC)y((ox@4_GEqcGXL95+iiD%~6NU?K!0rl+{7W z?l*ISQyCMT;5Zoqx0Nsoh#FAbr`ZdC-2EyBs3J3$;{>P+b%>tAlEc{I!eyAoR2%`M zknamqvDt!A?5H15NgP5W`qa!?S=iI?GQfhll#LcyT)J?~?au=497SCqv^Oxfrc@-? z=v_pmfQEI-6(&mHBLZ5O+~}#cW-rirkINFXJT2)B)<_@52Ie{O`sayV25r-@nSmD< z89qS4ZHFkI^;VM;(ku%}RByo92+aUR)*&!t(M6vUo}xU;R2`UH(=#>O)eaL0kf_cj z+sGwPIn|R!(^<^!@H0Z2adFY18k#HUpEaxnlw2IaPYbc^^p%n+W#3=&CQvWime@}t zQ|!mo0toyko|G8=v-x?i4~x(i<4EIPDngyH%CVVY)k@tb+T=U0nI4&{Z4cRM1%}lh zK|H_Ye&u4xFZ<=3o8`-evR}&hTq&PvWGfTx++=mK+s?{S&1_9+Pi$Vu z9aorW+$cO}|9q#^@OfutwsYGB?;>taB5pqWX`8*)u05kCdGq`Qmc8FTvwq$Pv-WuX z`TZANDeG7_o>!QDwPbIfm!?$Q@gkvUFwIGYBt4vxy7#4fow`^Z2BwHY{HFXWya1l> Q+s_$Q2dVpKzxn+C0hxjfuK)l5 literal 0 HcmV?d00001 diff --git a/denoisplit/configs/allencell_config.py b/denoisplit/configs/allencell_config.py new file mode 100644 index 0000000..e9670c7 --- /dev/null +++ b/denoisplit/configs/allencell_config.py @@ -0,0 +1,99 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.AllenCellMito + data.channel_1 = 1 + data.channel_2 = 2 + # + data.ch1_frame_std_quantile = 0.45 + data.ch2_frame_std_quantile = 0.45 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/biosr_config.py b/denoisplit/configs/biosr_config.py new file mode 100644 index 0000000..59cf9c6 --- /dev/null +++ b/denoisplit/configs/biosr_config.py @@ -0,0 +1,129 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.BioSR_MRC + # data.channel_1 = 0 + # data.channel_2 = 1 + data.ch1_fname = 'ER/GT_all.mrc' + data.ch2_fname = 'Microtubules/GT_all.mrc' + data.num_channels = 2 + + data.poisson_noise_factor = 1000 + + data.enable_gaussian_noise = True + data.trainig_datausage_fraction = 1.0 + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + config.data.synthetic_gaussian_scale = 6675 + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = '' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.reconstruction_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 1.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + + model.enable_noise_model = False + model.noise_model_type = 'gmm' + fname = '/home/ashesh.ashesh/training/noise_model/2403/139/GMMNoiseModel_BioSR-__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch1_fpath = fname + model.noise_model_ch2_fpath = fname + model.noise_model_learnable = False + assert model.enable_noise_model == False or model.predict_logvar is None + + # model.noise_model_ch1_fpath = fname_format.format('2307/58', 'actin') + # model.noise_model_ch2_fpath = fname_format.format('2307/59', 'mito') + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + # training.precision = 16 + return config diff --git a/denoisplit/configs/biosr_new_config.py b/denoisplit/configs/biosr_new_config.py new file mode 100644 index 0000000..e8cba98 --- /dev/null +++ b/denoisplit/configs/biosr_new_config.py @@ -0,0 +1,128 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.BioSR_MRC + # data.channel_1 = 0 + # data.channel_2 = 1 + data.ch1_fname = 'ER/GT_all.mrc' + data.ch2_fname = 'Microtubules/GT_all.mrc' + data.num_channels = 2 + + data.poisson_noise_factor = 1000 + + data.enable_gaussian_noise = True + data.trainig_datausage_fraction = 1.0 + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + config.data.synthetic_gaussian_scale = 8900 + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = '' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.reconstruction_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 1.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + + model.enable_noise_model = True + model.noise_model_type = 'gmm' + model.noise_model_ch1_fpath = '/home/ashesh.ashesh/training/noise_model/2402/439/GMMNoiseModel_ER-GT_all__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch2_fpath = '/home/ashesh.ashesh/training/noise_model/2402/442/GMMNoiseModel_Microtubules-GT_all__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_learnable = False + assert model.enable_noise_model == False or model.predict_logvar is None + + # model.noise_model_ch1_fpath = fname_format.format('2307/58', 'actin') + # model.noise_model_ch2_fpath = fname_format.format('2307/59', 'mito') + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + return config diff --git a/denoisplit/configs/biosr_reconstructive_config.py b/denoisplit/configs/biosr_reconstructive_config.py new file mode 100644 index 0000000..5f5b5ce --- /dev/null +++ b/denoisplit/configs/biosr_reconstructive_config.py @@ -0,0 +1,136 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.grid_size = 1 + data.data_type = DataType.BioSR_MRC + # data.channel_1 = 0 + # data.channel_2 = 1 + data.ch1_fname = 'Microtubules/GT_all.mrc' + data.ch2_fname = 'ER/GT_all.mrc' + + # amounnt of data (supervised and unsupervised) which you want to use for training. + data.trainig_datausage_fraction = 1 + data.training_validtarget_fraction = None + # when creating a batch, what fraction of inputs should have target. + data.validtarget_random_fraction = None + # data.validtarget_random_fraction_final = 0.9 + # data.validtarget_random_fraction_stepepoch = 0.005 + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + # if multiscale_lowres_count is 3, then there are two additional inputs other than the original input. input channel count is 3 + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = False + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + model.skip_bottomk_buvalues = 3 + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + model.decoder.multiscale_retain_spatial_dims = True + model.decoder.conv2d_bias = True + model.reconstruction_mode = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise', 'ch_invariant_pixelwise] + model.predict_logvar = None + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = True + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + # model.pretrained_weights_path = '/home/ashesh.ashesh/training/disentangle/2311/D16-M3-S0-L0/11/BaselineVAECL_best.ckpt' + + training = config.training + training.lr = 0.001 / 2 + training.lr_scheduler_patience = int(60 / data.trainig_datausage_fraction if 'trainig_datausage_fraction' in + data else 60) + training.max_epochs = int(400 / data.trainig_datausage_fraction if 'trainig_datausage_fraction' in data else 400) + training.batch_size = 32 + training.num_workers = 2 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + + training.earlystop_patience = int(200 / + data.trainig_datausage_fraction if 'trainig_datausage_fraction' in data else 200) + training.precision = 16 + training.check_val_every_n_epoch = int( + 1 / (data.trainig_datausage_fraction)) if 'trainig_datausage_fraction' in data else None + + return config diff --git a/denoisplit/configs/biosr_sparsely_supervised_config.py b/denoisplit/configs/biosr_sparsely_supervised_config.py new file mode 100644 index 0000000..298fb3a --- /dev/null +++ b/denoisplit/configs/biosr_sparsely_supervised_config.py @@ -0,0 +1,160 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.grid_size = 1 + data.data_type = DataType.BioSR_MRC + # note that this is dependant on image_size. + # data.std_background_arr = [500.0, 500.0] + # data.channel_1 = 0 + # data.channel_2 = 1 + data.ch1_fname = 'Microtubules/GT_all.mrc' + data.ch2_fname = 'ER/GT_all.mrc' + + # amounnt of data (supervised and unsupervised) which you want to use for training. + data.trainig_datausage_fraction = 1 + # how much data will use the target. + data.training_validtarget_fraction = 0.01 + # when creating a batch, what fraction of inputs should have target. + data.validtarget_random_fraction = 0.5 + + data.validation_datausage_fraction = 0.08 + data.return_index = True + + # data.validtarget_random_fraction_final = 1 + # data.validtarget_random_fraction_stepepoch = 0.005 + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = True + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = True + data.randomized_channels = False + # if multiscale_lowres_count is 3, then there are two additional inputs other than the original input. input channel count is 3 + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.ElboRestrictedReconstruction + # loss.D_epsilon = 0.1 + # loss.critic_loss_weight = 0.001 + loss.mixed_rec_weight = 100.0 + loss.split_weight = 0.0 + loss.switch_to_nonorthogonal_epoch = 100000 + # loss.mixed_rec_w_step = 0.01 + # loss.exclusion_loss_weight = 0.005 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LadderVAERestrictedReconstruction + # model.classifier_fpath = '/home/ubuntu/ashesh/training/disentangle/texture_classifier.pth' + # model.classifier_loss_weight = 0.01 + + model.z_dims = [128, 128, 128, 128] + model.tethered_to_input = False + # model.tethered_learnable_scalar = True + # model.D_num_blocks_per_layer = 1 + # model.D_num_hierarchy_levels = 1 + # model.D_input_downsampling_count = 2 + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + model.decoder.multiscale_retain_spatial_dims = True + model.decoder.conv2d_bias = True + model.reconstruction_mode = False + model.skip_bottomk_buvalues = 0 + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise', 'ch_invariant_pixelwise] + model.predict_logvar = None #'ch_invariant_pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = True + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + # model.pretrained_weights_path = '/home/ashesh.ashesh/training/disentangle/2311/D16-M3-S0-L0/11/BaselineVAECL_best.ckpt' + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = int(30 / data.trainig_datausage_fraction if 'trainig_datausage_fraction' in + data else 30) + training.max_epochs = int(200 / data.trainig_datausage_fraction if 'trainig_datausage_fraction' in data else 200) + training.batch_size = 16 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.dump_epoch_interval = 10 + training.dump_kth_frame_prediction = 0 + + training.earlystop_patience = int(100 / + data.trainig_datausage_fraction if 'trainig_datausage_fraction' in data else 100) + training.precision = 32 + training.check_val_every_n_epoch = int( + 1 / (data.trainig_datausage_fraction)) if 'trainig_datausage_fraction' in data else None + + return config diff --git a/denoisplit/configs/biosr_supervised_config.py b/denoisplit/configs/biosr_supervised_config.py new file mode 100644 index 0000000..dd85fbf --- /dev/null +++ b/denoisplit/configs/biosr_supervised_config.py @@ -0,0 +1,146 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.grid_size = 1 + data.data_type = DataType.BioSR_MRC + # data.channel_1 = 0 + # data.channel_2 = 1 + data.ch1_fname = 'Microtubules/GT_all.mrc' + data.ch2_fname = 'ER/GT_all.mrc' + + # amounnt of data (supervised and unsupervised) which you want to use for training. + data.trainig_datausage_fraction = 1 + data.training_validtarget_fraction = 0.01 + data.validation_datausage_fraction = 0.08 + + # when creating a batch, what fraction of inputs should have target. + data.validtarget_random_fraction = 1.0 + # data.validtarget_random_fraction_final = 0.9 + # data.validtarget_random_fraction_stepepoch = 0.005 + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = True + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = True + data.randomized_channels = False + # if multiscale_lowres_count is 3, then there are two additional inputs other than the original input. input channel count is 3 + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + # data.ch1_min_alpha = 0.3 + # data.ch1_max_alpha = 0.7 + data.variable_intensity_aug = False + # data.variable_intensity_aug_scale_factor = 2 + # data.variable_intensity_aug_sigma = 0.5 + # data.variable_intensity_aug_quantile = 0.5 + # data.variable_intensity_bright_spot_count = 1 + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.mixed_rec_weight = 1 + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + model.tethered_to_input = False + # model.tethered_learnable_scalar = True + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + model.decoder.multiscale_retain_spatial_dims = True + model.decoder.conv2d_bias = True + model.reconstruction_mode = False + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise', 'ch_invariant_pixelwise] + model.predict_logvar = None #'ch_invariant_pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = True + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + # model.pretrained_weights_path = '/home/ashesh.ashesh/training/disentangle/2311/D16-M3-S0-L0/58/BaselineVAECL_best.ckpt' + # model.pretrained_weights_skip_likelihood = True + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = int(30 / data.trainig_datausage_fraction if 'trainig_datausage_fraction' in + data else 30) + training.max_epochs = int(200 / data.trainig_datausage_fraction if 'trainig_datausage_fraction' in data else 200) + training.batch_size = 16 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + + training.earlystop_patience = int(100 / + data.trainig_datausage_fraction if 'trainig_datausage_fraction' in data else 100) + training.precision = 32 + training.check_val_every_n_epoch = int( + 1 / (data.trainig_datausage_fraction)) if 'trainig_datausage_fraction' in data else None + + return config diff --git a/denoisplit/configs/biosr_usplit_config.py b/denoisplit/configs/biosr_usplit_config.py new file mode 100644 index 0000000..41f615e --- /dev/null +++ b/denoisplit/configs/biosr_usplit_config.py @@ -0,0 +1,127 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.BioSR_MRC + # data.channel_1 = 0 + # data.channel_2 = 1 + data.ch1_fname = 'CCPs/GT_all.mrc' + data.ch2_fname = 'F-actin/GT_all_a.mrc' + data.num_channels = 2 + + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = True + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + config.data.synthetic_gaussian_scale = 4575 + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 3 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = 'usplit' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.reconstruction_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + + model.enable_noise_model = False + model.noise_model_type = 'gmm' + fname = '/home/ashesh.ashesh/training/noise_model/2402/393/GMMNoiseModel_BioSR-__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch1_fpath = fname + model.noise_model_ch2_fpath = fname + model.noise_model_learnable = False + assert model.enable_noise_model == False or model.predict_logvar is None + + # model.noise_model_ch1_fpath = fname_format.format('2307/58', 'actin') + # model.noise_model_ch2_fpath = fname_format.format('2307/59', 'mito') + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + return config diff --git a/denoisplit/configs/bravenet_config.py b/denoisplit/configs/bravenet_config.py new file mode 100644 index 0000000..9b40332 --- /dev/null +++ b/denoisplit/configs/bravenet_config.py @@ -0,0 +1,62 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 2 + data.channel_2 = 3 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 2 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.MSE + + model = config.model + model.model_type = ModelType.BraveNet + + model.num_kernels = [32, 64, 128, 256] + model.kernel_size = 3 + model.padding = 1 + model.activation = 'relu' + model.final_activation = None + model.dropout = 0.1 + model.batch_normalization = True + model.strides = 1 + model.monitor = 'val_psnr' + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/customdata3curve_lvae_config.py b/denoisplit/configs/customdata3curve_lvae_config.py new file mode 100644 index 0000000..dccdea7 --- /dev/null +++ b/denoisplit/configs/customdata3curve_lvae_config.py @@ -0,0 +1,105 @@ +import math + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.frame_size = 128 + data.data_type = DataType.CustomSinosoidThreeCurve + data.total_size = 1000 + data.curve_amplitude = 8.0 + data.num_curves = 5 + data.max_rotation = 0.0 + data.curve_thickness = 21 + data.max_vshift_factor = 0.9 + data.max_hshift_factor = 0.3 + data.frequency_range_list = [(0.05, 0.07), (0.12, 0.14), (0.3, 0.32), (0.6, 0.62)] + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + # If this is set to true, then one mean and stdev is used for both channels. If False, two different + # meean and stdev are used. If None, 0 mean and 1 std is used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'constant' + data.padding_value = 0 + data.encourage_non_overlap_single_channel = True + data.vertical_min_spacing = data.curve_amplitude * 2 + # 0.5 would mean that 50% of the points would be covered with the connecting w. + data.connecting_w_len = 0.2 + data.curve_initial_phase = 0.0 + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the three values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 90 + training.max_epochs = 2400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 300 + training.precision = 16 + + return config diff --git a/denoisplit/configs/customdata_lvae_config.py b/denoisplit/configs/customdata_lvae_config.py new file mode 100644 index 0000000..26db6a0 --- /dev/null +++ b/denoisplit/configs/customdata_lvae_config.py @@ -0,0 +1,102 @@ +import math + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.frame_size = 256 + data.data_type = DataType.CustomSinosoid + data.total_size = 1000 + data.curve_amplitude = 8.0 + data.num_curves = 5 + data.max_rotation = math.pi / 8 + data.curve_thickness = 21 + data.max_vshift_factor = 0.9 + data.max_hshift_factor = 0.3 + data.frequency_range_list = [(0.03, 0.07), (0.12, 0.20), (0.3, 0.45), (0.55, 0.7)] + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + # If this is set to true, then one mean and stdev is used for both channels. If False, two different + # meean and stdev are used. If None, 0 mean and 1 std is used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'constant' + data.padding_value = 0 + data.encourage_non_overlap_single_channel = True + data.vertical_min_spacing = data.curve_amplitude * 2 + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #False + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the three values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 180 + training.max_epochs = 4800 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 1200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/dao3ch_config.py b/denoisplit/configs/dao3ch_config.py new file mode 100644 index 0000000..73bc46a --- /dev/null +++ b/denoisplit/configs/dao3ch_config.py @@ -0,0 +1,128 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.multifile_raw_dloader import SubDsetType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.Dao3Channel + data.subdset_type = SubDsetType.MultiChannel + data.num_channels = 3 + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 5 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = False + + # This is for intensity augmentation + data.ch1_min_alpha = 0.4 + data.ch1_max_alpha = 0.6 + data.alpha_weighted_target = True + # data.return_alpha = True + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.kl_loss_formulation = 'usplit' + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + + training = config.training + training.lr = 0.001 / 2 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 16 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/deepencoder_lvae_config.py b/denoisplit/configs/deepencoder_lvae_config.py new file mode 100644 index 0000000..cf3533e --- /dev/null +++ b/denoisplit/configs/deepencoder_lvae_config.py @@ -0,0 +1,124 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 2 + data.channel_2 = 3 + + data.ch1_min_alpha = None + data.ch1_max_alpha = None + data.return_alpha = True + data.return_individual_channels = True + + data.sampler_type = SamplerType.DefaultSampler + + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + # data.input_is_sum = True + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = True + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LVaeDeepEncoderIntensityAug + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #True + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'leakyrelu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = True + + training = config.training + training.lr = 0.001 / 2 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 128 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/default_config.py b/denoisplit/configs/default_config.py new file mode 100644 index 0000000..cf4e7d8 --- /dev/null +++ b/denoisplit/configs/default_config.py @@ -0,0 +1,38 @@ +import ml_collections +from denoisplit.core.sampler_type import SamplerType + + +def get_default_config(): + config = ml_collections.ConfigDict() + + config.data = ml_collections.ConfigDict() + config.data.sampler_type = SamplerType.DefaultSampler + + config.model = ml_collections.ConfigDict() + config.model.use_vampprior = False + config.model.encoder = ml_collections.ConfigDict() + config.model.decoder = ml_collections.ConfigDict() + config.model.decoder.conv2d_bias = True + + config.loss = ml_collections.ConfigDict() + + config.training = ml_collections.ConfigDict() + config.training.batch_size = 32 + + config.training.grad_clip_norm_value = 0.5 # Taken from https://github.com/openai/vdvae/blob/main/hps.py#L38 + config.training.gradient_clip_algorithm = 'value' + config.training.earlystop_patience = 100 + config.training.precision = 32 + config.training.pre_trained_ckpt_fpath = '' + + config.git = ml_collections.ConfigDict() + config.git.changedFiles = [] + config.git.branch = '' + config.git.untracked_files = [] + config.git.latest_commit = '' + + config.workdir = '/FILL_IN_THE_WORKDIR' + config.datadir = '' + config.hostname = '' + config.exptname = '' + return config diff --git a/denoisplit/configs/denoiser_splitting_config.py b/denoisplit/configs/denoiser_splitting_config.py new file mode 100644 index 0000000..1849b71 --- /dev/null +++ b/denoisplit/configs/denoiser_splitting_config.py @@ -0,0 +1,146 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 256 + data.data_type = DataType.SeparateTiffData + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'actin-60x-noise2-highsnr.tif' + data.ch2_fname = 'mito-60x-noise2-highsnr.tif' + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = True + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + data.synthetic_gaussian_scale = 1000 + data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + # This is for intensity augmentation + # data.ch1_min_alpha = 0.4 + # data.ch1_max_alpha = 0.55 + # data.return_alpha = True + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.kl_loss_formulation = 'usplit' + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.DenoiserSplitter + # denoiser splitter specific + model.synchronized_input_target = False # this should not change at all. This is the default behavior. + fpath = '/home/ashesh.ashesh/training/disentangle/{}/D7-M23-S0-L0/{}/BaselineVAECL_best.ckpt' + model.pre_trained_ckpt_fpath_ch1 = fpath.format(2402, 107) + model.pre_trained_ckpt_fpath_ch2 = fpath.format(2402, 109) + model.pre_trained_ckpt_fpath_input = fpath.format(2402, 110) + model.denoiser_mmse = 1 + model.use_noisy_input = False + model.use_noisy_target = False + model.use_both_noisy_clean_input = False + # model.denoiser_kinput_samples = -1 + ############################# + + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 60 + training.max_epochs = 800 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 400 + training.precision = 16 + + return config diff --git a/denoisplit/configs/denoiser_usplit_separate_config.py b/denoisplit/configs/denoiser_usplit_separate_config.py new file mode 100644 index 0000000..4a21e9c --- /dev/null +++ b/denoisplit/configs/denoiser_usplit_separate_config.py @@ -0,0 +1,134 @@ +""" +Here, the idea is to load the prediction of the denoiser as the input to the splitting setup. +""" +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.PredictedTiffData + data.channel_1 = 0 + data.channel_2 = 2 + + data.num_channels = 3 + data.ch1_fname = 'pred_disentangle_2403_D7-M23-S0-L0_18.tif' + data.ch2_fname = 'pred_disentangle_2403_D7-M23-S0-L0_16.tif' + data.ch_input_fname = 'pred_disentangle_2403_D7-M23-S0-L0_32.tif' + + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = False + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + # config.data.synthetic_gaussian_scale = 178 + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + # config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 5 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = 'usplit' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + model.num_targets = 2 + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + + model.enable_noise_model = False + model.noise_model_type = 'gmm' + fname_format = '/home/ashesh.ashesh/training/noise_model/{}/GMMNoiseModel_ventura_gigascience-{}__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch1_fpath = fname_format.format('2402/190', 'actin') + model.noise_model_ch2_fpath = fname_format.format('2402/191', 'mito') + + model.noise_model_learnable = False + assert model.enable_noise_model == False or model.predict_logvar is None + + # model.noise_model_ch1_fpath = fname_format.format('2307/58', 'actin') + # model.noise_model_ch2_fpath = fname_format.format('2307/59', 'mito') + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + return config diff --git a/denoisplit/configs/exp_microscopyv2_config.py b/denoisplit/configs/exp_microscopyv2_config.py new file mode 100644 index 0000000..c2af0ba --- /dev/null +++ b/denoisplit/configs/exp_microscopyv2_config.py @@ -0,0 +1,128 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.multifile_raw_dloader import SubDsetType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.ExpMicroscopyV2 + data.subdset_type = SubDsetType.MultiChannel + data.num_channels = 2 + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 2 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = False + + # This is for intensity augmentation + data.ch1_min_alpha = 0.4 + data.ch1_max_alpha = 0.6 + data.alpha_weighted_target = True + # data.return_alpha = True + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.kl_loss_formulation = 'usplit' + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 50.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + + training = config.training + training.lr = 0.001 / 2 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 16 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/hagen_usplit_config.py b/denoisplit/configs/hagen_usplit_config.py new file mode 100644 index 0000000..0f84c16 --- /dev/null +++ b/denoisplit/configs/hagen_usplit_config.py @@ -0,0 +1,125 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.SeparateTiffData + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'actin-60x-noise2-highsnr.tif' + data.ch2_fname = 'mito-60x-noise2-highsnr.tif' + data.poisson_noise_factor = 100 + data.enable_gaussian_noise = True + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + config.data.synthetic_gaussian_scale = 375 + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 5 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = 'usplit' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + + model.enable_noise_model = False + model.noise_model_type = 'gmm' + model.noise_model_ch1_fpath = '/home/ashesh.ashesh/training/noise_model/2402/483/GMMNoiseModel_ventura_gigascience-__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch2_fpath = '/home/ashesh.ashesh/training/noise_model/2402/483/GMMNoiseModel_ventura_gigascience-__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + + model.noise_model_learnable = False + assert model.enable_noise_model == False or model.predict_logvar is None + + # model.noise_model_ch1_fpath = fname_format.format('2307/58', 'actin') + # model.noise_model_ch2_fpath = fname_format.format('2307/59', 'mito') + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/hdn_biosr_denoiser_config.py b/denoisplit/configs/hdn_biosr_denoiser_config.py new file mode 100644 index 0000000..b10c894 --- /dev/null +++ b/denoisplit/configs/hdn_biosr_denoiser_config.py @@ -0,0 +1,125 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.BioSR_MRC + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'F-actin/GT_all_a.mrc' + data.ch2_fname = 'CCPs/GT_all.mrc' + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = True + data.synthetic_gaussian_scale = 4300 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1.0 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = '' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = None + # loss.kl_min = 1e-7 + + model = config.model + model.model_type = ModelType.Denoiser + # 4 values for denoise_channel {'Ch1', 'Ch2', 'input','all'} + model.denoise_channel = 'Ch1' + + model.encoder.batchnorm = True + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + # HDN specific parameters which were changed. + ######################### + model.enable_topdown_normalize_factor = False + model.encoder.dropout = 0.2 + model.decoder.dropout = 0.2 + model.decoder.stochastic_use_naive_exponential = True + model.decoder.blocks_per_layer = 5 + model.encoder.blocks_per_layer = 5 + model.encoder.n_filters = 32 + model.decoder.n_filters = 32 + model.z_dims = [32, 32, 32, 32, 32, 32] + loss.free_bits = 1.0 + model.analytical_kl = True + model.var_clip_max = None + model.logvar_lowerbound = None # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + ######################### + + model.decoder.conv2d_bias = True + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.mode_pred = False + + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + + model.enable_noise_model = True + model.noise_model_type = 'gmm' + # fname_format = '/home/ashesh.ashesh/training/noise_model/{}/GMMNoiseModel_{}-GT_all.mrc__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + # model.noise_model_ch1_fpath = fname_format.format('2402/279', 'CCPs') + # model.noise_model_ch2_fpath = fname_format.format('2402/285', 'ER') + model.noise_model_ch1_fpath = '/home/ashesh.ashesh/training/noise_model/2403/73/GMMNoiseModel_BioSR-F__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch2_fpath = '/home/ashesh.ashesh/training/noise_model/2403/82/GMMNoiseModel_BioSR-Microtubules_GT_all__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_learnable = False + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/hdn_denoiser_config.py b/denoisplit/configs/hdn_denoiser_config.py new file mode 100644 index 0000000..217e4a5 --- /dev/null +++ b/denoisplit/configs/hdn_denoiser_config.py @@ -0,0 +1,122 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.SeparateTiffData + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'actin-60x-noise2-highsnr.tif' + data.ch2_fname = 'mito-60x-noise2-highsnr.tif' + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = True + data.synthetic_gaussian_scale = 1000 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1.0 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = '' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = None + # loss.kl_min = 1e-7 + + model = config.model + model.model_type = ModelType.Denoiser + # 4 values for denoise_channel {'Ch1', 'Ch2', 'input','all'} + model.denoise_channel = 'input' + + model.encoder.batchnorm = True + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + # HDN specific parameters which were changed. + model.enable_topdown_normalize_factor = False + model.encoder.dropout = 0.2 + model.decoder.dropout = 0.2 + model.decoder.stochastic_use_naive_exponential = True + model.decoder.blocks_per_layer = 5 + model.encoder.blocks_per_layer = 5 + model.encoder.n_filters = 32 + model.decoder.n_filters = 32 + model.z_dims = [32, 32, 32, 32, 32, 32] + loss.free_bits = 1.0 + model.analytical_kl = True + model.var_clip_max = None + model.logvar_lowerbound = None # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + ######################### + + model.decoder.conv2d_bias = True + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.mode_pred = False + + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + + model.enable_noise_model = True + model.noise_model_type = 'gmm' + fname_format = '/home/ashesh.ashesh/training/noise_model/{}/GMMNoiseModel_ventura_gigascience-{}__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch1_fpath = '/home/ashesh.ashesh/training/noise_model/2402/513/GMMNoiseModel_ventura_gigascience-mito_actin_6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch2_fpath = '/home/ashesh.ashesh/training/noise_model/2402/521/GMMNoiseModel_ventura_gigascience-mito__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_learnable = False + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/hdn_hagen_restricted_config.py b/denoisplit/configs/hdn_hagen_restricted_config.py new file mode 100644 index 0000000..a26f774 --- /dev/null +++ b/denoisplit/configs/hdn_hagen_restricted_config.py @@ -0,0 +1,122 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.SeparateTiffData + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'actin-60x-noise2-lowsnr.tif' + data.ch2_fname = 'mito-60x-noise2-lowsnr.tif' + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = False + data.synthetic_gaussian_scale = 250 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1.0 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = '' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = None + # loss.kl_min = 1e-7 + + model = config.model + model.model_type = ModelType.Denoiser + # 4 values for denoise_channel {'Ch1', 'Ch2', 'input','all'} + model.denoise_channel = 'input' + + model.encoder.batchnorm = True + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + # HDN specific parameters which were changed. + model.enable_topdown_normalize_factor = False + model.encoder.dropout = 0.2 + model.decoder.dropout = 0.2 + model.decoder.stochastic_use_naive_exponential = True + model.decoder.blocks_per_layer = 5 + model.encoder.blocks_per_layer = 5 + model.encoder.n_filters = 32 + model.decoder.n_filters = 32 + model.z_dims = [32, 32, 32] + loss.free_bits = 1.0 + model.analytical_kl = False + model.var_clip_max = 20 + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + ######################### + + model.decoder.conv2d_bias = True + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.mode_pred = False + + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + + model.enable_noise_model = True + model.noise_model_type = 'gmm' + fname_format = '/home/ashesh.ashesh/training/noise_model/{}/GMMNoiseModel_ventura_gigascience-{}__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch1_fpath = '/home/ashesh.ashesh/training/noise_model/2403/10/GMMNoiseModel_ventura_gigascience-actin_mito_6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch2_fpath = '/home/ashesh.ashesh/training/noise_model/2402/512/GMMNoiseModel_ventura_gigascience-mito__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_learnable = False + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/hdn_paviaatn_denoiser_config.py b/denoisplit/configs/hdn_paviaatn_denoiser_config.py new file mode 100644 index 0000000..f067c32 --- /dev/null +++ b/denoisplit/configs/hdn_paviaatn_denoiser_config.py @@ -0,0 +1,120 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 2 + data.channel_2 = 3 + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = True + data.synthetic_gaussian_scale = 304 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1.0 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = '' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = None + # loss.kl_min = 1e-7 + + model = config.model + model.model_type = ModelType.Denoiser + # 4 values for denoise_channel {'Ch1', 'Ch2', 'input','all'} + model.denoise_channel = 'Ch1' + + model.encoder.batchnorm = True + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + # HDN specific parameters which were changed. + model.enable_topdown_normalize_factor = False + model.encoder.dropout = 0.2 + model.decoder.dropout = 0.2 + model.decoder.stochastic_use_naive_exponential = True + model.decoder.blocks_per_layer = 5 + model.encoder.blocks_per_layer = 5 + model.encoder.n_filters = 32 + model.decoder.n_filters = 32 + model.z_dims = [32, 32, 32, 32, 32, 32] + loss.free_bits = 1.0 + model.analytical_kl = True + model.var_clip_max = None + model.logvar_lowerbound = None # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + ######################### + + model.decoder.conv2d_bias = True + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.mode_pred = False + + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + + model.enable_noise_model = True + model.noise_model_type = 'gmm' + fname_format = '/home/ashesh.ashesh/training/noise_model/{}/GMMNoiseModel_microscopy-OptiMEM100x014__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch1_fpath = fname_format.format('2402/501') + model.noise_model_ch2_fpath = fname_format.format('2402/270') + model.noise_model_learnable = False + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/ht_iba1_ki64_config.py b/denoisplit/configs/ht_iba1_ki64_config.py new file mode 100644 index 0000000..0e922c4 --- /dev/null +++ b/denoisplit/configs/ht_iba1_ki64_config.py @@ -0,0 +1,123 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.ht_iba1_ki67_rawdata_loader import SubDsetType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.HTIba1Ki67 + data.subdset_type = SubDsetType.OnlyIba1 + # data.subdset_types = [SubDsetType.OnlyIba1, SubDsetType.Iba1Ki64] + # data.subdset_types_probab = [1.0, 0.0] + # data.validation_subdset_type_idx = 0 + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.01 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = True + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = True + data.input_is_sum = True + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + # Replacing one channel's content with empty patch. + # data.empty_patch_replacement_enabled_list = [True, False] + data.empty_patch_replacement_channel_idx = 0 + data.empty_patch_replacement_enabled = True + data.empty_patch_replacement_probab = 0.3 + data.empty_patch_max_val_threshold = 180 + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/ht_iba1_ki64_multidata_config.py b/denoisplit/configs/ht_iba1_ki64_multidata_config.py new file mode 100644 index 0000000..3882d40 --- /dev/null +++ b/denoisplit/configs/ht_iba1_ki64_multidata_config.py @@ -0,0 +1,132 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.ht_iba1_ki67_rawdata_loader import SubDsetType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.HTIba1Ki67 + data.subdset_type = None + data.validation_subdset_type_idx = 0 + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.01 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + # If this is set to true, then one mean and stdev is used for both channels while computing input. + # Otherwise, two different meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + # Replacing one channel's content with empty patch. + data.empty_patch_replacement_enabled = False + data.empty_patch_replacement_channel_idx = 0 + data.empty_patch_replacement_probab = 0.5 + data.empty_patch_max_val_threshold = 180 + + loss = config.loss + loss.loss_type = LossType.ElboMixedReconstruction + loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVaeTwoDatasetMultiOptim + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + + model.learn_intensity_map = True + model.enable_learnable_interchannel_weights = True + model.only_optimize_interchannel_weights = True + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + # training.val_fraction = 0.0 + # training.test_fraction = 0.0 + training.earlystop_patience = 100 + training.precision = 16 + + # when working with multi datasets, it might make sense to predict the mixing constants. This will be applied to + # dataset which will have mixed reconstruction as loss + data.subdset_types = [SubDsetType.OnlyIba1, SubDsetType.Iba1Ki64] + data.subdset_types_probab = [0.7, 0.3] + data.empty_patch_replacement_enabled_list = [True, False] + training.test_fraction = [0, 0.2] + training.val_fraction = [0.2, 0] + data.input_is_sum_list = [True, False] + data.input_is_sum = False + return config diff --git a/denoisplit/configs/lvae_with_stitch_config.py b/denoisplit/configs/lvae_with_stitch_config.py new file mode 100644 index 0000000..75077b8 --- /dev/null +++ b/denoisplit/configs/lvae_with_stitch_config.py @@ -0,0 +1,107 @@ +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 2 + data.channel_2 = 3 + data.nbr_set_count = None + + data.sampler_type = SamplerType.NeighborSampler + data.threshold = 0.02 + data.deterministic_grid = True + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.ElboWithNbrConsistency + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + loss.nbr_consistency_w = 0.0 + + model = config.model + model.model_type = ModelType.LadderVaeStitch2Stage + model.z_dims = [128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'channelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + model.offset_prediction_input_z_idx = 3 + model.offset_latent_dims = 50 + model.offset_prediction_scalar_prediction = True + model.regularize_offset = True + model.offset_regularization_w = 0.001 + model.offset_prediction_focus_on_opposite_gradients = True + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.gridsizes = np.arange(6, 20, 2) + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/microscopy_mc_lvae_twindecoder_config.py b/denoisplit/configs/microscopy_mc_lvae_twindecoder_config.py new file mode 100644 index 0000000..d8c197f --- /dev/null +++ b/denoisplit/configs/microscopy_mc_lvae_twindecoder_config.py @@ -0,0 +1,71 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 256 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 0 + data.channel_2 = 2 + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = True + data.normalized_input = True + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = True + data.randomized_channels = True + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVaeTwinDecoder + model.z_dims = [128] + model.encoder.blocks_per_layer = 5 + model.decoder.blocks_per_layer = 5 + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.n_filters = 64 + model.dropout = 0.1 + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 6 + # predict_logvar takes one of the three values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'global' + model.use_vampprior = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 4 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.2 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/microscopy_multi_channel_lvae_critic_config.py b/denoisplit/configs/microscopy_multi_channel_lvae_critic_config.py new file mode 100644 index 0000000..1a9739e --- /dev/null +++ b/denoisplit/configs/microscopy_multi_channel_lvae_critic_config.py @@ -0,0 +1,75 @@ +""" +Configuration file for the VAE model with critic +""" +import ml_collections +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 256 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 0 + data.channel_2 = 2 + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = True + data.normalized_input = True + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = True + + loss = config.loss + loss.loss_type = LossType.ElboWithCritic + loss.kl_weight = 0.005 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + loss.critic_loss_weight = 0.005 + + model = config.model + model.model_type = ModelType.LadderVAECritic + model.z_dims = [128, 128, 128] + model.encoder.blocks_per_layer = 5 + model.decoder.blocks_per_layer = 5 + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.n_filters = 64 + model.dropout = 0.2 + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = True + model.mode_pred = False + model.var_clip_max = 8 + # Discriminator params + model.critic = ml_collections.ConfigDict() + model.critic.ndf = 64 + model.critic.netD = 'n_layers' + model.critic.layers_D = 2 + model.critic.norm = 'none' + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 4 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.2 + training.earlystop_patience = 100 + training.precision = 16 + return config diff --git a/denoisplit/configs/multi_encoder_config.py b/denoisplit/configs/multi_encoder_config.py new file mode 100644 index 0000000..0be6e6f --- /dev/null +++ b/denoisplit/configs/multi_encoder_config.py @@ -0,0 +1,84 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 0 + data.channel_2 = 2 + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = True + data.normalized_input = True + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = True + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + data.mixed_input_type = 'consistent_with_single_inputs' + data.supervised_data_fraction = 0.02 + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVaeSepEncoderSingleOptim + model.z_dims = [128, 128, 128, 128] + model.encoder.blocks_per_layer = 1 + model.decoder.blocks_per_layer = 1 + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.n_filters = 64 + model.dropout = 0.1 + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the three values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'global' + model.logvar_lowerbound = -2.49 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + # stochastic layers below this are shared. + model.share_bottom_up_starting_idx = 0 + model.fbu_num_blocks = 3 + # if true, then the mixed branch does not effect the vae training. it only updates its own weights. + model.separate_mix_branch_training = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.2 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/notmnist_lvae_config.py b/denoisplit/configs/notmnist_lvae_config.py new file mode 100644 index 0000000..2d8c3fe --- /dev/null +++ b/denoisplit/configs/notmnist_lvae_config.py @@ -0,0 +1,55 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.data_type = DataType.NotMNIST + data.img_dsample = 1 + data.image_size = 28 // data.img_dsample + data.label1 = 'A' + data.label2 = 'B' + data.sampler_type = SamplerType.RandomSampler + data.mean_val = 44.8525 + data.std_val = 73.395 + data.return_img_labels = False + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128] + model.encoder.blocks_per_layer = 3 + model.decoder.blocks_per_layer = 3 + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.n_filters = 64 + model.dropout = 0.0 + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = True + model.mode_pred = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 1000 + training.batch_size = 16 + training.num_workers = 4 + return config diff --git a/denoisplit/configs/pavia2Vanilla_config.py b/denoisplit/configs/pavia2Vanilla_config.py new file mode 100644 index 0000000..083f8c3 --- /dev/null +++ b/denoisplit/configs/pavia2Vanilla_config.py @@ -0,0 +1,106 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.pavia2_enums import Pavia2DataSetChannels + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.Pavia2VanillaSplitting + data.channel_1 = Pavia2DataSetChannels.NucRFP670 + data.channel_2 = Pavia2DataSetChannels.TUBULIN + data.channel_2_downscale_factor = 1 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 4 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.channel_1_w = 5 + loss.channel_2_w = 1 + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + loss.lres_recloss_w = [0.4, 0.2, 0.2, 0.2] + + model = config.model + model.model_type = ModelType.LadderVAEMultiTarget + model.z_dims = [128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'global' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 16 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/pavia2_config.py b/denoisplit/configs/pavia2_config.py new file mode 100644 index 0000000..b04691c --- /dev/null +++ b/denoisplit/configs/pavia2_config.py @@ -0,0 +1,107 @@ +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.pavia2_enums import Pavia2DataSetChannels + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.Pavia2 + data.dset_type = None # This will be filled in the dataloader + data.channel_idx_list = [ + Pavia2DataSetChannels.NucRFP670, Pavia2DataSetChannels.NucMTORQ, Pavia2DataSetChannels.TUBULIN + ] + data.channelwise_quantile = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # mixed probablity will be 1 - the sum of following these. + data.dset_clean_sample_probab = 0.5 + data.dset_bleedthrough_sample_probab = 0.25 + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = False + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 4 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.ElboMixedReconstruction + loss.mixed_rec_weight = 0.1 + loss.rec_loss_channel_weights = [5, 1, 1] + + loss.kl_weight = 0.001 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVaeMixedRecons + model.z_dims = [128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #False + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'global' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/pavia3_config.py b/denoisplit/configs/pavia3_config.py new file mode 100644 index 0000000..62e5fcc --- /dev/null +++ b/denoisplit/configs/pavia3_config.py @@ -0,0 +1,129 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.pavia3_rawdata_loader import Pavia3SeqAlpha, Pavia3SeqPowerLevel + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.Pavia3SeqData + # data.channel_1 = 0 + # data.channel_2 = 1 + # data.ch1_fname = 'ER/GT_all.mrc' + # data.ch2_fname = 'Microtubules/GT_all.mrc' + data.num_channels = 2 + data.power_level = Pavia3SeqPowerLevel.Medium + data.alpha_level = Pavia3SeqAlpha.Balanced + + data.enable_gaussian_noise = False + data.trainig_datausage_fraction = 1.0 + data.poisson_noise_factor = -1 + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + config.data.synthetic_gaussian_scale = None + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + # config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = '' + + loss.kl_weight = 1.0 + loss.reconstruction_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 1.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + + model.enable_noise_model = False + model.noise_model_type = 'gmm' + fname = '/home/ashesh.ashesh/training/noise_model/2403/139/GMMNoiseModel_BioSR-__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch1_fpath = fname + model.noise_model_ch2_fpath = fname + model.noise_model_learnable = False + assert model.enable_noise_model == False or model.predict_logvar is None + + # model.noise_model_ch1_fpath = fname_format.format('2307/58', 'actin') + # model.noise_model_ch2_fpath = fname_format.format('2307/59', 'mito') + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 8 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + # training.precision = 16 + return config diff --git a/denoisplit/configs/pavia_atn_config.py b/denoisplit/configs/pavia_atn_config.py new file mode 100644 index 0000000..2ee8f8d --- /dev/null +++ b/denoisplit/configs/pavia_atn_config.py @@ -0,0 +1,128 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 2 + data.channel_2 = 3 + + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = True + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + config.data.synthetic_gaussian_scale = 228 + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 5 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = '' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 1.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + + model.enable_noise_model = True + model.noise_model_type = 'gmm' + fname_format = '/home/ashesh.ashesh/training/noise_model/{}/GMMNoiseModel_microscopy-OptiMEM100x014.tif__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch1_fpath = fname_format.format('2402/240') + model.noise_model_ch2_fpath = fname_format.format('2402/244') + + model.noise_model_learnable = False + assert model.enable_noise_model == False or model.predict_logvar is None + + # model.noise_model_ch1_fpath = fname_format.format('2307/58', 'actin') + # model.noise_model_ch2_fpath = fname_format.format('2307/59', 'mito') + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + return config diff --git a/denoisplit/configs/pavia_atn_usplit_config.py b/denoisplit/configs/pavia_atn_usplit_config.py new file mode 100644 index 0000000..5e41a41 --- /dev/null +++ b/denoisplit/configs/pavia_atn_usplit_config.py @@ -0,0 +1,128 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 2 + data.channel_2 = 3 + + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = True + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + config.data.synthetic_gaussian_scale = 228 + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 5 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = 'usplit' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + + model.enable_noise_model = False + model.noise_model_type = 'gmm' + fname_format = '/home/ashesh.ashesh/training/noise_model/{}/GMMNoiseModel_ventura_gigascience-{}__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch1_fpath = fname_format.format('2402/190', 'actin') + model.noise_model_ch2_fpath = fname_format.format('2402/191', 'mito') + + model.noise_model_learnable = False + assert model.enable_noise_model == False or model.predict_logvar is None + + # model.noise_model_ch1_fpath = fname_format.format('2307/58', 'actin') + # model.noise_model_ch2_fpath = fname_format.format('2307/59', 'mito') + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + return config diff --git a/denoisplit/configs/pavia_deterministic_lvae_config.py b/denoisplit/configs/pavia_deterministic_lvae_config.py new file mode 100644 index 0000000..33fec8e --- /dev/null +++ b/denoisplit/configs/pavia_deterministic_lvae_config.py @@ -0,0 +1,96 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 512 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 2 + data.channel_2 = 3 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #False + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = True + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 16 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/pembl_config.py b/denoisplit/configs/pembl_config.py new file mode 100644 index 0000000..88c29b0 --- /dev/null +++ b/denoisplit/configs/pembl_config.py @@ -0,0 +1,94 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.Prevedel_EMBL + data.channel_1 = 0 + data.channel_2 = 1 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.95 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = False + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #False + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the three values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 800 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.2 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/places_lvae_config.py b/denoisplit/configs/places_lvae_config.py new file mode 100644 index 0000000..c9aa8f6 --- /dev/null +++ b/denoisplit/configs/places_lvae_config.py @@ -0,0 +1,53 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.data_type = DataType.Places365 + data.img_dsample = 2 + data.image_size = 128 // data.img_dsample + data.label1 = 'ice_skating_rink-outdoor' + data.label2 = 'waiting_room' + data.sampler_type = SamplerType.RandomSampler + data.return_img_labels = False + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.kl_weight = 0.01 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128] + model.encoder.blocks_per_layer = 3 + model.decoder.blocks_per_layer = 3 + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.n_filters = 64 + model.dropout = 0.2 + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = True + model.mode_pred = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 1000 + training.batch_size = 16 + training.num_workers = 4 + return config diff --git a/denoisplit/configs/places_lvae_twindecoder_config.py b/denoisplit/configs/places_lvae_twindecoder_config.py new file mode 100644 index 0000000..a4391c6 --- /dev/null +++ b/denoisplit/configs/places_lvae_twindecoder_config.py @@ -0,0 +1,53 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.data_type = DataType.Places365 + data.img_dsample = 2 + data.image_size = 128 // data.img_dsample + data.label1 = 'ice_skating_rink-outdoor' + data.label2 = 'waiting_room' + data.sampler_type = SamplerType.RandomSampler + data.return_img_labels = False + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.kl_weight = 0.0001 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVaeTwinDecoder + model.z_dims = [128, 128, 128] + model.encoder.blocks_per_layer = 3 + model.decoder.blocks_per_layer = 3 + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.n_filters = 64 + model.dropout = 0.2 + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = True + model.mode_pred = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 1000 + training.batch_size = 16 + training.num_workers = 4 + return config diff --git a/denoisplit/configs/semi_supervised_config.py b/denoisplit/configs/semi_supervised_config.py new file mode 100644 index 0000000..0ad9906 --- /dev/null +++ b/denoisplit/configs/semi_supervised_config.py @@ -0,0 +1,106 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.SemiSupBloodVesselsEMBL + data.mix_fpath = '' #THG-SJS42_0-1000_FITC_221116-1.tif' + data.ch1_fpath = '' #FITC_C1-SJS42_0-1000_FITC_221116-1.tif' + data.mix_fpath_list = [ + 'THG_MS29_z0_403um_sl4_bin10_z03_fr3_p9_lz290_px512_XYn119n152_AOFull_FITC_00002.tif', + 'THG_MS29_z0_905um_sl4_bin10_z03_fr3_p28_lz250_px512_XYn119n152_AOFull_FITC_00001.tif', + 'THG_MS29_z0_905um_sl4_bin10_z03_fr3_p33_lz250_px512_XYn119n152_AOFull_FITC_00001.tif' + ] + data.ch1_fpath_list = [x.replace('THG_', 'FITC_') for x in data.mix_fpath_list] + + # data.ignore_frames = [list(range(7)) + list(range(249, 260))] + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = False + # if this is set to True, then for each image, you normalize using it's mean and std. + # data.use_per_image_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 3 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.ElboSemiSupMixedReconstruction + loss.mixed_rec_weight = 1 + loss.exclusion_loss_weight = 0.1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVaeSemiSupervised + model.z_dims = [128, 128, 128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/shroff_config.py b/denoisplit/configs/shroff_config.py new file mode 100644 index 0000000..eda251a --- /dev/null +++ b/denoisplit/configs/shroff_config.py @@ -0,0 +1,100 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.ShroffMitoEr + data.enable_max_projection = True + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 4 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.2 + training.test_fraction = 0.2 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/sox2golgi_config.py b/denoisplit/configs/sox2golgi_config.py new file mode 100644 index 0000000..6833f33 --- /dev/null +++ b/denoisplit/configs/sox2golgi_config.py @@ -0,0 +1,127 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.multifile_raw_dloader import SubDsetType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.TavernaSox2Golgi + data.subdset_type = SubDsetType.TwoChannel + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 2 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = False + + # This is for intensity augmentation + data.ch1_min_alpha = 0.4 + data.ch1_max_alpha = 0.6 + data.alpha_weighted_target = True + # data.return_alpha = True + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.kl_loss_formulation = 'usplit' + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + + training = config.training + training.lr = 0.001 / 2 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 128 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/sox2golgi_v2_config.py b/denoisplit/configs/sox2golgi_v2_config.py new file mode 100644 index 0000000..8c922aa --- /dev/null +++ b/denoisplit/configs/sox2golgi_v2_config.py @@ -0,0 +1,128 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.multifile_raw_dloader import SubDsetType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.TavernaSox2GolgiV2 + data.subdset_type = SubDsetType.MultiChannel + # all channels: ['555-647', 'GT_Cy5', 'GT_TRITC'] + data.channel_1 = 'GT_Cy5' + data.channel_2 = 'GT_TRITC' + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = False + + # This is for intensity augmentation + # data.ch1_min_alpha = 0.4 + # data.ch1_max_alpha = 0.6 + # data.alpha_weighted_target = True + # data.return_alpha = True + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.kl_loss_formulation = 'usplit' + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = True + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + + training = config.training + training.lr = 0.001 / 2 + training.lr_scheduler_patience = 30 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + # training.precision = 16 + + return config diff --git a/denoisplit/configs/splitter_denoiser_config.py b/denoisplit/configs/splitter_denoiser_config.py new file mode 100644 index 0000000..d88c604 --- /dev/null +++ b/denoisplit/configs/splitter_denoiser_config.py @@ -0,0 +1,131 @@ +from tkinter.tix import Tree + +import numpy as np + +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.SeparateTiffData + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'actin-60x-noise2-lowsnr.tif' + data.ch2_fname = 'mito-60x-noise2-lowsnr.tif' + data.poisson_noise_factor = -1 + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = False + + # This is for intensity augmentation + # data.ch1_min_alpha = 0.4 + # data.ch1_max_alpha = 0.55 + # data.return_alpha = True + + loss = config.loss + loss.loss_type = LossType.Elbo + loss.kl_loss_formulation = '' + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 1.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.SplitterDenoiser + model.pre_trained_ckpt_fpath_splitter = '/home/ashesh.ashesh/training/disentangle/2312/D7-M3-S0-L0/0/BaselineVAECL_best.ckpt' + + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'channelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + model.enable_noise_model = True + model.noise_model_type = 'gmm' + model.noise_model_ch1_fpath = '/home/ashesh.ashesh/training/N2V/2312/18/GMMNoiseModel_ventura_gigascience-actin_10_3_Clip0.5-100_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch2_fpath = '/home/ashesh.ashesh/training/N2V/2312/17/GMMNoiseModel_ventura_gigascience-mito_10_3_Clip0.5-100_Sig0.125_UpNone_Norm0_bootstrap.npz' + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/twodset_config.py b/denoisplit/configs/twodset_config.py new file mode 100644 index 0000000..2513834 --- /dev/null +++ b/denoisplit/configs/twodset_config.py @@ -0,0 +1,141 @@ +from tkinter.tix import Tree + +import numpy as np + +import ml_collections +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 256 + data.data_type = DataType.TwoDset + data.channel_1 = None + data.channel_2 = None + + # Specific to TwoDset + data.dset0 = ml_collections.ConfigDict() + data.dset0.channel_1 = 0 + data.dset0.channel_2 = 2 + data.dset0.data_type = DataType.OptiMEM100_014 + data.dset1 = ml_collections.ConfigDict() + data.dset1.channel_1 = 0 + data.dset1.channel_2 = 3 + data.dset1.data_type = DataType.OptiMEM100_014 + data.subdset_types_probab = [0.5, 0.5] + ############################# + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = False + + # This is for intensity augmentation + # data.ch1_min_alpha = 0.4 + # data.ch1_max_alpha = 0.55 + # data.return_alpha = True + + loss = config.loss + loss.loss_type = LossType.ElboRestrictedReconstruction + loss.split_weight = 1 + loss.mixed_rec_weight = 1 + # loss.exclusion_loss_weight = 0.01 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LadderVAETwoDataSetRestRecon + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = True + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + model.enable_learnable_interchannel_weights = True + + training = config.training + training.lr = 0.001 / 2 + training.lr_scheduler_patience = 30 + training.max_epochs = 200 + training.batch_size = 16 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + # training.precision = 16 + + return config diff --git a/denoisplit/configs/twodset_finetuning_config.py b/denoisplit/configs/twodset_finetuning_config.py new file mode 100644 index 0000000..3bed51b --- /dev/null +++ b/denoisplit/configs/twodset_finetuning_config.py @@ -0,0 +1,154 @@ +from tkinter.tix import Tree + +import numpy as np + +import ml_collections +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.TwoDset + data.channel_1 = None + data.channel_2 = None + data.ch1_fname = '' + data.ch2_fname = '' + # Specific to TwoDset + data.dset0 = ml_collections.ConfigDict() + data.dset0.data_type = DataType.BioSR_MRC + data.dset0.ch1_fname = 'ER/GT_all.mrc' + data.dset0.ch2_fname = 'Microtubules/GT_all.mrc' + data.dset0.synthetic_gaussian_scale = 6675 + data.dset0.poisson_noise_factor = 1000 + data.dset0.enable_gaussian_noise = True + + data.dset1 = ml_collections.ConfigDict() + data.dset1.data_type = DataType.BioSR_MRC + data.dset1.ch1_fname = 'ER/GT_all.mrc' + data.dset1.ch2_fname = 'Microtubules/GT_all.mrc' + data.dset1.synthetic_gaussian_scale = 4450 + data.dset1.poisson_noise_factor = 1000 + data.dset1.enable_gaussian_noise = True + data.subdset_types_probab = [0.5, 0.5] + ############################# + + data.poisson_noise_factor = 1000 + + data.enable_gaussian_noise = True + data.trainig_datausage_fraction = 1.0 + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + config.data.synthetic_gaussian_scale = 4450 + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + # loss.loss_type = LossType.Elbo + loss.loss_type = LossType.ElboRestrictedReconstruction + # this is not uSplit. + loss.kl_loss_formulation = '' + + loss.mixed_rec_weight = 1.0 + loss.split_weight = 1.0 + loss.kl_weight = 1.0 + # loss.reconstruction_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 1.0 + + model = config.model + model.model_type = ModelType.LadderVAETwoDataSetFinetuning + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + model.non_stochastic_version = False + model.enable_noise_model = False + model.noise_model_type = 'gmm' + # model.noise_model_ch1_fpath = '/home/ashesh.ashesh/training/noise_model/2402/226/GMMNoiseModel_ER-GT_all.mrc__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + # model.noise_model_ch2_fpath = '/home/ashesh.ashesh/training/noise_model/2402/206/GMMNoiseModel_CCPs-GT_all.mrc__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + + ################# + # this must be the input. + model.finetuning_noise_model_ch1_fpath = '/group/jug/ashesh/training_pre_eccv/noise_model/2402/475/GMMNoiseModel_BioSR-ER_GT_all_Microtubules_GT_all_6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.finetuning_noise_model_ch2_fpath = '' + model.finetuning_noise_model_type = 'gmm' + model.pretrained_weights_path = '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/2/BaselineVAECL_best.ckpt' + ################ + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 1 + training.max_epochs = 10 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 2 + # training.precision = 16 + + return config diff --git a/denoisplit/configs/twodset_sox2golgi_v2_config.py b/denoisplit/configs/twodset_sox2golgi_v2_config.py new file mode 100644 index 0000000..657a638 --- /dev/null +++ b/denoisplit/configs/twodset_sox2golgi_v2_config.py @@ -0,0 +1,142 @@ +from tkinter.tix import Tree + +import numpy as np + +import ml_collections +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.data_loader.multifile_raw_dloader import SubDsetType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.TwoDset + data.channel_1 = None + data.channel_2 = None + data.subdset_type = SubDsetType.MultiChannel + + # Specific to TwoDset + data.dset0 = ml_collections.ConfigDict() + data.dset0.channel_1 = 'GT_Cy5' + data.dset0.channel_2 = 'GT_TRITC' + data.dset0.data_type = DataType.TavernaSox2GolgiV2 + data.dset1 = ml_collections.ConfigDict() + data.dset1.channel_1 = '555-647' + data.dset1.channel_2 = '555-647' + data.dset1.data_type = DataType.TavernaSox2GolgiV2 + data.subdset_types_probab = [0.5, 0.5] + ############################# + + data.sampler_type = SamplerType.DefaultSampler + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + data.background_quantile = 0.0 + # With background quantile, one is setting the avg background value to 0. With this, any negative values are also set to 0. + # This, together with correct background_quantile should altogether get rid of the background. The issue here is that + # the background noise is also a distribution. So, some amount of background noise will remain. + data.clip_background_noise_to_zero = False + + # we will not subtract the mean of the dataset from every patch. We just want to subtract the background and normalize using std. This way, background will be very close to 0. + # this will help in the all scaling related approaches where we want to multiply the frame with some factor and then add them. we will then effectively just do these scaling on the + # foreground pixels and the background will anyways will remain very close to 0. + data.skip_normalization_using_mean = False + + data.input_is_sum = False + + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = False + + # This is for intensity augmentation + # data.ch1_min_alpha = 0.4 + # data.ch1_max_alpha = 0.55 + # data.return_alpha = True + + loss = config.loss + loss.loss_type = LossType.ElboRestrictedReconstruction + loss.mixed_rec_weight = 0.0 + # loss.split_weight = + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + # loss.ch1_recons_w = 1 + # loss.ch2_recons_w = 5 + + model = config.model + model.model_type = ModelType.LadderVAETwoDataSetRestRecon + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = 'pixelwise' + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = True + model.enable_noise_model = False + model.noise_model_ch1_fpath = None + model.noise_model_ch1_fpath = None + model.enable_learnable_interchannel_weights = True + + training = config.training + training.lr = 0.001 / 2 + training.lr_scheduler_patience = 30 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + # training.precision = 16 + + return config diff --git a/denoisplit/configs/twotiff_bravenet_config.py b/denoisplit/configs/twotiff_bravenet_config.py new file mode 100644 index 0000000..27f71e9 --- /dev/null +++ b/denoisplit/configs/twotiff_bravenet_config.py @@ -0,0 +1,65 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.SeparateTiffData + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'actin-60x-noise2-highsnr.tif' + data.ch2_fname = 'mito-60x-noise2-highsnr.tif' + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 2 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.MSE + # loss.mixed_rec_weight = 1 + + model = config.model + model.model_type = ModelType.BraveNet + + model.num_kernels = [32, 64, 128, 256] + model.kernel_size = 3 + model.padding = 1 + model.activation = 'relu' + model.final_activation = None + model.dropout = 0.1 + model.batch_normalization = True + model.strides = 1 + model.monitor = 'val_psnr' + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/twotiff_config.py b/denoisplit/configs/twotiff_config.py new file mode 100644 index 0000000..31261f6 --- /dev/null +++ b/denoisplit/configs/twotiff_config.py @@ -0,0 +1,125 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 128 + data.data_type = DataType.SeparateTiffData + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'actin-60x-noise2-lowsnr.tif' + data.ch2_fname = 'mito-60x-noise2-lowsnr.tif' + data.poisson_noise_factor = -1 + data.enable_gaussian_noise = False + # data.validtarget_random_fraction = 1.0 + # data.training_validtarget_fraction = 0.2 + config.data.synthetic_gaussian_scale = 375 + # if True, then input has 'identical' noise as the target. Otherwise, noise of input is independently sampled. + config.data.input_has_dependant_noise = True + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + # data.grid_size = 1 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 1 + + data.channelwise_quantile = False + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + data.input_is_sum = False + loss = config.loss + loss.loss_type = LossType.Elbo + # this is not uSplit. + loss.kl_loss_formulation = '' + + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1.0 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 1.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.batchnorm = True + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.batchnorm = True + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + + #False + config.model.decoder.conv2d_bias = True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_loss' # {'val_loss','val_psnr'} + + model.enable_noise_model = True + model.noise_model_type = 'gmm' + model.noise_model_ch1_fpath = '/home/ashesh.ashesh/training/noise_model/2403/202/GMMNoiseModel_N2V_inputs_igor-actin__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + model.noise_model_ch2_fpath = '/home/ashesh.ashesh/training/noise_model/2403/203/GMMNoiseModel_N2V_inputs_igor-mito__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz' + + model.noise_model_learnable = False + assert model.enable_noise_model == False or model.predict_logvar is None + + # model.noise_model_ch1_fpath = fname_format.format('2307/58', 'actin') + # model.noise_model_ch2_fpath = fname_format.format('2307/59', 'mito') + model.non_stochastic_version = False + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 15 + training.max_epochs = 200 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 100 + training.precision = 16 + + return config diff --git a/denoisplit/configs/twotiff_deterministic_config.py b/denoisplit/configs/twotiff_deterministic_config.py new file mode 100644 index 0000000..3e27184 --- /dev/null +++ b/denoisplit/configs/twotiff_deterministic_config.py @@ -0,0 +1,98 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 256 + data.data_type = DataType.SeparateTiffData + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'actin-60x-noise2-highsnr.tif' + data.ch2_fname = 'mito-60x-noise2-highsnr.tif' + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = None + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.Elbo + # loss.mixed_rec_weight = 1 + + loss.kl_weight = 1 + loss.kl_annealing = False + loss.kl_annealtime = 10 + loss.kl_start = -1 + loss.kl_min = 1e-7 + loss.free_bits = 0.0 + + model = config.model + model.model_type = ModelType.LadderVae + model.z_dims = [128, 128, 128, 128] + + model.encoder.blocks_per_layer = 1 + model.encoder.n_filters = 64 + model.encoder.dropout = 0.1 + model.encoder.res_block_kernel = 3 + model.encoder.res_block_skip_padding = False + + model.decoder.blocks_per_layer = 1 + model.decoder.n_filters = 64 + model.decoder.dropout = 0.1 + model.decoder.res_block_kernel = 3 + model.decoder.res_block_skip_padding = False + #True + + model.skip_nboundary_pixels_from_loss = None + model.nonlin = 'elu' + model.merge_type = 'residual' + model.batchnorm = True + model.stochastic_skip = True + model.learn_top_prior = True + model.img_shape = None + model.res_block_type = 'bacdbacd' + + model.gated = True + model.no_initial_downscaling = True + model.analytical_kl = False + model.mode_pred = False + model.var_clip_max = 20 + # predict_logvar takes one of the four values: [None,'global','channelwise','pixelwise'] + model.predict_logvar = None + model.logvar_lowerbound = -5 # -2.49 is log(1/12), from paper "Re-parametrizing VAE for stablity." + model.multiscale_lowres_separate_branch = False + model.multiscale_retain_spatial_dims = True + model.monitor = 'val_psnr' # {'val_loss','val_psnr'} + model.non_stochastic_version = True + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/twotiff_unet_config.py b/denoisplit/configs/twotiff_unet_config.py new file mode 100644 index 0000000..cdcda95 --- /dev/null +++ b/denoisplit/configs/twotiff_unet_config.py @@ -0,0 +1,61 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.SeparateTiffData + data.channel_1 = 0 + data.channel_2 = 1 + data.ch1_fname = 'actin-60x-noise2-highsnr.tif' + data.ch2_fname = 'mito-60x-noise2-highsnr.tif' + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 5 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.MSE + # loss.mixed_rec_weight = 1 + + model = config.model + model.model_type = ModelType.UNet + model.n_levels = 5 + model.init_channel_count = 32 + model.enable_context_transfer = False + model.context_transfer_initial_weight_factor = 0 + model.multiscale_lowres_separate_branch = True + model.monitor = 'val_psnr' + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/configs/unet_config.py b/denoisplit/configs/unet_config.py new file mode 100644 index 0000000..3424d0e --- /dev/null +++ b/denoisplit/configs/unet_config.py @@ -0,0 +1,59 @@ +from denoisplit.configs.default_config import get_default_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType + + +def get_config(): + config = get_default_config() + data = config.data + data.image_size = 64 + data.data_type = DataType.OptiMEM100_014 + data.channel_1 = 0 + data.channel_2 = 2 + + data.sampler_type = SamplerType.DefaultSampler + data.threshold = 0.02 + data.deterministic_grid = False + data.normalized_input = True + data.clip_percentile = 0.995 + # If this is set to true, then one mean and stdev is used for both channels. Otherwise, two different + # meean and stdev are used. + data.use_one_mu_std = True + data.train_aug_rotate = False + data.randomized_channels = False + data.multiscale_lowres_count = 5 + data.padding_mode = 'reflect' + data.padding_value = None + # If this is set to True, then target channels will be normalized from their separate mean. + # otherwise, target will be normalized just the same way as the input, which is determined by use_one_mu_std + data.target_separate_normalization = True + + loss = config.loss + loss.loss_type = LossType.MSE + # loss.mixed_rec_weight = 1ma + + model = config.model + model.model_type = ModelType.UNet + model.n_levels = 5 + model.init_channel_count = 32 + model.enable_context_transfer = False + model.context_transfer_initial_weight_factor = 0 + model.multiscale_lowres_separate_branch = True + model.monitor = 'val_psnr' + + training = config.training + training.lr = 0.001 + training.lr_scheduler_patience = 30 + training.max_epochs = 400 + training.batch_size = 32 + training.num_workers = 4 + training.val_repeat_factor = None + training.train_repeat_factor = None + training.val_fraction = 0.1 + training.test_fraction = 0.1 + training.earlystop_patience = 200 + training.precision = 16 + + return config diff --git a/denoisplit/core/__init__.py b/denoisplit/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/denoisplit/core/__pycache__/__init__.cpython-39.pyc b/denoisplit/core/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ccca7f5eb538e1509974adfd0776a3150208b491 GIT binary patch literal 154 zcmYe~<>g`kg2#1?XTZlX-=vg K$l%XF%m4tvDJ3ER literal 0 HcmV?d00001 diff --git a/denoisplit/core/__pycache__/custom_enum.cpython-39.pyc b/denoisplit/core/__pycache__/custom_enum.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e463ce2fb268581cddd661c71e5df92d9469c99 GIT binary patch literal 909 zcmZ`%OKaRP5SCicOo9kmO&K zLVMi5q-%ddZ#i{FW*4Uq!F(EdMwBw^AKRIpoeLlYN#N4VDa!1u(+`Xe!h_k82Ns@gJx zUUtg`4_|!&rXK@z*R7>WyohtkB6sLLuI)meM#Ea%H?vY0=6JQ4=U}_dHtErHoR&ka{uewdz4w4~HGWoCO`2EQhm(cA3+Q8N``E_+>IFr&f}esj=w&N7>!=mn z*$NIh>??HEQ9$<1)hBPrH4GnrlK76EtPhVxEp=5l$MSQon_1{6oT|b~I3$#W^Uzf& zRx;g9hwDbEF=ir(KN(KW6)28(4fm| F`3-~GyY~P9 literal 0 HcmV?d00001 diff --git a/denoisplit/core/__pycache__/data_split_type.cpython-39.pyc b/denoisplit/core/__pycache__/data_split_type.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e2381a6083e132fa579e3de08d10738e7413769 GIT binary patch literal 2595 zcmai0&5ImG6tAl8p6Q*P*{sR9yGcYlegr0wT@}$wNEBlfkwvn>LzB>SrfPOO>FJ(S z_e3|;Ah;`f5fr>A9^ysFpCEeh;6?Bt9_#995xfWF>gE10hy%`EW73zwE|Y-@ zcD%SD8?w2};-=y%Jj(XroSIXi48IKIoNVp-aZ4_P0-Bna?Js@Vkqf&)+*TcV=(^B9 zskU5{56Qzj-eoUdh!4e!>LInT0}Zeq+Fuvl+LlM~>&l1a(#QV)aZ9nmdMkT)73*>9 zznN9_Iw7wX<6)nu2M5RICCus(0L5Z1Su7;S>qYEKFAk)S*9MT-u$}X1ooU3G_mr|`sRg{@iV~SR!5soyDpkU(mNevZON88$m z#1OM05OUxB9JNns&qe@*CcUD%2w?a}Y=uok&1!yI7}(?(`-<=IiFc4<#8(0||3fz5 zQb=z%G~Ri(!w>9z+7HMl{<@~1>yyo9gLEJjk6>0^fK6uDmG*?w{mblAal_v@V3wY+ zV)Yrz-@U^vucqc)j;h z)^M(E15E}x?blgZ*bdR|Z(DU)4$RcS zkYSMMrtyI|>h6G4qyX)3*IP~+)4$YAHcZfE|0$8XkbykI4@jgNW)j_*3yyG^$6%`7nbs5#^brod=u(aPV z$3-30TPo9$R@F$s`ZrZHb3^4Wq-#c5|9YfyHB?1ifwhq3Fy97aIgH9eK?9v`JB3E$ z8q!H-R08Pf(W;Z=YJv;$>|10KRhwUK>-el{x`a znx{oyB}j^y6%yEbtd=0OdJ=#&LPT)`6HpLbQ(u!R1JwEW$WM#1fdY2gs;{=c61 z#0QSnjUVpI`Go7|5AZklrTE38brbx}9dTJq+LMm)O&j0((7r>r)FHitUXGUr;0bVc z?`^%t`ZPYDf)_MZ8BOKIg==rlg{2K#1=J@&x85*)7a%KKu-A|m ziU?51+MuTH7EkLOl|HI%cCNoQF0Kt7>kLUJWE1HtOIk!j8zSQIHjXi#$ci1-2UlHb-`j-vx&jPL1<@9ma zo}I3%)RR~H$h~ryDDY_11m=40)R4~1!5}Zw+8NdQSIaVY%4td!y++_(1+c+LQvtd6 rC*eT<3(rjdYMiC!T2Yl~!v<|{u^BcOxwzXtzI2*e6Qy$qi_!WwLq%z; literal 0 HcmV?d00001 diff --git a/denoisplit/core/__pycache__/data_type.cpython-39.pyc b/denoisplit/core/__pycache__/data_type.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86c8d2e5139d55bc758eb6680e79bca082c7b1eb GIT binary patch literal 1053 zcmb7@&2G~`5XbF&G@nk=v`x|vBo1)MC2iAEI3QG#Mx}y;3R^kM#oA^z%}N_@YCEAl zae$ZMId}_SIYqnyCw3e}3pdvCZ)ZHaJG+0+GRw*vy8ZZMj=v=g<2yMITS_~p`VAgy zpn;||rY4xCac*D&lV1!>a`ST%5}2}$W_qbd8BH@v^}P9XM9#xzYUfnHL8!qEFwxKx zO-Nz_QkaA^reF=zkij*`Vg_=Ug*@hd1dC82lnE8WI-yF~AZ!x02sJ{T&>(DU44RLktm}Gg%3U|gyY5usT#{XM z-J3a+za#1X;KFvI+@)kA9vq!KgX}mME*xCe*FQ0mTuP)%*&sXz$? z>(b{7j$FFEe&-!nuchQ(mrL0fp@NFdXUu0Icf@#1!a(Ei`Od`WygT<79O^co3VS~5 zNTqPdgMiB*UUTh|Ed*;rZPgE%C!}QdOo}iR-Zkv>ZfDF3g!1}gm%AlDJf{^0gMbfMy~1@}E>tK0UulGg$XXG|S+ zC(QG>gtAU^pJ3Pq>p@hz)qkfC+fl~(sLlc&M(bK86r+&iA0@2#I7c?WiG|4z#7Id- z_E*DyqJLkEpQrm1HRby(nDAiIT6Oy)g?t~mr$j8n$_z*m9rATZui}Qf2wSr|p9+ua zE;!c6nyLSN67dRyW-{81Q^t8(l&3X{i^1jkGWt~H@yPqludJs!5M^JkitiO&h=9fx GlfM9@X%y`M literal 0 HcmV?d00001 diff --git a/denoisplit/core/__pycache__/data_utils.cpython-39.pyc b/denoisplit/core/__pycache__/data_utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58310725c4ce7abb806c25c4aa0389dc51bf6122 GIT binary patch literal 6468 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 bnDqj|8T*w30^|rP8^+Sv#S4qCIfwoOPxkFn literal 0 HcmV?d00001 diff --git a/denoisplit/core/__pycache__/loss_type.cpython-39.pyc b/denoisplit/core/__pycache__/loss_type.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5918258b0263e5ba9a95fd22fb1c90054196eb82 GIT binary patch literal 598 zcmZuuO>5&Y5S45vansM!_RyvGK#BiADTNUB(&kVv6y_pQjY(^yGPFd|q?cH2~`YFQek+Obll!=_-qr_@8U zEcyy0^Wx6I0pqO=t66P>)o{%DwS6>rW3;P$s2d%ut02D4=kViy_u{UeQPuijD!qYI z{-2xD=FR%M!$YpmuHYx{H-=QL4qvbMBkBX1zk`35*~*nBTl$spt7*Sw+M&tNRL z!iJvuj%rt%tRSmYAg`wDP0jwWJ^qLwmC2{Ct1c!noOE)X#*{Uty79r4%FsL3>~q)o VK3LBVsnDk9y|WkmCZ2ou;x{o9nEn6& literal 0 HcmV?d00001 diff --git a/denoisplit/core/__pycache__/metric_monitor.cpython-39.pyc b/denoisplit/core/__pycache__/metric_monitor.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fff8aace8a0031d244f8689edcacc77da6c82135 GIT binary patch literal 709 zcmY*XyJ{Oj6uozLr7S{9z=bOpX}8g)4j~wV2?1si9=KC0GHOYA zQXzgM3f?*3&+u4Uv7wbRY}7ri5|fw|IyEEIj)&Q$-MYHE?7Mo~yGlwQMQp(bz@Oqd zu;Cl>)6aCv2R@L-GH9X}xf-&Yve8ZNeY7^db2$&=Hgw1L)Z6CTrReg9+!*TLMX~N% zTan?TIvnYbsUfLfJSrJ)0xCd7datWo0+dz}lrbX9_2mKj;DOXS8 zA9!+-%DMwHnaNBZGm~OAOAyHSD}F!`LZ3d^l^B9Ks67S45yv%Bm|~0;h)0~fBTfW< zBQ)ai3Z4ROt5X?dCAsB%u<_I2QN_a$LPUvWWxPu${Ecmr<`tEMi z2sbWjxz>Waq%AZzO1=nAPfDY$w4Kl$dy-wntkmmTFzKJ!WxD4kjOjuN#$3XfGQ5W@ zb5q71`=b8Kj4uW>O>VbncXYW$-vfCSz@Z)cf!cj&KA4|HUKu6w!dAjo*>L2g;Ueck z8@Xy~*$u7@ZfRPPD?i)NCF@|itl6{#kbcv456pzbIF7>IG9~UfumT|SfUN9oXA~2# c;TFCOh06b~25$-pH#r-oKKF~azIIA}0Ts@M6951J literal 0 HcmV?d00001 diff --git a/denoisplit/core/__pycache__/model_type.cpython-39.pyc b/denoisplit/core/__pycache__/model_type.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..427a84ae3a1932340f8da2b738e58911111dbe97 GIT binary patch literal 1231 zcmZvcOK;Oa5XbE}X`NS-Hm|k`sO6SRA|Z|lH8cSswMA+|4|B1s%#y6+7wdIPxgY^w zhOd+>r-*OBi5)w3L&aMDd3JU@`=9l$?P|58srLJ;{_$I0(|%EByD6V`rta`W0X5Ve z&DBBIwYM7P(DR@0F z@@PN-^RR;j*u@<%aTkhcLJ5md#u8Mp3{|Ya9#)}-dr-$3>|-4ca330Y08MN_3!Bi! z7Id%;huDE5JcMIBf-W9I54%cWZ&keXkvX&bfUOOsVoe3E3xplQF2N)e3A8xtGND4K z67~o+LY=TrI3P3#O+t&%CUgjggd@T+p-bo~T=k!W%nP}^A4Lmjk0R+`vxQ(Gzh#?5qY0d3CWQ-!sYSpzAOB)Y?t5U4 zndhr=1=Le(8aQ04XsD-FIs&IzzH1gr!RInv04bt*oUoULJk(CX@j7KijwTPIZ@9-~ zq?yP%!m8T{(3nR?5fy)UTd#hO54@>c(@%6Afsh!8{73?^;a#K17Z*(_9bg6YH7s Rt<0CnX?aC|m5^d9#$S_gUn~Fs literal 0 HcmV?d00001 diff --git a/denoisplit/core/__pycache__/nn_submodules.cpython-39.pyc b/denoisplit/core/__pycache__/nn_submodules.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4657ac044719f650e87aa4e4337952ad0789e74 GIT binary patch literal 4310 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 AQUCw| literal 0 HcmV?d00001 diff --git a/denoisplit/core/__pycache__/tiff_reader.cpython-39.pyc b/denoisplit/core/__pycache__/tiff_reader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..070bf26e361691ecd5c71fdca999f8def9ee87f7 GIT binary patch literal 886 zcmZ`%JC74F5VrS`Y;p;@L(n0#ZBpz~T!lh}IO-InTM0$h+Q}Nc5A4lBPC1&p3h4@d zM*fmpDr!0^X1u!N#KY3Oc0KdWd}B5q4+)%apXvGw1&hJ`<3aEe#GHcSgi}Q_3f5Cz z>1Tc!WC11I=fO3}LLTxS*dFim2yCCzC7BGqLnc{FJlm6{7L21c>|Er4cXtpc067CO z$DmrW2Q=>8c$ajKb^MDL!x+vR(Qb8RViuqBxZ0M@E@oP@-E$09vfP+yG5t8jATL-| z31wWKjas>0ucZYb{d5SmBgHC(X_dRL%GbKZZCMPDp|g)g!PuLf;zK;Tn|D>Zrm7ym;1 zUHk-ocYC1^sD6x9BOAJRrLmiAXx__`ZA2n#_gFgKaU@5nOSxCy?ZT}gnw2%*Dlx}a N4GtdBV?T 0: + imb_count = int(diff_fraction * total_size / 2) + val = list(np.random.RandomState(seed=955).permutation(val)) + test += val[:imb_count] + val = val[imb_count:] + elif diff_fraction < 0: + imb_count = int(-1 * diff_fraction * total_size / 2) + test = list(np.random.RandomState(seed=955).permutation(test)) + val += test[:imb_count] + test = test[imb_count:] + return val, test + + +def get_datasplit_tuples(val_fraction: float, test_fraction: float, total_size: int, starting_test: bool = False): + if starting_test: + # test => val => train + test = list(range(0, int(total_size * test_fraction))) + val = list(range(test[-1] + 1, test[-1] + 1 + int(total_size * val_fraction))) + train = list(range(val[-1] + 1, total_size)) + else: + # {test,val}=> train + test_val_size = int((val_fraction + test_fraction) * total_size) + train = list(range(test_val_size, total_size)) + + if test_val_size == 0: + test = [] + val = [] + return train, val, test + + # Split the test and validation in chunks. + chunksize = max(1, min(3, test_val_size // 2)) + + nchunks = test_val_size // chunksize + + test = [] + val = [] + s = 0 + for i in range(nchunks): + if i % 2 == 0: + val += list(np.arange(s, s + chunksize)) + else: + test += list(np.arange(s, s + chunksize)) + s += chunksize + + if i % 2 == 0: + test += list(np.arange(s, test_val_size)) + else: + p1, p2 = split_in_half(s, test_val_size) + test += p1 + val += p2 + + val, test = adjust_for_imbalance_in_fraction_value(val, test, val_fraction, test_fraction, total_size) + + return train, val, test + + +if __name__ == '__main__': + train, val, test = get_datasplit_tuples(0.8, 0.2, 20) + print(train) + print(val) + print(test) + + train, val, test = get_datasplit_tuples(0.1, 0.1, 30, starting_test=True) + print(train) + print(val) + print(test) diff --git a/denoisplit/core/data_type.py b/denoisplit/core/data_type.py new file mode 100644 index 0000000..bebe6d5 --- /dev/null +++ b/denoisplit/core/data_type.py @@ -0,0 +1,31 @@ +from denoisplit.core.custom_enum import Enum + + +class DataType(Enum): + MNIST = 0 + Places365 = 1 + NotMNIST = 2 + OptiMEM100_014 = 3 + CustomSinosoid = 4 + Prevedel_EMBL = 5 + AllenCellMito = 6 + SeparateTiffData = 7 + CustomSinosoidThreeCurve = 8 + SemiSupBloodVesselsEMBL = 9 + Pavia2 = 10 + Pavia2VanillaSplitting = 11 + ExpansionMicroscopyMitoTub = 12 + ShroffMitoEr = 13 + HTIba1Ki67 = 14 + BSD68 = 15 + BioSR_MRC = 16 + TavernaSox2Golgi = 17 + Dao3Channel = 18 + ExpMicroscopyV2 = 19 + Dao3ChannelV2 = 20 + TavernaSox2GolgiV2 = 21 + TwoDset = 22 + PredictedTiffData = 23 + Pavia3SeqData = 24 + # Here, we have 16 splitting tasks. + NicolaData = 25 \ No newline at end of file diff --git a/denoisplit/core/data_utils.py b/denoisplit/core/data_utils.py new file mode 100644 index 0000000..23230ae --- /dev/null +++ b/denoisplit/core/data_utils.py @@ -0,0 +1,207 @@ +import time +from glob import glob + +import numpy as np +import torch +from sklearn.feature_extraction import image +from torch import nn +from tqdm import tqdm + + +class Interpolate(nn.Module): + """Wrapper for torch.nn.functional.interpolate.""" + + def __init__(self, size=None, scale=None, mode='bilinear', align_corners=False): + super().__init__() + assert (size is None) == (scale is not None) + self.size = size + self.scale = scale + self.mode = mode + self.align_corners = align_corners + + def forward(self, x): + out = F.interpolate(x, + size=self.size, + scale_factor=self.scale, + mode=self.mode, + align_corners=self.align_corners) + return out + + +class CropImage(nn.Module): + """Crops image to given size. + Args: + size + """ + + def __init__(self, size): + super().__init__() + self.size = size + + def forward(self, x): + return crop_img_tensor(x, self.size) + + +def normalize(img, mean, std): + """Normalize an array of images with mean and standard deviation. + Parameters + ---------- + img: array + An array of images. + mean: float + Mean of img array. + std: float + Standard deviation of img array. + """ + return (img - mean) / std + + +def denormalize(img, mean, std): + """Denormalize an array of images with mean and standard deviation. + Parameters + ---------- + img: array + An array of images. + mean: float + Mean of img array. + std: float + Standard deviation of img array. + """ + return (img * std) + mean + + +def convertToFloat32(train_images, val_images): + """Converts the data to float 32 bit type. + Parameters + ---------- + train_images: array + Training data. + val_images: array + Validation data. + """ + x_train = train_images.astype('float32') + x_val = val_images.astype('float32') + return x_train, x_val + + +def getMeanStdData(train_images, val_images): + """Compute mean and standrad deviation of data. + Parameters + ---------- + train_images: array + Training data. + val_images: array + Validation data. + """ + x_train_ = train_images.astype('float32') + x_val_ = val_images.astype('float32') + data = np.concatenate((x_train_, x_val_), axis=0) + mean, std = np.mean(data), np.std(data) + return mean, std + + +def convertNumpyToTensor(numpy_array): + """Convert numpy array to PyTorch tensor. + Parameters + ---------- + numpy_array: numpy array + Numpy array. + """ + return torch.from_numpy(numpy_array) + + +def augment_data(X_train): + """Augment data by 8-fold with 90 degree rotations and flips. + Parameters + ---------- + X_train: numpy array + Array of training images. + """ + X_ = X_train.copy() + + X_train_aug = np.concatenate((X_train, np.rot90(X_, 1, (1, 2)))) + X_train_aug = np.concatenate((X_train_aug, np.rot90(X_, 2, (1, 2)))) + X_train_aug = np.concatenate((X_train_aug, np.rot90(X_, 3, (1, 2)))) + X_train_aug = np.concatenate((X_train_aug, np.flip(X_train_aug, axis=1))) + + print('Raw image size after augmentation', X_train_aug.shape) + return X_train_aug + + +def extract_patches(x, patch_size, num_patches): + """Deterministically extract patches from array of images. + Parameters + ---------- + x: numpy array + Array of images. + patch_size: int + Size of patches to be extracted from each image. + num_patches: int + Number of patches to be extracted from each image. + """ + patches = np.zeros(shape=(x.shape[0] * num_patches, patch_size, patch_size)) + + for i in tqdm(range(x.shape[0])): + patches[i * num_patches:(i + 1) * num_patches] = image.extract_patches_2d(x[i], (patch_size, patch_size), + num_patches, + random_state=i) + return patches + + +def crop_img_tensor(x, size) -> torch.Tensor: + """Crops a tensor. + Crops a tensor of shape (batch, channels, h, w) to new height and width + given by a tuple. + Args: + x (torch.Tensor): Input image + size (list or tuple): Desired size (height, width) + Returns: + The cropped tensor + """ + return _pad_crop_img(x, size, 'crop') + + +def _pad_crop_img(x, size, mode) -> torch.Tensor: + """ Pads or crops a tensor. + Pads or crops a tensor of shape (batch, channels, h, w) to new height + and width given by a tuple. + Args: + x (torch.Tensor): Input image + size (list or tuple): Desired size (height, width) + mode (str): Mode, either 'pad' or 'crop' + Returns: + The padded or cropped tensor + """ + + assert x.dim() == 4 and len(size) == 2 + size = tuple(size) + x_size = x.size()[2:4] + if mode == 'pad': + cond = x_size[0] > size[0] or x_size[1] > size[1] + elif mode == 'crop': + cond = x_size[0] < size[0] or x_size[1] < size[1] + else: + raise ValueError("invalid mode '{}'".format(mode)) + if cond: + raise ValueError('trying to {} from size {} to size {}'.format(mode, x_size, size)) + dr, dc = (abs(x_size[0] - size[0]), abs(x_size[1] - size[1])) + dr1, dr2 = dr // 2, dr - (dr // 2) + dc1, dc2 = dc // 2, dc - (dc // 2) + if mode == 'pad': + return nn.functional.pad(x, [dc1, dc2, dr1, dr2, 0, 0, 0, 0]) + elif mode == 'crop': + return x[:, :, dr1:x_size[0] - dr2, dc1:x_size[1] - dc2] + + +def pad_img_tensor(x, size) -> torch.Tensor: + """Pads a tensor. + Pads a tensor of shape (batch, channels, h, w) to new height and width + given by a tuple. + Args: + x (torch.Tensor): Input image + size (list or tuple): Desired size (height, width) + Returns: + The padded tensor + """ + + return _pad_crop_img(x, size, 'pad') diff --git a/denoisplit/core/dloader_type.py b/denoisplit/core/dloader_type.py new file mode 100644 index 0000000..9267d42 --- /dev/null +++ b/denoisplit/core/dloader_type.py @@ -0,0 +1,6 @@ +from denoisplit.core.custom_enum import Enum + + +class DloaderType(Enum): + Default = 0 + SemiSupervised = 1 diff --git a/denoisplit/core/empty_patch_fetcher.py b/denoisplit/core/empty_patch_fetcher.py new file mode 100644 index 0000000..5936be5 --- /dev/null +++ b/denoisplit/core/empty_patch_fetcher.py @@ -0,0 +1,54 @@ +import numpy as np +from tqdm import tqdm + + +class EmptyPatchFetcher: + """ + The idea is to fetch empty patches so that real content can be replaced with this. + """ + + def __init__(self, idx_manager, patch_size, data_frames, max_val_threshold=None): + self._frames = data_frames + self._idx_manager = idx_manager + self._max_val_threshold = max_val_threshold + self._idx_list = [] + self._patch_size = patch_size + self._grid_size = 1 + self.set_empty_idx() + + print(f'[{self.__class__.__name__}] MaxVal:{self._max_val_threshold}') + + def compute_max(self, window): + """ + Rolling compute. + """ + N, H, W = self._frames.shape + randnum = -954321 + assert self._grid_size == 1 + max_data = np.zeros((N, H - window, W - window)) * randnum + + for h in tqdm(range(H - window)): + for w in range(W - window): + max_data[:, h, w] = self._frames[:, h:h + window, w:w + window].max(axis=(1, 2)) + + assert (max_data != 954321).any() + return max_data + + def set_empty_idx(self): + max_data = self.compute_max(self._patch_size) + empty_loc = np.where(np.logical_and(max_data >= 0, max_data < self._max_val_threshold)) + # print(max_data.shape, len(empty_loc)) + self._idx_list = [] + for idx in range(len(empty_loc[0])): + n_idx = empty_loc[0][idx] + h_start = empty_loc[1][idx] + w_start = empty_loc[2][idx] + # print(n_idx,h_start,w_start) + self._idx_list.append(self._idx_manager.idx_from_hwt(h_start, w_start, n_idx, grid_size=self._grid_size)) + + self._idx_list = np.array(self._idx_list) + + assert len(self._idx_list) > 0 + + def sample(self): + return (np.random.choice(self._idx_list), self._grid_size) diff --git a/denoisplit/core/filename_utils.py b/denoisplit/core/filename_utils.py new file mode 100644 index 0000000..106696f --- /dev/null +++ b/denoisplit/core/filename_utils.py @@ -0,0 +1,22 @@ +import os + + +def replace_space(directory: str, replace_token: str = '_'): + """ + Replaces space present in all files/subdirectories with replace_token. + Note that it does not touch nested directories. + """ + for fname in os.listdir(directory): + new_fname = fname.replace(" ", replace_token) + if new_fname == fname: + continue + if os.path.exists(os.path.join(directory, new_fname)): + print(new_fname, 'exists in the directory. Please delete it before proceeding') + print('Aborting') + return + for fname in os.listdir(directory): + new_fname = fname.replace(" ", replace_token) + src = os.path.join(directory, fname) + dst = os.path.join(directory, new_fname) + os.rename(src, dst) + print(src, '--->', dst) diff --git a/denoisplit/core/likelihoods.py b/denoisplit/core/likelihoods.py new file mode 100644 index 0000000..a0d8bb3 --- /dev/null +++ b/denoisplit/core/likelihoods.py @@ -0,0 +1,241 @@ +import math +from typing import Union + +import numpy as np +import torch +from torch import nn + +from denoisplit.core.stable_dist_params import StableLogVar + + +class LikelihoodModule(nn.Module): + + def distr_params(self, x): + return None + + def set_params_to_same_device_as(self, correct_device_tensor): + pass + + @staticmethod + def logvar(params): + return None + + @staticmethod + def mean(params): + return None + + @staticmethod + def mode(params): + return None + + @staticmethod + def sample(params): + return None + + def log_likelihood(self, x, params): + return None + + def forward(self, input_, x): + distr_params = self.distr_params(input_) + mean = self.mean(distr_params) + mode = self.mode(distr_params) + sample = self.sample(distr_params) + logvar = self.logvar(distr_params) + if x is None: + ll = None + else: + ll = self.log_likelihood(x, distr_params) + dct = { + 'mean': mean, + 'mode': mode, + 'sample': sample, + 'params': distr_params, + 'logvar': logvar, + } + return ll, dct + + +class NoiseModelLikelihood(LikelihoodModule): + + def __init__(self, ch_in, color_channels, data_mean, data_std, noiseModel): + super().__init__() + self.parameter_net = nn.Identity() #nn.Conv2d(ch_in, color_channels, kernel_size=3, padding=1) + self.data_mean = data_mean + self.data_std = data_std + self.noiseModel = noiseModel + + def set_params_to_same_device_as(self, correct_device_tensor): + if isinstance(self.data_mean, torch.Tensor): + if self.data_mean.device != correct_device_tensor.device: + self.data_mean = self.data_mean.to(correct_device_tensor.device) + self.data_std = self.data_std.to(correct_device_tensor.device) + elif isinstance(self.data_mean, dict): + for key in self.data_mean.keys(): + self.data_mean[key] = self.data_mean[key].to(correct_device_tensor.device) + self.data_std[key] = self.data_std[key].to(correct_device_tensor.device) + + def get_mean_lv(self, x): + return self.parameter_net(x), None + + def distr_params(self, x): + mean, lv = self.get_mean_lv(x) + # mean, lv = x.chunk(2, dim=1) + + params = { + 'mean': mean, + 'logvar': lv, + } + return params + + @staticmethod + def mean(params): + return params['mean'] + + @staticmethod + def mode(params): + return params['mean'] + + @staticmethod + def sample(params): + # p = Normal(params['mean'], (params['logvar'] / 2).exp()) + # return p.rsample() + return params['mean'] + + def log_likelihood(self, x, params): + predicted_s_denormalized = params['mean'] * self.data_std['target'] + self.data_mean['target'] + x_denormalized = x * self.data_std['target'] + self.data_mean['target'] + # predicted_s_cloned = predicted_s_denormalized + # predicted_s_reduced = predicted_s_cloned.permute(1, 0, 2, 3) + + # x_cloned = x_denormalized + # x_cloned = x_cloned.permute(1, 0, 2, 3) + # x_reduced = x_cloned[0, ...] + # import pdb;pdb.set_trace() + likelihoods = self.noiseModel.likelihood(x_denormalized, predicted_s_denormalized) + # likelihoods = self.noiseModel.likelihood(x, params['mean']) + logprob = torch.log(likelihoods) + return logprob + + +class GaussianLikelihood(LikelihoodModule): + + def __init__(self, + ch_in, + color_channels, + predict_logvar: Union[None, str] = None, + logvar_lowerbound=None, + conv2d_bias=True): + super().__init__() + # If True, then we also predict pixelwise logvar. + self.predict_logvar = predict_logvar + self.logvar_lowerbound = logvar_lowerbound + self.conv2d_bias = conv2d_bias + assert self.predict_logvar in [None, 'global', 'pixelwise', 'channelwise'] + logvar_ch_needed = self.predict_logvar is not None + # self.parameter_net = nn.Conv2d(ch_in, + # color_channels * (1 + logvar_ch_needed), + # kernel_size=3, + # padding=1, + # bias=self.conv2d_bias) + self.parameter_net = nn.Identity() + print(f'[{self.__class__.__name__}] PredLVar:{self.predict_logvar} LowBLVar:{self.logvar_lowerbound}') + + def get_mean_lv(self, x): + x = self.parameter_net(x) + if self.predict_logvar is not None: + # pixelwise mean and logvar + mean, lv = x.chunk(2, dim=1) + if self.predict_logvar in ['channelwise', 'global']: + if self.predict_logvar == 'channelwise': + # logvar should be of the following shape (batch,num_channels). Other dims would be singletons. + N = np.prod(lv.shape[:2]) + new_shape = (*mean.shape[:2], *([1] * len(mean.shape[2:]))) + elif self.predict_logvar == 'global': + # logvar should be of the following shape (batch). Other dims would be singletons. + N = lv.shape[0] + new_shape = (*mean.shape[:1], *([1] * len(mean.shape[1:]))) + else: + raise ValueError(f"Invalid value for self.predict_logvar:{self.predict_logvar}") + + lv = torch.mean(lv.reshape(N, -1), dim=1) + lv = lv.reshape(new_shape) + + if self.logvar_lowerbound is not None: + lv = torch.clip(lv, min=self.logvar_lowerbound) + else: + mean = x + lv = None + return mean, lv + + def distr_params(self, x): + mean, lv = self.get_mean_lv(x) + + params = { + 'mean': mean, + 'logvar': lv, + } + return params + + @staticmethod + def mean(params): + return params['mean'] + + @staticmethod + def mode(params): + return params['mean'] + + @staticmethod + def sample(params): + # p = Normal(params['mean'], (params['logvar'] / 2).exp()) + # return p.rsample() + return params['mean'] + + @staticmethod + def logvar(params): + return params['logvar'] + + def log_likelihood(self, x, params): + if self.predict_logvar is not None: + logprob = log_normal(x, params['mean'], params['logvar']) + else: + logprob = -0.5 * (params['mean'] - x)**2 + return logprob + + +def log_normal(x, mean, logvar): + """ + Log of the probability density of the values x untder the Normal + distribution with parameters mean and logvar. + :param x: tensor of points, with shape (batch, channels, dim1, dim2) + :param mean: tensor with mean of distribution, shape + (batch, channels, dim1, dim2) + :param logvar: tensor with log-variance of distribution, shape has to be + either scalar or broadcastable + """ + var = torch.exp(logvar) + log_prob = -0.5 * (((x - mean)**2) / var + logvar + torch.tensor(2 * math.pi).log()) + return log_prob + + +class GaussianLikelihoodWithStitching(GaussianLikelihood): + + def forward(self, input_, x, offset): + distr_params = self.distr_params(input_) + distr_params['mean'] = distr_params['mean'] + offset + + mean = self.mean(distr_params) + mode = self.mode(distr_params) + sample = self.sample(distr_params) + logvar = self.logvar(distr_params) + if x is None: + ll = None + else: + ll = self.log_likelihood(x, distr_params) + dct = { + 'mean': mean, + 'mode': mode, + 'sample': sample, + 'params': distr_params, + 'logvar': logvar, + } + return ll, dct diff --git a/denoisplit/core/loss_type.py b/denoisplit/core/loss_type.py new file mode 100644 index 0000000..d2b7705 --- /dev/null +++ b/denoisplit/core/loss_type.py @@ -0,0 +1,12 @@ +from denoisplit.core.custom_enum import Enum + + +class LossType: + Elbo = 0 + ElboWithCritic = 1 + ElboMixedReconstruction = 2 + MSE = 3 + ElboWithNbrConsistency = 4 + ElboSemiSupMixedReconstruction = 5 + ElboCL = 6 + ElboRestrictedReconstruction = 7 \ No newline at end of file diff --git a/denoisplit/core/metric_callback.py b/denoisplit/core/metric_callback.py new file mode 100644 index 0000000..d75853e --- /dev/null +++ b/denoisplit/core/metric_callback.py @@ -0,0 +1,17 @@ +""" +Custom class to track a metric and call a specific function when the criterion is fullfilled. +""" +from pytorch_lightning.callbacks import Callback + + +class ValMetricCallback(Callback): + def __int__(self, mode, callback_fn): + super().__init__() + assert mode in ['min', 'max'] + + # def on_validation_epoch_end(self, trainer: "pl.Trainer", pl_module: "pl.LightningModule") -> None: + # import pdb + # pdb.set_trace() + + def on_validation_end(self, trainer: "pl.Trainer", pl_module: "pl.LightningModule") -> None: + psnr = trainer.callback_metrics['val_psnr'] diff --git a/denoisplit/core/metric_monitor.py b/denoisplit/core/metric_monitor.py new file mode 100644 index 0000000..64c1130 --- /dev/null +++ b/denoisplit/core/metric_monitor.py @@ -0,0 +1,12 @@ +class MetricMonitor: + def __init__(self, metric): + assert metric in ['val_loss', 'val_psnr'] + self.metric = metric + + def mode(self): + if self.metric == 'val_loss': + return 'min' + elif self.metric == 'val_psnr': + return 'max' + else: + raise ValueError(f'Invalid metric:{self.metric}') diff --git a/denoisplit/core/mixed_input_type.py b/denoisplit/core/mixed_input_type.py new file mode 100644 index 0000000..4505132 --- /dev/null +++ b/denoisplit/core/mixed_input_type.py @@ -0,0 +1,10 @@ +from denoisplit.core.custom_enum import Enum + + +class MixedInputType(Enum): + # aligned means that mixed input has the same distribution as in reality: it is not the case that any two + # random images from the two crops are mixed to create this mixed input. Instead only co-located channels are mixed. + Aligned = 'aligned' + Randomized = 'randomized' + # this means that the mixed input is simply the average of the individual channels + ConsistentWithSingleInputs = 'consistent_with_single_inputs' diff --git a/denoisplit/core/model_type.py b/denoisplit/core/model_type.py new file mode 100644 index 0000000..168f5ff --- /dev/null +++ b/denoisplit/core/model_type.py @@ -0,0 +1,33 @@ +from denoisplit.core.custom_enum import Enum + + +class ModelType(Enum): + LadderVae = 3 + LadderVaeTwinDecoder = 4 + LadderVAECritic = 5 + # Separate vampprior: two optimizers + LadderVaeSepVampprior = 6 + # one encoder for mixed input, two for separate inputs. + LadderVaeSepEncoder = 7 + LadderVAEMultiTarget = 8 + LadderVaeSepEncoderSingleOptim = 9 + UNet = 10 + BraveNet = 11 + LadderVaeStitch = 12 + LadderVaeSemiSupervised = 13 + LadderVaeStitch2Stage = 14 # Note that previously trained models will have issue. + # since earlier, LadderVaeStitch2Stage = 13, LadderVaeSemiSupervised = 14 + LadderVaeMixedRecons = 15 + LadderVaeCL = 16 + LadderVaeTwoDataSet = 17 #on one subdset, apply disentanglement, on other apply reconstruction + LadderVaeTwoDatasetMultiBranch = 18 + LadderVaeTwoDatasetMultiOptim = 19 + LVaeDeepEncoderIntensityAug = 20 + AutoRegresiveLadderVAE = 21 + LadderVAEInterleavedOptimization = 22 + Denoiser = 23 + DenoiserSplitter = 24 + SplitterDenoiser = 25 + LadderVAERestrictedReconstruction = 26 + LadderVAETwoDataSetRestRecon = 27 + LadderVAETwoDataSetFinetuning = 28 diff --git a/denoisplit/core/nn_submodules.py b/denoisplit/core/nn_submodules.py new file mode 100644 index 0000000..a4be6cc --- /dev/null +++ b/denoisplit/core/nn_submodules.py @@ -0,0 +1,124 @@ +""" +Taken from https://github.com/juglab/HDN/blob/e30edf7ec2cd55c902e469b890d8fe44d15cbb7e/lib/nn.py +""" +import torch +import torchvision.transforms.functional as F +from torch import nn + + +class ResidualBlock(nn.Module): + """ + Residual block with 2 convolutional layers. + Input, intermediate, and output channels are the same. Padding is always + 'same'. The 2 convolutional layers have the same groups. No stride allowed, + and kernel sizes have to be odd. + The result is: + out = gate(f(x)) + x + where an argument controls the presence of the gating mechanism, and f(x) + has different structures depending on the argument block_type. + block_type is a string specifying the structure of the block, where: + a = activation + b = batch norm + c = conv layer + d = dropout. + For example, bacdbacd has 2x (batchnorm, activation, conv, dropout). + """ + + default_kernel_size = (3, 3) + + def __init__(self, + channels: int, + nonlin, + kernel=None, + groups=1, + batchnorm: bool = True, + block_type: str = None, + dropout=None, + gated=None, + skip_padding=False, + conv2d_bias=True): + super().__init__() + if kernel is None: + kernel = self.default_kernel_size + elif isinstance(kernel, int): + kernel = (kernel, kernel) + elif len(kernel) != 2: + raise ValueError("kernel has to be None, int, or an iterable of length 2") + assert all([k % 2 == 1 for k in kernel]), "kernel sizes have to be odd" + kernel = list(kernel) + self.skip_padding = skip_padding + pad = [0] * len(kernel) if self.skip_padding else [k // 2 for k in kernel] + print(kernel, pad) + self.gated = gated + modules = [] + + if block_type == 'cabdcabd': + for i in range(2): + conv = nn.Conv2d(channels, channels, kernel[i], padding=pad[i], groups=groups, bias=conv2d_bias) + modules.append(conv) + modules.append(nonlin()) + if batchnorm: + modules.append(nn.BatchNorm2d(channels)) + if dropout is not None: + modules.append(nn.Dropout2d(dropout)) + + elif block_type == 'bacdbac': + for i in range(2): + if batchnorm: + modules.append(nn.BatchNorm2d(channels)) + modules.append(nonlin()) + conv = nn.Conv2d(channels, channels, kernel[i], padding=pad[i], groups=groups, bias=conv2d_bias) + modules.append(conv) + if dropout is not None and i == 0: + modules.append(nn.Dropout2d(dropout)) + + elif block_type == 'bacdbacd': + for i in range(2): + if batchnorm: + modules.append(nn.BatchNorm2d(channels)) + modules.append(nonlin()) + conv = nn.Conv2d(channels, channels, kernel[i], padding=pad[i], groups=groups, bias=conv2d_bias) + modules.append(conv) + modules.append(nn.Dropout2d(dropout)) + + else: + raise ValueError("unrecognized block type '{}'".format(block_type)) + + if gated: + modules.append(GateLayer2d(channels, 1, nonlin)) + self.block = nn.Sequential(*modules) + + def forward(self, x): + + out = self.block(x) + if out.shape != x.shape: + return out + F.center_crop(x, out.shape[-2:]) + else: + return out + x + + +class ResidualGatedBlock(ResidualBlock): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs, gated=True) + + +class GateLayer2d(nn.Module): + """ + Double the number of channels through a convolutional layer, then use + half the channels as gate for the other half. + """ + + def __init__(self, channels, kernel_size, nonlin=nn.LeakyReLU): + super().__init__() + assert kernel_size % 2 == 1 + pad = kernel_size // 2 + self.conv = nn.Conv2d(channels, 2 * channels, kernel_size, padding=pad) + self.nonlin = nonlin() + + def forward(self, x): + x = self.conv(x) + x, gate = torch.chunk(x, 2, dim=1) + x = self.nonlin(x) # TODO remove this? + gate = torch.sigmoid(gate) + return x * gate diff --git a/denoisplit/core/non_stochastic.py b/denoisplit/core/non_stochastic.py new file mode 100644 index 0000000..2120e2a --- /dev/null +++ b/denoisplit/core/non_stochastic.py @@ -0,0 +1,158 @@ +""" +Adapted from https://github.com/juglab/HDN/blob/e30edf7ec2cd55c902e469b890d8fe44d15cbb7e/lib/stochastic.py +""" +import math +from typing import Union + +import numpy as np +import torch +import torchvision.transforms.functional as F +from torch import nn +from torch.distributions import kl_divergence +from torch.distributions.normal import Normal + +from denoisplit.core.stable_dist_params import StableLogVar, StableMean +from denoisplit.core.stable_exp import log_prob + + +class NonStochasticBlock2d(nn.Module): + """ + Non-stochastic version of the NormalStochasticBlock2d + """ + + def __init__(self, + c_in: int, + c_vars: int, + c_out, + kernel: int = 3, + groups=1, + conv2d_bias: bool = True, + transform_p_params: bool = True): + """ + Args: + c_in: This is the channel count of the tensor input to this module. + c_vars: This is the size of the latent space + c_out: Output of the stochastic layer. Note that this is different from z. + kernel: kernel used in convolutional layers. + transform_p_params: p_params are transformed if this is set to True. + """ + super().__init__() + assert kernel % 2 == 1 + pad = kernel // 2 + self.transform_p_params = transform_p_params + self.c_in = c_in + self.c_out = c_out + self.c_vars = c_vars + + if transform_p_params: + self.conv_in_p = nn.Conv2d(c_in, 2 * c_vars, kernel, padding=pad, bias=conv2d_bias, groups=groups) + self.conv_in_q = nn.Conv2d(c_in, 2 * c_vars, kernel, padding=pad, bias=conv2d_bias, groups=groups) + self.conv_out = nn.Conv2d(c_vars, c_out, kernel, padding=pad, bias=conv2d_bias, groups=groups) + + def compute_kl_metrics(self, p, p_params, q, q_params, mode_pred, analytical_kl, z): + """ + Compute KL (analytical or MC estimate) and then process it in multiple ways. + """ + + kl_dict = { + 'kl_elementwise': None, # (batch, ch, h, w) + 'kl_samplewise': None, # (batch, ) + 'kl_spatial': None, # (batch, h, w) + 'kl_channelwise': None # (batch, ch) + } + return kl_dict + + def process_p_params(self, p_params, var_clip_max): + if self.transform_p_params: + p_params = self.conv_in_p(p_params) + else: + + assert p_params.size(1) == 2 * self.c_vars, f'{p_params.shape} {self.c_vars}' + + # Define p(z) + p_mu, p_lv = p_params.chunk(2, dim=1) + return p_mu, None + + def process_q_params(self, q_params, var_clip_max, allow_oddsizes=False): + # Define q(z) + q_params = self.conv_in_q(q_params) + q_mu, q_lv = q_params.chunk(2, dim=1) + + if q_mu.shape[-1] % 2 == 1 and allow_oddsizes is False: + q_mu = F.center_crop(q_mu, q_mu.shape[-1] - 1) + + return q_mu, None + + def forward(self, + p_params: torch.Tensor, + q_params: torch.Tensor = None, + forced_latent: Union[None, torch.Tensor] = None, + use_mode: bool = False, + force_constant_output: bool = False, + analytical_kl: bool = False, + mode_pred: bool = False, + use_uncond_mode: bool = False, + var_clip_max: Union[None, float] = None): + """ + Args: + p_params: this is passed from top layers. + q_params: this is the merge of bottom up layer at this level and top down layers above this level. + forced_latent: If this is a tensor, then in stochastic layer, we don't sample by using p() & q(). We simply + use this as the latent space sampling. + use_mode: If it is true, we still don't sample from the q(). We simply + use the mean of the distribution as the latent space. + force_constant_output: This ensures that only the first sample of the batch is used. Typically used + when infernce_mode is False + analytical_kl: If True, typical KL divergence is calculated. Otherwise, a one-sample approximate of it is + calculated. + mode_pred: If True, then only prediction happens. Otherwise, KL divergence loss also gets computed. + use_uncond_mode: Used only when mode_pred=True + var_clip_max: This is the maximum value the log of the variance of the latent vector for any layer can reach. + + """ + + debug_qvar_max = 0 + assert (forced_latent is None) or (not use_mode) + + p_mu, _ = self.process_p_params(p_params, var_clip_max) + + p_params = (p_mu, None) + + if q_params is not None: + # At inference time, just don't centercrop the q_params even if they are odd in size. + q_mu, _ = self.process_q_params(q_params, var_clip_max, allow_oddsizes=mode_pred is True) + q_params = (q_mu, None) + debug_qvar_max = torch.Tensor([1]).to(q_mu.device) + # Sample from q(z) + sampling_distrib = q_mu + q_size = q_mu.shape[-1] + if p_mu.shape[-1] != q_size and mode_pred is False: + p_mu.centercrop_to_size(q_size) + else: + # Sample from p(z) + sampling_distrib = p_mu + + # Generate latent variable (typically by sampling) + z = sampling_distrib + + # Copy one sample (and distrib parameters) over the whole batch. + # This is used when doing experiment from the prior - q is not used. + if force_constant_output: + z = z[0:1].expand_as(z).clone() + p_params = (p_params[0][0:1].expand_as(p_params[0]).clone(), + p_params[1][0:1].expand_as(p_params[1]).clone()) + + # Output of stochastic layer + out = self.conv_out(z) + + kl_dict = {} + logprob_q = None + + data = kl_dict + data['z'] = z # sampled variable at this layer (batch, ch, h, w) + data['p_params'] = p_params # (b, ch, h, w) where b is 1 or batch size + data['q_params'] = q_params # (batch, ch, h, w) + data['logprob_q'] = logprob_q # (batch, ) + data['qvar_max'] = debug_qvar_max + + return out, data diff --git a/denoisplit/core/numpy_decorator.py b/denoisplit/core/numpy_decorator.py new file mode 100644 index 0000000..6c0d548 --- /dev/null +++ b/denoisplit/core/numpy_decorator.py @@ -0,0 +1,22 @@ +import numpy as np +import torch + + +def allow_numpy(func): + """ + All optional arguements are passed as is. positional arguments are checked. if they are numpy array, + they are converted to torch Tensor. + """ + + def numpy_wrapper(*args, **kwargs): + new_args = [] + for arg in args: + if isinstance(arg, np.ndarray): + arg = torch.Tensor(arg) + new_args.append(arg) + new_args = tuple(new_args) + + output = func(*new_args, **kwargs) + return output + + return numpy_wrapper diff --git a/denoisplit/core/psnr.py b/denoisplit/core/psnr.py new file mode 100644 index 0000000..d2431af --- /dev/null +++ b/denoisplit/core/psnr.py @@ -0,0 +1,63 @@ +""" +Computes PSNR of a batch of monochrome images. +NOTE that a numpy version and torch.Tensor version have slightly different values. +e9b29ba0b21f3b5fbd0f915309dcd18ecfee0f55 +""" +import torch + +from denoisplit.core.numpy_decorator import allow_numpy + + +def zero_mean(x): + return x - torch.mean(x, dim=1, keepdim=True) + + +def fix_range(gt, x): + a = torch.sum(gt * x, dim=1, keepdim=True) / (torch.sum(x * x, dim=1, keepdim=True)) + return x * a + + +def fix(gt, x): + gt_ = zero_mean(gt) + return fix_range(gt_, zero_mean(x)) + + +def _PSNR_internal(gt, pred, range_=None): + if range_ is None: + range_ = torch.max(gt, dim=1).values - torch.min(gt, dim=1).values + + mse = torch.mean((gt - pred) ** 2, dim=1) + return 20 * torch.log10(range_ / torch.sqrt(mse)) + + +@allow_numpy +def PSNR(gt, pred, range_=None): + ''' + Compute PSNR. + Parameters + ---------- + gt: array + Ground truth image. + pred: array + Predicted image. + ''' + assert len(gt.shape) == 3, 'Images must be in shape: (batch,H,W)' + + gt = gt.view(len(gt), -1) + pred = pred.view(len(gt), -1) + return _PSNR_internal(gt, pred, range_=range_) + + +@allow_numpy +def RangeInvariantPsnr(gt, pred): + """ + NOTE: Works only for grayscale images. + Adapted from https://github.com/juglab/ScaleInvPSNR/blob/master/psnr.py + It rescales the prediction to ensure that the prediction has the same range as the ground truth. + """ + assert len(gt.shape) == 3, 'Images must be in shape: (batch,H,W)' + gt = gt.view(len(gt), -1) + pred = pred.view(len(gt), -1) + ra = (torch.max(gt, dim=1).values - torch.min(gt, dim=1).values) / torch.std(gt, dim=1) + gt_ = zero_mean(gt) / torch.std(gt, dim=1, keepdim=True) + return _PSNR_internal(zero_mean(gt_), fix(gt_, pred), ra) diff --git a/denoisplit/core/sampler_type.py b/denoisplit/core/sampler_type.py new file mode 100644 index 0000000..dba5541 --- /dev/null +++ b/denoisplit/core/sampler_type.py @@ -0,0 +1,11 @@ +from denoisplit.core.custom_enum import Enum + + +class SamplerType(Enum): + DefaultSampler = 0 + RandomSampler = 1 + SingleImgSampler = 2 + NeighborSampler = 3 + ContrastiveSampler = 4 + DefaultGridSampler = 5 + IntensityAugSampler = 6 \ No newline at end of file diff --git a/denoisplit/core/sampler_utils.py b/denoisplit/core/sampler_utils.py new file mode 100644 index 0000000..99faf8b --- /dev/null +++ b/denoisplit/core/sampler_utils.py @@ -0,0 +1,11 @@ +class LevelIndexIterator: + def __init__(self, index_list) -> None: + self._index_list = index_list + self._N = len(self._index_list) + self._cur_position = 0 + + def next(self): + output_pos = self._cur_position + self._cur_position += 1 + self._cur_position = self._cur_position % self._N + return self._index_list[output_pos] diff --git a/denoisplit/core/seamless_stitch_base.py b/denoisplit/core/seamless_stitch_base.py new file mode 100644 index 0000000..7002be7 --- /dev/null +++ b/denoisplit/core/seamless_stitch_base.py @@ -0,0 +1,95 @@ +""" +SeamlessStitchBase class will ensure the basic functionality +""" +import torch + + +class SeamlessStitchBase: + def __init__(self, grid_size, stitched_frame): + assert len(stitched_frame.shape) == 4, 'Frame should be of shape (num_images,H,W,2)' + self._data = stitched_frame + self._sz = grid_size + self._N = stitched_frame.shape[-1] // self._sz + assert stitched_frame.shape[-1] % self._sz == 0 + + def patch_location(self, row_idx, col_idx): + """ + Top left location of the patch + """ + return self._sz * row_idx, self._sz * col_idx + + def get_lboundary(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + return self._data[..., h:h + self._sz, w:w + 1] + + def get_rboundary(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + return self._data[..., h:h + self._sz, w + self._sz - 1:w + self._sz] + + def get_tboundary(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + return self._data[..., h:h + 1, w:w + self._sz] + + def get_bboundary(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + return self._data[..., h + self._sz - 1:h + self._sz, w:w + self._sz] + +# gradient near the boundary of one patch + + def get_lgradient(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + Nd = len(self._data.shape) + return torch.diff(self._data[..., h:h + self._sz, w:w + 2], dim=Nd - 1) + + def get_rgradient(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + Nd = len(self._data.shape) + return torch.diff(self._data[..., h:h + self._sz, w + self._sz - 2:w + self._sz], dim=Nd - 1) + + def get_tgradient(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + Nd = len(self._data.shape) + return torch.diff(self._data[..., h:h + 2, w:w + self._sz], dim=Nd - 2) + + def get_bgradient(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + Nd = len(self._data.shape) + return torch.diff(self._data[..., h + self._sz - 2:h + self._sz, w:w + self._sz], dim=Nd - 2) + + +# gradient at the boundary of two patches. + + def get_lneighbor_gradient(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + Nd = len(self._data.shape) + return torch.diff(self._data[..., h:h + self._sz, w - 1:w + 1], dim=Nd - 1) + + def get_rneighbor_gradient(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + Nd = len(self._data.shape) + return torch.diff(self._data[..., h:h + self._sz, w + self._sz - 1:w + self._sz + 1], dim=Nd - 1) + + def get_tneighbor_gradient(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + Nd = len(self._data.shape) + return torch.diff(self._data[..., h - 1:h + 1, w:w + self._sz], dim=Nd - 2) + + def get_bneighbor_gradient(self, row_idx, col_idx): + h, w = self.patch_location(row_idx, col_idx) + Nd = len(self._data.shape) + return torch.diff(self._data[..., h + self._sz - 1:h + self._sz + 1, w:w + self._sz], dim=Nd - 2) + + def get_ch0_offset(self, row_idx, col_idx): + pass + + def get_data(self): + return self._data.cpu().numpy().copy() + + def get_output(self): + data = self.get_data() + for row_idx in range(self._N): + for col_idx in range(self._N): + h, w = self.patch_location(row_idx, col_idx) + data[..., 0, h:h + self._sz, w:w + self._sz] += self.get_ch0_offset(row_idx, col_idx) + data[..., 1, h:h + self._sz, w:w + self._sz] -= self.get_ch0_offset(row_idx, col_idx) + return data \ No newline at end of file diff --git a/denoisplit/core/stable_dist_params.py b/denoisplit/core/stable_dist_params.py new file mode 100644 index 0000000..92ff3cc --- /dev/null +++ b/denoisplit/core/stable_dist_params.py @@ -0,0 +1,54 @@ +from denoisplit.core.stable_exp import StableExponential +import torch +import torchvision.transforms.functional as F + + +class StableLogVar: + + def __init__(self, logvar, enable_stable=True, var_eps=1e-6): + """ + Args: + var_eps: var() has this minimum value. + """ + self._lv = logvar + self._enable_stable = enable_stable + self._eps = var_eps + + def get(self): + if self._enable_stable is False: + return self._lv + + return torch.log(self.get_var()) + + def get_var(self): + if self._enable_stable is False: + return torch.exp(self._lv) + return StableExponential(self._lv).exp() + self._eps + + def get_std(self): + return torch.sqrt(self.get_var()) + + def centercrop_to_size(self, size): + if self._lv.shape[-1] == size: + return + + diff = self._lv.shape[-1] - size + assert diff > 0 and diff % 2 == 0 + self._lv = F.center_crop(self._lv, (size, size)) + + +class StableMean: + + def __init__(self, mean): + self._mean = mean + + def get(self): + return self._mean + + def centercrop_to_size(self, size): + if self._mean.shape[-1] == size: + return + + diff = self._mean.shape[-1] - size + assert diff > 0 and diff % 2 == 0 + self._mean = F.center_crop(self._mean, (size, size)) diff --git a/denoisplit/core/stable_exp.py b/denoisplit/core/stable_exp.py new file mode 100644 index 0000000..a586230 --- /dev/null +++ b/denoisplit/core/stable_exp.py @@ -0,0 +1,63 @@ +import math + +import torch + + +class StableExponential: + """ + Here, the idea is that everything is done on the tensor which you've given in the constructor. + when exp() is called, what that means is that we want to compute self._tensor.exp() + when log() is called, we want to compute torch.log(self._tensor.exp()) + + What is done here is that definition of exp() has been changed. This, naturally, has changed the result of log. + but the log is still the mathematical log, that is, it takes the math.log() on whatever comes out of exp(). + """ + + def __init__(self, tensor): + self._raw_tensor = tensor + posneg_dic = self.posneg_separation(self._raw_tensor) + self.pos_f, self.neg_f = posneg_dic['filter'] + self.pos_data, self.neg_data = posneg_dic['value'] + + def posneg_separation(self, tensor): + pos = tensor > 0 + pos_tensor = torch.clip(tensor, min=0) + + neg = tensor <= 0 + neg_tensor = torch.clip(tensor, max=0) + + return {'filter': [pos, neg], 'value': [pos_tensor, neg_tensor]} + + def exp(self): + return torch.exp(self.neg_data) * self.neg_f + (1 + self.pos_data) * self.pos_f + + def log(self): + """ + Note that if you have the output from exp(). You could simply apply torch.log() on it and that should give + identical numbers. + """ + return self.neg_data * self.neg_f + torch.log(1 + self.pos_data) * self.pos_f + + +def log_prob(nn_output_mu, nn_output_logvar, x): + """ + This computes the log_probablity of a Normal distribution. + Args: + nn_output_mu: mean of the distribution + nn_output_logvar: log(variance) of the distribution. Note that for numerical stablity, this is no longer a + log(variance). We define a different function to get variance from this value. This is done this way for + stability. + x: input for which the log_prob needs to be computed. + """ + assert False, "This code is not compatible with Stable exponential. Ideally, StableLogVar should be passed here." + mu = nn_output_mu + # compute the + var_gen = StableExponential(nn_output_logvar) + var = var_gen.exp() + logstd = 1 / 2 * var_gen.log() + return -((x - mu)**2) / (2 * var) - logstd - math.log(math.sqrt(2 * math.pi)) + + +if __name__ == '__main__': + stable = StableExponential(torch.Tensor([-0.1]).mean()) + print(stable.exp()) \ No newline at end of file diff --git a/denoisplit/core/stochastic.py b/denoisplit/core/stochastic.py new file mode 100644 index 0000000..b4b7379 --- /dev/null +++ b/denoisplit/core/stochastic.py @@ -0,0 +1,285 @@ +""" +Adapted from https://github.com/juglab/HDN/blob/e30edf7ec2cd55c902e469b890d8fe44d15cbb7e/lib/stochastic.py +""" +import math +from typing import Union + +import numpy as np +import torch +import torchvision.transforms.functional as F +from torch import nn +from torch.distributions import kl_divergence +from torch.distributions.normal import Normal + +from denoisplit.core.stable_dist_params import StableLogVar, StableMean +from denoisplit.core.stable_exp import log_prob + + +class NormalStochasticBlock2d(nn.Module): + """ + Transform input parameters to q(z) with a convolution, optionally do the + same for p(z), then sample z ~ q(z) and return conv(z). + If q's parameters are not given, do the same but sample from p(z). + """ + + def __init__(self, + c_in: int, + c_vars: int, + c_out, + kernel: int = 3, + transform_p_params: bool = True, + use_naive_exponential=False): + """ + Args: + c_in: This is the channel count of the tensor input to this module. + c_vars: This is the size of the latent space + c_out: Output of the stochastic layer. Note that this is different from z. + kernel: kernel used in convolutional layers. + transform_p_params: p_params are transformed if this is set to True. + """ + super().__init__() + assert kernel % 2 == 1 + pad = kernel // 2 + self.transform_p_params = transform_p_params + self.c_in = c_in + self.c_out = c_out + self.c_vars = c_vars + self._use_naive_exponential = use_naive_exponential + + if transform_p_params: + self.conv_in_p = nn.Conv2d(c_in, 2 * c_vars, kernel, padding=pad) + self.conv_in_q = nn.Conv2d(c_in, 2 * c_vars, kernel, padding=pad) + self.conv_out = nn.Conv2d(c_vars, c_out, kernel, padding=pad) + + # def forward_swapped(self, p_params, q_mu, q_lv): + # + # if self.transform_p_params: + # p_params = self.conv_in_p(p_params) + # else: + # assert p_params.size(1) == 2 * self.c_vars + # + # # Define p(z) + # p_mu, p_lv = p_params.chunk(2, dim=1) + # p = Normal(p_mu, (p_lv / 2).exp()) + # + # # Define q(z) + # q = Normal(q_mu, (q_lv / 2).exp()) + # # Sample from q(z) + # sampling_distrib = q + # + # # Generate latent variable (typically by sampling) + # z = sampling_distrib.rsample() + # + # # Output of stochastic layer + # out = self.conv_out(z) + # + # data = { + # 'z': z, # sampled variable at this layer (batch, ch, h, w) + # 'p_params': p_params, # (b, ch, h, w) where b is 1 or batch size + # } + # return out, data + + def get_z(self, sampling_distrib, forced_latent, use_mode, mode_pred, use_uncond_mode): + + # Generate latent variable (typically by sampling) + if forced_latent is None: + if use_mode: + z = sampling_distrib.mean + else: + if mode_pred: + if use_uncond_mode: + z = sampling_distrib.mean + + else: + z = sampling_distrib.rsample() + else: + z = sampling_distrib.rsample() + else: + z = forced_latent + return z + + def sample_from_q(self, q_params, var_clip_max): + """ + Note that q_params should come from outside. It must not be already transformed since we are doing it here. + """ + _, _, q = self.process_q_params(q_params, var_clip_max) + return q.rsample() + + def compute_kl_metrics(self, p, p_params, q, q_params, mode_pred, analytical_kl, z): + """ + Compute KL (analytical or MC estimate) and then process it in multiple ways. + """ + if mode_pred is False: # if not predicting + if analytical_kl: + kl_elementwise = kl_divergence(q, p) + else: + kl_elementwise = kl_normal_mc(z, p_params, q_params) + kl_samplewise = kl_elementwise.sum((1, 2, 3)) + kl_channelwise = kl_elementwise.sum((2, 3)) + # Compute spatial KL analytically (but conditioned on samples from + # previous layers) + kl_spatial = kl_elementwise.sum(1) + else: # if predicting, no need to compute KL + kl_elementwise = kl_samplewise = kl_spatial = kl_channelwise = None + + kl_dict = { + 'kl_elementwise': kl_elementwise, # (batch, ch, h, w) + 'kl_samplewise': kl_samplewise, # (batch, ) + 'kl_spatial': kl_spatial, # (batch, h, w) + 'kl_channelwise': kl_channelwise # (batch, ch) + } + return kl_dict + + def process_p_params(self, p_params, var_clip_max): + if self.transform_p_params: + p_params = self.conv_in_p(p_params) + else: + assert p_params.size(1) == 2 * self.c_vars + + # Define p(z) + p_mu, p_lv = p_params.chunk(2, dim=1) + if var_clip_max is not None: + p_lv = torch.clip(p_lv, max=var_clip_max) + + p_mu = StableMean(p_mu) + p_lv = StableLogVar(p_lv, enable_stable=not self._use_naive_exponential) + p = Normal(p_mu.get(), p_lv.get_std()) + return p_mu, p_lv, p + + def process_q_params(self, q_params, var_clip_max, allow_oddsizes=False): + # Define q(z) + q_params = self.conv_in_q(q_params) + q_mu, q_lv = q_params.chunk(2, dim=1) + if var_clip_max is not None: + q_lv = torch.clip(q_lv, max=var_clip_max) + + if q_mu.shape[-1] % 2 == 1 and allow_oddsizes is False: + q_mu = F.center_crop(q_mu, q_mu.shape[-1] - 1) + q_lv = F.center_crop(q_lv, q_lv.shape[-1] - 1) + # clip_start = np.random.rand() > 0.5 + # q_mu = q_mu[:, :, 1:, 1:] if clip_start else q_mu[:, :, :-1, :-1] + # q_lv = q_lv[:, :, 1:, 1:] if clip_start else q_lv[:, :, :-1, :-1] + + q_mu = StableMean(q_mu) + q_lv = StableLogVar(q_lv, enable_stable=not self._use_naive_exponential) + q = Normal(q_mu.get(), q_lv.get_std()) + return q_mu, q_lv, q + + def forward(self, + p_params: torch.Tensor, + q_params: torch.Tensor = None, + forced_latent: Union[None, torch.Tensor] = None, + use_mode: bool = False, + force_constant_output: bool = False, + analytical_kl: bool = False, + mode_pred: bool = False, + use_uncond_mode: bool = False, + var_clip_max: Union[None, float] = None): + """ + Args: + p_params: this is passed from top layers. + q_params: this is the merge of bottom up layer at this level and top down layers above this level. + forced_latent: If this is a tensor, then in stochastic layer, we don't sample by using p() & q(). We simply + use this as the latent space sampling. + use_mode: If it is true, we still don't sample from the q(). We simply + use the mean of the distribution as the latent space. + force_constant_output: This ensures that only the first sample of the batch is used. Typically used + when infernce_mode is False + analytical_kl: If True, typical KL divergence is calculated. Otherwise, a one-sample approximate of it is + calculated. + mode_pred: If True, then only prediction happens. Otherwise, KL divergence loss also gets computed. + use_uncond_mode: Used only when mode_pred=True + var_clip_max: This is the maximum value the log of the variance of the latent vector for any layer can reach. + + """ + + debug_qvar_max = 0 + assert (forced_latent is None) or (not use_mode) + + p_mu, p_lv, p = self.process_p_params(p_params, var_clip_max) + + p_params = (p_mu, p_lv) + + if q_params is not None: + # At inference time, just don't centercrop the q_params even if they are odd in size. + q_mu, q_lv, q = self.process_q_params(q_params, var_clip_max, allow_oddsizes=mode_pred is True) + q_params = (q_mu, q_lv) + debug_qvar_max = torch.max(q_lv.get()) + # Sample from q(z) + sampling_distrib = q + q_size = q_mu.get().shape[-1] + if p_mu.get().shape[-1] != q_size and mode_pred is False: + p_mu.centercrop_to_size(q_size) + p_lv.centercrop_to_size(q_size) + else: + # Sample from p(z) + sampling_distrib = p + + # Generate latent variable (typically by sampling) + z = self.get_z(sampling_distrib, forced_latent, use_mode, mode_pred, use_uncond_mode) + + # Copy one sample (and distrib parameters) over the whole batch. + # This is used when doing experiment from the prior - q is not used. + if force_constant_output: + z = z[0:1].expand_as(z).clone() + p_params = (p_params[0][0:1].expand_as(p_params[0]).clone(), + p_params[1][0:1].expand_as(p_params[1]).clone()) + + # Output of stochastic layer + out = self.conv_out(z) + + # Compute log p(z)# NOTE: disabling its computation. + # if mode_pred is False: + # logprob_p = p.log_prob(z).sum((1, 2, 3)) + # else: + # logprob_p = None + + if q_params is not None: + # Compute log q(z) + logprob_q = q.log_prob(z).sum((1, 2, 3)) + # compute KL divergence metrics + kl_dict = self.compute_kl_metrics(p, p_params, q, q_params, mode_pred, analytical_kl, z) + else: + kl_dict = {} + logprob_q = None + + data = kl_dict + data['z'] = z # sampled variable at this layer (batch, ch, h, w) + data['p_params'] = p_params # (b, ch, h, w) where b is 1 or batch size + data['q_params'] = q_params # (batch, ch, h, w) + # data['logprob_p'] = logprob_p # (batch, ) + data['logprob_q'] = logprob_q # (batch, ) + data['qvar_max'] = debug_qvar_max + + return out, data + + +def kl_normal_mc(z, p_mulv, q_mulv): + """ + One-sample estimation of element-wise KL between two diagonal + multivariate normal distributions. Any number of dimensions, + broadcasting supported (be careful). + :param z: + :param p_mulv: + :param q_mulv: + :return: + """ + assert isinstance(p_mulv, tuple) + assert isinstance(q_mulv, tuple) + p_mu, p_lv = p_mulv + q_mu, q_lv = q_mulv + + p_std = p_lv.get_std() + q_std = q_lv.get_std() + + p_distrib = Normal(p_mu.get(), p_std) + q_distrib = Normal(q_mu.get(), q_std) + return q_distrib.log_prob(z) - p_distrib.log_prob(z) + + # the prior + + +def log_Normal_diag(x, mean, log_var): + constant = -0.5 * torch.log(torch.Tensor([2 * math.pi])).item() + log_normal = constant + -0.5 * (log_var + torch.pow(x - mean, 2) / torch.exp(log_var)) + return log_normal diff --git a/denoisplit/core/tiff_reader.py b/denoisplit/core/tiff_reader.py new file mode 100644 index 0000000..0a540b3 --- /dev/null +++ b/denoisplit/core/tiff_reader.py @@ -0,0 +1,19 @@ +import numpy as np +from skimage.io import imread, imsave + + +def load_tiff(path): + """ + Returns a 4d numpy array: num_imgs*h*w*num_channels + """ + data = imread(path, plugin='tifffile') + return data + + +def save_tiff(path, data): + imsave(path, data, plugin='tifffile') + + +def load_tiffs(paths): + data = [load_tiff(path) for path in paths] + return np.concatenate(data, axis=0) diff --git a/denoisplit/data_loader/__pycache__/allencell_rawdata_loader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/allencell_rawdata_loader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc365728b1406ece72c55d79386f8a4db42bd1ce GIT binary patch literal 3684 zcmcIn&5zqe6rUM?=3{ruQc9Qd5kWy1O1A4Hr9f4I+5W{Ok^9LB4wyLDn(3*w4v_kL&GuPUG=ql z#4&x{H=wQfreA@!>eDS^RUgA_WYeN~H5$2oHw}Be#A5l3)!Q zeSi{#y6NsX3KCDnZ;u{ayaq*qlKcWyAC~wN{hp>IW0{iD2Xsbf$~VeXooZA4KJ8JT z`N};r)31{mof-mB1)>VX6o@7eO(2zwrfgf;VSId_!1ub4nJC*LLZ*W32O%?rta41I zf$V1?Glk43WIh2iR5q|zxWKd!yg%T?{lvqik#7Y(=R?;Xj2@hMs!K`+$Zn}yjMaF>uxd#l0ma**1eG*touPc3Pr##x+2i8W61B~#SrjyH;RJT3!Wzlut81YDFDPX4K3*Crcf+`Q+l|Ea(F@_;XkLj%o*N}sp)>#L`Kby* zMWur_Ucm~<^BPugg_2jWvjo-uGW)q_&W`I5+k^`c+q61`dvKfXGu*5LR&177?V*yh zQIe};Hyz~a_9%=G88_g&ToW4yJ81YJ$2~m3?)CpfKVQaaR7JRgRCxe7&WvKlazLjHNw{S2X@w|Rq``dsdXn8^#v`$UR--Et~rky_+67a)oP?F!E zg49$brwam<_u#Gj)Udd`JWWRoZ zYp7zfnvONh*2+;2=)8h65U(6}~m<2Z`&>kK5rkjGFZCXV&_p{1V8m8ef4X*W%sbcu&xA z&WUSP+@(!##KoVAUY7@Wp$fa?Z=4(3`13LqirT_o{ literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/base_data_loader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/base_data_loader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43c7d7c273a2c32a2552b4fdcde5ba4ba209b983 GIT binary patch literal 847 zcmb_ay^a$>44&Oha?5c62}%&!f+kmFUjU&KKSD@on{;VLbFq_**qvEC6Lh4YfP0y| z(zZMT9Tj#~~@)%Ns#)7IFai$z@9P%J$av~kY5RbgY{UEzGhbMHTf zUD7?Sd^{u|ye0C);X%N9xl?q+4SrSS+BaC5u*R^S_NH8Tz!K1TJ8NqjdpGnhGuQQ= zdU?*1Xt)YY+b`Xd7D)#SsQqW8+O)d07g#U+#zk3hkoi=yJ-xYx>0i?ReMKb2N!rj* zluX#GoW1Vh3Zu4gp&R4O3Tec_KYX6u;&bcif8#Kg!Yi`COWNYSYYd*=!Qk+)nvA+! zYiAnNx;xgo@vy1IKhgTr#?<`{NkNitPWMG!Enx4-7DzssAjtT6nrC^ok5!XoZ|_R# O@)v!>my-FDp?(7tu*L@f literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/dao_3ch_rawdata_loader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/dao_3ch_rawdata_loader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e98b8140c875c1ff25540e5a097662f3c587f713 GIT binary patch literal 1550 zcmZux&2A$_5bhp({O{Ot>|~QbHb6i!+O?C7#0ddX!U4qQfO8sY)tXF~?Qwc$ygf6l zHnN07_PP?+MVz?pBk(GH<%GloAh=M~_7aPwM^p1vb#-^uSJmS;n>B{xkMH^TRf)0R zNLe3cRKCDB-R6u*Cb?oBeI3Ok$18Bc1yzh(&$YOyN>SM>TkNVzRQ0MBb5--|=vz{a zsOdGWt*kbpme-2fUfb#wwHbB1j>T2A6?MI?#Wln|4+D^O*?7Uc9od7HZ2rvUhHSlX zy&l|??Q7>pt~+?b`pQkU8|`^}oWb5L^Y)=Tdk6N#yRzdQKo1UJA6m2fatojCOV>Mu z_uzdvyydqXSA6gWpR*_Tyd#`Df{wN+yxz za|J27S5@Lmk%i+iD)mu*b)JGq$3zIuG}@Z|V-fXCcyuUn5#9zOaX`y;Y{a!UTMnQq|DcjB+h;WUY0=%-Ui zr-S8Z7$g#g65=GZDKDW-bx27I$`Ul;g_9K*g+)>F zmnBQrYsWN*N%;s7>865G3(9oah$rr#DG-NZe80B(;vBi?3ya@is4V=gsrCoi!C9B5D+Y z1l7*$rsrXh-F!Tp=p>&HXZd7RGFy=0xu2Y_BL8;TCd0{3uW0=GxhB%Fhc5ab87E0i z!A~tV@S-5n|b{lhd>`t8l=G6@aTaJq^f-h;Kx>^{qG z9N2cFE~9=Fa%r`twVdi6ok2}U?8bfsLYTcsiS@*n^%D}g*1P1tLxPH>w@7TGFzzK? zVpF8UjXT$2oSA}x*tp2n1Pl+2n@)X9>#pz?QT0vb(1&8<^1+`3|6_yTSvL#mz6%d9HLz-{wXrAbrgnM%}U zEkG6IRmu~UO{XCEAAgd}vPo^@R7?-{hje054aqMOMB1xr;T_w}39LF|n82>`#J-GVs zuST<~5Tmr2iDq`#Eu%@r#fXct%1mxM)*v!6;2<1AjzsZIo;0G!nnj(+^t%n)VST9| zo(lzP{HFv>H;^vsTr^v7cN1Ygs84P72HmF-m9K#enc3R#MpzNX+ktxmmzXZ{4cP|S1wd)*JR_X7E>KIkYY)MGMt*izloI8)&Wf%B70!E503OJozmxrz zDR&+{W>U3Y>vQ`#J0+^$dMgUlU(v^``SD}&gsLqphR(9GzP6UZGFB6U(Aa=(*mlA87ub5n2K46kJq{5+fpUhza>rNECjduQo)13FE{?Cf z!CQlq+0pUU&fqSMg8~3O9x`ne*@b2&M_0R93008smp;RLnpKUq>r~COJ+HDd4!}E^ zq9P6^v!jmHPA#GQB=(oK%d`*@pAe|c2D?=vINF;+iKutp*477kuB}{@23zf%VF_yM zi!|5v8C0qcKDwBQ8cTN=X%8djnbbXGl1WugvvYYLPLw-Hc7eo!i70{CZdr&e_RS7d zb{yz*USwD1DkfrMNwax%V_>4&dq z5An@Qq`-FT(tPl$hxu=ld2AE?=KtDnS`YC-+zc2d=#4Dkb0AGB{CA;V7P)v2AE#yy Qh;2p8hfa;U&+@~60ZT-?A^-pY literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/exp_microscopyv2_rawdata_loader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/exp_microscopyv2_rawdata_loader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5864365ede22a73e5fa29865bf961962176dfdf GIT binary patch literal 1861 zcmZuyOK;mo5aupLiIOE-mLKvXu@lElts<3*AV5=~XbZ%-6s<4Li9oQRxhskG@{#4r zFDNKb=Ncf_7Cp4R^(XYN?6oJO{~)K%tei+lx&(*c%r0klX1*cAMx*Ay`1dE$Z~2b% z4=S^x0?K!A7Y~TzaEBA=1o)(qBs6ddVpoVg z0iK(DO|*FPH^LWr>y;O*iCcW>guWqa4|bjPuqW2s9kI>s@|9pm ztce}5En3I-_$plO*IuwIJ`wlD?iINr@W!X_@V@hWBiMtvJ+UkH)*%b)&T;3866Xzh zQRn2)>8xL49uGRi)Mc!N3MCV#p##5@G3wxX|z{$B7alN6XW6 zlyscAC$Sn(b0Y(>>HrA@Extf zIAw4M`*wuqn;jICCvX=)1ZM!X{uAS%2Oama_4GU!Do#YIKY#S-%WiZTe_;FSe{7G@ z_Lrj?;BPA4KJN{)MD)U9D2ics^5{hw7d~#3=Ly+h*|&{0i)j!7f=~)8~^THXJHG+zkFvBM57at1RhuYop_noaGo|VvcHk~rARN*pB|@jy zTRU%j#uDrc26?MJv2OR{NMH7P1C@>P-tlN~!&S>fq+pm95bz8U+3CaH;MZSp{QYf* zPEQ2wbI|$B(5x_SSZIZWFtsE+5tF_(3sEMeun8=>;ZdZJJf^I|lxK-T)|fJ+FHQ#v z3uip|B;*%r8F2+zgw$5ZT(yLzP1{1Y^4%y?q8p70oh3}bYYIQ+X8XexHl0(hDC~ZP z1o_w*ep?uRoP<*N-!KnmoLN7UHtpK>!=qt;GCr|d2H2ddZQKK!&{h{qkcNq1%xol* z&1Pg$X2zi)>K?AYi((7KZ4`Gv81ET=*i_r%T*aw2t`w>9Ad3TGNNl`f7y<>S^svZw qlmB&+@sSkYV8a$)fbdCua#5cmYECrQuljy-u4c6|@qtXscJ@EsuI?ZJ literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/ht_iba1_ki67_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/ht_iba1_ki67_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..545cf940e4e955b918f4918a2f96e23d276fe662 GIT binary patch literal 1481 zcmZ`(Pj4JG6t`z)cW3`^($F?s$O)9oPMTKqQbD09D538g*{SJZl$5(Vt8if3c zO1*VKc?`q+1d}9^MkJ<;Qk0#@iCyNFvKx7EgEc7mm`G1HUJ}_*jcb=RRZBL{9Q`Bg zZ$*CGW^GDT`px44nOtTHB)b3s7;2@LZHrYo`{S9F);bmag#cXM~;ed#27HG2c>2Vif4-OpQ+UemAX zl>_mdll9JV@`Z>(xo3*0gyi>fyqnJkd}H8fFd73h|Fa~zJf4bs8gsDT(`cG99}ST5 z1A7PcPs0l(pQ~A#m|PdLJWLbYetI!e8H)R^^^A(<*2iExlo!^I08x~FAi4)`|9T!Q z(^v(IBN;bDoG;ac(=D$EhqLlzW_iUWlk#(F5>XUZghl(FR`y zX~HlFp6`@8dW=Pwa1MOxU^oD79xm2Tf`v|tELatb4HAKbdj_Yunu{b9!QsK-{e%05 z4>_`hi$rp)1J5;h3zG$IUVQg0wx8dhd=&l$1q^>_0f$?5fQuz|WpQl}7{KRRRK@D& z%H;p3qa@WaFl4PH50k9O?VvD++v5dbxe0t;PJl-ti^e4t>mbE=YJ07 z=P55aw_%0$Zfc^3AhEY==c*c*dawtZ!suJD**2>kwlU8{zO)`@Vf#lgm+ZtJf^AH& z6s)z0XGgO%2KWFrC6W?2zmxzW+X5UBD%-=a;`Ig>0Jm-~w8np{#$Tv)BbC@jro$w! t5e(U^k!99@RPpjX3Yr};qY!t>mO^8_;dbZo9YxGi1S1R;^zKs;(wGxC5baP}Iqp(!}!Y=9pogeKZXMmt%7>JbXdN)hEp%N*45W{Y75UPz_+flNfYsd7o1)VXI7;AVKQz-rvY@DM{2t23+nTSKDw+0M~E8RXOIe4Oium%Ttpa_W7LNA$MqxaTjNIO-2}c zYO3(S*;NJkU(r3#XP@qpqS~Jx*_0e<_cfJI7FF)S-9WxzJ$8n`ikZDx7_05GVYR4& z)9Vk*w96TOQ^r}$r_zj!2ldpb%%w}_uRM(6_@VhLc>c^n$XvU5YK zNT2SpU2t0g5jtk!mZez+p@R{m?S2-eEhaIiXu1XWZUy(@k<<+imt>G{-cS$__bLDK z@$u^K;HAaS^<!}rLFhFSleqNSGxN8R#yyEl%*z;wT*z0PoglqKeVmjl4;c> zVn)}^O$wQ$7p=>SIMP7a^kmpY33@_-$m6bGEs+)REnPuAX!xFCftGyQh)0RWHZ9BS zAs1j+K8wWUpP2^{`V>s&h#o>+R)b7bga15G2A@ag#wqjI9E{D=hTEi&tzLswSf3;a z`2Z4W?V8bMIqItI4?6GVLgx1s9m`pFGZCrEJIh!-323~z7OX1K3)3j5sfX}GC>UgzVy6U(!42kb zV-|@~pdU@*pqs_9FdofeJ9Kuy!9MaDvMwPpurmQ{a>->JyNcwvfIGpv_Lj;T@Cx2t cIYP?=w=}>VO{?j6HoW!bGamF^aFtE}1~93n4gdfE literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/intensity_augm_tiff_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/intensity_augm_tiff_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8524bad1dbd62854e38a363745ad61049b2046b6 GIT binary patch literal 7200 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 literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/lc_multich_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/lc_multich_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ede361fbc5119f35be3de95f43f9444cf6b36a31 GIT binary patch literal 7661 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 literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/lc_multich_explicit_input_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/lc_multich_explicit_input_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b9ddea7fc35388a5467a06765008e1ee9930b52 GIT binary patch literal 2373 zcmb7F&5s*36u0LqlWe+LC?G0YWYkkcl`RM%kd_rv%U1>4!4lTF+ANWgr?9RklEKhWVU zA>?=bSbZY+_!OG?2#g?tmZYKsS_OlE;&)Jng9zSX8CS_5q2vo9A`u@G5zFK#9JEBR zOM1yOSWS9?i|TfLqS{ylgmJ- zao+DQr}DZ2kIVv`Y`-W=I9y&&wUO*DobWVSvuvlfaG-H!eP~tdDl3awp+>7$*q5w{ ziLMgPnOVbzx~^CT(Qzn;!zx*tRUG>4wvwzWMq|tNGiC8k{>uLn3*$79E~Bwpm52T1 z8UX(6389A+z_FEe8}KOukd&2e4H&CHCY8TXsl zW?l=qDWs~4UEq>!x~Ay@QFz1d%`)c|@;x7Oxg=e)FBgqRe{!hXaL`xqzF2*PuG85E z=Tf!*&sWL+AC43ego1jG<4YrmV=tWD_KC&9_!6jkjR9k{tm?gnFo>EbY{T$Xej=eU z@gC=fk{D%2x8Rn&K&S9>Z!H-EsEA^(5YwzY%aTT|((7n8&>%+oRWPqZYru*CtdGwJ z>zoZhkYZosc>oblpEc+p1#dtzzk!*PCuB~aQlMb42ff_d~PoJ)(QDh(&UYRBa(uFOi!B*NF7TU=eu&w{Ub3!%oRO_B$nu z);yU(OozloUOg+c%P2)Vo)cV6HUf`fqULNjlI8382UZ!D;MzXR@nLL;+J&d(v|K>5PTiu3+f zS?5`4wxM$xr(qOzQFc(6Ue~4Q&S7u2!KKRXmXhnbQB41)s!?b7ui4HDW3Iy4PZ+M%=Fe+Ip`2AFb{Rg!bp;k>HF6hP&!%lQK+ z+2u@&b5ZAl8uiu(T{**ZqNZETHMg;R M3{rao5bTD318$X-F#rGn literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/multi_channel_determ_tiff_dloader_randomized.cpython-39.pyc b/denoisplit/data_loader/__pycache__/multi_channel_determ_tiff_dloader_randomized.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43ef02bb704266d45702aa24148dc73cd73cc1ce GIT binary patch literal 1170 zcma)5Piqu06i?<~r|Y&B1lq&<^6tnp=)ac1oHa}uD{0!{S1rClEC5#4Eq2S zLnUIEMG`kr8R1~ZGABQ67GpQ-#rV0UF~eW+3911Pi;st8a)J_6rciC-@11Alj+;g( zVV$Vnh`QdPiY>1RB?!g%=PK&5_bP)a4B!%332K4%ka_3u5ju?)_zb^`4x_`^#e2zV z>f+PPtt`+H_|Nbmz7mxj!ahXhXTbCO#Oy4hMOsI@Xpt=9FstE3{4QeP8N~;3P%LGK zySY*JALG@GD#fK87yV1r+7!-E0H>z#F7PG>!0ATr7nRX%%UN-LqON$(2vS<|y-t z<+3&@BrR_)s|X3Uh}^p3*uL(7i0$hU+utx$MJfrE6Y>rH*_+IC!za|vxSfsrX;Nv% zCyXmCc3UZ2Z`$6Zj*`BqCQaxuvSfs?t}%#%mLRN;AU!^Dz}dLnH#uNfgJCy7p(Mi_ z_zsM9oJWJ?VDmp3Y2ZS`5&1JBMgnXD&x!j52dvw?OwI%3^OG${i z1qJjf)M9Q275>Bx7&bI-9(C(c?pFw5x`Nc1+i#&UOxX6Rnl}JxHQ4t%sycqg?1G>1 nN2-LB^qdV7K0ufC()C>-;d-Ax>_I%ju(E-xBpyb2G>rcOE~-lv literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/multi_channel_train_val_data.cpython-39.pyc b/denoisplit/data_loader/__pycache__/multi_channel_train_val_data.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c1080b24545faa898be61c0e10ab0210e5ac2d7 GIT binary patch literal 1522 zcmZux&5s*36t_L&`A8-oR28u80=Y(7C8FFagrKDdP>GOs;Sg0Cjbdjr>C9yCc-!4* zA|%2Q{sKVSy&!Sr&+(PhivOS-%6p!)O$#3R`F;6~-+Mnh>2z8I#^2x5`H@e^UnuMk z7lcn?Rv8dM1kFfJr<5YkGB$N!buu^SQ*L!`=H>p>w>-~+Je-D>_p(;rp0@L78i5?i zw(x(YA`sz^eA*G6o!k;_kh_8%lVSH7{z!(@@NbHARZM{Ei9{!HRc5J<^+hQ`6=thM z#5$eNK?ptv`w1GD=^%fMuBb3KPo<7=`)>DHnaK*aboX@NH{S$h*E!}Xid)i+HkC}Q@bHNYDhU@UM1-vKx zD+fIIW%~-XQO#=`7h~2=?TX-M59$z3*1)zmLsuzR%i=-%IRt=ufqjmr2 zWe$UUCFI>98%?e$oc9{L2epWvBw0LH$xK5bO-IX0zZ8cZ!%LMG+Jv(vYW(3V_Kw0L z7`I4rsW6%e@n^RB3TtILUn}`U3Yoh^QhY9gOXw?GK`EgYaxRUaWFCPO62h7Ncev&miBi zki{yst!`M`;<1g3=#XlhpJh6YU*z}tQAXv3>AtSQrdRI+A@mjvo(C+T5zHSj7AZOih-6nFFFJ^w!z3$8L4_CE#aEe*h!_en5N5<_vH_ zYO2}N0i@ik$)&6L(z~L^MEkW{a~&X_w$3AG<8Ay+V0}aIRW+%-gFSz1X@TV@u=xM6 zw88Q_Sb}|vj)aRR5(MzZC)dwmtovUS(5+Mqc4ezZ>$lRK3TtbtjOeKr30yEIPtF^# zIG<&i@sbK}sJaP7F#a6+pg+2!;DsT^$z);p3F5&x-zJ%HPXLf6d~iOKB_ebfs$1aL zprMCcAIU3RgiX6rac+D>6f%KDHEn3Z=uuTybyruN zI`y6JoT_n3rM!mg&p*(cKYd=)KA_6vWubBjDfkI8p$Xm78anQVXLQVlsnavlvpT6p zip!Rl?qnJnE~mU~C)dbvIql^;g+`%MY!tbk@k*U?qs-;3SLsw6Rb6{s6FHH;r-{7G z?VF7S)C;1BdQnzUUqrnm%BYw3jmDDDZ)o+(1IVSV*Y&t`#R;7oJ+B?!yxWs_kfjHM z^1{_lFTDG0Cv-QiNn}!?LG}9Ow|2a+eR<=G*L4J*8FBe_)fQj(+AUvpq#wprs=wh2 zdFL(1cUt`2VoQd0sGPQM?>e3>FbsMtPxs}LT$5L2PzgK~Bx|u@2z~HNN|bX+nwu8N zX0swwGA%PQD|0dUd)0(jkQGQRev_=Iw zD#z6uZNKHoYi&mzS_MC7dF4GJG(wrSab@7t)om-x?RX23PcGtI^ zomQOpcRF_9I-U&Ta?cS0J=$Bh9n}irs^fXx+jdL(Qt=n=(!|WEOvywFUPcz_k!EY5 zzOQW>krA1Z6{Vtdl!>xYF3LxRs2G)^a#V?`(L%H+^!p106HLTduUAwNJ;X&)d{a3t z$rqPG8HD3%)$gi~4(N0HFF8c!;8wJfr%{%sfs4Z;~bgEn5=7Frs$1$T z+Qg{@v!*Bg7%EODll&B3&4Q6^=pl_0Lb!)l@iri>X~4o9osSyU&Gq&5dX>z>cRJFx z@>l~3~zROu^EI)(F|kjR=4ZLCX6t)MB5D+k8!pK zo0lrQtKk1Mb)K>psCj8%2(I)z+n$)ir>O}+N0INOMGd}$ESo+K%oc(CFNTTSGU(Ec zkE`blJ#S`B?!(3BQx|ngS8xm29A`0b6eBlL9JmQ`5!Qr@$R-Y=k(2qvLBLfMMlPbr zE~3OPqC5uFz(E{Y6YN3^$|T~_f(|b#Qz9b>E+TteY6q#a?`Kj!D$ast%wWu0Ok)hB zIh3W&VBC5&L0}DK#V~v{F+N7Oyvl5>ywt>9-#`jz2(9`^?)tcYa$1{X<|>FDgHR zI@D+JegbwZ2EmgsG30?S&kXblSb&BeUQ`~5LiUr;XToEjL0#1;o8~Sy7>VaY&O9|E z%$PA}8HY^%GJSay*^qIB9_hQ9x&r3WH_g!6H`En@@~##<_ontPm}nCr5xql7wTz~* zsvV>c6Sm5X*ec7hg0&v!+zrR~rDwk|E?!)#=a|CO=P+`dhd=j&(D7ZVzJ>>iI96Sv zSC-p_%UYxQ12hpIgWxc4MHTtuPn4z(Ii5$< zS`pQITB9r$#3Jq$u_TspuZk051@{GUQk=qlQLKv7xG#w_;w%cnBUIuos=J8vY8s7-2!VCB4~~+Bc|WyRZV}?GFcqew@;*HD z744m0?NumZUe(?<_Nsdeu#b$;c69YiE?HX^O4_D%kPUNDRcNb3)C<#*w@6XjQT$y= zdKcCyZOahp`wNGyaznI6x zy%W)igW{pKw-PNyE5cgUUeflKqGgnGTwabAQO%u#ESW&FcHuT1HFA3(+$2Vzl_a_Vdg>X2zURT921*VbKQB7(xm^1StMAT(P<_ zjE zRCDKRF5*SJsV}JK&^|V?C5@NuIl`+fy-!gH9>gi-_}Ie|sl_K5_`IXD2U{HOG)`mt zB7MPu36la75Vkr9PMOhz4F>@eF=d?MJ&k%AW#+W{$%#ntab55nr653qmBxCzQNiw~ z$y@d$Vr&#Rmbb$l*le6)ksEnv%TBb_$WfU!g-$SQY^+$`8R{lxy^Rz^$h1mYFY6Y5 z9K!u8ok|;3Q2DZPoSz@GMEmlG*1yxs$F<}B^zuh&vryy_EIkiLQN*umEb5DTe`Sia zjt><^KJy#|2A**kvtcossHpc}o|g9$L>wl18eTM;6cV!^?I~zRV1VkL8JXkRY^TS24@13) zc5#s>AswG~@z{{io-WRI=mBlXGk8h`bpy{QTqJwP@8Q{RkOCTB!%Fl|PtRtu?}s*+ zWST55*>bW1h(Pp1+Gs-4WWJz?L`bq0mWhrU<^@mRN9*4r4I{Z3K_gEQXCn7 zOWR`?0p%_3AzXs;41xd?Zay>*tVln^Ss4d&^%Tpe-ol4*#qD-*Jc1LE!EuJ+W50w7 z@WNUxj5ec6&DH1I=;n7w0kMn*eCPG5-hX0Rr!%8WZJ(!LKrv2agb4Gt4E1D$bH*Jl zSQ!8uGvaxgBamQT3FNn*8G|I1?DbMN>3mL+e945rgVF#j$-xJ0vF6T+TK*ns5Y**? z`79x2b$V74rZlxa1QJ>!2Fh?l4VjCO9&1CU`7o%}ckuh$JVBftPJag=QD$$a5?+&e%3i!EF1VB>9*I z%X6Wx=ir?gYro<&joD(qW_ z7uwE;*n;ir?}9q9AuQx z<9RnSIEJ?IcxKt+f{l~^upP>dZ6lH%FJA)Es$Mo`xpU%+`pV2^m=r3yE>7IYV*kso znEbgSPns}2Q8!bmBAQY}6pE}z5wsNT)Rjls7YS* zdS~J3-;3YMrm|Mn%%-y$zMI(`erZKL)tBQGHibArcn7ukDLyXeGx9aJtK?b|NRR$= zNu1W|+*b6Tj3OY%PtU%W^sg5FXTU#Nb`m5jMR1Sn6D@hDUGI<9<0{;P)EK7#IdiI#FrvDpDb|B}DX}jzAZO?N?;^ffr#MXmXWzKTN d+1HZO->;H)3+RL}Yfwl3^~LJN{{U{JbVL9E literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/multifile_raw_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/multifile_raw_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..926a1b6f5b5318073c62974d1e9c4ead62c79429 GIT binary patch literal 6769 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 Dv%8Vd literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/notmnist_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/notmnist_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54781084dadfb6afb9a3c0c071ed2461a9023c59 GIT binary patch literal 3600 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 t1J#qExt;2@Vrv(VfKm~1+ZpE>VuA4E5 zAL-4_6)hZp|C%-TPFmLA=w|ZB;^q#{=(i|@Rks8acAItVy3MGbX=gf4-C@>!OE@C? z!V+2OJkQj#xX+0^?(@&>dQRp=VcS-}5i|9IDAs4hY`rLRq9hA)MrOBWpF8!EEWMhO z#nk z_O~UEL*DYflHB8su+s?x-VQhY1~qrQF5i&xj+6oS0`3PwK1BuN!iE?7=!$>blHBij zo3cjpdQsHtU`{j&FZO7b4avhMk6K<=@^yZNKfw6}=Uu*X_ZDxoydaS6Xq7)$eR7LO zT}Zr6fdXG1EQtf{xw8NchjTdWI502W^TCvX$jy~`I z*Z0Z!if@1ztI7t>edPKS3z9RVN-2QJPI$~4R8 zZGSV6uwm@|m0V5|e{M{}{fIY1)scd4JVTQZez2)MwuynTNZcA3ti~TU$4??o*1dce zb4qoYdwK=2O3#DwG?*JM7hwR?!yWDRGcr1^{JJ(c+(M%K*x)9_SOxS2n8t5%T7S68 z7qS^Y4!aY}j080+z+HNgApng>37Q*W9ETk)Q3X&4hcv5M^`Ti+E3bINi{vV#lRS_T z>#k_vxRJjr`Bgni*Q;x5*SOaSdxW3n$THJVnpjOk6QCh2hwHVy7#2&dcldJOaw$dV zctgc{H8&`@Zh#1J-9gcHJE7>csa|qja>?*X-gQOTKy!X*>p{-AcHdGZ%%h8c{$#Bc zBJ{in5!I@h%UUB8a!tq}^dEKGer&3dsUqmzcIXMI){KIhHQbIDfFe|_`%F2Q{0Pn{ zhoZoooWpcm3h>nN4t4x9iUYt4`}bf|;k!S)C&Sz!Y#_Hn3j62ezA1}Ja-_4e)C{hT^VqEqB4@|O0p znxz_9dOvfZAJP!oTivez6x(-FTLTmo?nGBHZs_?E!_RT--IFPGHwlf@{r|4#zoDl( zOB!)1##CnjYvgW(?da2l-0a%{&Q-_;c_iYf4 zMhD4DbfaZHkIG2qz04-zi-CHOZv5K*BZ%iE`>7$BeWnQPReO-75Q+y&I+7$dybdBi ziv5P$+NnAkH-oI+4D^TrOOZvXwG+Ed6?R--JiUimBa(^q*gccdVzTcPWfm}m^wN5K zACr=wR)^&VA>kwU-5j(lrMy(ej%0v+zUin6;Ph=gB)1C1}YU(=oF9OTD4f zrhec53i(cJb!Ro^D?7+vB;8P60A=G|ERg{r>xjcHZzGAp0~MI8m6|oxR*~(*+|a%0 zjZR8N-7wI(n6{EhS!l%}lV=PZESqBlRS@ zCDf~sdKV5=Z+h&MhUCAoh8#BpoDuJ+MI$%bnDHBYMH+y7Dq-MKv_Y_5AUyRhr9!&saYILSFEJ?8!NCeY) zDEH2k+{BpY54HW&peeyAu^NZZZQP{5r8g~5CPD`r7X^}oFanA8GXm)b)wVMr)~v}s zX)l?IBE63hz^b`q6y=&;BL)S2gs1hnX-7`OPkn+edpHe6={>H`ovB|NtXIhS-ob^GFMG5aVSy%64&d2wVI1%6#K|_6yiqB9~O&UJPU~AF)e3Bq$we*Gw|9}AzC6b2Hh}MQD z+dZ8kiHU)Dts>%_QhNpsV_+Gz6To^WOMn@`7R!`!A^BROL@TGS1teUBCRDGo-Jgxq ztb2H^5L_oV^m(cqM!x>yh>tfqziKEXSfd-ivuVCt>CB0LsV`q1WKbqDXA-nC5t(^> z^fGzU7Alk{twK{p?=A`3Dhj7R;WRdNfP0)p%9HeO_fpEH#MUC25!2i2H~1e@M9eBr z1qGTqLB%O5^c%v#dx74tKcELSDkz0g*QlVlQa7pi4i$&sN!`H%pb78qq}_zZnxW`T zUQzb)9?pn>S+L9bLI%ItLZO%|I>os{rZ|gV9(Q!)@hj^w^a-Hj`GM=c;TZYm4iz*b zpiNtZ{|~&|`+q_4hLXnh>XIUm4f63e)@3B+N3`*)sQR8TB8@?GoLH*p;Qqd z%_}PjX$(fmnR$8Dn?Jq54)Vi~P)5nIg9q8JBGt745A3N`KPX7#LE*OfnD!aOwIbq5 YXRc(IGL_l#*VYB3boy68?oeU>0ooRh%K!iX literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/pavia2_3ch_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/pavia2_3ch_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba46d4c5df3ac34fa6198d2be4fd1ecc707e73ed GIT binary patch literal 2380 zcmZ`)%Z}SN6cr`QmR~c@q?sfrnkYdN#6V#80koT-Et+780IbyQVrH37=%*lBH7nVSrq2e!;DRQWnlej*AsCE2F&mfH9V7cn8g~*W;R9C zdSO2|W=LPV?=@+Yww@VYi#oIozs_@`VR&r-*Oiwm5YvD&Rzs-qO?HO1v}YN~1Gzx~ zq)>=(4v^$|mXN)OVV>qB57PvbVlKCrizK0GjD4PFS(waale4_wiQikhgBtgtS59gM>SLWGAs*$^z6$*zhU_S0k*&Uq93@s@Jh zdqN^S%bxMjjM zhEqr(2LXWM@ivy8;Yy4ovO8xvUR{-+hh6-=Rd+>=u0p2uwdHU_&<` z!WH3s7WyQ~U8pQZ^MI$tJaA_`joq4cON(OU?xwfhMZl8Ej5d&@E-)=;Nq$>_NZgg* z1#?9ayJ7Aw!aP`66KRD+Ga2wI6pJ8@n48XEvsjuNomqPHy35!7)o!Y~sa(~jNA5HT zg&UIt1{WI2Byy+r4OVXqwk_+j6gHp1W@ziHfQ3~5N*idoH zIlB3FZmk~~wkPoH>`Znh!;X@R1TKoP>|h+Hv;aZHvWM}H1&Qh}7F?ez=E=rhnnt?l zG_$#KFZ*?g`z(quUW5CtLa)ofhLKVp@ji5pZJ;;aSEgwqvjNRAUk$b$i>ng~Tuj0Q zv<%6Ps*g&br)54Np(uh zjy5$XfEJ6CA3*Mgm%JNVjI;uc))Z(|D^RUITvc=>-&fZT_$g=Ask48oDt2~K#Mz-V zlT2TZUx)La``S^Z&|>MQ7VIHxlg)afVkjF5l(eTDLL*x>9QcPxW6)_(WsoMV%Z?ra zJ!K1ITIsRu38h%e4Hl42S~=meDbj-bOxhVxI$uknmNS(?>D;N<@tM*haSOTu>LJG( Y+;rf#i5k#M=pl#I`*+jn!Ius6AGE2aD*ylh literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/pavia2_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/pavia2_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc0046300e9a4ca039cf492d5059e735fec1c7aa GIT binary patch literal 7953 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 literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/pavia2_enums.cpython-39.pyc b/denoisplit/data_loader/__pycache__/pavia2_enums.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cd2930537dc23bae08f00becf1354d26476ce1d1 GIT binary patch literal 1089 zcmah|%Z}496m=d>(-$h50U^PHZ8vR(1#A$a)09z1G?cc(!<#6?hE&R@+zP`ta?Q@S$f_A$>p#A);z5S*U@&mzkGXXq?o=+ig!nK$r z8q+j#Lb%S2uY?;y`(iL1u*oT4s;~jr;x)iEg-yUVuLG_tOnGBYy3GsNm2|bz9Hm7P zBG_&~s5<->B!V!F6Q*;G8C+*3HyGt6Y(mTH(_pg7-s)T$ zuq*c5f?#VVJZf&gDtF++-KsE)Q&7e#Z(LGl7zJr6;#{Jz7b@tO;jvz~Ch@W*#ef`G z-7CV`lj;2j4znShES}AtGddV9#vZFJ&W_KXj=jHPR9O>Ow;r zZ~rX@iZIK=OGUg8GGAsXJ8)6rTyR%}S-Q#Mjo_c`S@7X52bH}py;4r8yKZUB1}}F~ z?!fWbbJPGSOGNwW{>PCwE6T^Q5PTiUtaulpEtT-H4Li$g5WtXENHRK%MUb-A_DV)4 z%a4NZH19rHI{lHTY5 literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/pavia2_rawdata_loader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/pavia2_rawdata_loader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82bfe8fffbe41957b82ea06cafda82243186ea82 GIT binary patch literal 4308 zcmbssU2hx5areG>{In#?s%1OPwMo+u6)5r3NnjXOEu&50FsUUZ^&!FG$~{WQ9*^|i z$&rL3T2um>KJ@E72&BFVDEizV&|h({eKPvkx1eY{vqwr?CGJB@;%0YtW_M?2W@l#I za=Ad@_xGRE{^Bwre?w&crvdT+zUT`8jM#)xrUcZcqE&1aS~bvyx~)^BX@N1!*}0)< zn*!H^{IFmbhDEzLEZHR(Gg$6~*kxw2JhT;7U`1%Ju@WmoyTB^!8nlaEX|U9%Y=JGF zQ2RRjhL>YYpHp_7EuZN2GP^m&Z?F}>Z!l$>R9BCFTX;9N_T0#7S-m|s480(F$Lj9) z0&hQByX zP2o2ImlTT<;P%4)E6_cHS3aOjg5I(n$o@U|0Lp!^kR|5ukS z&YZL%iQbSD(2x$q96O1rlt zRkkHsM>6DHvBS$1yE0QOW|dJ!Qj45FjJ6o{91u+k8*QtjF% zxV*EqxwDxnTU%9C+yj0KCUaZ?5kE*Ii4wJ>aR(h z$NoeOyMnI(e1j`|s^BY5`Q8wGCE)x06+TVyl{3Cy5vbR6W}KK=^)S)mN}|C|dZJ?; z&^=nj8o&>CEi7uRJ|7M3JeF7vR$F#Sbf?u;s*7q%3JI9OPz%>l1E^+E9xP2L=CV`e zGdTB|k`)Q!wm}i4jG|P-w3=#zksop_f-p#7iU+l4mlE?Q$4vSdI~4#&uZRSTTwj;p ztJhL}%>6LtIxwdi#xr4j+x!vSXgm#n9oPB}f;SMLIXT|ww1_OzQ*!h}{u%-dfFf~M z4UTaj%?sa&p+w~0Lfpvwm}6a(YA9MJ{daMqs0#8ILO*~pp&>$Vfio?`cL_~p2}%XN z4m{wZ6O~dJLswq8}?0BQY4%W&@?KtdfZlLy?$h zv6dLe^jQ5^o#ZCw1e^_>2At<{0fM!ax z*98ro@f2uziDt%S2Cn@}ni$}4YPa^~q8~nY1D}b4T%596;cIXbaeRAW`buzocHm(7 z#xWtKYT$(&?^&vD1_6|4kubv|j^z5F<+#~M^&Rf|VXA)U2C25=MRA&cbkOt0F+2&* z3z-dzs9Xoiy}rN8F#@F}5Xb3r7hWKvFfGS0?*h#Pt07xH#>G)ANT@IaJEmZU-qlpH zgb^>BfV{Zpk71GM4gf+8Fnxut2w0#?(27qn6}}1dmmB=AK*gH{23M{a99{$iZFg#R zZ~`ztjOe!s_V1C{5RQ=hiX(vW!Eg*5p%51br3*(e2W1%l#ncflY3K;%paQhdr;cz* zLq{+N*MRnysUuv{%y@yR7mlEHYw%=vfkiN{1E?;Fd&|Fv19%P6{LByPm)(YaYc|?& z*yz(Rf->K8`e3>d7kY8QKnan(OE9Uhe#IL@DN$F z6Om9PNmRY?L5}jzsYNJAgf#QsaK!cl?>-tY!l{~WLi8%p1-h)76|-!bX5P$I78h3F L@%c|hQU3KGY#tW- literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/pavia3_rawdata_loader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/pavia3_rawdata_loader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e511b3f451be52b4f61119ed783379358da73fe9 GIT binary patch literal 3211 zcmb_e&5s;M6|d^=>G|+@*Xv{*1C0c+2hfZ?Mn+gGD<&I}ME1yHtsq8;TJ5fynV$4? z&sNv$#-kn~v3n#!TsROR?H+UE$lt-SuAD4#K;ni#@Lu(7 zv*{D~{`yNg8a4>|3sx?E7F6DXRQw(UBSXR{Gg3OFIyZ(U z(9?B0t3W0ttbR;}P1ayd$Xl$%ExjZG#vbWxED!v5x!^wt4tbE~5ewvm2O>HQSR|uh z%rh<`$yxC9S@4)Im${TlFcSGJcpM!hQE;;##FHq?cv?+3oFwriU^y>>ESJF~I^cT6 zB%3ef`Or=`@SlTT$e=@&^-i{!bqv+qg$?)SX(FFIn{#z#%w>pYD6lD%i+Rcm7+xFf z_J77B#zl-PT>MO^yalQF4hT*_*JNlg3c5Ci7Bh!7cbLWOV{$}?E_2}auG-YsxU
  • l%@M3SA>ewUwL5>NoMQ2mC1L|MC~y~I zIu!nY8J6+S<+ZO+PPdvc=y=Kt!z`NdFjRgR&T_U$vD^s5{Y8{kJ!>~pjY38;iDz6+ zawb}^pT64#(Zn`X3Kj}2-41Wv>UT5Nzo8dV-We$t%3D@Y z7C><{R&?1h2i<`{4*49&FZv`Y2G6nf{NM0(JYhpw*&@ouT$w4)ln34tq1&nka^gs! z&-Hhe6V2y5W6H?psvhTA3_P7d>Nv_C%_9j6mM0K(m5A89s?fHk$BZq1DQz#%Ko){&O<_Q3L zN~H}sJ*B56!oIR3IdMw!6b<3}%03%y0=UM?DXkN?bTrK0lU`{Z(Upa-<}oR)T`-@O zD{E7~beYL44V^uB#TE_NAD`bnNcs+7XXK-XwnwnN-x~YYUPU{d>MDSY(Y+;Z!1#5o z_&aG*$T*+P?>~U4~6q_8d`B326pPo$O~m@EUamsWR=Tn z+Cz^~F3tk_75HKS7v}<=TJc?|h&OQoZ&(+3E^#XyRmYCkP~Z~E(I^*yHj=GAzp`-b z`YmcN4*X-7S0EV>dL2j=F>M%#t@shN#b|ryA8v+8WBNBJlys^caY_LrTY@`7vLM+b z^8g;*_sOql>7a{2@*vf8`wq5Cza*tyI!7j;S7)>&pF#Xl+91u+0cpv`NfRyQGx7%y zqm$B*jcE%anB&qtxg^`u%cpdY$PJ_hxmmhLR6D-)p}F!_wUw{OUxD#|D%}!X`{f+n zvjshWhMwA&dagpx7trHh>|ywJyMtxpA-X8f(Q8C6X5M8 zJZ(ZI**KKEke$~qpoLhky@X#y{u%>i&qb0+f$pU&1Xh_3(iFVCkPsJX<52Dh5S4fO z0_|LU8;9CY1Q3xjKZqcHd4eaXD;JDLuTV#;2!SI;$yl|pau!u#q}4cxQe>4_CV8fs zc={LB3zxWyyVNA^5+>{u<>E9fczOnu*3E7M>8hH5V{zMeV3FdRAP7bo^mY2W(V%Y{ zK3L&3;FhR&{dl@%yz5Y^4ea*+d@A64@f%&KmY&$ literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/places_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/places_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a0eda83fc0e18b95663be4e2593c62f7c05ddae GIT binary patch literal 3480 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 M{2KPZ;;?n&Kd$fg>Hq)$ literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/schroff_rawdata_loader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/schroff_rawdata_loader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97e7b0c0b56b1278bc0fca8a91edbd1d0a63960d GIT binary patch literal 3834 zcmcgvTW{P%6!whmUGKGNl0pM5HBv7ugiRVif)YX@C6y43swU!L1+v_o*{l<4=9Q-)-gv7(;+%0d*(6)3&b zJb!#i8ovVd8xHy(9R^pSMYo`18Y8||OW&kMVN89!Wz>w8Su+XF>wcz{t!05OF_UHP zk($M_%(|!5axBO4@XoUWE5f_L$bwcW@4$Dp`3jY#Yi{f=w0$pLTyJwZy2N9L!Bm7( zPQ2Rod9+Pr&JSJY#9pH@S4ZV~PX-7B+AOr_XXqGV^q!Vz*R&1N)tRnFM2(DuifLx3 z8GU!%R3jr@XPE;~9+;)zmFHD&ADKqy-$ zyI|+C7L$h*-a1l)Kpcy5;(5?SjA8dA4NzAV1cBkK5HSR=&RcV#u!HdKxP6z~0q4xV9mY+& z-gJY2`;i@ocGJDXZ4YWA_8@O<%=;aLmx`X+U#N#c-HmwwO<*=vGBVpxxqi7vOvzKQ ze%t2`B#Q$MTjurH3j=B5=PswODQV#7P;BMMfFjC)7=-~EDbq4BNSTy%Xh4_A88S@7 z1>mTg(Dfdy3G_9p9=!=ZxKA5IA)ys(8wv}*N#_s`t(ff2k(h1*PC^eL1E_TsP|HxL zr6+n~q^k@7earYv@0#6AH=EGdSTI54{B=75&F#qRK>1(>+g@;}jJ(K> zR@?1R#GEZwh%7~r=dl+oIWdP*W6&|DTsjIel}n3Vg3jz6ar-sWLtfouYv9L%>-)}b z@g36tm7f03B2J9MR}RXVIwVKAZXnd*iTspiDLJBwDj$r(YsY4Vm^}J*v~KW8bsV}Y zbB@O|19YG0>E0=Q0=E@NE*ozhb|*V--+=4QmCkeH_DwEkQ*58}d|nS%gZK)Z1uw(i zN=c5iyf}1r!QW|MK}PZ<7l)^Gp9cbgRN#py%|)zBsekJF(pZFqmih<2FU_{_f>;`= zt`Uz@F$M7|ZYp4eKQL!!n;d)=Vt0o4LE8X#Zf%07LdLFZp)zP0h-B!-P>4&)<$kX zkiZ4?6$s3A!Fk|JJ~paw?^nk50D*XE zbVuDi)wd6I3NNRCg-_i-NU zvUA}`t`BmFm^=8PeGe$(-+!ILP zRTTS$pz2FintbsvEB@#?g5!UQz>ugbkIF>lZY8!a1@=sq)^samt3IE>V@D;YMJ+l+ Mih6#;I%}E#0L}spMgRZ+ literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/semi_supervised_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/semi_supervised_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72824aa85ed776082fc87ae996e98b5528ae747b GIT binary patch literal 2262 zcmb_d%ZnUE7_X{+&NH(~%q9_Z)UYrjyCi}K5nl-_3eIH{gjOj!Q#CU^>Bm^rvnERq zf*Z*x;8BRe?$N(UsFUD9#Iv9|`F+*1X0k+2R#RV9ef9XBzpvv?r%9mw{uLen)F$K? zT&y=27VkpWNCXiyB^iw<#W_n^GYvq;P2`t(Lx#6qeOURiJ9YN2nyM3RUK z5;4(|j&uc;-k4n?(i86Y&I2;0R*6pJi$H|;NfcOKLp1M)QTTwkBx-liZw>d3-ySToq+pf*m|wOh&Df8!+M=y8~U%ft2Ks z%xFa`Rymbhd6h3{6;w^Z9yTbc$czcPAo{hB$k((AE5e=9J@SC>98>+iYI=F0vN%l+q~Hm9 zT{ZB~g%gwFTof4}sbW4)@`>p#wB$uDdA8uX6s8xaY4IhW$XqIG`(yg)LGXDWd^dg* z9O>!BTq+ZCcswaNH$8sx^2%9egJ&4>S~@Qw=nDO0!cmcz;9hMmar?@CqT!f`%lL`< zn;^Pe-%fIojHEW_p2hU$D#=UJ;Cz(ET7x>ESRQAR^FhnFTBc*uvI0Q%IGLyb6tP}Y z2n&TVwEj^Y)UbD2adYwC6jfcg@FP{1a3GIw?M#bI?!n))c1DGeJ3{6~vNunY zvYzUCibmJ@zoQ{F*Nqc3e|vsUZNTfOqwWJCoshDpzd!wrF7;`T`Lsz7HlI%N?UNXd zDBfN*421{%I&}RikP_1EkS=LSXY9zS=rLWgiV0G>kj`Z0orm3T0CSLZbU5&hlgiw% zd~SSYbIG(Iz}cckig6$w>N$9J;Hc+eFmz~~SSi(qMNMA9*##h1p=%!qp&@P4gRRs0 zKRXph46m#jA^>ZcMdCFu)GAH(iMmqKLvqB>pwHNnEgi(Bpkrqb@d)^vd3Tul?$jx_ z^k=~lpbwn_t^gMtHCJzV%m3PSmparwDW`i-jZ$g<6Blt#+LK^qjMS5`gbRs`-+#nndhr7d}!o1%dG}UDoO_TGi5DWO_aMR}ei$$E) zRm?cLR0*Mj3}xn91=pcG+rqrR=4()pu3V_TxNB k)0nR+oI>DQnQMyok%x+#@U7Y>Z)0w11bUl=;QqGrHvzF)<^TWy literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/sinosoid_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/sinosoid_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96bf438419b5c3b5a55f9bf63d2de8fa8ee01699 GIT binary patch literal 12952 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 OrCv+C^V3u!tN#!8n~TE$ literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/sinosoid_threecurve_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/sinosoid_threecurve_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66521b3d4aaebb59c8a69bceda7548ba0705411f GIT binary patch literal 14126 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 literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/sox2golgi_v2_rawdata_loader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/sox2golgi_v2_rawdata_loader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9bb3f1255b81ef04d8830af36eff321e2cba97e7 GIT binary patch literal 3530 zcmaJ^TaOz_74E9OxNWx`&n=nR4Wzj$7Qx35ll>FG%ndA%%0Q?TM2a=u(|J{_1|} zoUh73tyaQ ze^E0wyatqWFyfpyM>O6zo`0%&3w&;GkuUg5Y#!uAwgB=Hw;5pE+FNEzkS;zpy%qi% zf1R%!ks|^tAX{2<8U{j!K?G`TBap$?Fbd`N!H@$m-{;boA_!xDKZtw= z)qs{aH#+xtz_{oV9A)z9P|iVKhn)Td1S5kiFEr(!rU-+(`3Ni zr02?A?)Jinr!99Yx#m8AR-7|eCN6*2jYf=Pi$O~beqzHGPH=-KxU&=Vk!IuB{5DVJ zs=pP5UB230ZN;qf3f4IXyRNXsnZ6xAXx}&&T{{qG$JZhMdUg$nsx_R+28@O+D8?;s;(sxt<@!j6d{Q*p*%# zTyW<1r<(XObbI!Gdl&q#9i+QF-E9>`yPGiHW;{+p6>x=`V(hgs%={?90Bfho!%jbm z`k}wy@kQ`prmi(S$QLj`i*=mNU4=Q*+aNTPlK-3jX)XSb`hQz>@l_Z>Aoq3A|EC`w z5Jm=K={$so)b_|R#TXsyg|4KI2w;Z#Wn@OCKc!<+nwfb-KA>Z3T#{C%9g$!Ed2IK! zaXGV?Hqyj4BV#KoDZQ83dnHC!v~fvk`ik~T?dMvL0Hc_X?2K$c|8Ygy8T2@!8`_8W z##I>0$ts{<9oL{&Ijdz=W<93kdREWqq6VdNT*>OJv;r$6+Wp_j>YkH1$T+H1S=DNj z+Fz;KGH@BzmVXRnZ$LWIi5AbVYQG_=@rFiJdLLv~Mt<59$Q${xOeD}|I0*VY^@m*e z-Q6ILd6e4|C4GrODReR+qwl5Yaed&v59?#{3k}#0tod7d-`Fa=3Y^hYuGgeFZM~6` z?x)0af+(8Kkt*jCUx8ur%B?6&Wj7fNZ@&${{{>k)yo@g91Anz{MM*b^(%Ya+n>DHU z8Z^quVUxBtPoBdEGaA9eFm2Xynxwfg4CHQZ?*u82fpqf{3x!gQy(Eka@4?OF_JGR( z{Wdp65chfRpwlX*_B$K76%2>qyE%=Ad9|Cw-9W;Ck~c5pW>3vgn;6T-;nRF+Fp6Xd zkpeBleeU;yu1o|pR&I^(f~fE40OFuhkQ!sF00F+vV=OQ@?WH*iVbvfvTl51_+z z5-=)Idn(${SzJY-455dEeqqsTh$*w$Qwv@PC`DW&4p}61kQHJOTjdI^ka=2HdL6I^ z)Hg_ri0?rAE_RxJ=rkBt>yXnAK!7iU2lU}4{S&!4)#;3`&*;XCZqDe|j9!}R;HCCv zQx|xv31kf6fB>L|dL0EuIsnMR;&UiIUjSE7cTs$y0A40d=<*6}>f#c%UPiHk0$H(1 zyb9RfS4TYYRm2O+mX(X(O}z(CM&DVg?(#!8t9 z(w3!TJEKp@C)yt^d|%0O1~X(-R$h#s>6rlpQc~p5Bm(LAu(Yd-5pRJwoPQ7EGmQH#ZVz5I$-q5abRUFr*PZyPs{+D3oV%vlyfA?aca)=?6Z`tT zICt><1~J!_VG`#x36Gf5pUrAso_hc43$-JVkCd0@ddg+)gz<1B{V?^@(I7X6B8;U# zf6WaQdROq!UVbh5Dpn_h7w1(1rhr93eCAcPI*9pR*cW$kvUgE@7lpFJJE$qIICTwS z0OmnXzX$@I!gy{_hhC<2O37=_4c(YrdKE06srI?;`vZK%`rt0rt<8bto^^NI zUq4v$Y$&(yy}P}BxYq8AWHfB=jrx--TV2TQ?O>k+!EM2Xd>1d|cF?^)3eyk`+G+Ry z@O%6|!y`Q1M3Zi+3lz%D=4H`=_2%W?CuZ4@gwYASy#uj0q>mLDvm67zK=}2KDpDJbhN|3t||z{_i*6%u&23=e;@=# zp!fj-dc@z@dPGv>@SWs}ui^ GW&Rg+D4u)( literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/target_index_switcher.cpython-39.pyc b/denoisplit/data_loader/__pycache__/target_index_switcher.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dfbd51e68ed87929bc58580138fba667f932cc5e GIT binary patch literal 5662 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 D1VYYn literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/train_val_data.cpython-39.pyc b/denoisplit/data_loader/__pycache__/train_val_data.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dfd024efa11130a3c90407ae60f1a557670ea9d1 GIT binary patch literal 4124 zcmai1%WoUU8Q)#LpQ81)t;B0vwnCYvEV6X~qYYZiLY&l6gHUw}UIwe(A-VGGqccO< z7HAZxdQ5;GTA)B0pt%$%&_n-#o_fx)r@7`-w0}Wb6#Zs)`4F9TcCpLf_x|Raoo|L# zrBc-3`qwY@-q+VP?Q2QQUTGkH1P?3gn&xO-&Cwl$=$_Fvbcs_W<)yo6FVoE^I!&@( zuA5UhL-JmsTTnPlie9M;PQWHhDuAmoUI1K+@g=~EFrA)g6gpbHdiL|;V@z?wH45;nauV31U&d0)1GDHX7QhL2I{)V{LFU)zix=FKIX^{{GQu)T#BSm#H>^7 zppat6wK=HuT!KYO29GttLFEyo&_nai`6(|X%8MZXZKC%Q zNdL;qQ|t3-3Wips~-lA;Pu`c=`% zjB+Q-;74bhfb%oB5Mj!ltkgMK`CM~yQbVEq2;>rdk$qK+Ma%qlf_zKK8~mLFd0ok$@a+Wo9VI8cks!aT zn@&C01Iza@i51Qo7n_YaO~LY22km3pFpq~^dVL)-l1T zZw(o9tyujm)mM6brPpsiI9pP+2_Q8uBp61{v2$486-5_z0LCrf#v%o!5(PO()l6wt z=2rb_$lZhegWY@g(7oO7iDjg^JcmtX+P_70Z^(GybzDDSf$NBh(gN2JxqeZ6G@uyo z4e2QsOBWQ|wqjO3q8RoUOwj(p!zZHhV?waMhY2}wc_0>*36u;&(u8=DSL@)=g4*FD z$mUy0q^i1*!58a^iF*^8oPvlkB9<@d72)26aTb-~WAT~Un& z3v^%6i}M;!TjPR^bUKt)YI*^Fe1|nEk2;~qUiXAX$WGHo^redx6T#Q*X2d?bqdth8kf#eF#^* zA#w;gfsK&J!Wj;h12tgOVog;}m8%&|9U5|%Ftvi!S{BzXs8HNgWmP6o2g^uDm%mj@ z9v4-I>(0ze*gwZ zQ`!~e>(+M~x98J+SDM^ThzEfXv@_&HlS}VP<)rBwH_o~2>e6N_A;5UAn?zWX+DT=f zXhSE$SnYZf!^_ez>7!(mmO7W*&Ktu`tWI0=W!sg8&4f|$=K)e%{aiHow;pvq)&8Q_ nd%zR^c?^w56)aCg1CvI>;aJo(RX{@3^a zv*Fxa&A{`|U$IT~hGG1J29uAC!B0`Lhp4#0S#0=Bx2A9E*77a1W^8vI-(f^!#csFa zS9ITwy>8X7>b?`#x^=&<`)=Im&iQlQrr*@#N<80P@E4fzk-SV*zb zdLUZc;jU=C)#4Bmh_cnz=c4r>O!8KqwzdSCZJ}SbHf7qKB-GoG23#rfzDzpKggmHE z`cU)$|(<^n@g%r0uDN9vKeiu=JZ*f8*-VLSi7*DcEyD-+ZNgOYS~=qq+DF! zB1t1{@FiAx0H?j_14o6z#W%U|u*??Y0@3Nm@CL^{Db_{=m z(=%e4r0tLajvnfpC|XnvbYQVm*d{T~2A8$hkOQs>!3A&a^s~IRnaY;zCrOlSX@5)7 zTx_K2y=+YV+?1q0c?8vSriE~T0eGvnX|m`$pv&kWhJE1hlXO#uC;G9|u4BO29^4i> zHu_ASFIY|^pxQ|zCs#D~*%HcSLsQwB>eDe5tV2`5S;tfa-PW2UDaksjwj<}zC=1>s z$x4+Ki$pf*m07CV%m%ZZR)PRjFjbIcBxHlxtj3mg862C@)sVQOr9s4a$ePC%y^BG? zo*K`LUzmI5o>iDn*)wC$EHtO6!3p5#oQ5NF2k*56%pIFsuzRzxG`&?=G>^KZzdNSa z^II$*t-uZi{6xdoge({!gYX9kvd~Gpy?zd`0!C@Ls$}>3LJWj_9j8?etUY|BDw}Zj z{Oz~eb}6gM(D_wUuY*~^6|j$*gGmJA;jBDQ&3^4A>3w{yL=M(q9$R8dCe?6>_KcVh z-($+gD%j9M(GK!^bRzt5_Qc#{;~oKiX>)g}N7996EFg^WRKI)1Fn0Fb!YUkYJ~4qj z*1HB!#?>Pr5=O=jf(z{S3H1)_VZCAxduk6FX_SMWoHamIbrcOQzU*GYyqkv-KBXKj zYx!d^B`>3bRU#tk2<;XNNc+1=tel}8`Zieh~u zTfBilu+P2#K#-`lo39V9B9{oIXaUb!S-;myWlj*6iC!py<}Ko?6(+m|zBCASqzE+$ zWgS|atH6PId`UAm#039j7{}=YZKbqnEoS{mPbQKJ^<8{ zlv7SL6=hcFSR;p7qF$*1^pIo00nSmcoTDR4ir_eJX`4MEgDm1mjdq2M!(Pyf9*Ve= z_5sLbmhw%iW(@5E%>5Z9^H6C+gRvbjtN*d}6gN{szJ?7)+~}}^yG5S?WLefK%&bMA zS}?g%m~v&A7XO7fC)t#oH-L;b^UT4S8Oxekb~w);|NlH+A)cR_AG*L&f?30(Pu1lH9 zQ4Znh+#V{NVO%vxHZkstq~E`h1oY(>ke!03pR#wtmhtcQAOh~xN zE-`sQcjRK`3w<>|SDaNrKEjg#5i`o5T58Bb6?d=7BG0svpp zx{AXM5wDCi(;ib!*vYZ=?I>%}f1-l`f(T;DDlT@k!&_SfLHr0jQc`c zN0~~woqm_Dbgo1oO1sLYR#l+rFwdo`(2%mz^Vp*8l_-x$k1L0~fhoUAm&G8CvfQtB z(kKZw+(a~{L!D*1-9yGps5a26OF1kVRcQTvrqcYrOvk5#ogP@JtteFj9YXkOp zg4q}?Ae;|Q&G_WRMu(#eVK|urMFNeiqcj%=w*`-!L`+pDL+^$Ubp+Gt$q+HU;p9bs z)Vnm}RPru9^e>d*1qx}%!4pqx-)8s`;luW#Jcc!@76jdt_ha0oRU-)QBUvi%)e2cZ zPdh;%&wx(;fGPqRN%5~tqbUE86!GQzR8f?Y*Qp|WliCJ8ryd<};?O#{=>)2Z7Zet? zCOl?Wjenc2`E8@^o$!u%o>%wI*KE)6T(5>d&pRV&MSD>>Nx$2BG|bKORCczJg2%Y- z$Fb1xl&Q1&4zDlntDRJeRZ3R^J=VWENXj$R$yq9GM|3ODAn3n2@m_B*yzOt`#~Ymh z0nO-_E=gFV+J{ib9sCM{AHh1?qn`^T-TVCWhtT)J9Hiwvdl*5biv^OhdG*F2t9HXA misNwn34%y1uvf`mdGD5be~*%zjP8OSf~p78FaH);!}>3ud@s2G literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/two_tiff_rawdata_loader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/two_tiff_rawdata_loader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b04f06c5c05734794e6c07872965cbcfd930811 GIT binary patch literal 2163 zcmZuyOOG2x5bhq2?HRw;>umOs2XQz63&BnnAz&3nphO%{vO?^_VH7l)OtHC|`cyO#Ld_-Q0fuVw6d9F46J9z=gfS5uk5Yz*7yz9VhgPO*t%_b7rZX-GO|YYFY;Bk zxJC{rct%_&8sV9R#g>N%E=SL?7R#!?1j0KJ1|#Ob>GRY1NwygT-$@F zl{>C6hq;ePUcEu~D66shV{7KZP3o#KZbH3&Q?1+`FMzHA+%HJ8<{DwGyO#X*3-SZa zUA6$3YabBUXQ}FV5$yiR-Te-DKXm|ER7-g&x6u!HX|u)0_U+QFHmlDX#{TqO>qjb< zb2qPnpBKA~ZrSKIKvzGZTQRyV&^35C+j;KPNwTtZ%bgk0W?23UQBn2$K(qOa~}22H*Q?jMu)CJ%M(Y8*)wX36B*3LNtf46^$cVpNGBO8t95 zY|z@f8fRe;%WFV9-*8w0V}Pz5Jc#5W-u&+(cIsS=n*ZDTRCl}>a$%+fGWJcXfM6Ow|~5twPc z_@&@13KeHN&_UQ%x)k$Nm*psc2DHNr;x2s_$GQ?o+@`AoNR;|uLtsFhAvh)=Pzp; zooTm7d&C~-Dtbf0F^+&TNGK+J2XyCTo$y_jn=lcpP21F=HjFl{Sv6`M*)N83B=DLEWIx}1 zuRj#obkZMBhjY{#O!n{bR82+T52Ilq!-%IL@2^{j_?IEtFdbs8p#`dtVHxdmT~5O+ zmg^;hrvg=C32mNB4D+T~1{oMnlgUGI9_b6FGfaJYVJ3Lb)b3@y462Hnul=tnf}_CH z+1K^>IQxQQdkJ&(=Sf49_`Y6D0yT*<6-RfV&5+WS`C6L9N?&}%A)-n4piPb2BGcj{ zjN!z^Vo1JkF7`3%&%ELXVob0gg~2CiaPD;jSrn--L8R!){J<;7oQ9^l6LWtUOr?y1 z)Q87Ka`86m90N{hWbr<*qGx1sdI!Ukn)=!b9_UJx$WeCx7*_H95(co&Rk+?X=GX9P hknh0cSPlTSK^rCKT?c>&RPnPa)IsjZE_G;!{s&ASZAt(D literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/__pycache__/vanilla_dloader.cpython-39.pyc b/denoisplit/data_loader/__pycache__/vanilla_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cb098af583d5b382e7fff46e37a2e3f301dce417 GIT binary patch literal 22810 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 std_thresh + return ch_mask + + +def get_train_val_data(dirname, data_config, datasplit_type, val_fraction, test_fraction): + fpaths = get_train_val_datafiles(dirname, datasplit_type, val_fraction, test_fraction) + print( + f'Loading {dirname} with Channels {data_config.channel_1},{data_config.channel_2}, Mode:{DataSplitType.name(datasplit_type)}' + ) + data = load_tiffs(fpaths)[..., [data_config.channel_1, data_config.channel_2]] + if 'ch1_frame_std_quantile' in data_config: + q_ch1 = data_config.ch1_frame_std_quantile + ch1_mask = get_std_mask(data[..., 0], q_ch1) + + q_ch2 = data_config.ch2_frame_std_quantile + ch2_mask = get_std_mask(data[..., 1], q_ch2) + mask = np.logical_or(ch1_mask, ch2_mask) + print(f'Skipped {(~mask).sum()} entries. Picking {mask.sum()} entries') + return data[mask].copy() + return data \ No newline at end of file diff --git a/denoisplit/data_loader/base_data_loader.py b/denoisplit/data_loader/base_data_loader.py new file mode 100644 index 0000000..824466a --- /dev/null +++ b/denoisplit/data_loader/base_data_loader.py @@ -0,0 +1,10 @@ +class BaseDataLoader: + + def per_side_overlap_pixelcount(self): + raise NotImplementedError("Implement this for running it on notebooks") + + def get_idx_manager(self): + raise NotImplementedError("Implement this for running it on notebooks") + + def get_grid_size(self): + raise NotImplementedError("Implement this for running it on notebooks") diff --git a/denoisplit/data_loader/cngb_mito_actin_dloader.py b/denoisplit/data_loader/cngb_mito_actin_dloader.py new file mode 100644 index 0000000..64ca4f0 --- /dev/null +++ b/denoisplit/data_loader/cngb_mito_actin_dloader.py @@ -0,0 +1,34 @@ +from typing import Tuple + +import numpy as np + +from denoisplit.core.tiff_reader import load_tiff +from denoisplit.data_loader.tiff_dloader import TiffLoader + + +class CngbMitoActinLoader(TiffLoader): + def __init__(self, + img_sz: int, + mito_fpath: str, + actin_fpath: str, + enable_flips: bool = False, + thresh: float = None): + super().__init__(img_sz, enable_flips=enable_flips, thresh=thresh) + self._mito_fpath = mito_fpath + self._actin_fpath = actin_fpath + + self._mito_data = load_tiff(self._mito_fpath).astype(np.float32) + fac = 255 / self._mito_data.max() + self._mito_data *= fac + + self._actin_data = load_tiff(self._actin_fpath).astype(np.float32) + fac = 255 / self._actin_data.max() + self._actin_data *= fac + + assert len(self._mito_data) == len(self._actin_data) + self.N = len(self._mito_data) + + def _load_img(self, index: int) -> Tuple[np.ndarray, np.ndarray]: + img1 = self._mito_data[index] + img2 = self._actin_data[index] + return img1[None], img2[None] diff --git a/denoisplit/data_loader/crop_synchronizer.py b/denoisplit/data_loader/crop_synchronizer.py new file mode 100644 index 0000000..de03074 --- /dev/null +++ b/denoisplit/data_loader/crop_synchronizer.py @@ -0,0 +1,68 @@ +import numpy as np + + +class CropSynchronizer: + """ + Ensures that for each noise level, same crop gets delivered. + """ + def __init__(self, img_sz, dataset_size, max_same_crop_count, noise_levels): + self._img_sz = img_sz + self._size = dataset_size + self.noise_levels = noise_levels + # What was the last crop used. + self._last_random_crop = None + # How many times has the same crop being used (for each noise level). + self._same_crop_count = None + # number of times same crop would be used for each noise level before we randomly resample. + self._max_same_crop_count = max_same_crop_count + assert isinstance(self._max_same_crop_count, int) + self.init() + + def init(self): + self._last_random_crop = {} + self._same_crop_count = {} + for noise_level in self.noise_levels: + self._same_crop_count[noise_level] = [0] * self._size + self._last_random_crop = [None] * self._size + + def time_to_sample(self, base_index): + if self._last_random_crop[base_index] is None: + return True + + for noise_level in self.noise_levels: + if self._same_crop_count[noise_level][base_index] < self._max_same_crop_count: + return False + return True + + def reset_crop_count(self, base_index, noise_index): + self._same_crop_count[self.noise_levels[noise_index]][base_index] = 0 + + def _increment_crop_count(self, base_index, noise_index): + self._same_crop_count[self.noise_levels[noise_index]][base_index] += 1 + + def get_hw(self, base_index, noise_index): + self._increment_crop_count(base_index, noise_index) + return self._last_random_crop[base_index] + + def set_hw(self, base_index, noise_index, hw): + self._last_random_crop[base_index] = hw + for i in range(len(self.noise_levels)): + self.reset_crop_count(base_index, i) + + self._increment_crop_count(base_index, noise_index) + + def get_random_crop_shape(self, h, w, base_index, noise_index, force_sample=False): + """ + Random starting position for the crop for the img with index `index`. + """ + + if force_sample is True or self.time_to_sample(base_index): + h_start = np.random.choice(h - self._img_sz) + w_start = np.random.choice(w - self._img_sz) + h_flip, w_flip = np.random.choice(2, size=2) == 1 + self.set_hw(base_index, noise_index, (h_start, w_start, h_flip, w_flip)) + else: + hw = self.get_hw(base_index, noise_index) + h_start, w_start, h_flip, w_flip = hw + + return h_start, w_start, h_flip, w_flip diff --git a/denoisplit/data_loader/dao_3ch_rawdata_loader.py b/denoisplit/data_loader/dao_3ch_rawdata_loader.py new file mode 100644 index 0000000..547fa43 --- /dev/null +++ b/denoisplit/data_loader/dao_3ch_rawdata_loader.py @@ -0,0 +1,39 @@ +import os +from ast import literal_eval as make_tuple +from collections.abc import Sequence +from random import shuffle +from typing import List + +import numpy as np + +from denoisplit.core.custom_enum import Enum +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from denoisplit.core.tiff_reader import load_tiff +from denoisplit.data_loader.multifile_raw_dloader import SubDsetType +from denoisplit.data_loader.multifile_raw_dloader import get_train_val_data as get_train_val_data_twochannels + + +def get_multi_channel_files(): + return ['reduced_SIM1-100.tif', 'reduced_SIM101-200.tif', 'reduced_SIM201-263.tif'] + + +def get_train_val_data(datadir, data_config, datasplit_type: DataSplitType, val_fraction=None, test_fraction=None): + assert data_config.subdset_type == SubDsetType.MultiChannel + return get_train_val_data_twochannels(datadir, + data_config, + datasplit_type, + get_multi_channel_files, + val_fraction=val_fraction, + test_fraction=test_fraction) + + +if __name__ == '__main__': + from denoisplit.data_loader.multifile_raw_dloader import SubDsetType + from ml_collections.config_dict import ConfigDict + data_config = ConfigDict() + data_config.subdset_type = SubDsetType.MultiChannel + datadir = '/group/jug/ashesh/data/Dao3ChannelReduced/' + data = get_train_val_data(datadir, data_config, DataSplitType.Train, val_fraction=0.1, test_fraction=0.1) + print(len(data)) + for i in range(len(data)): + print(i, data[i][0].shape) diff --git a/denoisplit/data_loader/doubledip_input.py b/denoisplit/data_loader/doubledip_input.py new file mode 100644 index 0000000..c0e6a6d --- /dev/null +++ b/denoisplit/data_loader/doubledip_input.py @@ -0,0 +1,17 @@ +""" +Here, we create the input which is needed for the doubledip to work upon. +Every data point will have 2 mixed input. Here, we are simply passing the channels to the output +""" +import os.path +import numpy as np + + +def dump_individual_channels(dset, idx_list, outputdir, label): + outputdir = os.path.join(outputdir, label) + if not os.path.exists(outputdir): + os.mkdir(outputdir) + + for idx in idx_list: + _, tar = dset[idx] + fpath = os.path.join(outputdir, f'{idx}.npy') + np.save(fpath, tar) diff --git a/denoisplit/data_loader/embl_semisup_rawdata_loader.py b/denoisplit/data_loader/embl_semisup_rawdata_loader.py new file mode 100644 index 0000000..cb2c7f6 --- /dev/null +++ b/denoisplit/data_loader/embl_semisup_rawdata_loader.py @@ -0,0 +1,46 @@ +""" + +""" +from typing import Union + +import numpy as np +import os +from denoisplit.core import data_split_type +from denoisplit.core.tiff_reader import load_tiff +from denoisplit.core.data_type import DataType +from denoisplit.core.data_split_type import DataSplitType + + +def get_random_datasplit_tuples(val_fraction, test_fraction, N): + if test_fraction is None: + test_fraction = 0.0 + + idx_arr = np.random.RandomState(seed=955).permutation(np.arange(N)) + trainN = int((1 - val_fraction - test_fraction) * N) + valN = int(val_fraction * N) + return idx_arr[:trainN].copy(), idx_arr[trainN:trainN + valN].copy(), idx_arr[trainN + valN:].copy() + + +def get_train_val_data(datadir, data_config, datasplit_type: DataSplitType, val_fraction=None, test_fraction=None): + fpath_mix = os.path.join(datadir, data_config.mix_fpath) + fpath_ch1 = os.path.join(datadir, data_config.ch1_fpath) + print(f'Loading Mix:{fpath_mix} & Ch1:{fpath_ch1} datasplit mode:{DataSplitType.name(datasplit_type)}') + + data_mix = load_tiff(fpath_mix).astype(np.float32) + data_ch1 = load_tiff(fpath_ch1).astype(np.float32) + + if datasplit_type == DataSplitType.All: + return {'mix': data_mix, 'C1': data_ch1} + + assert len(data_mix) == len(data_ch1) + # Here, we have a very clear distribution shift as we increase the index. So, best option is to random splitting. + train_idx, val_idx, test_idx = get_random_datasplit_tuples(val_fraction, test_fraction, len(data_mix)) + + if datasplit_type == DataSplitType.Train: + return {'mix': data_mix[train_idx], 'C1': data_ch1[train_idx]} + elif datasplit_type == DataSplitType.Val: + return {'mix': data_mix[val_idx], 'C1': data_ch1[val_idx]} + elif datasplit_type == DataSplitType.Test: + return {'mix': data_mix[test_idx], 'C1': data_ch1[test_idx]} + else: + raise Exception("invalid datasplit") diff --git a/denoisplit/data_loader/exp_microscopyv2_rawdata_loader.py b/denoisplit/data_loader/exp_microscopyv2_rawdata_loader.py new file mode 100644 index 0000000..e08aec0 --- /dev/null +++ b/denoisplit/data_loader/exp_microscopyv2_rawdata_loader.py @@ -0,0 +1,54 @@ +import os +from ast import literal_eval as make_tuple +from collections.abc import Sequence +from random import shuffle +from typing import List + +import numpy as np + +from czifile import imread as imread_czi +from denoisplit.core.custom_enum import Enum +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from denoisplit.core.tiff_reader import load_tiff +from denoisplit.data_loader.multifile_raw_dloader import SubDsetType +from denoisplit.data_loader.multifile_raw_dloader import get_train_val_data as get_train_val_data_twochannels + + +def get_multi_channel_files(): + return [ + 'Experiment-447.czi', + 'Experiment-449.czi', + 'Experiment-448.czi', + # 'Experiment-452.czi' + ] + + +def load_data(fpath): + # (4, 1, 4, 22, 512, 512, 1) + data = imread_czi(fpath) + clean_data = data[3, 0, [0, 2], ..., 0] + clean_data = np.swapaxes(clean_data[..., None], 0, 4)[0] + return clean_data + + +def get_train_val_data(datadir, data_config, datasplit_type: DataSplitType, val_fraction=None, test_fraction=None): + assert data_config.subdset_type == SubDsetType.MultiChannel + return get_train_val_data_twochannels(datadir, + data_config, + datasplit_type, + get_multi_channel_files, + load_data_fn=load_data, + val_fraction=val_fraction, + test_fraction=test_fraction) + + +if __name__ == '__main__': + from denoisplit.data_loader.multifile_raw_dloader import SubDsetType + from ml_collections.config_dict import ConfigDict + data_config = ConfigDict() + data_config.subdset_type = SubDsetType.MultiChannel + datadir = '/group/jug/ashesh/data/expansion_microscopy_v2/' + data = get_train_val_data(datadir, data_config, DataSplitType.Train, val_fraction=0.1, test_fraction=0.1) + print(len(data)) + for i in range(len(data)): + print(i, data[i][0].shape) diff --git a/denoisplit/data_loader/ht_iba1_ki67_dloader.py b/denoisplit/data_loader/ht_iba1_ki67_dloader.py new file mode 100644 index 0000000..dbf0cad --- /dev/null +++ b/denoisplit/data_loader/ht_iba1_ki67_dloader.py @@ -0,0 +1,37 @@ +from denoisplit.core.loss_type import LossType +from denoisplit.data_loader.ht_iba1_ki67_rawdata_loader import SubDsetType +from denoisplit.data_loader.two_dset_dloader import TwoDsetDloader + + +class IBA1Ki67DataLoader(TwoDsetDloader): + + def get_loss_idx(self, dset_idx): + if self._subdset_types[dset_idx] == SubDsetType.OnlyIba1: + loss_idx = LossType.Elbo + elif self._subdset_types[dset_idx] == SubDsetType.Iba1Ki64: + loss_idx = LossType.ElboMixedReconstruction + else: + raise Exception("Invalid subdset type") + return loss_idx + + +if __name__ == '__main__': + from denoisplit.configs.ht_iba1_ki64_config import get_config + config = get_config() + fpath = '/group/jug/ashesh/data/Stefania/20230327_Ki67_and_Iba1_trainingdata' + dloader = IBA1Ki67DataLoader( + config.data, + fpath, + datasplit_type=DataSplitType.Train, + val_fraction=0.1, + test_fraction=0.1, + normalized_input=True, + use_one_mu_std=True, + enable_random_cropping=False, + max_val=[1000, 2000], + ) + mean_val, std_val = dloader.compute_mean_std() + dloader.set_mean_std(mean_val, std_val) + inp, tar, dset_idx, loss_idx = dloader[0] + len(dloader) + print('This is working') diff --git a/denoisplit/data_loader/ht_iba1_ki67_rawdata_loader.py b/denoisplit/data_loader/ht_iba1_ki67_rawdata_loader.py new file mode 100644 index 0000000..b6be0f1 --- /dev/null +++ b/denoisplit/data_loader/ht_iba1_ki67_rawdata_loader.py @@ -0,0 +1,76 @@ +import os + +import numpy as np + +from czifile import imread as imread_czi +from denoisplit.core.custom_enum import Enum +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples + + +class SubDsetType(Enum): + OnlyIba1 = 'Iba1' + Iba1Ki64 = 'Iba1_Ki67' + + +def get_iba1_ki67_files(): + return [f'{i}.czi' for i in range(1, 31)] + + +def get_iba1_only_files(): + return [f'Iba1only_{i}.czi' for i in range(1, 16)] + + +def load_czi(fpaths): + imgs = [] + for fpath in fpaths: + img = imread_czi(fpath) + assert img.shape[3] == 1 + img = np.swapaxes(img, 0, 3) + # the first dimension of img stored in imgs will have dim of 1, where the contenation will happen + imgs.append(img) + return np.concatenate(imgs, axis=0) + + +def get_train_val_data(datadir, data_config, datasplit_type: DataSplitType, val_fraction=None, test_fraction=None): + dset_subtype = data_config.subdset_type + + if dset_subtype == SubDsetType.OnlyIba1: + fnames = get_iba1_only_files() + elif dset_subtype == SubDsetType.Iba1Ki64: + fnames = get_iba1_ki67_files() + + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, len(fnames)) + if datasplit_type == DataSplitType.All: + pass + elif datasplit_type == DataSplitType.Train: + print(train_idx) + fnames = [fnames[i] for i in train_idx] + elif datasplit_type == DataSplitType.Val: + print(val_idx) + fnames = [fnames[i] for i in val_idx] + elif datasplit_type == DataSplitType.Test: + print(test_idx) + fnames = [fnames[i] for i in test_idx] + else: + raise Exception("invalid datasplit") + + fpaths = [os.path.join(datadir, dset_subtype, x) for x in fnames] + data = load_czi(fpaths) + print('Loaded from', SubDsetType.name(dset_subtype), datadir, data.shape) + if dset_subtype == SubDsetType.Iba1Ki64: + # We just need the combined channel. we don't need the nuclear channel. + # in order for the whole setup to work well, I'm just copying the channel twice. + # when creating the input, the average of these channels will still be exactly this channel, which is what we want. + # we want this channel as input to the network. + # Note that mean and the stdev used to normalize this data will be different, but we can try to do that initially. + data = data[..., 1:] + data = np.tile(data, (1, 1, 1, 2)) + return data + + +if __name__ == '__main__': + from ml_collections.config_dict import ConfigDict + data_config = ConfigDict() + data_config.subdset_type = SubDsetType.OnlyIba1 + datadir = '/Users/ashesh.ashesh/Documents/Datasets/HT_Stefania/20230327_Ki67_and_Iba1_trainingdata/' + data = get_train_val_data(datadir, data_config, DataSplitType.Val, val_fraction=0.1, test_fraction=0.1) diff --git a/denoisplit/data_loader/intensity_augm_tiff_dloader.py b/denoisplit/data_loader/intensity_augm_tiff_dloader.py new file mode 100644 index 0000000..118ec73 --- /dev/null +++ b/denoisplit/data_loader/intensity_augm_tiff_dloader.py @@ -0,0 +1,222 @@ +""" +Here, the motivation is to have Intensity based augmentation We'll change the amount of the overlap in order for it. +""" +from typing import List, Tuple, Union + +import numpy as np + +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.data_loader.vanilla_dloader import MultiChDloader + + +class Interval: + + def __init__(self, minv, maxv): + self._minv = minv + self._maxv = maxv + + def __contains__(self, val): + lhs = self._minv < val + rhs = val < self._maxv + return lhs and rhs + + def sample(self): + diff = self._maxv - self._minv + return self._minv + np.random.rand() * diff + + +class AlphaClasses: + """ + A class to sample alpha values. They will be used to compute the weighted average of the two channels. + """ + + def __init__(self, minv, maxv, nintervals=10): + self._minv = minv + self._maxv = maxv + step = (self._maxv - self._minv) / nintervals + self._intervals = [] + for minv_class in np.arange(self._minv, self._maxv + 1e-5, step): + self._intervals.append(Interval(minv_class, minv_class + step)) + print(f'[{self.__class__.__name__}] {self._minv}-{self._maxv} {nintervals}') + + def class_ids(self): + return list(range(len(self._intervals))) + + def sample(self, class_idx=None): + if class_idx is not None: + return self._intervals[class_idx].sample(), class_idx + else: + class_idx = np.random.randint(0, high=len(self._intervals)) + return self._intervals[class_idx].sample(), class_idx + + +class IntensityAugTiffDloader(MultiChDloader): + + def __init__(self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + enable_random_cropping: bool = False, + use_one_mu_std=None, + allow_generation=False, + max_val=None): + super().__init__(data_config, + fpath, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=enable_random_cropping, + use_one_mu_std=use_one_mu_std, + allow_generation=allow_generation, + max_val=max_val) + assert self._data.shape[-1] == 2 + self._ch1_min_alpha = data_config.ch1_min_alpha + self._ch1_max_alpha = data_config.ch1_max_alpha + self._ch1_alpha_interval_count = data_config.get('ch1_alpha_interval_count', 1) + self._alpha_sampler = None + self._cl_std_filter = data_config.get('cl_std_filter', None) + + if self._ch1_max_alpha is not None and self._ch1_min_alpha is not None: + self._alpha_sampler = AlphaClasses(self._ch1_min_alpha, + self._ch1_max_alpha, + nintervals=self._ch1_alpha_interval_count) + + print(f'[{self.__class__.__name__}] CL_std_lowerb', self._cl_std_filter) + # assert self._use_one_mu_std is False, "We need individual channels mean and std to be able to get correct mean for alpha alphas." + + def _sample_alpha(self, alpha_class_idx=None): + if self._ch1_min_alpha is None or self._ch1_max_alpha is None: + return None + alpha, alpha_class_idx = self._alpha_sampler.sample(class_idx=alpha_class_idx) + return alpha, alpha_class_idx + + def _compute_mean_std_with_alpha(self, alpha): + mean, std = self.get_mean_std() + mean = mean.squeeze() + std = std.squeeze() + mean = mean[0] * alpha + mean[1] * (1 - alpha) + std = std[0] * alpha + std[1] * (1 - alpha) + return mean, std + + def _compute_input_with_alpha(self, img_tuples, alpha, use_alpha_invariant_mean=False): + assert len(img_tuples) == 2 + assert self._normalized_input is True, "normalization should happen here" + + inp = img_tuples[0] * alpha + img_tuples[1] * (1 - alpha) + if use_alpha_invariant_mean: + mean, std = self._compute_mean_std_with_alpha(0.5) + else: + mean, std = self._compute_mean_std_with_alpha(alpha) + + inp = (inp - mean) / std + return inp.astype(np.float32) + + def _compute_input(self, img_tuples): + alpha, _ = self._sample_alpha() + assert alpha is not None + return self._compute_input_with_alpha(img_tuples, alpha) + + +class IntensityAugCLTiffDloader(IntensityAugTiffDloader): + """ + Dataset used in contrastive learning. + """ + + def __init__(self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + enable_random_cropping: bool = False, + use_one_mu_std=None, + allow_generation=False, + return_individual_channels: bool = False, + return_alpha: bool = False, + use_alpha_invariant_mean=False, + max_val=None): + """ + Args: + return_alpha: IF True, return the actual alpha value instead of the alpha class. Otherwise, it returns alpha_class + use_alpha_invariant_mean: If True, then mean and stdev corresponding to alpha=0.5 is used to normalize all inputs. If False + , input is normalized with a mean,stdev computing using the alpha. + """ + super().__init__(data_config, + fpath, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=enable_random_cropping, + use_one_mu_std=use_one_mu_std, + allow_generation=allow_generation, + max_val=max_val) + assert self._enable_random_cropping is False, "We need id for each image and so this must be false. \ + Our custom sampler will provide index with single grid_size" + + self._return_individual_channels = return_individual_channels + self._return_alpha = return_alpha + self._use_alpha_invariant_mean = use_alpha_invariant_mean + print(f'[{self.__class__.__name__}] RetChannels', self._return_individual_channels, 'RetAlpha', + self._return_alpha, 'AlphaInvMean', use_alpha_invariant_mean) + + def _compute_input(self, img_tuples, alpha_class_idx): + if alpha_class_idx == -1: + # alpha=0.5 is the solution. + alpha = 0.5 + else: + alpha, alpha_class_idx = self._sample_alpha(alpha_class_idx=alpha_class_idx) + + assert alpha is not None + return self._compute_input_with_alpha( + img_tuples, alpha, use_alpha_invariant_mean=self._use_alpha_invariant_mean), alpha, alpha_class_idx + + def __getitem__(self, index: Union[int, Tuple[int, int, int, int]]) -> Tuple[np.ndarray, np.ndarray]: + if isinstance(index, tuple) or isinstance(index, np.ndarray): + if len(index) == 4: + ch1_idx, ch2_idx, grid_size, alpha_class_idx = index + elif len(index) == 3: + ch1_idx, ch2_idx, grid_size = index + alpha_class_idx = np.random.randint(0, high=self._ch1_alpha_interval_count) if self._is_train else -1 + else: + ch1_idx = index + ch2_idx = index + grid_size = self._img_sz + alpha_class_idx = -1 + + index1 = (ch1_idx, grid_size) + img1_tuples = self._get_img(index1) + index2 = (ch2_idx, grid_size) + img2_tuples = self._get_img(index2) + + assert self._enable_rotation is False + img_tuples = (img1_tuples[0], img2_tuples[1]) + + inp, alpha, _ = self._compute_input(img_tuples, alpha_class_idx=alpha_class_idx) + + alpha_val = alpha_class_idx + if self._return_alpha: + alpha_val = alpha + + # Filter needed in contrastive learning to ensure that zero content has its own class. + if self._cl_std_filter is not None: + assert len(img_tuples) == 2 + if img_tuples[0].std() <= self._cl_std_filter[0]: + ch1_idx = -1 + if img_tuples[1].std() <= self._cl_std_filter[1]: + ch2_idx = -1 + + if self._return_individual_channels: + target = np.concatenate(img_tuples, axis=0) + return (inp, target, alpha_val, ch1_idx, ch2_idx) + + return inp, alpha_val, ch1_idx, ch2_idx diff --git a/denoisplit/data_loader/lc_multich_dloader.py b/denoisplit/data_loader/lc_multich_dloader.py new file mode 100644 index 0000000..5ce37ed --- /dev/null +++ b/denoisplit/data_loader/lc_multich_dloader.py @@ -0,0 +1,225 @@ +""" +Here, the input image is of multiple resolutions. Target image is the same. +""" +from typing import List, Tuple, Union + +import numpy as np +from skimage.transform import resize + +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.core.data_type import DataType +from denoisplit.data_loader.patch_index_manager import GridAlignement +from denoisplit.data_loader.vanilla_dloader import MultiChDloader + + +class LCMultiChDloader(MultiChDloader): + + def __init__( + self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + use_one_mu_std=None, + num_scales: int = None, + enable_random_cropping=False, + padding_kwargs: dict = None, + allow_generation: bool = False, + lowres_supervision=None, + max_val=None, + grid_alignment=GridAlignement.LeftTop, + overlapping_padding_kwargs=None, + print_vars=True, + ): + """ + Args: + num_scales: The number of resolutions at which we want the input. Note that the target is formed at the + highest resolution. + """ + self._padding_kwargs = padding_kwargs # mode=padding_mode, constant_values=constant_value + if overlapping_padding_kwargs is not None: + assert self._padding_kwargs == overlapping_padding_kwargs, 'During evaluation, overlapping_padding_kwargs should be same as padding_args. \ + It should be so since we just use overlapping_padding_kwargs when it is not None' + + else: + overlapping_padding_kwargs = padding_kwargs + + super().__init__(data_config, + fpath, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=enable_random_cropping, + use_one_mu_std=use_one_mu_std, + allow_generation=allow_generation, + max_val=max_val, + grid_alignment=grid_alignment, + overlapping_padding_kwargs=overlapping_padding_kwargs, + print_vars=print_vars) + self.num_scales = num_scales + assert self.num_scales is not None + self._scaled_data = [self._data] + self._scaled_noise_data = [self._noise_data] + + assert isinstance(self.num_scales, int) and self.num_scales >= 1 + self._lowres_supervision = lowres_supervision + assert isinstance(self._padding_kwargs, dict) + assert 'mode' in self._padding_kwargs + + for _ in range(1, self.num_scales): + shape = self._scaled_data[-1].shape + assert len(shape) == 4 + new_shape = (shape[0], shape[1] // 2, shape[2] // 2, shape[3]) + ds_data = resize(self._scaled_data[-1], new_shape) + self._scaled_data.append(ds_data) + # do the same for noise + if self._noise_data is not None: + noise_data = resize(self._scaled_noise_data[-1], new_shape) + self._scaled_noise_data.append(noise_data) + + def _init_msg(self): + msg = super()._init_msg() + msg += f' Pad:{self._padding_kwargs}' + return msg + + def _load_scaled_img(self, scaled_index, index: Union[int, Tuple[int, int]]) -> Tuple[np.ndarray, np.ndarray]: + if isinstance(index, int): + idx = index + else: + idx, _ = index + imgs = self._scaled_data[scaled_index][idx % self.N] + imgs = tuple([imgs[None, :, :, i] for i in range(imgs.shape[-1])]) + if self._noise_data is not None: + noisedata = self._scaled_noise_data[scaled_index][idx % self.N] + noise = tuple([noisedata[None, :, :, i] for i in range(noisedata.shape[-1])]) + factor = np.sqrt(2) if self._input_is_sum else 1.0 + # since we are using this lowres images for just the input, we need to add the noise of the input. + assert self._lowres_supervision is None or self._lowres_supervision is False + imgs = tuple([img + noise[0] * factor for img in imgs]) + return imgs + + def _crop_img(self, img: np.ndarray, h_start: int, w_start: int): + """ + Here, h_start, w_start could be negative. That simply means we need to pick the content from 0. So, + the cropped image will be smaller than self._img_sz * self._img_sz + """ + return self._crop_img_with_padding(img, h_start, w_start) + + def _get_img(self, index: int): + """ + Returns the primary patch along with low resolution patches centered on the primary patch. + """ + img_tuples, noise_tuples = self._load_img(index) + assert self._img_sz is not None + h, w = img_tuples[0].shape[-2:] + if self._enable_random_cropping: + h_start, w_start = self._get_random_hw(h, w) + else: + h_start, w_start = self._get_deterministic_hw(index) + + cropped_img_tuples = [self._crop_flip_img(img, h_start, w_start, False, False) for img in img_tuples] + cropped_noise_tuples = [self._crop_flip_img(noise, h_start, w_start, False, False) for noise in noise_tuples] + h_center = h_start + self._img_sz // 2 + w_center = w_start + self._img_sz // 2 + allres_versions = {i: [cropped_img_tuples[i]] for i in range(len(cropped_img_tuples))} + for scale_idx in range(1, self.num_scales): + scaled_img_tuples = self._load_scaled_img(scale_idx, index) + + h_center = h_center // 2 + w_center = w_center // 2 + + h_start = h_center - self._img_sz // 2 + w_start = w_center - self._img_sz // 2 + + scaled_cropped_img_tuples = [ + self._crop_flip_img(img, h_start, w_start, False, False) for img in scaled_img_tuples + ] + for ch_idx in range(len(img_tuples)): + allres_versions[ch_idx].append(scaled_cropped_img_tuples[ch_idx]) + + output_img_tuples = tuple([np.concatenate(allres_versions[ch_idx]) for ch_idx in range(len(img_tuples))]) + return output_img_tuples, cropped_noise_tuples + + def __getitem__(self, index: Union[int, Tuple[int, int]]): + img_tuples, noise_tuples = self._get_img(index) + assert self._enable_rotation is False + + assert self._lowres_supervision != True + if len(noise_tuples) > 0: + target = np.concatenate([img[:1] + noise for img, noise in zip(img_tuples, noise_tuples)], axis=0) + else: + target = np.concatenate([img[:1] for img in img_tuples], axis=0) + + # add noise to input + if len(noise_tuples) > 0: + factor = np.sqrt(2) if self._input_is_sum else 1.0 + input_tuples = [] + for x in img_tuples: + x[0] = x[0] + noise_tuples[0] * factor + input_tuples.append(x) + else: + input_tuples = img_tuples + + inp, alpha = self._compute_input(input_tuples) + + output = [inp, target] + + if self._return_alpha: + output.append(alpha) + + if isinstance(index, int): + return tuple(output) + + _, grid_size = index + output.append(grid_size) + return tuple(output) + + # if isinstance(index, int): + # return inp, target + + # _, grid_size = index + # return inp, target, grid_size + + +if __name__ == '__main__': + # from denoisplit.configs.microscopy_multi_channel_lvae_config import get_config + import matplotlib.pyplot as plt + + from denoisplit.configs.twotiff_config import get_config + config = get_config() + padding_kwargs = {'mode': config.data.padding_mode} + if 'padding_value' in config.data and config.data.padding_value is not None: + padding_kwargs['constant_values'] = config.data.padding_value + + dset = LCMultiChDloader(config.data, + '/group/jug/ashesh/data/ventura_gigascience_small/', + DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=config.data.normalized_input, + enable_rotation_aug=config.data.train_aug_rotate, + enable_random_cropping=config.data.deterministic_grid is False, + use_one_mu_std=config.data.use_one_mu_std, + allow_generation=False, + num_scales=config.data.multiscale_lowres_count, + max_val=None, + padding_kwargs=padding_kwargs, + grid_alignment=GridAlignement.LeftTop, + overlapping_padding_kwargs=None) + + mean, std = dset.compute_mean_std() + dset.set_mean_std(mean, std) + + inp, tar = dset[0] + print(inp.shape, tar.shape) + _, ax = plt.subplots(figsize=(10, 2), ncols=5) + ax[0].imshow(inp[0]) + ax[1].imshow(inp[1]) + ax[2].imshow(inp[2]) + ax[3].imshow(tar[0]) + ax[4].imshow(tar[1]) diff --git a/denoisplit/data_loader/lc_multich_explicit_input_dloader.py b/denoisplit/data_loader/lc_multich_explicit_input_dloader.py new file mode 100644 index 0000000..e58ef6b --- /dev/null +++ b/denoisplit/data_loader/lc_multich_explicit_input_dloader.py @@ -0,0 +1,47 @@ +from typing import Tuple, Union + +import numpy as np + +from denoisplit.data_loader.lc_multich_dloader import LCMultiChDloader + + +class LCMultiChExplicitInputDloader(LCMultiChDloader): + """ + The first index of the data is the input, other indices are targets. + # 1. mean, stdev needs to handled differently for input and target. + # 2. input computation will ofcourse be different. + Note that for normalizing the input, we compute the stats from all the channels of the data. One might want to + compute the stats from the first channel only. + """ + + def get_mean_std_for_input(self): + mean, std = super().get_mean_std_for_input() + return mean[:, :1], std[:, :1] + + def compute_individual_mean_std(self): + """ + Here, we remove the mean and stdev computation for the input. + """ + mean, std = super().compute_individual_mean_std() + return mean[:, 1:], std[:, 1:] + + def __getitem__(self, index: Union[int, Tuple[int, int]]): + img_tuples, noise_tuples = self._get_img(index) + assert self._enable_rotation is False + assert len(noise_tuples) == 0, 'Noise is not supported in this data loader.' + assert self._lowres_supervision != True + target = np.concatenate([img[:1] for img in img_tuples[1:]], axis=0) + input_tuples = img_tuples[:1] + inp, alpha = self._compute_input(input_tuples) + + output = [inp, target] + + if self._return_alpha: + output.append(alpha) + + if isinstance(index, int): + return tuple(output) + + _, grid_size = index + output.append(grid_size) + return tuple(output) diff --git a/denoisplit/data_loader/mcdt_twinindex_dloader.py b/denoisplit/data_loader/mcdt_twinindex_dloader.py new file mode 100644 index 0000000..c418aa7 --- /dev/null +++ b/denoisplit/data_loader/mcdt_twinindex_dloader.py @@ -0,0 +1,26 @@ +""" +Multi channel deterministic tiff data loader which takes as input two indices: one for each channel +""" + +import numpy as np + +from denoisplit.data_loader.vanilla_dloader import MultiChDloader + + +class TwinIndexDloader(MultiChDloader): + + def __getitem__(self, idx): + idx1, idx2 = idx + img1, _ = self._get_img(idx1) + _, img2 = self._get_img(idx2) + + if self._enable_rotation: + rot_dic = self._rotation_transform(image=img1[0], mask=img2[0]) + img1 = rot_dic['image'][None] + img2 = rot_dic['mask'][None] + target = np.concatenate([img1, img2], axis=0) + if self._normalized_input: + img1, img2 = self.normalize_img(img1, img2) + + inp = (0.5 * img1 + 0.5 * img2).astype(np.float32) + return inp, target diff --git a/denoisplit/data_loader/multi_channel_determ_tiff_dloader_randomized.py b/denoisplit/data_loader/multi_channel_determ_tiff_dloader_randomized.py new file mode 100644 index 0000000..8eded53 --- /dev/null +++ b/denoisplit/data_loader/multi_channel_determ_tiff_dloader_randomized.py @@ -0,0 +1,28 @@ +""" +Here, the two images are not from same location of the same time point. +""" +from typing import Union + +import numpy as np + +from denoisplit.data_loader.vanilla_dloader import MultiChDloader + + +class MultiChDeterministicTiffRandDloader(MultiChDloader): + + def _get_img(self, index: int): + """ + Returns the two channels. Here, for training, two randomly cropped channels are passed on. + """ + if self._is_train: + cropped_img1_l1, cropped_img2_l1 = super()._get_img(index) + index = np.random.choice(np.arange(len(self))) + cropped_img1_l2, cropped_img2_l2 = super()._get_img(index) + if np.random.rand() > 0.5: + return cropped_img1_l1, cropped_img2_l2 + else: + return cropped_img1_l2, cropped_img2_l1 + + else: + # for validation, use the aligned data as this is the target. + return super()._get_img(index) diff --git a/denoisplit/data_loader/multi_channel_train_val_data.py b/denoisplit/data_loader/multi_channel_train_val_data.py new file mode 100644 index 0000000..b044a81 --- /dev/null +++ b/denoisplit/data_loader/multi_channel_train_val_data.py @@ -0,0 +1,44 @@ +from typing import Union + +import numpy as np +from denoisplit.core import data_split_type + +from denoisplit.core.tiff_reader import load_tiff +from denoisplit.core.data_type import DataType +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples + + +def train_val_data(fpath, data_config, datasplit_type: DataSplitType, val_fraction=None, test_fraction=None): + print(f'Loading {fpath} with Channels {data_config.channel_1},{data_config.channel_2},' + f'datasplit mode:{DataSplitType.name(datasplit_type)}') + data = load_tiff(fpath) + if data_config.data_type == DataType.Prevedel_EMBL: + # Ensure that the last dimension is the channel dimension. + data = data[..., None] + data = np.swapaxes(data, 1, 4) + data = data.squeeze() + + return _train_val_data(data, + datasplit_type, + data_config.channel_1, + data_config.channel_2, + val_fraction=val_fraction, + test_fraction=test_fraction) + + +def _train_val_data(data, datasplit_type: DataSplitType, channel_1, channel_2, val_fraction=None, test_fraction=None): + assert data.shape[-1] > max(channel_1, channel_2), 'Invalid channels' + data = data[..., [channel_1, channel_2]] + if datasplit_type == DataSplitType.All: + return data.astype(np.float32) + + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, len(data)) + + if datasplit_type == DataSplitType.Train: + return data[train_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Val: + return data[val_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Test: + return data[test_idx].astype(np.float32) + else: + raise Exception("invalid datasplit") \ No newline at end of file diff --git a/denoisplit/data_loader/multifile_dset.py b/denoisplit/data_loader/multifile_dset.py new file mode 100644 index 0000000..c7eec7c --- /dev/null +++ b/denoisplit/data_loader/multifile_dset.py @@ -0,0 +1,265 @@ +import numpy as np + +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.core.data_type import DataType +from denoisplit.core.empty_patch_fetcher import EmptyPatchFetcher +from denoisplit.data_loader.lc_multich_dloader import LCMultiChDloader +from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager +from denoisplit.data_loader.train_val_data import get_train_val_data +from denoisplit.data_loader.vanilla_dloader import MultiChDloader + + +class SingleFileLCDset(LCMultiChDloader): + + def __init__(self, + preloaded_data, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + use_one_mu_std=None, + num_scales: int = None, + enable_random_cropping=False, + padding_kwargs: dict = None, + allow_generation: bool = False, + lowres_supervision=None, + max_val=None, + grid_alignment=GridAlignement.LeftTop, + overlapping_padding_kwargs=None, + print_vars=True): + self._preloaded_data = preloaded_data + super().__init__(data_config, + fpath, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + use_one_mu_std=use_one_mu_std, + num_scales=num_scales, + enable_random_cropping=enable_random_cropping, + padding_kwargs=padding_kwargs, + allow_generation=allow_generation, + lowres_supervision=lowres_supervision, + max_val=max_val, + grid_alignment=grid_alignment, + overlapping_padding_kwargs=overlapping_padding_kwargs, + print_vars=print_vars) + + @property + def data_path(self): + return self._fpath + + def rm_bkground_set_max_val_and_upperclip_data(self, max_val, datasplit_type): + pass + + def load_data(self, data_config, datasplit_type, val_fraction=None, test_fraction=None, allow_generation=None): + self._data = self._preloaded_data + self.N = len(self._data) + + +class SingleFileDset(MultiChDloader): + + def __init__(self, + preloaded_data, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + enable_random_cropping: bool = False, + use_one_mu_std=None, + allow_generation=False, + max_val=None, + grid_alignment=GridAlignement.LeftTop, + overlapping_padding_kwargs=None, + print_vars=True): + self._preloaded_data = preloaded_data + super().__init__(data_config, + fpath, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=enable_random_cropping, + use_one_mu_std=use_one_mu_std, + allow_generation=allow_generation, + max_val=max_val, + grid_alignment=grid_alignment, + overlapping_padding_kwargs=overlapping_padding_kwargs, + print_vars=print_vars) + + def rm_bkground_set_max_val_and_upperclip_data(self, max_val, datasplit_type): + pass + + @property + def data_path(self): + return self._fpath + + def load_data(self, data_config, datasplit_type, val_fraction=None, test_fraction=None, allow_generation=None): + self._data = self._preloaded_data + if 'channel_1' in data_config and isinstance(data_config.channel_1, int): + assert 'channel_2' in data_config + self._data = self._data[..., [data_config.channel_1, data_config.channel_2]].copy() + + self.N = len(self._data) + + +class MultiFileDset: + """ + Here, we handle dataset having multiple files. Each file can have a different spatial dimension and number of frames (Z stack). + """ + + def __init__(self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + enable_random_cropping: bool = False, + use_one_mu_std=None, + max_val=None, + grid_alignment=GridAlignement.LeftTop, + padding_kwargs=None, + overlapping_padding_kwargs=None): + + self._fpath = fpath + self._background_quantile = data_config.get('background_quantile', 0.0) + data = get_train_val_data(data_config, + self._fpath, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + self.dsets = [] + + for i in range(len(data)): + prefetched_data, fpath_tuple = data[i] + if data_config.multiscale_lowres_count is not None and data_config.multiscale_lowres_count > 1: + + self.dsets.append( + SingleFileLCDset(prefetched_data[None], + data_config, + fpath_tuple, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=enable_random_cropping, + use_one_mu_std=use_one_mu_std, + allow_generation=False, + num_scales=data_config.multiscale_lowres_count, + max_val=max_val, + grid_alignment=grid_alignment, + padding_kwargs=padding_kwargs, + overlapping_padding_kwargs=overlapping_padding_kwargs, + print_vars=i == len(data) - 1)) + + else: + self.dsets.append( + SingleFileDset(prefetched_data[None], + data_config, + fpath_tuple, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=enable_random_cropping, + use_one_mu_std=use_one_mu_std, + allow_generation=False, + max_val=max_val, + grid_alignment=grid_alignment, + overlapping_padding_kwargs=overlapping_padding_kwargs, + print_vars=i == len(data) - 1)) + + self.rm_bkground_set_max_val_and_upperclip_data(max_val, datasplit_type) + count = 0 + avg_height = 0 + avg_width = 0 + for dset in self.dsets: + shape = dset.get_data_shape() + avg_height += shape[1] + avg_width += shape[2] + count += shape[0] + + avg_height = int(avg_height / len(self.dsets)) + avg_width = int(avg_width / len(self.dsets)) + print(f'{self.__class__.__name__} avg height: {avg_height}, avg width: {avg_width}, count: {count}') + + def rm_bkground_set_max_val_and_upperclip_data(self, max_val, datasplit_type): + assert self._background_quantile == 0.0 + self.set_max_val(max_val, datasplit_type) + self.upperclip_data() + + def set_mean_std(self, mean_val, std_val): + for dset in self.dsets: + dset.set_mean_std(mean_val, std_val) + + def get_mean_std(self): + return self.dsets[0].get_mean_std() + + def compute_max_val(self): + max_val_arr = [] + for dset in self.dsets: + max_val_arr.append(dset.compute_max_val()) + return np.max(max_val_arr) + + def set_max_val(self, max_val, datasplit_type): + if datasplit_type == DataSplitType.Train: + assert max_val is None + max_val = self.compute_max_val() + for dset in self.dsets: + dset.set_max_val(max_val, datasplit_type) + + def upperclip_data(self): + for dset in self.dsets: + dset.upperclip_data() + + def get_max_val(self): + return self.dsets[0].get_max_val() + + def get_img_sz(self): + return self.dsets[0].get_img_sz() + + def compute_mean_std(self): + cum_mean = 0 + cum_std = 0 + for dset in self.dsets: + mean, std = dset.compute_mean_std() + cum_mean += mean + cum_std += std + return cum_mean / len(self.dsets), cum_std / len(self.dsets) + + def compute_individual_mean_std(self): + cum_mean = 0 + cum_std = 0 + for dset in self.dsets: + mean, std = dset.compute_individual_mean_std() + cum_mean += mean + cum_std += std + return cum_mean / len(self.dsets), cum_std / len(self.dsets) + + def __len__(self): + out = 0 + for dset in self.dsets: + out += len(dset) + return out + + def __getitem__(self, idx): + cum_len = 0 + for dset in self.dsets: + cum_len += len(dset) + if idx < cum_len: + rel_idx = idx - (cum_len - len(dset)) + return dset[rel_idx] + + raise IndexError('Index out of range') diff --git a/denoisplit/data_loader/multifile_raw_dloader.py b/denoisplit/data_loader/multifile_raw_dloader.py new file mode 100644 index 0000000..b60a7e0 --- /dev/null +++ b/denoisplit/data_loader/multifile_raw_dloader.py @@ -0,0 +1,189 @@ +import os +from ast import literal_eval as make_tuple +from collections.abc import Sequence +from random import shuffle +from typing import List + +import numpy as np + +from denoisplit.core.custom_enum import Enum +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from denoisplit.core.tiff_reader import load_tiff + + +class TwoChannelData(Sequence): + """ + each element in data_arr should be a N*H*W array + """ + + def __init__(self, data_arr1, data_arr2, paths_data1=None, paths_data2=None): + assert len(data_arr1) == len(data_arr2) + self.paths1 = paths_data1 + self.paths2 = paths_data2 + + self._data = [] + for i in range(len(data_arr1)): + assert data_arr1[i].shape == data_arr2[i].shape + assert len( + data_arr1[i].shape) == 3, f'Each element in data arrays should be a N*H*W, but {data_arr1[i].shape}' + self._data.append(np.concatenate([data_arr1[i][..., None], data_arr2[i][..., None]], axis=-1)) + + def __len__(self): + n = 0 + for x in self._data: + n += x.shape[0] + return n + + def __getitem__(self, idx): + n = 0 + for dataidx, x in enumerate(self._data): + if idx < n + x.shape[0]: + if self.paths1 is None: + return x[idx - n], None + else: + return x[idx - n], (self.paths1[dataidx], self.paths2[dataidx]) + n += x.shape[0] + raise IndexError('Index out of range') + + +class MultiChannelData(Sequence): + """ + each element in data_arr should be a N*H*W array + """ + + def __init__(self, data_arr, paths=None): + self.paths = paths + + self._data = data_arr + + def __len__(self): + n = 0 + for x in self._data: + n += x.shape[0] + return n + + def __getitem__(self, idx): + n = 0 + for dataidx, x in enumerate(self._data): + if idx < n + x.shape[0]: + if self.paths is None: + return x[idx - n], None + else: + return x[idx - n], (self.paths[dataidx]) + n += x.shape[0] + raise IndexError('Index out of range') + + +class SubDsetType(Enum): + TwoChannel = 0 + OneChannel = 1 + MultiChannel = 2 + + +def subset_data(dataA, dataB, dataidx_list): + dataidx_list = sorted(dataidx_list) + subset_dataA = [] + subset_dataB = [] if dataB is not None else None + cur_dataidx = 0 + cumulative_datacount = 0 + for arr_idx in range(len(dataA)): + for data_idx in range(len(dataA[arr_idx])): + cumulative_datacount += 1 + if dataidx_list[cur_dataidx] == cumulative_datacount - 1: + subset_dataA.append(dataA[arr_idx][data_idx:data_idx + 1]) + if dataB is not None: + subset_dataB.append(dataB[arr_idx][data_idx:data_idx + 1]) + cur_dataidx += 1 + if cur_dataidx >= len(dataidx_list): + break + if cur_dataidx >= len(dataidx_list): + break + return subset_dataA, subset_dataB + + +def get_train_val_data(datadir, + data_config, + datasplit_type: DataSplitType, + get_multi_channel_files_fn, + load_data_fn=None, + val_fraction=None, + test_fraction=None): + dset_subtype = data_config.subdset_type + if load_data_fn is None: + load_data_fn = load_tiff + + if dset_subtype == SubDsetType.TwoChannel: + fnamesA, fnamesB = get_multi_channel_files_fn() + fpathsA = [os.path.join(datadir, x) for x in fnamesA] + fpathsB = [os.path.join(datadir, x) for x in fnamesB] + dataA = [load_data_fn(fpath) for fpath in fpathsA] + dataB = [load_data_fn(fpath) for fpath in fpathsB] + elif dset_subtype == SubDsetType.OneChannel: + fnamesmixed = get_multi_channel_files_fn() + fpathsmixed = [os.path.join(datadir, x) for x in fnamesmixed] + fpathsA = fpathsB = fpathsmixed + dataA = [load_data_fn(fpath) for fpath in fpathsmixed] + # Note that this is important. We need to ensure that the sum of the two channels is the same as sum of these two channels. + dataA = [x / 2 for x in dataA] + dataB = [x.copy() for x in dataA] + elif dset_subtype == SubDsetType.MultiChannel: + fnamesA = get_multi_channel_files_fn() + fpathsA = [os.path.join(datadir, x) for x in fnamesA] + dataA = [load_data_fn(fpath) for fpath in fpathsA] + fnamesB = None + fpathsB = None + dataB = None + + if dataB is not None: + assert len(dataA) == len(dataB) + for i in range(len(dataA)): + assert dataA[i].shape == dataB[ + i].shape, f'{dataA[i].shape} != {dataB[i].shape}, {fpathsA[i]} != {fpathsB[i]} in shape' + + if len(dataA[i].shape) == 2: + dataA[i] = dataA[i][None] + dataB[i] = dataB[i][None] + + count = np.sum([x.shape[0] for x in dataA]) + framewise_fpathsA = [] + for onedata_A, onepath_A in zip(dataA, fpathsA): + framewise_fpathsA += [onepath_A] * onedata_A.shape[0] + + framewise_fpathsB = None + if dataB is not None: + framewise_fpathsB = [] + for onedata_B, onepath_B in zip(dataB, fpathsB): + framewise_fpathsB += [onepath_B] * onedata_B.shape[0] + + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, count) + + if datasplit_type == DataSplitType.All: + pass + elif datasplit_type == DataSplitType.Train: + # print(train_idx) + dataA, dataB = subset_data(dataA, dataB, train_idx) + framewise_fpathsA = [framewise_fpathsA[i] for i in train_idx] + if dataB is not None: + framewise_fpathsB = [framewise_fpathsB[i] for i in train_idx] + elif datasplit_type == DataSplitType.Val: + # print(val_idx) + dataA, dataB = subset_data(dataA, dataB, val_idx) + framewise_fpathsA = [framewise_fpathsA[i] for i in val_idx] + if dataB is not None: + framewise_fpathsB = [framewise_fpathsB[i] for i in val_idx] + elif datasplit_type == DataSplitType.Test: + # print(test_idx) + dataA, dataB = subset_data(dataA, dataB, test_idx) + framewise_fpathsA = [framewise_fpathsA[i] for i in test_idx] + if dataB is not None: + framewise_fpathsB = [framewise_fpathsB[i] for i in test_idx] + else: + raise Exception("invalid datasplit") + + if dset_subtype == SubDsetType.MultiChannel: + data = MultiChannelData(dataA, paths=framewise_fpathsA) + else: + data = TwoChannelData(dataA, dataB, paths_data1=framewise_fpathsA, paths_data2=framewise_fpathsB) + print('Loaded from', SubDsetType.name(dset_subtype), datadir, len(data)) + print('') + return data diff --git a/denoisplit/data_loader/notmnist_dloader.py b/denoisplit/data_loader/notmnist_dloader.py new file mode 100644 index 0000000..87f40d5 --- /dev/null +++ b/denoisplit/data_loader/notmnist_dloader.py @@ -0,0 +1,87 @@ +import os +import pickle +from typing import Union + +import numpy as np +from skimage.io import imread +from tqdm import tqdm + +from git.objects import base + + +class NotMNISTNoisyLoader: + """ + """ + def __init__(self, data_fpath: str, img_files_pkl, label1, label2, return_labels: bool = False) -> None: + + # train/val split is defined in this file. It contains the list of images one needs to load from fpath_dict + self._img_files_pkl = img_files_pkl + self._datapath = data_fpath + self.labels = None + print(f'[{self.__class__.__name__}] Data fpath:', self._datapath) + self.N = None + self._return_labels = return_labels + self._l1 = label1 + self._l2 = label2 + self._all_data = self.load(labels=[self._l1, self._l2]) + self._l1_index = self.labels.index(label1) + self._l2_index = self.labels.index(label2) + self._l1_N = len(self._all_data[label1]) + self._l2_N = len(self._all_data[label2]) + + def get_label_idx_range(self): + return { + '1': [0, self._l1_N], + '2': [self._l1_N, self._l1_N + self._l2_N], + } + + def _load_one_directory(self, directory, img_files_dict, labels=None): + data_dict = {} + if labels is None: + labels = img_files_dict.keys() + for label in labels: + data = np.zeros((len(img_files_dict[label]), 27, 27), dtype=np.float32) + for i, img_fname in tqdm(enumerate(img_files_dict[label])): + img_fpath = os.path.join(directory, label, img_fname) + data[i] = imread(img_fpath) + + data = np.pad(data, pad_width=((0, 0), (1, 0), (1, 0))) + data = data[:, None, ...].copy() + + data_dict[label] = data + return data_dict + + def load(self, labels=None): + with open(self._img_files_pkl, 'rb') as f: + img_files_dict = pickle.load(f) + + data = self._load_one_directory(self._datapath, img_files_dict, labels=labels) + + sz = sum([data[label].shape[0] for label in data.keys()]) + self.labels = sorted(list(data.keys())) + label_sizes = [len(data[label]) for label in self.labels] + self.cumlative_label_sizes = [np.sum(label_sizes[:i]) for i in range(1, 1 + len(label_sizes))] + + self.N = sz + return data + + def __getitem__(self, index_tuple): + index1, index2 = index_tuple + assert index1 < self._l1_N, 'Index1 must be from first label' + assert index2 >= self._l1_N and index2 < self.__len__(), 'Index2 must be from second label' + img1 = self._all_data[self._l1][index1] + img2 = self._all_data[self._l2][index2 % self._l1_N] + + inp = (img1 + img2) / 2 + target = np.concatenate([img1, img2], axis=0) + return inp, target + + def get_mean_std(self): + data = [] + data.append(self._all_data[self._l1]) + data.append(self._all_data[self._l2]) + all_data = np.concatenate(data) + return np.mean(all_data), np.std(all_data) + + def __len__(self): + return self._l1_N + self._l2_N diff --git a/denoisplit/data_loader/patch_index_manager.py b/denoisplit/data_loader/patch_index_manager.py new file mode 100644 index 0000000..5dd217c --- /dev/null +++ b/denoisplit/data_loader/patch_index_manager.py @@ -0,0 +1,199 @@ +""" +We would like to have a common logic to map between an index and location on the image. +We assume the data to be of shape N * H * W * C (C: channels, H,W: spatial dimensions, N: time/number of frames) +We assume the square patches. +The extra content on the right side will not be used( as shown below). +.-----------.-. +| | | +| | | +| | | +| | | +.-----------.-. + +""" +from tkinter import Grid + +from denoisplit.core.custom_enum import Enum + + +class GridAlignement(Enum): + """ + A patch is formed by padding the grid with content. If the grids are 'Center' aligned, then padding is to done equally on all 4 sides. + On the other hand, if grids are 'LeftTop' aligned, padding is to be done on the right and bottom end of the grid. + In the former case, one needs (patch_size - grid_size)//2 amount of content on the right end of the frame. + In the latter case, one needs patch_size - grid_size amount of content on the right end of the frame. + """ + LeftTop = 0 + Center = 1 + + +class GridIndexManager: + + def __init__(self, data_shape, grid_size, patch_size, grid_alignement) -> None: + self._data_shape = data_shape + self._default_grid_size = grid_size + self.patch_size = patch_size + self.N = self._data_shape[0] + self._align = grid_alignement + + def get_data_shape(self): + return self._data_shape + + def use_default_grid(self, grid_size): + return grid_size is None or grid_size < 0 + + def grid_rows(self, grid_size): + if self._align == GridAlignement.LeftTop: + extra_pixels = (self.patch_size - grid_size) + elif self._align == GridAlignement.Center: + # Center is exclusively used during evaluation. In this case, we use the padding to handle edge cases. + # So, here, we will ideally like to cover all pixels and so extra_pixels is set to 0. + # If there was no padding, then it should be set to (self.patch_size - grid_size) // 2 + extra_pixels = 0 + + return ((self._data_shape[-3] - extra_pixels) // grid_size) + + def grid_cols(self, grid_size): + if self._align == GridAlignement.LeftTop: + extra_pixels = (self.patch_size - grid_size) + elif self._align == GridAlignement.Center: + extra_pixels = 0 + + return ((self._data_shape[-2] - extra_pixels) // grid_size) + + def grid_count(self, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + return self.N * self.grid_rows(grid_size) * self.grid_cols(grid_size) + + def hwt_from_idx(self, index, grid_size=None): + t = self.get_t(index) + return (*self.get_deterministic_hw(index, grid_size=grid_size), t) + + def idx_from_hwt(self, h_start, w_start, t, grid_size=None): + """ + Given h,w,t (where h,w constitutes the top left corner of the patch), it returns the corresponding index. + """ + if grid_size is None: + grid_size = self._default_grid_size + + nth_row = h_start // grid_size + nth_col = w_start // grid_size + + index = self.grid_cols(grid_size) * nth_row + nth_col + return index * self._data_shape[0] + t + + def get_t(self, index): + return index % self.N + + def get_top_nbr_idx(self, index, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + ncols = self.grid_cols(grid_size) + index -= ncols * self.N + if index < 0: + return None + + return index + + def get_bottom_nbr_idx(self, index, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + ncols = self.grid_cols(grid_size) + index += ncols * self.N + if index > self.grid_count(grid_size=grid_size): + return None + + return index + + def get_left_nbr_idx(self, index, grid_size=None): + if self.on_left_boundary(index, grid_size=grid_size): + return None + + index -= self.N + return index + + def get_right_nbr_idx(self, index, grid_size=None): + if self.on_right_boundary(index, grid_size=grid_size): + return None + index += self.N + return index + + def on_left_boundary(self, index, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + factor = index // self.N + ncols = self.grid_cols(grid_size) + + left_boundary = (factor // ncols) != (factor - 1) // ncols + return left_boundary + + def on_right_boundary(self, index, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + factor = index // self.N + ncols = self.grid_cols(grid_size) + + right_boundary = (factor // ncols) != (factor + 1) // ncols + return right_boundary + + def on_top_boundary(self, index, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + ncols = self.grid_cols(grid_size) + return index < self.N * ncols + + def on_bottom_boundary(self, index, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + ncols = self.grid_cols(grid_size) + return index + self.N * ncols > self.grid_count(grid_size=grid_size) + + def on_boundary(self, idx, grid_size=None): + if self.on_left_boundary(idx, grid_size=grid_size): + return True + + if self.on_right_boundary(idx, grid_size=grid_size): + return True + + if self.on_top_boundary(idx, grid_size=grid_size): + return True + + if self.on_bottom_boundary(idx, grid_size=grid_size): + return True + return False + + def get_deterministic_hw(self, index: int, grid_size=None): + """ + Fixed starting position for the crop for the img with index `index`. + """ + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + # _, h, w, _ = self._data_shape + # assert h == w + factor = index // self.N + ncols = self.grid_cols(grid_size) + + ith_row = factor // ncols + jth_col = factor % ncols + h_start = ith_row * grid_size + w_start = jth_col * grid_size + return h_start, w_start + + +if __name__ == '__main__': + grid_size = 32 + patch_size = 64 + index = 13 + manager = GridIndexManager((1, 499, 469, 2), grid_size, patch_size, GridAlignement.Center) + h_start, w_start = manager.get_deterministic_hw(index) + print(h_start, w_start, manager.grid_count()) + print(manager.grid_rows(grid_size), manager.grid_cols(grid_size)) diff --git a/denoisplit/data_loader/pavia2_3ch_dloader.py b/denoisplit/data_loader/pavia2_3ch_dloader.py new file mode 100644 index 0000000..379229d --- /dev/null +++ b/denoisplit/data_loader/pavia2_3ch_dloader.py @@ -0,0 +1,59 @@ +from denoisplit.data_loader.pavia2_dloader import Pavia2V1Dloader, Pavia2DataSetChannels +from denoisplit.core.data_split_type import DataSplitType +import numpy as np + + +class Pavia2ThreeChannelDloader(Pavia2V1Dloader): + + def __init__(self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + enable_random_cropping: bool = False, + use_one_mu_std=None, + allow_generation=False, + max_val=None) -> None: + + # which are the indices for bleedthrough nucleus, clean nucleus, tubulin + self._bt_nuc_idx = data_config.channel_idx_list.index(Pavia2DataSetChannels.NucMTORQ) + self._cl_nuc_idx = data_config.channel_idx_list.index(Pavia2DataSetChannels.NucRFP670) + self._tubuln_idx = data_config.channel_idx_list.index(Pavia2DataSetChannels.TUBULIN) + + # self._relv_channel_idx = [Pavia2DataSetChannels.NucRFP670, Pavia2DataSetChannels.NucMTORQ, Pavia2DataSetChannels.TUBULIN] + super().__init__(data_config, fpath, datasplit_type, val_fraction, test_fraction, normalized_input, + enable_rotation_aug, enable_random_cropping, use_one_mu_std, allow_generation, max_val) + + def get_max_val(self): + return self._dloader_clean.get_max_val() + + def process_data(self): + """ + We are ignoring the actin channel. + We know that MTORQ(uise) has sigficant bleedthrough from TUBULIN channels. So, when MTORQ has no content, then + we sum it with TUBULIN so that tubulin has whole of its content. + When MTORQ has content, then we sum RFP670 with tubulin. This makes sure that tubulin channel has the same data distribution. + During validation/testing, we always feed sum of these three channels as the input. + """ + pass + + +if __name__ == '__main__': + from denoisplit.configs.pavia2_config import get_config + config = get_config() + fpath = '/group/jug/ashesh/data/pavia2/' + dloader = Pavia2ThreeChannelDloader(config.data, + fpath, + datasplit_type=DataSplitType.Train, + val_fraction=0.1, + test_fraction=0.1, + normalized_input=True, + use_one_mu_std=False, + enable_random_cropping=True) + mean_val, std_val = dloader.compute_mean_std() + dloader.set_mean_std(mean_val, std_val) + inp, tar, source = dloader[0] + print('This is working') \ No newline at end of file diff --git a/denoisplit/data_loader/pavia2_dloader.py b/denoisplit/data_loader/pavia2_dloader.py new file mode 100644 index 0000000..04c9098 --- /dev/null +++ b/denoisplit/data_loader/pavia2_dloader.py @@ -0,0 +1,300 @@ +import numpy as np +import torch + +import ml_collections +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.data_loader.lc_multich_dloader import LCMultiChDloader +from denoisplit.data_loader.patch_index_manager import GridIndexManager +from denoisplit.data_loader.pavia2_enums import Pavia2BleedthroughType +from denoisplit.data_loader.pavia2_rawdata_loader import Pavia2DataSetChannels, Pavia2DataSetType +from denoisplit.data_loader.vanilla_dloader import MultiChDloader + + +class Pavia2V1Dloader: + + def __init__(self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + enable_random_cropping: bool = False, + use_one_mu_std=None, + allow_generation=False, + max_val=None) -> None: + + self._datasplit_type = datasplit_type + self._enable_random_cropping = enable_random_cropping + self._dloader_clean = self._dloader_bleedthrough = self._dloader_mix = None + self._use_one_mu_std = use_one_mu_std + + self._mean = None + self._std = None + assert normalized_input is True, "We are doing the normalization in this dataloader.So you better pass it as True" + # We don't normalalize inside the self._dloader_clean or bleedthrough. We normalize in this class. + normalized_input = False + use_LC = 'multiscale_lowres_count' in data_config and data_config.multiscale_lowres_count is not None + data_class = LCMultiChDloader if use_LC else MultiChDloader + + kwargs = { + 'normalized_input': normalized_input, + 'enable_rotation_aug': enable_rotation_aug, + 'use_one_mu_std': use_one_mu_std, + 'allow_generation': allow_generation, + 'datasplit_type': datasplit_type + } + if use_LC: + padding_kwargs = {'mode': data_config.padding_mode} + if 'padding_value' in data_config and data_config.padding_value is not None: + padding_kwargs['constant_values'] = data_config.padding_value + kwargs['padding_kwargs'] = padding_kwargs + kwargs['num_scales'] = data_config.multiscale_lowres_count + + if self._datasplit_type == DataSplitType.Train: + # assert enable_random_cropping is True + dconf = ml_collections.ConfigDict(data_config) + # take channels mean from this. + dconf.dset_type = Pavia2DataSetType.JustMAGENTA + self._clean_prob = dconf.dset_clean_sample_probab + self._bleedthrough_prob = dconf.dset_bleedthrough_sample_probab + assert self._clean_prob + self._bleedthrough_prob <= 1 + self._dloader_clean = data_class(dconf, + fpath, + val_fraction=val_fraction, + test_fraction=test_fraction, + enable_random_cropping=True, + max_val=None, + **kwargs) + + dconf.dset_type = Pavia2DataSetType.JustCYAN + self._dloader_bleedthrough = data_class(dconf, + fpath, + val_fraction=val_fraction, + test_fraction=test_fraction, + enable_random_cropping=True, + max_val=None, + **kwargs) + + dconf.dset_type = Pavia2DataSetType.MIXED + self._dloader_mix = data_class(dconf, + fpath, + val_fraction=val_fraction, + test_fraction=test_fraction, + enable_random_cropping=True, + max_val=None, + **kwargs) + else: + assert enable_random_cropping is False + dconf = ml_collections.ConfigDict(data_config) + dconf.dset_type = Pavia2DataSetType.JustMAGENTA + # we want to evaluate on mixed samples. + self._clean_prob = 1.0 + self._bleedthrough_prob = 0.0 + self._dloader_clean = data_class(dconf, + fpath, + val_fraction=val_fraction, + test_fraction=test_fraction, + enable_random_cropping=enable_random_cropping, + max_val=max_val, + **kwargs) + self.process_data() + + # needed just during evaluation. + self._img_sz = self._dloader_clean._img_sz + self._grid_sz = self._dloader_clean._grid_sz + + print(f'[{self.__class__.__name__}] BleedTh prob:{self._bleedthrough_prob} Clean prob:{self._clean_prob}') + + def sum_channels(self, data, first_index_arr, second_index_arr): + fst_channel = data[..., first_index_arr].sum(axis=-1, keepdims=True) + scnd_channel = data[..., second_index_arr].sum(axis=-1, keepdims=True) + return np.concatenate([fst_channel, scnd_channel], axis=-1) + + def process_data(self): + """ + We are ignoring the actin channel. + We know that MTORQ(uise) has sigficant bleedthrough from TUBULIN channels. So, when MTORQ has no content, then + we sum it with TUBULIN so that tubulin has whole of its content. + When MTORQ has content, then we sum RFP670 with tubulin. This makes sure that tubulin channel has the same data distribution. + During validation/testing, we always feed sum of these three channels as the input. + """ + + if self._datasplit_type == DataSplitType.Train: + self._dloader_clean._data = self._dloader_clean._data[ + ..., [Pavia2DataSetChannels.NucRFP670, Pavia2DataSetChannels.TUBULIN]] + self._dloader_bleedthrough._data = self._dloader_bleedthrough._data[ + ..., [Pavia2DataSetChannels.NucMTORQ, Pavia2DataSetChannels.TUBULIN]] + self._dloader_mix._data = self._dloader_mix._data[ + ..., [Pavia2DataSetChannels.NucRFP670, Pavia2DataSetChannels.NucMTORQ, Pavia2DataSetChannels.TUBULIN]] + self._dloader_mix._data = self.sum_channels(self._dloader_mix._data, [0, 1], [2]) + self._dloader_mix._data[..., 0] = self._dloader_mix._data[..., 0] / 2 + # self._dloader_clean._data = self.sum_channels(self._dloader_clean._data, [1], [0, 2]) + # In bleedthrough dataset, the nucleus channel is empty. + # self._dloader_bleedthrough._data = self.sum_channels(self._dloader_bleedthrough._data, [0], [1, 2]) + else: + self._dloader_mix._data = self._dloader_mix._data[ + ..., [Pavia2DataSetChannels.NucRFP670, Pavia2DataSetChannels.NucMTORQ, Pavia2DataSetChannels.TUBULIN]] + self._dloader_mix._data = self.sum_channels(self._dloader_mix._data, [0, 1], [2]) + + def set_img_sz(self, image_size, grid_size, alignment=None): + """ + Needed just for the notebooks + If one wants to change the image size on the go, then this can be used. + Args: + image_size: size of one patch + grid_size: frame is divided into square grids of this size. A patch centered on a grid having size `image_size` is returned. + """ + self._img_sz = image_size + self._grid_sz = grid_size + if self._dloader_mix is not None: + self._dloader_mix.set_img_sz(image_size, grid_size, alignment=alignment) + + if self._dloader_clean is not None: + self._dloader_clean.set_img_sz(image_size, grid_size, alignment=alignment) + + if self._dloader_bleedthrough is not None: + self._dloader_bleedthrough.set_img_sz(image_size, grid_size, alignment=alignment) + + self.idx_manager = GridIndexManager(self.get_data_shape(), self._grid_sz, self._img_sz, alignment) + + def get_mean_std(self): + """ + Needed just for running the notebooks + """ + return self._mean, self._std + + def get_data_shape(self): + N = 0 + default_shape = None + if self._dloader_mix is not None: + default_shape = self._dloader_mix.get_data_shape() + N += default_shape[0] + + if self._dloader_clean is not None: + default_shape = self._dloader_clean.get_data_shape() + N += default_shape[0] + + if self._dloader_bleedthrough is not None: + default_shape = self._dloader_bleedthrough.get_data_shape() + N += default_shape[0] + + default_shape = list(default_shape) + default_shape[0] = N + return tuple(default_shape) + + def __len__(self): + sz = 0 + if self._dloader_clean is not None: + sz += int(self._clean_prob * len(self._dloader_clean)) + if self._dloader_bleedthrough is not None: + sz += int(self._bleedthrough_prob * len(self._dloader_bleedthrough)) + if self._dloader_mix is not None: + mix_prob = 1 - self._clean_prob - self._bleedthrough_prob + sz += int(mix_prob * len(self._dloader_mix)) + return sz + + def compute_individual_mean_std(self): + mean_, std_ = self._dloader_clean.compute_individual_mean_std() + mean_dict = {'target': mean_, 'mix': mean_.sum(axis=1, keepdims=True)} + std_dict = {'target': std_, 'mix': np.sqrt((std_**2).sum(axis=1, keepdims=True))} + # NOTE: dataloader2 does not has clean channel. So, no mean should be computed on it. + # mean_std2 = self._dloader_bleedthrough.compute_individual_mean_std() if self._dloader_bleedthrough is not None else (None,None) + return mean_dict, std_dict + + # if mean_std2 is None: + # return mean_std1 + + # mean_val = (mean_std1[0] + mean_std2[0]) / 2 + # std_val = (mean_std1[1] + mean_std2[1]) / 2 + + # return (mean_val, std_val) + + def compute_mean_std(self): + if self._use_one_mu_std is False: + return self.compute_individual_mean_std() + else: + raise ValueError('This must not be called. We want to compute individual mean so that they can be \ + passed on to the model') + mean_std1 = self._dloader_clean.compute_mean_std() + mean_std2 = self._dloader2.compute_mean_std() if self._dloader_bleedthrough is not None else (None, None) + if mean_std2 is None: + return mean_std1 + + mean_val = (mean_std1[0] + mean_std2[0]) / 2 + std_val = (mean_std1[1] + mean_std2[1]) / 2 + + return (mean_val, std_val) + + def set_mean_std(self, mean_val, std_val): + self._mean = mean_val + self._std = std_val + + # self._dloader_clean.set_mean_std(mean_val, std_val) + # if self._dloader_bleedthrough is not None: + # self._dloader_bleedthrough.set_mean_std(mean_val, std_val) + + def normalize_input(self, inp): + return (inp - self._mean['mix'][0]) / self._std['mix'][0] + + def __getitem__(self, index): + """ + Returns: + (inp,tar,mixed_recons_flag): When mixed_recons_flag is set, then do only the mixed reconstruction. This is set when we've bleedthrough + """ + coin_flip = np.random.rand() + if self._datasplit_type == DataSplitType.Train: + + if coin_flip <= self._clean_prob: + idx = np.random.randint(len(self._dloader_clean)) + inp, tar = self._dloader_clean[idx] + mixed_recons_flag = Pavia2BleedthroughType.Clean + # print('Clean', idx) + elif coin_flip > self._clean_prob and coin_flip <= self._clean_prob + self._bleedthrough_prob: + idx = np.random.randint(len(self._dloader_bleedthrough)) + inp, tar = self._dloader_bleedthrough[idx] + mixed_recons_flag = Pavia2BleedthroughType.Bleedthrough + # print('Bleedthrough') + else: + idx = np.random.randint(len(self._dloader_mix)) + inp, tar = self._dloader_mix[idx] + mixed_recons_flag = Pavia2BleedthroughType.Mixed + # print('Mixed', idx) + + # dataloader takes the average of the K channels. To, undo that, we are multipying it with K. + inp = len(tar) * inp + inp = self.normalize_input(inp) + return (inp, tar, mixed_recons_flag) + + else: + inp, tar = self._dloader_clean[index] + inp = len(tar) * inp + inp = self.normalize_input(inp) + return (inp, tar, Pavia2BleedthroughType.Clean) + + def get_max_val(self): + max_val = self._dloader_clean.get_max_val() + return max_val + + +if __name__ == '__main__': + from denoisplit.configs.pavia2_config import get_config + config = get_config() + fpath = '/group/jug/ashesh/data/pavia2/' + dloader = Pavia2V1Dloader( + config.data, + fpath, + datasplit_type=DataSplitType.Val, + val_fraction=0.1, + test_fraction=0.1, + normalized_input=True, + use_one_mu_std=False, + enable_random_cropping=False, + max_val=100, + ) + mean_val, std_val = dloader.compute_mean_std() + dloader.set_mean_std(mean_val, std_val) + inp, tar, source = dloader[0] + len(dloader) + print('This is working') \ No newline at end of file diff --git a/denoisplit/data_loader/pavia2_enums.py b/denoisplit/data_loader/pavia2_enums.py new file mode 100644 index 0000000..6f314d2 --- /dev/null +++ b/denoisplit/data_loader/pavia2_enums.py @@ -0,0 +1,23 @@ +from denoisplit.core.custom_enum import Enum + +class Pavia2DataSetType(Enum): + JustCYAN = '0b001' + JustMAGENTA = '0b010' + MIXED = '0b100' + + +class Pavia2DataSetChannels(Enum): + NucRFP670 = 0 + NucMTORQ = 1 + ACTIN = 2 + TUBULIN = 3 + + +class Pavia2DataSetVersion(Enum): + DD = 'DenoisedDeconvolved' + RAW = 'Raw data' + +class Pavia2BleedthroughType(Enum): + Clean = 0 + Bleedthrough = 1 + Mixed = 2 \ No newline at end of file diff --git a/denoisplit/data_loader/pavia2_rawdata_loader.py b/denoisplit/data_loader/pavia2_rawdata_loader.py new file mode 100644 index 0000000..868c3f7 --- /dev/null +++ b/denoisplit/data_loader/pavia2_rawdata_loader.py @@ -0,0 +1,121 @@ +""" +It has 4 channels: Nucleus, Nucleus, Actin, Tubulin +It has 3 sets: Only CYAN, ONLY MAGENTA, MIXED. +It has 2 versions: denoised and raw data. +""" +import os +import numpy as np +from nd2reader import ND2Reader +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from denoisplit.data_loader.pavia2_enums import Pavia2DataSetType, Pavia2DataSetChannels, Pavia2DataSetVersion + + +def load_nd2(fpaths): + """ + Load .nd2 images. + """ + images = [] + for fpath in fpaths: + with ND2Reader(fpath) as img: + # channels are the last dimension. + img = np.concatenate([x[..., None] for x in img], axis=-1) + images.append(img[None]) + # number of images is the first dimension. + return np.concatenate(images, axis=0) + + +def get_mixed_fnames(version): + if version == Pavia2DataSetVersion.RAW: + return [ + 'HaCaT005.nd2', 'HaCaT009.nd2', 'HaCaT013.nd2', 'HaCaT016.nd2', 'HaCaT019.nd2', 'HaCaT029.nd2', + 'HaCaT037.nd2', 'HaCaT041.nd2', 'HaCaT044.nd2', 'HaCaT051.nd2', 'HaCaT054.nd2', 'HaCaT059.nd2', + 'HaCaT066.nd2', 'HaCaT071.nd2', 'HaCaT006.nd2', 'HaCaT011.nd2', 'HaCaT014.nd2', 'HaCaT017.nd2', + 'HaCaT020.nd2', 'HaCaT031.nd2', 'HaCaT039.nd2', 'HaCaT042.nd2', 'HaCaT045.nd2', 'HaCaT052.nd2', + 'HaCaT056.nd2', 'HaCaT063.nd2', 'HaCaT067.nd2', 'HaCaT007.nd2', 'HaCaT012.nd2', 'HaCaT015.nd2', + 'HaCaT018.nd2', 'HaCaT027.nd2', 'HaCaT034.nd2', 'HaCaT040.nd2', 'HaCaT043.nd2', 'HaCaT046.nd2', + 'HaCaT053.nd2', 'HaCaT058.nd2', 'HaCaT065.nd2', 'HaCaT068.nd2' + ] + + +def get_justcyan_fnames(version): + if version == Pavia2DataSetVersion.RAW: + return [ + 'HaCaT023.nd2', 'HaCaT024.nd2', 'HaCaT026.nd2', 'HaCaT032.nd2', 'HaCaT033.nd2', 'HaCaT036.nd2', + 'HaCaT048.nd2', 'HaCaT049.nd2', 'HaCaT057.nd2', 'HaCaT060.nd2', 'HaCaT062.nd2' + ] + + +def get_justmagenta_fnames(version): + if version == Pavia2DataSetVersion.RAW: + return [ + 'HaCaT008.nd2', 'HaCaT021.nd2', 'HaCaT025.nd2', 'HaCaT030.nd2', 'HaCaT038.nd2', 'HaCaT050.nd2', + 'HaCaT061.nd2', 'HaCaT069.nd2', 'HaCaT010.nd2', 'HaCaT022.nd2', 'HaCaT028.nd2', 'HaCaT035.nd2', + 'HaCaT047.nd2', 'HaCaT055.nd2', 'HaCaT064.nd2', 'HaCaT070.nd2' + ] + + +def version_dir(dset_version): + if dset_version == Pavia2DataSetVersion.RAW: + return "RAW_DATA" + elif dset_version == Pavia2DataSetVersion.DD: + return "DD" + + +def load_data(datadir, dset_type, dset_version=Pavia2DataSetVersion.RAW): + print(f'Loading Data from', datadir, Pavia2DataSetType.name(dset_type), Pavia2DataSetVersion.name(dset_version)) + if dset_type == Pavia2DataSetType.JustCYAN: + datadir = os.path.join(datadir, version_dir(dset_version), 'ONLY_CYAN') + fnames = get_justcyan_fnames(dset_version) + elif dset_type == Pavia2DataSetType.JustMAGENTA: + datadir = os.path.join(datadir, version_dir(dset_version), 'ONLY_MAGENTA') + fnames = get_justmagenta_fnames(dset_version) + elif dset_type == Pavia2DataSetType.MIXED: + datadir = os.path.join(datadir, version_dir(dset_version), 'MIXED') + fnames = get_mixed_fnames(dset_version) + + fpaths = [os.path.join(datadir, x) for x in fnames] + data = load_nd2(fpaths) + return data + + +def get_train_val_data(datadir, data_config, datasplit_type: DataSplitType, val_fraction=None, test_fraction=None): + dset_type = data_config.dset_type + data = load_data(datadir, dset_type) + data = data[..., data_config.channel_idx_list] + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, len(data)) + if datasplit_type == DataSplitType.All: + data = data.astype(np.float32) + elif datasplit_type == DataSplitType.Train: + data = data[train_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Val: + data = data[val_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Test: + data = data[test_idx].astype(np.float32) + else: + raise Exception("invalid datasplit") + + return data + + +def get_train_val_data_vanilla(datadir, + data_config, + datasplit_type: DataSplitType, + val_fraction=None, + test_fraction=None): + dset_type = Pavia2DataSetType.JustMAGENTA + data = load_data(datadir, dset_type) + data = data[..., [data_config.channel_1, data_config.channel_2]] + data[..., 1] = data[..., 1] / data_config.channel_2_downscale_factor + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, len(data)) + if datasplit_type == DataSplitType.All: + data = data.astype(np.float32) + elif datasplit_type == DataSplitType.Train: + data = data[train_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Val: + data = data[val_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Test: + data = data[test_idx].astype(np.float32) + else: + raise Exception("invalid datasplit") + + return data diff --git a/denoisplit/data_loader/pavia3_rawdata_loader.py b/denoisplit/data_loader/pavia3_rawdata_loader.py new file mode 100644 index 0000000..a1748cb --- /dev/null +++ b/denoisplit/data_loader/pavia3_rawdata_loader.py @@ -0,0 +1,92 @@ +""" +Here, we load the raw data generated by Pezzotti from Pavia (2 channel data which does not have the input channel). +""" +import os + +import numpy as np + +from denoisplit.core.custom_enum import Enum +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from nd2reader import ND2Reader + + +class Pavia3SeqPowerLevel(Enum): + High = 'High' + Medium = 'Medium' + Low = 'Low' + + @staticmethod + def subdir(power_level): + return { + Pavia3SeqPowerLevel.High: 'Main', + Pavia3SeqPowerLevel.Medium: 'Divided_2', + Pavia3SeqPowerLevel.Low: 'Divided_4' + }[power_level] + + +class Pavia3SeqAlpha(Enum): + Balanced = "Balanced" + MediumSkew = "MediumSkew" + HighSkew = "HighSkew" + + @staticmethod + def subdir(alpha_level): + return { + Pavia3SeqAlpha.Balanced: 'Cond_1', + Pavia3SeqAlpha.MediumSkew: 'Cond_2', + Pavia3SeqAlpha.HighSkew: 'Cond_3' + }[alpha_level] + + +def load_one_file(fpath): + """ + '/group/jug/ashesh/data/pavia3_sequential/Cond_2/Main/1_002.nd2' + """ + output = {} + with ND2Reader(fpath) as fobj: + for c in range(len(fobj.metadata['channels'])): + output[c] = [] + for z in fobj.metadata['z_levels']: + img = fobj.get_frame_2D(c=c, z=z) + img = img[None, ..., None] + output[c].append(img) + output[c] = np.concatenate(output[c], axis=0) + return np.concatenate([output[0], output[1]], axis=-1) + + +def load_data(rootdatadir, power_level, alpha_level): + subdir = os.path.join(rootdatadir, Pavia3SeqAlpha.subdir(alpha_level), Pavia3SeqPowerLevel.subdir(power_level)) + fpaths = [] + for fname in os.listdir(subdir): + fpath = os.path.join(subdir, fname) + fpaths.append(fpath) + + fpaths = sorted(fpaths) + data = [load_one_file(fpath) for fpath in fpaths] + return np.concatenate(data, axis=0) + + +def get_train_val_data(dirname, data_config, datasplit_type, val_fraction, test_fraction): + power_level = data_config.power_level + alpha_level = data_config.alpha_level + assert power_level in [Pavia3SeqPowerLevel.High, Pavia3SeqPowerLevel.Medium, Pavia3SeqPowerLevel.Low] + assert alpha_level in [Pavia3SeqAlpha.Balanced, Pavia3SeqAlpha.MediumSkew, Pavia3SeqAlpha.HighSkew] + + data = load_data(dirname, power_level, alpha_level) + print(f'Loaded from {dirname} Power:{power_level} Alpha:{alpha_level} Mode:{DataSplitType.name(datasplit_type)}') + + if datasplit_type == DataSplitType.All: + return data.astype(np.float32) + + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, len(data), starting_test=True) + if datasplit_type == DataSplitType.Train: + return data[train_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Val: + return data[val_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Test: + return data[test_idx].astype(np.float32) + + +if __name__ == '__main__': + data = load_data('/group/jug/ashesh/data/pavia3_sequential', Pavia3SeqPowerLevel.High, Pavia3SeqAlpha.Balanced) + print(data.shape) diff --git a/denoisplit/data_loader/places_dloader.py b/denoisplit/data_loader/places_dloader.py new file mode 100644 index 0000000..93c2b30 --- /dev/null +++ b/denoisplit/data_loader/places_dloader.py @@ -0,0 +1,85 @@ +import os +import pickle +from typing import Union + +import numpy as np +from skimage.io import imread +from tqdm import tqdm + + +class PlacesLoader: + """ + """ + def __init__(self, data_fpath: str, label1, label2, return_labels: bool = False, img_dsample=None) -> None: + + self._datapath = data_fpath + self.labels = None + print(f'[{self.__class__.__name__}] Data fpath:', self._datapath, f'{label1} {label2}') + self.N = None + self._return_labels = return_labels + self._img_dsample = img_dsample + self._l1 = label1 + self._l2 = label2 + self._all_data = self.load(labels=[self._l1, self._l2]) + self._l1_index = self.labels.index(label1) + self._l2_index = self.labels.index(label2) + self._l1_N = len(self._all_data[label1]) + self._l2_N = len(self._all_data[label2]) + + def get_label_idx_range(self): + return { + '1': [0, self._l1_N], + '2': [self._l1_N, self._l1_N + self._l2_N], + } + + def _load_label(self, directory, label): + label_direc = os.path.join(directory, label) + fpaths = [] + for img_fname in os.listdir(label_direc): + img_fpath = os.path.join(label_direc, img_fname) + fpaths.append(img_fpath) + + return sorted(fpaths) + + def _load(self, directory, labels): + data_dict = {} + for label in labels: + data = self._load_label(directory, label) + data_dict[label] = data + return data_dict + + def load(self, labels=None): + data = self._load(self._datapath, labels=labels) + + sz = sum([len(data[label]) for label in data.keys()]) + self.labels = sorted(list(data.keys())) + label_sizes = [len(data[label]) for label in self.labels] + self.cumlative_label_sizes = [np.sum(label_sizes[:i]) for i in range(1, 1 + len(label_sizes))] + + self.N = sz + return data + + def _get_img(self, img_fpath): + img = imread(img_fpath) + # downsampling the image. + img = img[::self._img_dsample, ::self._img_dsample] + # img = np.pad(img, pad_width=((1, 0), (1, 0))) + img = img[None] + return img + + def __getitem__(self, index_tuple): + index1, index2 = index_tuple + assert index1 < self._l1_N, 'Index1 must be from first label' + assert index2 >= self._l1_N and index2 < self.__len__(), 'Index2 must be from second label' + img1 = self._get_img(self._all_data[self._l1][index1]) + img2 = self._get_img(self._all_data[self._l2][index2 % self._l1_N]) + + inp = (0.5 * img1 + 0.5 * img2).astype(np.float32) + target = np.concatenate([img1, img2], axis=0) + return inp, target + + def get_mean_std(self): + return 0.0, 255.0 + + def __len__(self): + return self._l1_N + self._l2_N diff --git a/denoisplit/data_loader/raw_mrc_dloader.py b/denoisplit/data_loader/raw_mrc_dloader.py new file mode 100644 index 0000000..c09553b --- /dev/null +++ b/denoisplit/data_loader/raw_mrc_dloader.py @@ -0,0 +1,64 @@ +import os + +import numpy as np + +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from denoisplit.core.tiff_reader import load_tiff +from denoisplit.data_loader.read_mrc import read_mrc + + +def get_mrc_data(fpath): + # HXWXN + _, data = read_mrc(fpath) + data = data[None] + data = np.swapaxes(data, 0, 3) + return data[..., 0] + + +def get_train_val_data(dirname, data_config, datasplit_type, val_fraction, test_fraction): + # actin-60x-noise2-highsnr.tif mito-60x-noise2-highsnr.tif + num_channels = data_config.get('num_channels', 2) + fpaths = [] + data_list = [] + for i in range(num_channels): + fpath1 = os.path.join(dirname, data_config.get(f'ch{i + 1}_fname')) + fpaths.append(fpath1) + data = get_mrc_data(fpath1)[..., None] + data_list.append(data) + + dirname = os.path.dirname(os.path.dirname(fpaths[0])) + '/' + + msg = ','.join([x[len(dirname):] for x in fpaths]) + print(f'Loaded from {dirname} Channels:{len(fpaths)} {msg} Mode:{DataSplitType.name(datasplit_type)}') + N = data_list[0].shape[0] + for data in data_list: + N = min(N, data.shape[0]) + + cropped_data = [] + for data in data_list: + cropped_data.append(data[:N]) + + data = np.concatenate(cropped_data, axis=3) + + if datasplit_type == DataSplitType.All: + return data.astype(np.float32) + + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, len(data), starting_test=True) + if datasplit_type == DataSplitType.Train: + return data[train_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Val: + return data[val_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Test: + return data[test_idx].astype(np.float32) + + +if __name__ == '__main__': + from ml_collections.config_dict import ConfigDict + data_config = ConfigDict() + data_config.num_channels = 3 + data_config.ch1_fname = 'CCPs/GT_all.mrc' + data_config.ch2_fname = 'ER/GT_all.mrc' + data_config.ch3_fname = 'Microtubules/GT_all.mrc' + datadir = '/group/jug/ashesh/data/BioSR/' + data = get_train_val_data(datadir, data_config, DataSplitType.Train, val_fraction=0.1, test_fraction=0.1) + print(data.shape) diff --git a/denoisplit/data_loader/read_mrc.py b/denoisplit/data_loader/read_mrc.py new file mode 100644 index 0000000..30a1b7c --- /dev/null +++ b/denoisplit/data_loader/read_mrc.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +import matplotlib.pyplot as plt +import numpy as np + +rec_header_dtd = \ + [ + ("nx", "i4"), # Number of columns + ("ny", "i4"), # Number of rows + ("nz", "i4"), # Number of sections + + ("mode", "i4"), # Types of pixels in the image. Values used by IMOD: + # 0 = unsigned or signed bytes depending on flag in imodFlags + # 1 = signed short integers (16 bits) + # 2 = float (32 bits) + # 3 = short * 2, (used for complex data) + # 4 = float * 2, (used for complex data) + # 6 = unsigned 16-bit integers (non-standard) + # 16 = unsigned char * 3 (for rgb data, non-standard) + + ("nxstart", "i4"), # Starting point of sub-image (not used in IMOD) + ("nystart", "i4"), + ("nzstart", "i4"), + + ("mx", "i4"), # Grid size in X, Y and Z + ("my", "i4"), + ("mz", "i4"), + + ("xlen", "f4"), # Cell size; pixel spacing = xlen/mx, ylen/my, zlen/mz + ("ylen", "f4"), + ("zlen", "f4"), + + ("alpha", "f4"), # Cell angles - ignored by IMOD + ("beta", "f4"), + ("gamma", "f4"), + + # These need to be set to 1, 2, and 3 for pixel spacing to be interpreted correctly + ("mapc", "i4"), # map column 1=x,2=y,3=z. + ("mapr", "i4"), # map row 1=x,2=y,3=z. + ("maps", "i4"), # map section 1=x,2=y,3=z. + + # These need to be set for proper scaling of data + ("amin", "f4"), # Minimum pixel value + ("amax", "f4"), # Maximum pixel value + ("amean", "f4"), # Mean pixel value + + ("ispg", "i4"), # space group number (ignored by IMOD) + ("next", "i4"), # number of bytes in extended header (called nsymbt in MRC standard) + ("creatid", "i2"), # used to be an ID number, is 0 as of IMOD 4.2.23 + ("extra_data", "V30"), # (not used, first two bytes should be 0) + + # These two values specify the structure of data in the extended header; their meaning depend on whether the + # extended header has the Agard format, a series of 4-byte integers then real numbers, or has data + # produced by SerialEM, a series of short integers. SerialEM stores a float as two shorts, s1 and s2, by: + # value = (sign of s1)*(|s1|*256 + (|s2| modulo 256)) * 2**((sign of s2) * (|s2|/256)) + ("nint", "i2"), + # Number of integers per section (Agard format) or number of bytes per section (SerialEM format) + ("nreal", "i2"), # Number of reals per section (Agard format) or bit + # Number of reals per section (Agard format) or bit + # flags for which types of short data (SerialEM format): + # 1 = tilt angle * 100 (2 bytes) + # 2 = piece coordinates for montage (6 bytes) + # 4 = Stage position * 25 (4 bytes) + # 8 = Magnification / 100 (2 bytes) + # 16 = Intensity * 25000 (2 bytes) + # 32 = Exposure dose in e-/A2, a float in 4 bytes + # 128, 512: Reserved for 4-byte items + # 64, 256, 1024: Reserved for 2-byte items + # If the number of bytes implied by these flags does + # not add up to the value in nint, then nint and nreal + # are interpreted as ints and reals per section + + ("extra_data2", "V20"), # extra data (not used) + ("imodStamp", "i4"), # 1146047817 indicates that file was created by IMOD + ("imodFlags", "i4"), # Bit flags: 1 = bytes are stored as signed + + # Explanation of type of data + ("idtype", "i2"), # ( 0 = mono, 1 = tilt, 2 = tilts, 3 = lina, 4 = lins) + ("lens", "i2"), + # ("nd1", "i2"), # for idtype = 1, nd1 = axis (1, 2, or 3) + # ("nd2", "i2"), + ("nphase", "i4"), + ("vd1", "i2"), # vd1 = 100. * tilt increment + ("vd2", "i2"), # vd2 = 100. * starting angle + + # Current angles are used to rotate a model to match a new rotated image. The three values in each set are + # rotations about X, Y, and Z axes, applied in the order Z, Y, X. + ("triangles", "f4", 6), # 0,1,2 = original: 3,4,5 = current + + ("xorg", "f4"), # Origin of image + ("yorg", "f4"), + ("zorg", "f4"), + + ("cmap", "S4"), # Contains "MAP " + ("stamp", "u1", 4), # First two bytes have 17 and 17 for big-endian or 68 and 65 for little-endian + + ("rms", "f4"), # RMS deviation of densities from mean density + + ("nlabl", "i4"), # Number of labels with useful data + ("labels", "S80", 10) # 10 labels of 80 charactors + ] + + +def read_mrc(filename, filetype='image'): + + fd = open(filename, 'rb') + header = np.fromfile(fd, dtype=rec_header_dtd, count=1) + + nx, ny, nz = header['nx'][0], header['ny'][0], header['nz'][0] + + if header[0][3] == 1: + data_type = 'int16' + elif header[0][3] == 2: + data_type = 'float32' + elif header[0][3] == 4: + data_type = 'single' + nx = nx * 2 + elif header[0][3] == 6: + data_type = 'uint16' + + data = np.ndarray(shape=(nx, ny, nz)) + imgrawdata = np.fromfile(fd, data_type) + fd.close() + + if filetype == 'image': + for iz in range(nz): + data_2d = imgrawdata[nx * ny * iz:nx * ny * (iz + 1)] + data[:, :, iz] = data_2d.reshape(nx, ny, order='F') + else: + data = imgrawdata + + return header, data + + +def write_mrc(filename, img_data, header): + + if img_data.dtype == 'int16': + header[0][3] = 1 + elif img_data.dtype == 'float32': + header[0][3] = 2 + elif img_data.dtype == 'uint16': + header[0][3] = 6 + + fd = open(filename, 'wb') + for i in range(len(rec_header_dtd)): + header[rec_header_dtd[i][0]].tofile(fd) + + nx, ny, nz = header['nx'][0], header['ny'][0], header['nz'][0] + imgrawdata = np.ndarray(shape=(nx * ny * nz), dtype='uint16') + for iz in range(nz): + imgrawdata[nx * ny * iz:nx * ny * (iz + 1)] = img_data[:, :, iz].reshape(nx * ny, order='F') + imgrawdata.tofile(fd) + + fd.close() + return diff --git a/denoisplit/data_loader/schroff_rawdata_loader.py b/denoisplit/data_loader/schroff_rawdata_loader.py new file mode 100644 index 0000000..508a3f7 --- /dev/null +++ b/denoisplit/data_loader/schroff_rawdata_loader.py @@ -0,0 +1,63 @@ +import os + +import numpy as np + +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from denoisplit.core.tiff_reader import load_tiff + + +def get_data_from_paths(fpaths1, fpaths2, enable_max_projection=False): + data1 = [load_tiff(path)[..., None] for path in fpaths1] + + data2 = [load_tiff(path)[..., None] for path in fpaths2] + if enable_max_projection: + data1 = [np.max(x, axis=1, keepdims=True) for x in data1] + data2 = [np.max(x, axis=1, keepdims=True) for x in data2] + + # squishing the 1st and 2nd dimension. + data1 = [x.reshape(np.prod(x.shape[:2]), *x.shape[2:]) for x in data1] + data2 = [x.reshape(np.prod(x.shape[:2]), *x.shape[2:]) for x in data2] + + data1 = np.concatenate(data1, axis=0) + data2 = np.concatenate(data2, axis=0) + assert data1.shape[0] == data2.shape[0], 'For now, we need both channels to have identical data' + data = np.concatenate([data1, data2], axis=3) + return data + + +def get_train_val_data(dirname, data_config, datasplit_type, val_fraction, test_fraction): + # actin-60x-noise2-highsnr.tif mito-60x-noise2-highsnr.tif + all_fpaths1 = [os.path.join(dirname, x) for x in mito_channel_fnames()] + all_fpaths2 = [os.path.join(dirname, x) for x in er_channel_fnames()] + + assert len(all_fpaths1) == len(all_fpaths2), 'Currently, only same sized data in both channels is supported' + + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, + test_fraction, + len(all_fpaths1), + starting_test=True) + if datasplit_type == DataSplitType.Train: + fpaths1 = [all_fpaths1[idx] for idx in train_idx] + fpaths2 = [all_fpaths2[idx] for idx in train_idx] + elif datasplit_type == DataSplitType.Val: + fpaths1 = [all_fpaths1[idx] for idx in val_idx] + fpaths2 = [all_fpaths2[idx] for idx in val_idx] + elif datasplit_type == DataSplitType.Test: + fpaths1 = [all_fpaths1[idx] for idx in test_idx] + fpaths2 = [all_fpaths2[idx] for idx in test_idx] + elif datasplit_type == DataSplitType.All: + fpaths1 = all_fpaths1 + fpaths2 = all_fpaths2 + + print(f'Loading from {dirname}, Mode:{DataSplitType.name(datasplit_type)}, PerChannelFilecount:{len(fpaths1)}') + data = get_data_from_paths(fpaths1, fpaths2, enable_max_projection=data_config.enable_max_projection) + return data + + +def mito_channel_fnames(): + # return [f'Mitotracker_Green_0{i}.tif' for i in [1,2,3,4,5,6]] + return [f'Mitotracker_Green_0{i}.tif' for i in [1, 3, 4, 5, 6]] + + +def er_channel_fnames(): + return [f'ER-eGFP_only_0{i}.tif' for i in [1, 3, 4, 5, 6]] diff --git a/denoisplit/data_loader/semi_supervised_dloader.py b/denoisplit/data_loader/semi_supervised_dloader.py new file mode 100644 index 0000000..ffdd63d --- /dev/null +++ b/denoisplit/data_loader/semi_supervised_dloader.py @@ -0,0 +1,78 @@ +from typing import Union + +import numpy as np + +from denoisplit.core.mixed_input_type import MixedInputType +from denoisplit.data_loader.vanilla_dloader import MultiChDloader + + +class SemiSupDloader(MultiChDloader): + + def __init__( + self, + data_config, + fpath: str, + is_train: Union[None, bool] = None, + val_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + use_one_mu_std=None, + mixed_input_type=None, + supervised_data_fraction=0.0, + allow_generation=False, + ): + super().__init__(data_config, + fpath, + is_train=is_train, + val_fraction=val_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=False, + use_one_mu_std=use_one_mu_std, + allow_generation=allow_generation) + """ + Args: + mixed_input_type: If set to 'aligned', the mixed input always comes from the co-aligned channels mixing. If + set to 'randomized', when the data is not supervised, it is created by mixing random crops of the two + channels. Note that when data is supervised, then all three channels are in sync: mix = channel1 + channel2 + and both channel crops are aligned. + supervised_data_fraction: What fraction of the data is supervised ? + """ + assert self._enable_rotation is False + self._mixed_input_type = mixed_input_type + assert MixedInputType.contains(self._mixed_input_type) + + self._supervised_data_fraction = supervised_data_fraction + self._supervised_indices = self._get_supervised_indices() + print(f'[{self.__class__.__name__}] Supf:{self._supervised_data_fraction}') + + def _get_supervised_indices(self): + N = len(self) + arr = np.random.permutation(N) + return arr[:int(N * self._supervised_data_fraction)] + + def __getitem__(self, index): + if index in self._supervised_indices: + mixed, singlechannnels = super().__getitem__(index) + return mixed, singlechannnels, True # np.array([1]) + + elif self._mixed_input_type == MixedInputType.Aligned: + mixed, _ = super().__getitem__(index) + index = np.random.randint(len(self)) + img1, _ = self._get_img(index) + index = np.random.randint(len(self)) + _, img2 = self._get_img(index) + singlechannels = np.concatenate([img1, img2], axis=0) + return mixed, singlechannels, False # np.array([0]) + + elif self._mixed_input_type == MixedInputType.ConsistentWithSingleInputs: + index = np.random.randint(len(self)) + img1, _ = self._get_img(index) + index = np.random.randint(len(self)) + _, img2 = self._get_img(index) + singlechannels = np.concatenate([img1, img2], axis=0) + if self._normalized_input: + img1, img2 = self.normalize_img(img1, img2) + + mixed = (0.5 * img1 + 0.5 * img2).astype(np.float32) + return mixed, singlechannels, False diff --git a/denoisplit/data_loader/single_channel/__init__.py b/denoisplit/data_loader/single_channel/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/denoisplit/data_loader/single_channel/__pycache__/__init__.cpython-39.pyc b/denoisplit/data_loader/single_channel/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77792a028c9a27abd8741d299f7864db6e3cddbc GIT binary patch literal 176 zcmYe~<>g`kf+uy1X(0MBh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o10WKO;XkRX?#f zBegg~4?^iD=clCVr=;fPX9gGKWR^gf#Sms&ryk0@&Ee@O9{FKt1R6CG$pMjVG0G|yl=>Px# literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/single_channel/__pycache__/multi_dataset_dloader.cpython-39.pyc b/denoisplit/data_loader/single_channel/__pycache__/multi_dataset_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f71f05b6ce5974b6b413c15de6179f55674607c8 GIT binary patch literal 5979 zcmc&&TW=&s74F;g+%LYYFS|~5l90=C{ny{kp;YfK#OGaw)_MB0zaYN5KobK3(5mee5ZQG9(x@*;)Nbnbyam;zdGkT z=ZsgamNY#7`c&`yHyZ}BJjQwIj-Y%+aWyJDgTqJ2W=6*38a>()CU=3VCzOi<|vnkobduH&+wC)9m;Gk1sd5*WPNj zBO!P^h(hLv-DVOsy(aTJ9WHp7V5nesJi(hWPZE4zZI-Tw&1B1un{6-Vm(~0s=Pag? zVI=xq;O}ts;4uvvc*09~w%%bixVKvRg6?snWysuzp&x}ZcVmd%q272$`0RSf_}%xt z(Ccy`Yt-_i!0(2jGQBm}REp-Y?4L@e|U;6F9iR@mV*n zwQQN|47_AZ)(FZYB;_0ry-xz}iYW0CT#V}tyK-UD=!GomyKNB-20&NV1|B1+ac@CJ zy0NqcPlh6F*8th%nMI+2^cGUAK~EDc)q8qk>>BaPxNK7SUF|cytEHN2rTTsj=o$wG zYIc%O3N!+#xNGd{>)J;TZW^Q7sGgMe%c*{#j~Z#6naf(*a4RTTs#Hx&OdD!qKdGgS z)JVu2Oe<*>Uv=^Ow3^nIwa{Q1%k7m%GvSq_ero?xS{{%2`_veFuR5AZ zwVt)#NM{aoUE6+>YP6dk+FkWc)n-wfWg2cMzai(_nONTOWA1Jby)c17UK2n^`+~BE zMNz>^R&INN+Yw%yu0mE59w$fD#-X|~*AEB7L=Ybe0$9b6_J?kqFxl{eAiCpr zdB~xVG+Dmy-E}d2tE`q1^ECDxWeb!YP9+wpx`a%Y!eQTy+a9<>)TwnDS!+&~{MZlU z#0%TpsrCK4t`aRb@Z&`064GmFsfz6~NMS6^E>Gk+_cRb>kz*CwB$wunKX7X8trw;z ztn~x89R&ebn8dR5Rup#p?z-PjWbtruSv(vj3bfTC9l-Vm10FJ&cm00Xjdx_h?SflS zYRyV3=0Qi66}7b0oPs#uo1k-^`YA*RCk2bteObZangv{i;wot(|(#{@bqB^qRiYI*W8xC#$zf zz$cG|0wu)`Z=%5Tkq%bSda&WpA){yR>Lc(#kMw?iWTtv*QY(FZMH}hcD`oiN5F?vdVbJ15LWw*Hs!tw~}Sg zQ?D8%HoHC5=Q`SA(ohYE%>uhwqoD7sor%HmS=t88Fn<b4UsahC){x8AvA1uHo#@ zkF3-p7G(OK4*tuH?9|vd(j3#4HDaFBM9rSmwrh#m10wJw%spe2S2c57D-a8I$V;#` zU=o)za_B^Y2*HPJ5%H6VDIg!}((>;5F#uIqHri1iYy)oLUP$aBp2c>h5e{S-iqnSb zhDfcV0$6;HJ{DA8PY9XE02c*8FiVTtrHM8t>vEg79n}Se6PF-0lT;(v1I$7C^&Ne^$}V^n}XEYirx@sBv-JBW&W&`9W!6Z5R6;e$0A_H?)uMn8}&ed-WE_^GN%NjLfk$%6ckfY*;s?TAX75v@{uf@JR~vL04XN+)xcppXCG~P&9)jx zWAPk28bOLfXf7Q>bK&Ww+P-<9IGwmGHFqtvBlU8M(}~w?V(}ELzK8f_`;zjL4C1CD z2&o$?zdtXY!_=Zh8Lci}K_<&SyX*F|P$5&E674fH@DpT8ejlNP8zVH4#mwZRDBh!4 zPN93Tfe#5%TtcS7M%wxkxMt_uXI}r&+Q;;O_Ir5wAEQFtGG_KGuy4k`evom!A+Esx zH4|$;mzoENIx=?OE>SDBkVs&pAwB?~0Jn@!HevrT0^abZM(AaFkk1e)E1}H%J<-JK zim?@k$Q-!XyQipRViL<^*YJ?0l}B?@f_{d1evNd<#wEP~oED6VVH-7b=kl3YP3`KK zDI~BCiTD{*rZi;%ngR+|#ttGg0Y@GA$LM-YOUg=O$9`^R@3W&EQsl`)-M|!|BOR&5 z*~ge#?DxujLCli`XIafRu#O8owc&D#$V?sG&^p&WmSW`=c|p4Dkz0BPdRM1VZ9a#hI_7 z04f2w9FPM9DWGr>E)k@F*zzwZ{Z9Wt8(A4(OuuEsFH=~VT7b&f_=2W_fcz3Kr5NHv zYRK4A?Ld~uDbKJ#El}rfq5#pE&_x4up(i-&uC5$l5Chcx3OWHsa?r9oh_hd78n zx$d7aYP@xFso>5(clIr2LtEtyJlC#K2EM-5I!|#%==Hhl%988$BQ`{E;>wCkfo?GV z0*_A!a=4`RNfZSLh7iAr7ijmy>dMs%34=M!@*i_*c}IZDwJD$`~5fH zbGN*p6Auxe+{WJmY;Bz*oTYzPUi|4=_fLPM=WnlH6LZ*L>k{1^i`uR$okdQev5AJ1vTv8FG3L{si!pK$p9n{{+#Qo5oDl@BauTPD_KZab8 zHIo-lv}O|?{hg$)*tt5@YkI}_Sm3&PygG?oRrv0_{y$C8Zy(M=;gz}?K~AsJnwl@W zns_w^-tH0p<0}(ebWl6%B=fX?=8L1hOCY*v!vB{7_nrNBvPf$ww}K)T@h)XQp^U_s zo$ot zLL!lR>VMEfbL_t~S5B3R?AGlZ@ z9xT3vspmk1BS_+m@s}nfrDIBvcM~`D#$M`=eY++}Fs^~zOX_K3+^{k~X{N1l%kn|e zPCMg{gFlel2T(OiP4vjd_%l zwqQ0Vbj!gBtM)+$C$2>EITbC@KJ&&KPaV%0cfsqfxwaQ)(?o91c$UdzY29eI?-_qG z=f%uypaYj4o2xS84-?5$Uho2eRmkhsDH$qq<7ln4jB@JGAH zKR(E0m`}o}azux*4hyaz7lZIYF_Q`faW-GTdVeO5!gQgFaK<0YP{fmoR5B~VRPt=7 z3$cHEf0RE7iy1GfGk7@5i%`jg7gB^pzEu7tY=U=I*+Wp3qZL_*F{=_C>R3pOre4gY zGIhq{42p-DE?a2HU_VP248Ccuuq;<8PvT=KU=vu{ZyQg`WMW#Vk41SliKhy?NVR~N zHrCff@d)!^I)&85<+8V~O<@8QX25K$eY(e!B!9xDGLyo22>Lb2rKH&3D!6;3A??07ouH4VXI2ZJ7EVkivmNa}M4Vn;_4Elc1mnZW#z{ z4|mG}&a1d76}||b(b8dF;lnv7HsAwWZnaV0Ro6hLdJoABAjVDO!#*914Bfu{>NN~# zd5<5)x?fXhiwRiOPBfdF7GyGlI?7-g-y(!@6PXz@g6*5A^ePfe^7@AwHliYq3iTnr zw&W&orhx&p%07XmMl}xc;Gxy?ZxGxf#~-~jhHs8W6pt+j^4P65h#@dGgwV6+fX-Xa z4cnm?s}Haf=|~aS*LT4!Y$j9Fj}}rMOXFdU_o?;HxKQ5f=6B!JYgPPTfF5nFA;-7g zY4q9wgzGpH^3ViI77LZVcczRQ-ZjHlcf<8T8gp>K5DT6W5|t6&o}& zbr%Jr}6HrS%>0O<#S4tRIO>D2Vt1)?rt)?B?rT)12^Jpr |`zF?5zLcos>F zY|(F2H8e!cU*V3RLPFz#>f4syF*N{i26bczGmWW=1=D~$>se_rG$}4*${2o3W8FJs zg9P+CX_Gc>k|wFsIynyCnWL5C{l*B!?(S$8`Ukjv5798=sRT4^GM46I0rv_sZN?rg zc(Q!s>Ov`OZR0)6^TdLK>ciSPuP~?TYb02y>Qf-5mIyb)mh?KB$I@(6$jtP z1K2tWivxjC-vUzi9kTZPMJY6q2lMaVX0us$?TP*sB18V~<1D6Cb8^buZsl`&|W z@nHwNwT5*qNLpkZM7fg6#~mN9Ne8yYFR$Fn`_EQ(t)S}Q?SC2-*nIv!dmr;GP7;2B jwF(i^y0Q|LOF*fAQ>ElCwzTd6sYA+pv`!)M__+T8>a?vt literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/single_channel/__pycache__/single_channel_mc_dloader.cpython-39.pyc b/denoisplit/data_loader/single_channel/__pycache__/single_channel_mc_dloader.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eaa5e68624b1e5a68690172c44b5226eaae716f2 GIT binary patch literal 4718 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 literal 0 HcmV?d00001 diff --git a/denoisplit/data_loader/single_channel/multi_dataset_dloader.py b/denoisplit/data_loader/single_channel/multi_dataset_dloader.py new file mode 100644 index 0000000..67cf4d7 --- /dev/null +++ b/denoisplit/data_loader/single_channel/multi_dataset_dloader.py @@ -0,0 +1,186 @@ +""" +If one has multiple .tif files, each corresponding to a different hardware setting. +In this case, one needs to normalize these separate files separately. +""" +import ml_collections +import torch +import enum +from typing import Union, Tuple +import numpy as np + +from denoisplit.data_loader.patch_index_manager import GridIndexManager, GridAlignement +from denoisplit.core import data_split_type +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.data_loader.single_channel.single_channel_dloader import SingleChannelDloader +from denoisplit.data_loader.single_channel.single_channel_mc_dloader import SingleChannelMSDloader + + +class SingleChannelMultiDatasetDloader: + + def __init__(self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + enable_random_cropping: bool = False, + use_one_mu_std=None, + num_scales=None, + padding_kwargs: dict = None, + allow_generation=False, + max_val=None) -> None: + + assert isinstance(data_config.mix_fpath_list, tuple) or isinstance(data_config.mix_fpath_list, list) + self._dsets = [] + self._channelwise_quantile = data_config.get('channelwise_quantile', False) + + for i, fpath_tuple in enumerate(zip(data_config.mix_fpath_list, data_config.ch1_fpath_list)): + new_data_config = ml_collections.ConfigDict(data_config) + new_data_config.mix_fpath = fpath_tuple[0] + new_data_config.ch1_fpath = fpath_tuple[1] + if num_scales is None: + dset = SingleChannelDloader(new_data_config, + fpath, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=enable_random_cropping, + use_one_mu_std=use_one_mu_std, + allow_generation=allow_generation, + max_val=max_val[i] if max_val is not None else None) + else: + dset = SingleChannelMSDloader(new_data_config, + fpath, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=enable_random_cropping, + use_one_mu_std=use_one_mu_std, + allow_generation=allow_generation, + num_scales=num_scales, + padding_kwargs=padding_kwargs, + max_val=max_val[i] if max_val is not None else None) + self._dsets.append(dset) + self._img_sz = self._dsets[0]._img_sz + self._grid_sz = self._dsets[0]._grid_sz + + def get_data_shape(self): + N = 0 + default_shape = list(self._dsets[0]._data.shape) + for dset in self._dsets: + N += dset._data.shape[0] + + default_shape[0] = N + return tuple(default_shape) + + def compute_mean_std(self, allow_for_validation_data=False): + mean_arr = [] + std_arr = [] + for dset in self._dsets: + mean, std = dset.compute_mean_std(allow_for_validation_data=allow_for_validation_data) + mean_arr.append(mean[None]) + std_arr.append(std[None]) + + mean_vec = np.concatenate(mean_arr, axis=0) + std_vec = np.concatenate(std_arr, axis=0) + return mean_vec, std_vec + + def compute_individual_mean_std(self): + mean_arr = [] + std_arr = [] + for i, dset in enumerate(self._dsets): + mean_, std_ = dset.compute_individual_mean_std() + mean_arr.append(mean_[None]) + std_arr.append(std_[None]) + return np.concatenate(mean_arr, axis=0), np.concatenate(std_arr, axis=0) + + def get_mean_std(self): + mean_arr = [] + std_arr = [] + for i, dset in enumerate(self._dsets): + mean_, std_ = dset.get_mean_std() + mean_arr.append(mean_[None]) + std_arr.append(std_[None]) + return np.concatenate(mean_arr, axis=0), np.concatenate(std_arr, axis=0) + + def set_mean_std(self, mean_val, std_val): + for i, dset in enumerate(self._dsets): + dset.set_mean_std(mean_val[i], std_val[i]) + + def set_img_sz(self, image_size, grid_size, alignment=GridAlignement.LeftTop): + self._img_sz = image_size + self._grid_sz = grid_size + self.idx_manager = GridIndexManager(self.get_data_shape(), self._grid_sz, self._img_sz, alignment) + for dset in self._dsets: + dset.set_img_sz(image_size, grid_size, alignment=alignment) + + def get_max_val(self): + max_val_arr = [] + for dset in self._dsets: + max_val = dset.get_max_val() + if self._channelwise_quantile: + max_val_arr.append(np.array(max_val)[None]) + else: + max_val_arr.append(max_val) + + if self._channelwise_quantile: + # 2D + return np.concatenate(max_val_arr, axis=0) + else: + # 1D + return np.array(max_val_arr) + + def set_max_val(self, max_val): + for i, dset in enumerate(self._dsets): + dset.set_max_val(max_val[i]) + + def _get_dataset_index(self, index): + cum_index = 0 + for i, dset in enumerate(self._dsets): + if index < cum_index + len(dset): + return i, index - cum_index + cum_index += len(dset) + raise ValueError('Too large index:', index) + + def __getitem__(self, index: Union[int, Tuple[int, int]]) -> Tuple[np.ndarray, np.ndarray]: + dset_index, data_index = self._get_dataset_index(index) + output = (*self._dsets[dset_index][data_index], dset_index) + assert len(output) == 3 + return output + + def __len__(self): + tot_len = 0 + for dset in self._dsets: + tot_len += len(dset) + return tot_len + + +if __name__ == '__main__': + from denoisplit.configs.semi_supervised_config import get_config + config = get_config() + datadir = '/group/jug/ashesh/data/EMBL_halfsupervised/Demixing_3P/' + val_fraction = 0.1 + test_fraction = 0.1 + + dset = SingleChannelMultiDatasetDloader(config.data, + datadir, + datasplit_type=DataSplitType.Train, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=config.data.normalized_input, + enable_rotation_aug=False, + enable_random_cropping=False, + use_one_mu_std=config.data.use_one_mu_std, + allow_generation=False, + max_val=None) + + mean_val, std_val = dset.compute_mean_std() + dset.set_mean_std(mean_val, std_val) + inp, tar, dset_index = dset[0] + print(inp.shape, tar.shape, dset_index) diff --git a/denoisplit/data_loader/single_channel/single_channel_dloader.py b/denoisplit/data_loader/single_channel/single_channel_dloader.py new file mode 100644 index 0000000..ff9ac0b --- /dev/null +++ b/denoisplit/data_loader/single_channel/single_channel_dloader.py @@ -0,0 +1,59 @@ +import enum +from copy import deepcopy +from typing import Tuple, Union + +import numpy as np + +from denoisplit.core import data_split_type +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.data_loader.train_val_data import get_train_val_data +from denoisplit.data_loader.vanilla_dloader import MultiChDloader + + +class SingleChannelDloader(MultiChDloader): + + def __init__(self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + enable_random_cropping: bool = False, + use_one_mu_std=None, + allow_generation=False, + max_val=None): + super().__init__(data_config, fpath, datasplit_type, val_fraction, test_fraction, normalized_input, + enable_rotation_aug, enable_random_cropping, use_one_mu_std, allow_generation, max_val) + + assert self._use_one_mu_std is False, 'One of channels is target. Other is input. They must have different mean/std' + assert self._normalized_input is True, 'Now that input is not related to target, this must be done on dataloader side' + + def load_data(self, data_config, datasplit_type, val_fraction=None, test_fraction=None, allow_generation=None): + data_dict = get_train_val_data(data_config, + self._fpath, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + allow_generation=allow_generation) + self._data = np.concatenate([data_dict['mix'][..., None], data_dict['C1'][..., None]], axis=-1) + self.N = len(self._data) + + def normalize_input(self, inp): + return (inp - self._mean.squeeze()[0]) / self._std.squeeze()[0] + + def __getitem__(self, index: Union[int, Tuple[int, int]]) -> Tuple[np.ndarray, np.ndarray]: + inp, target = self._get_img(index) + if self._enable_rotation: + # passing just the 2D input. 3rd dimension messes up things. + rot_dic = self._rotation_transform(image=img1[0], mask=img2[0]) + img1 = rot_dic['image'][None] + img2 = rot_dic['mask'][None] + + inp = self.normalize_input(inp) + if isinstance(index, int): + return inp, target + + _, grid_size = index + return inp, target, grid_size diff --git a/denoisplit/data_loader/single_channel/single_channel_mc_dloader.py b/denoisplit/data_loader/single_channel/single_channel_mc_dloader.py new file mode 100644 index 0000000..cb897a1 --- /dev/null +++ b/denoisplit/data_loader/single_channel/single_channel_mc_dloader.py @@ -0,0 +1,158 @@ +""" +Here, the input image is of multiple resolutions. Target image is the same. +""" +from typing import List, Tuple, Union + +import numpy as np +from skimage.transform import resize +from denoisplit.core.data_split_type import DataSplitType + +from denoisplit.data_loader.single_channel.single_channel_dloader import SingleChannelDloader +from denoisplit.core.data_type import DataType + + +class SingleChannelMSDloader(SingleChannelDloader): + + def __init__( + self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + use_one_mu_std=None, + num_scales: int = None, + enable_random_cropping=False, + padding_kwargs: dict = None, + allow_generation: bool = False, + max_val=None, + ): + """ + Args: + num_scales: The number of resolutions at which we want the input. Note that the target is formed at the + highest resolution. + """ + self._padding_kwargs = padding_kwargs # mode=padding_mode, constant_values=constant_value + super().__init__(data_config, + fpath, + datasplit_type=datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + normalized_input=normalized_input, + enable_rotation_aug=enable_rotation_aug, + enable_random_cropping=enable_random_cropping, + use_one_mu_std=use_one_mu_std, + allow_generation=allow_generation, + max_val=max_val) + + self.num_scales = num_scales + assert self.num_scales is not None + self._scaled_data = [self._data] + assert isinstance(self.num_scales, int) and self.num_scales >= 1 + # self.enable_padding_while_cropping is used only for overlapping_dloader. This is a hack and at some point be + # fixed properly + self.enable_padding_while_cropping = False + assert isinstance(self._padding_kwargs, dict) + assert 'mode' in self._padding_kwargs + + for _ in range(1, self.num_scales): + shape = self._scaled_data[-1].shape + assert len(shape) == 4 + new_shape = (shape[0], shape[1] // 2, shape[2] // 2, shape[3]) + ds_data = resize(self._scaled_data[-1], new_shape) + self._scaled_data.append(ds_data) + + def _init_msg(self): + msg = super()._init_msg() + msg += f' Pad:{self._padding_kwargs}' + return msg + + def _load_scaled_img(self, scaled_index, index: Union[int, Tuple[int, int]]) -> Tuple[np.ndarray, np.ndarray]: + if isinstance(index, int): + idx = index + else: + idx, _ = index + imgs = self._scaled_data[scaled_index][idx % self.N] + return imgs[None, :, :, 0], imgs[None, :, :, 1] + + def _crop_img(self, img: np.ndarray, h_start: int, w_start: int): + """ + Here, h_start, w_start could be negative. That simply means we need to pick the content from 0. So, + the cropped image will be smaller than self._img_sz * self._img_sz + """ + h_end = h_start + self._img_sz + w_end = w_start + self._img_sz + h_start = max(0, h_start) + w_start = max(0, w_start) + new_img = img[..., h_start:h_end, w_start:w_end] + return new_img + + def _get_img(self, index: int): + """ + Loads an image. + Crops the image such that cropped image has content. + """ + img1, img2 = self._load_img(index) + assert self._img_sz is not None + h, w = img1.shape[-2:] + if self._enable_random_cropping: + h_start, w_start = self._get_random_hw(h, w) + else: + h_start, w_start = self._get_deterministic_hw(index) + img1_cropped = self._crop_flip_img(img1, h_start, w_start, False, False) + img2_cropped = self._crop_flip_img(img2, h_start, w_start, False, False) + + h_center = h_start + self._img_sz // 2 + w_center = w_start + self._img_sz // 2 + img1_versions = [img1_cropped] + img2_versions = [img2_cropped] + for scale_idx in range(1, self.num_scales): + img1, img2 = self._load_scaled_img(scale_idx, index) + h_center = h_center // 2 + w_center = w_center // 2 + h_start = h_center - self._img_sz // 2 + w_start = w_center - self._img_sz // 2 + + img1_cropped = self._crop_flip_img(img1, h_start, w_start, False, False) + img2_cropped = self._crop_flip_img(img2, h_start, w_start, False, False) + + h_start = max(0, -h_start) + w_start = max(0, -w_start) + h_end = h_start + img1_cropped.shape[1] + w_end = w_start + img1_cropped.shape[2] + if self.enable_padding_while_cropping: + assert img1_cropped.shape == img1_versions[-1].shape + assert img2_cropped.shape == img2_versions[-1].shape + img1_padded = img1_cropped + img2_padded = img2_cropped + + else: + h_max, w_max = img1_versions[-1].shape[1:] + assert img1_versions[-1].shape == img2_versions[-1].shape + padding = np.array([[0, 0], [h_start, h_max - h_end], [w_start, w_max - w_end]]) + # mode=padding_mode, constant_values=constant_value + img1_padded = np.pad(img1_cropped, padding, **self._padding_kwargs) + img2_padded = np.pad(img2_cropped, padding, **self._padding_kwargs) + + # img1_padded[:, h_start:h_end, w_start:w_end] = img1_cropped + # img2_padded[:, h_start:h_end, w_start:w_end] = img2_cropped + + img1_versions.append(img1_padded) + img2_versions.append(img2_padded) + + img1 = np.concatenate(img1_versions, axis=0) + img2 = np.concatenate(img2_versions, axis=0) + return img1, img2 + + def __getitem__(self, index: Union[int, Tuple[int, int]]): + inp, target = self._get_img(index) + target = target[:1] # we don't need lower resolution for target. + assert self._enable_rotation is False + inp = self.normalize_input(inp) + + if isinstance(index, int): + return inp, target + _, grid_size = index + return inp, target, grid_size diff --git a/denoisplit/data_loader/sinosoid_dloader.py b/denoisplit/data_loader/sinosoid_dloader.py new file mode 100644 index 0000000..a18f268 --- /dev/null +++ b/denoisplit/data_loader/sinosoid_dloader.py @@ -0,0 +1,440 @@ +import os.path +import pickle +from typing import Union + +import numpy as np +import math +from tqdm import tqdm +import lzma +from denoisplit.core.data_split_type import DataSplitType,get_datasplit_tuples + + +def angle_shift(w1, w2, point): + """ + Find x such that: cos(w2*(point +x) = cos(w1*point) + """ + # there should be two points at which the gradient's value should be same. + # if I select the correct point, then I don't need to shift + # d/dx(sin(w2*point +d)) = d/dx(sin(w1*point)) + # w2*cos() = w1*cos() + assert w2 >= w1, 'w2 must be larger than w1. otherwise angle is not always possible' + theta = np.arccos(w1 * np.cos(w1 * point) / w2) + return theta - w2 * point + + +def generate_one_curve(w1, w2, max_angle, granularity=0.1): + r1 = np.arange(0, max_angle // 2, granularity) + shift = angle_shift(w1, w2, r1[-1]) + first_val = r1[-1] + shift / w2 + r2 = np.arange(first_val, first_val + max_angle // 2, granularity) + lefthalf = np.sin(w1 * r1) + value_shift = np.sin(w1 * r1[-1]) - np.sin(w2 * r2[0]) + righthalf = np.sin(w2 * r2) + value_shift + + y = np.concatenate([lefthalf[:-1], righthalf]) + x = np.concatenate([r1[:-1], r2 - shift / w2]) + return y, x + + +def apply_rotation(xy, radians): + """ + Adapted from https://gist.github.com/LyleScott/e36e08bfb23b1f87af68c9051f985302 + Args: + xy: (2,N) + """ + c, s = np.cos(radians), np.sin(radians) + j = np.array([[c, -s], [s, c]]) + m = np.dot(j, xy) + return np.array(m) + + +def post_processing(x, curve, img_sz): + x = x.astype(np.int) + # x can be < 0 due to horizontal shift. + x_filtr = np.logical_and(x < img_sz, x >= 0) + x = x[x_filtr] + curve = curve[x_filtr] + curve = curve.astype(np.int) + y_filtr = curve < img_sz + + curve = curve[y_filtr] + x = x[y_filtr] + return x, curve + + +def rotate_curve(x, curve, rotate_radian): + shift = (max(x) - min(x)) / 2 + x = x - shift + x = x.reshape(1, -1) + curve = curve.reshape(1, -1) + xy = np.concatenate([x, curve], axis=0) + xy = apply_rotation(xy, rotate_radian) + x = xy[0] + shift + x = x - min(x) + curve = xy[1] + return x, curve + + +def get_img(w_list, img_sz, vertical_shifts: list, horizontal_shifts: list, rotate_radians: list, + curve_amplitudes: list, random_w12_flips: list, curve_thickness): + assert len(vertical_shifts) == len(rotate_radians) + assert len(vertical_shifts) == len(curve_amplitudes) + img = np.zeros((img_sz, img_sz)) + for i in range(len(w_list)): + w1, w2 = w_list[i] + add_to_img(img, + w1, + w2, + vertical_shift=vertical_shifts[i], + horizontal_shift=horizontal_shifts[i], + flip_about_vertical=random_w12_flips[i], + rotate_radian=rotate_radians[i], + curve_amplitude=curve_amplitudes[i], + thickness=curve_thickness) + + return img + + +def add_thickness(img, thickness, x, curve): + thickness = (thickness - 1) // 2 + + for row_shift in range(-thickness, thickness): + for col_shift in range(-thickness, thickness): + if row_shift == 0 and col_shift == 0: + continue + temp_curve = curve + col_shift + temp_x = x + row_shift + filtr_x = np.logical_and(temp_x > 0, temp_x < img.shape[-1]) + filtr_curve = np.logical_and(temp_curve > 0, temp_curve < img.shape[-1]) + filtr = np.logical_and(filtr_x, filtr_curve) + img[temp_curve[filtr], temp_x[filtr]] += 1 / (np.sqrt(0.5 * (col_shift**2 + row_shift**2))) + + +def add_to_img(img, + w1, + w2, + vertical_shift=None, + horizontal_shift: int = 0.0, + flip_about_vertical=False, + rotate_radian=None, + curve_amplitude=None, + thickness=None): + assert thickness % 2 == 1 + max_angle = img.shape[-1] + abs(int(horizontal_shift)) + granularity = 0.1 + curve, x = generate_one_curve(w1, w2, max_angle, granularity=granularity) + curve *= curve_amplitude + if flip_about_vertical: + min_x = min(x) + max_x = max(x) + x = min_x + (max_x - min_x) - (x - min_x) + # positive + curve = curve - min(curve) + # vertical shift + curve += vertical_shift + if rotate_radian != 0: + x, curve = rotate_curve(x, curve, rotate_radian) + + if horizontal_shift: + x += horizontal_shift + x, curve = post_processing(x, curve, img.shape[-1]) + img[curve, x] += 1 + add_thickness(img, thickness, x, curve) + + +class Range: + + def __init__(self, min_val, max_val): + assert min_val < max_val + self.min = min_val + self.max = max_val + + def inrange(self, val): + return val >= self.min and val < self.max + + def sample(self): + return np.random.rand() * (self.max - self.min) + self.min + + +def sample_for_channel1(w_rangelist): + assert len(w_rangelist) == 4 + if np.random.rand() > 0.5: + return w_rangelist[0].sample(), w_rangelist[2].sample() + else: + return w_rangelist[1].sample(), w_rangelist[3].sample() + + +def sample_for_channel2(w_rangelist): + assert len(w_rangelist) == 4 + if np.random.rand() > 0.5: + return w_rangelist[0].sample(), w_rangelist[3].sample() + else: + return w_rangelist[1].sample(), w_rangelist[2].sample() + + +def spaced_out_vertical_shifts(max_value, num_curves, min_spacing): + """ + Sometimes the vertical shifts are too close.The idea is to generate them in such a way that they don't + overlap on each other + min_spacing: enforces the minimum distance between the start point of the curves + """ + if num_curves == 1: + return np.random.rand() * max_value + + bucket_size = 1 / num_curves + # normalizing min_spacing + min_spacing = min_spacing / max_value + + assert bucket_size > min_spacing, 'min_spacing is too small' + + # adding bucket_size/10 ensures that 1 also comes in this range. + disjoint_ranges = np.arange(0, 1 + bucket_size / 10, bucket_size) + output = [] + range_s = 0 + for range_e in disjoint_ranges[1:]: + # generate a value between [start_s+min_spacing/2, end_s-min_spacing/2] + norm_shift = np.random.rand() * (bucket_size - min_spacing) + range_s + min_spacing / 2 + output.append(norm_shift * max_value) + range_s = range_e + assert len(output) == num_curves + return output + + +def generate_dataset(w_rangelist, + size, + img_sz, + num_curves=3, + curve_amplitude=64, + max_rotation=math.pi / 8, + max_vertical_shift_factor=0.8, + max_horizontal_shift_factor=0.3, + flip_w12_randomly=False, + curve_thickness=31, + encourage_non_overlap_single_channel=False, + vertical_min_spacing=0): + """ + + Args: + w_rangelist: + size: + img_sz: + num_curves: + curve_amplitude: + max_rotation: + max_vertical_shift_factor: + max_horizontal_shift_factor: + flip_w12_randomly: + encourage_non_overlap_single_channel: If True, curves of a single channel are well spaced vertically to prevent + overlap. Note that there is overlap of curves between the two channels. + curve_thickness: + + Returns: + + """ + ch1_dset = [] + ch2_dset = [] + + def sample_angle(): + return 2 * np.random.rand() * max_rotation - max_rotation + + def get_random_w12_flips(): + if flip_w12_randomly: + random_w12_flips = [np.random.rand() > 0.5 for _ in range(num_curves)] + else: + random_w12_flips = [False] * num_curves + return random_w12_flips + + def get_shifts(): + if encourage_non_overlap_single_channel: + rand_vertical_shifts = spaced_out_vertical_shifts(img_sz * max_vertical_shift_factor, num_curves, + vertical_min_spacing) + else: + rand_vertical_shifts = [np.random.rand() * img_sz * max_vertical_shift_factor for _ in range(num_curves)] + rand_horizontal_shifts = [np.random.rand() * img_sz * max_horizontal_shift_factor for _ in range(num_curves)] + rand_horizontal_shifts = [x * -1 if np.random.rand() > 0.5 else x for x in rand_horizontal_shifts] + return rand_vertical_shifts, rand_horizontal_shifts + + for _ in tqdm(range(size)): + w1_list = [sample_for_channel1(w_rangelist) for _ in range(num_curves)] + rotate_radians = [sample_angle() for _ in range(num_curves)] + vertical_shifts, horizontal_shifts = get_shifts() + img1 = get_img(w1_list, img_sz, vertical_shifts, horizontal_shifts, rotate_radians, + [curve_amplitude] * num_curves, get_random_w12_flips(), curve_thickness) + + w2_list = [sample_for_channel2(w_rangelist) for _ in range(num_curves)] + vertical_shifts, horizontal_shifts = get_shifts() + rotate_radians = [sample_angle() for _ in range(num_curves)] + img2 = get_img(w2_list, img_sz, vertical_shifts, horizontal_shifts, rotate_radians, + [curve_amplitude] * num_curves, get_random_w12_flips(), curve_thickness) + + ch1_dset.append(img1[None]) + ch2_dset.append(img2[None]) + return np.concatenate(ch1_dset, axis=0), np.concatenate(ch2_dset, axis=0) + + +class CustomDataManager: + """ + A class to manage(load/save) the data. + """ + + def __init__(self, data_dir, data_config): + self._dir = data_dir + self._dconfig = data_config + + def fname(self): + fname = 'sin' + fname += f'_N-{self._dconfig.total_size}' + fname += f'_Fsz-{self._dconfig.frame_size}' + fname += f'_CA-{np.round(self._dconfig.curve_amplitude, 2)}' + fname += f'_CT-{self._dconfig.curve_thickness}' + fname += f'_CN-{self._dconfig.num_curves}' + fname += f'_MR-{self._dconfig.max_rotation}' + fname += f'_VF-{self._dconfig.max_vshift_factor}' + fname += f'_HF-{self._dconfig.max_hshift_factor}' + if self._dconfig.encourage_non_overlap_single_channel: + fname += f'_NO-{self._dconfig.vertical_min_spacing}' + + fr = self._dconfig.frequency_range_list + diff = [fr[i][1] - fr[i][0] for i in range(len(fr))] + gap = [fr[i + 1][0] - fr[i][1] for i in range(len(fr) - 1)] + + diff = int(np.mean(diff) * 100) + gap = int(np.mean(gap) * 100) + fname += f'_FR-{diff}.{gap}' + fname += '.xz' + return fname + + def exists(self): + return os.path.exists(os.path.join(self._dir, self.fname())) + + def load(self, fname: Union[str, None] = None): + fpath = os.path.join(self._dir, self.fname()) + if not os.path.exists(fpath): + print(f'File {fpath} does not exist.') + return None + + with lzma.open(fpath, 'rb') as f: + data_dict = pickle.load(f) + print(f'Loaded from file {fpath}') + + # Note that simpler arguments are already included in the name itself. + assert tuple(data_dict['frequency_range_list']) == tuple(self._dconfig.frequency_range_list) + return data_dict + + def save(self, data_dict): + data_dict['frequency_range_list'] = self._dconfig.frequency_range_list + fpath = os.path.join(self._dir, self.fname()) + with lzma.open(fpath, 'wb') as f: + pickle.dump(data_dict, f) + print(f'File {fpath} saved.') + + def remove(self): + fpath = os.path.join(self._dir, self.fname()) + if os.path.exists(fpath): + os.remove(fpath) + + +def train_val_data(data_dir, + data_config, + datasplit_type, + val_fraction=None, + test_fraction=None, + allow_generation=False): + assert isinstance(allow_generation, bool) + datamanager = CustomDataManager(data_dir, data_config) + total_size = data_config.total_size + frequency_range_list = data_config.frequency_range_list + frame_size = data_config.frame_size + curve_amplitude = data_config.curve_amplitude + num_curves = data_config.num_curves + max_rotation = data_config.max_rotation + curve_thickness = data_config.curve_thickness + max_vertical_shift_factor = data_config.max_vshift_factor + max_horizontal_shift_factor = data_config.max_hshift_factor + encourage_non_overlap_single_channel = data_config.encourage_non_overlap_single_channel + if encourage_non_overlap_single_channel: + vertical_min_spacing = data_config.vertical_min_spacing + else: + vertical_min_spacing = 0 + # I think this needs to be True for the data to be only dependant on the pairing. And not who is on left/right. + flip_w12_randomly = True + if datamanager.exists(): + data_dict = datamanager.load() + else: + data_dict = None + fpath = os.path.join(data_dir, datamanager.fname()) + assert allow_generation is True, f"{fpath} does not exist and Data generation is not allowed" + + if data_dict is None: + print('Data not found in the file. generating the data') + w_rangelist = [Range(x[0], x[1]) for x in frequency_range_list] + imgs1, imgs2 = generate_dataset(w_rangelist, + total_size, + frame_size, + num_curves=num_curves, + curve_amplitude=curve_amplitude, + max_rotation=max_rotation, + max_vertical_shift_factor=max_vertical_shift_factor, + max_horizontal_shift_factor=max_horizontal_shift_factor, + flip_w12_randomly=flip_w12_randomly, + curve_thickness=curve_thickness, + encourage_non_overlap_single_channel=encourage_non_overlap_single_channel, + vertical_min_spacing=vertical_min_spacing) + imgs1 = imgs1[..., None] + imgs2 = imgs2[..., None] + data = np.concatenate([imgs1, imgs2], axis=3) + # test, val, train + + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, len(data)) + data_dict = { + 'train': data[train_idx], + 'val': data[val_idx], + 'test': data[test_idx], + 'frequency_range_list': frequency_range_list + } + datamanager.save(data_dict) + + if datasplit_type == DataSplitType.Train: + return data_dict['train'] + elif datasplit_type == DataSplitType.Val: + return data_dict['val'] + elif datasplit_type == DataSplitType.Test: + return data_dict['test'] + + +if __name__ == '__main__': + w1 = 0.05 + w2 = 0.15 + max_angle = 100 + # curve, x = generate_one_curve(w1, w2, max_angle) + # x = 2 * x / max_angle - 1 + # # x = np.arange(len(curve)) + # xy = np.concatenate([x.reshape(1, -1), curve.reshape(1, -1)], axis=0) + # rotated = apply_rotation(xy, math.pi / 200) + # print(curve.shape) + import matplotlib.pyplot as plt + + # img = np.zeros((512, 512)) + # vshift = np.random.rand() * img.shape[-1] + # max_rotate = math.pi / 8 + # rotate = 2 * np.random.rand() * max_rotate - max_rotate + # add_to_img(img, w1, w2, vertical_shift=vshift, rotate_radian=rotate) + # + # vshift = np.random.rand() * img.shape[-1] + # rotate = 2 * np.random.rand() * max_rotate - max_rotate + # add_to_img(img, w1, w2, vertical_shift=vshift, rotate_radian=rotate) + # plt.imshow(img) + # plt.plot(x, curve) + # plt.plot(rotated[0], rotated[1], color='r') + w_rangelist = [Range(0.05, 0.1), Range(0.15, 0.2), Range(0.25, 0.3), Range(0.35, 0.4)] + size = 10 + img_sz = 512 + imgs1, imgs2 = generate_dataset(w_rangelist, + size, + img_sz, + num_curves=3, + curve_amplitude=64, + max_rotation=math.pi / 8, + flip_w12_randomly=True) + plt.imshow(imgs1[0]) + plt.show() diff --git a/denoisplit/data_loader/sinosoid_threecurve_dloader.py b/denoisplit/data_loader/sinosoid_threecurve_dloader.py new file mode 100644 index 0000000..06924e3 --- /dev/null +++ b/denoisplit/data_loader/sinosoid_threecurve_dloader.py @@ -0,0 +1,522 @@ +import os.path +import pickle +from typing import Union + +import numpy as np +import math +from tqdm import tqdm +import lzma + +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples + + +def angle_shift(w1, w2, point, best_possible=True): + """ + Find x such that: cos(w2*(point +x) = cos(w1*point) + """ + # there should be two points at which the gradient's value should be same. + # if I select the correct point, then I don't need to shift + # d/dx(sin(w2*point +d)) = d/dx(sin(w1*point)) + # w2*cos() = w1*cos() + + # + possible_cos_val = w1 * np.cos(w1 * point) / w2 + if best_possible: + possible_cos_val = max(-1, possible_cos_val) + possible_cos_val = min(1, possible_cos_val) + else: + assert w2 >= w1, 'w2 must be larger than w1. otherwise angle is not always possible' + + theta = np.arccos(possible_cos_val) + return theta + + +def generate_one_curve(w_list, num_points, initial_phase=None, granularity=0.1): + N = len(w_list) + if initial_phase is None: + first_x = np.random.rand() * 2 * math.pi / w_list[0] + else: + first_x = initial_phase / w_list[0] + + prev_w = None + prev_last_y = None + y_shift = 0 + all_y = [] + for step, w in zip(num_points, w_list): + if prev_w: + x_shift = angle_shift(prev_w, w, x_space[-1]) + first_x = x_shift / w + + x_space = np.arange(first_x, first_x + step, granularity) + if prev_last_y: + y_shift = prev_last_y - np.sin(w * x_space[0]) + + y_space = np.sin(w * x_space) + y_shift + all_y.append(y_space[:-1]) + prev_last_y = y_space[-1] + prev_w = w + + y = np.concatenate(all_y) + return y + + +def apply_rotation(xy, radians): + """ + Adapted from https://gist.github.com/LyleScott/e36e08bfb23b1f87af68c9051f985302 + Args: + xy: (2,N) + """ + c, s = np.cos(radians), np.sin(radians) + j = np.array([[c, -s], [s, c]]) + m = np.dot(j, xy) + return np.array(m) + + +def post_processing(x, curve, img_sz): + x = x.astype(np.int) + # x can be < 0 due to horizontal shift. + x_filtr = np.logical_and(x < img_sz, x >= 0) + x = x[x_filtr] + curve = curve[x_filtr] + curve = curve.astype(np.int) + y_filtr = curve < img_sz + + curve = curve[y_filtr] + x = x[y_filtr] + return x, curve + + +def rotate_curve(x, curve, rotate_radian): + shift = (max(x) - min(x)) / 2 + x = x - shift + x = x.reshape(1, -1) + curve = curve.reshape(1, -1) + xy = np.concatenate([x, curve], axis=0) + xy = apply_rotation(xy, rotate_radian) + x = xy[0] + shift + x = x - min(x) + curve = xy[1] + return x, curve + + +def get_img(w_list, + img_sz, + vertical_shifts: list, + horizontal_shifts: list, + rotate_radians: list, + curve_amplitudes: list, + random_w12_flips: list, + curve_thickness, + connecting_w_len: float, + curve_initial_phase=None): + assert len(vertical_shifts) == len(rotate_radians) + assert len(vertical_shifts) == len(curve_amplitudes) + img = np.zeros((img_sz, img_sz)) + for i in range(len(w_list)): + add_to_img(img, + w_list[i], + vertical_shift=vertical_shifts[i], + horizontal_shift=horizontal_shifts[i], + flip_about_vertical=random_w12_flips[i], + rotate_radian=rotate_radians[i], + curve_amplitude=curve_amplitudes[i], + thickness=curve_thickness, + connecting_w_len=connecting_w_len, + curve_initial_phase=curve_initial_phase) + + return img + + +def add_thickness(img, thickness, x, curve): + thickness = (thickness - 1) // 2 + + for row_shift in range(-thickness, thickness): + for col_shift in range(-thickness, thickness): + if row_shift == 0 and col_shift == 0: + continue + temp_curve = curve + col_shift + temp_x = x + row_shift + filtr_x = np.logical_and(temp_x > 0, temp_x < img.shape[-1]) + filtr_curve = np.logical_and(temp_curve > 0, temp_curve < img.shape[-1]) + filtr = np.logical_and(filtr_x, filtr_curve) + img[temp_curve[filtr], temp_x[filtr]] += 1 / (np.sqrt(0.5 * (col_shift**2 + row_shift**2))) + + +def get_num_points(tot_points, num_w, connecting_w_len): + """ + Returns number of points we need for each sine curve with frequency w. + Args: + tot_points:Total number of points to be generated. + num_w: Number of frequencies in one curve + connecting_w_len: What fraction of points to be allocated for central curve. + + Returns: + + """ + if connecting_w_len is None: + num_points = [tot_points // num_w] * num_w + else: + assert num_w == 3 + connecting_points = int(connecting_w_len * tot_points) + edge_points = (tot_points - connecting_points) // 2 + num_points = [edge_points, connecting_points, edge_points] + return num_points + + +def add_to_img(img, + w_list, + vertical_shift=None, + horizontal_shift: int = 0.0, + flip_about_vertical=False, + rotate_radian=None, + curve_amplitude=None, + thickness=None, + connecting_w_len=None, + curve_initial_phase=None): + assert thickness % 2 == 1 + num_points = get_num_points(img.shape[1] + abs(horizontal_shift), len(w_list), connecting_w_len) + granularity = 0.1 + curve = generate_one_curve(w_list, num_points, granularity=granularity, initial_phase=curve_initial_phase) + x = np.arange(len(curve)) * granularity + curve *= curve_amplitude + if flip_about_vertical: + min_x = min(x) + max_x = max(x) + x = min_x + (max_x - min_x) - (x - min_x) + # positive + curve = curve - min(curve) + # vertical shift + curve += vertical_shift + if rotate_radian != 0: + x, curve = rotate_curve(x, curve, rotate_radian) + + if horizontal_shift: + x += horizontal_shift + x, curve = post_processing(x, curve, img.shape[-1]) + img[curve, x] += 1 + add_thickness(img, thickness, x, curve) + + +class Range: + + def __init__(self, min_val, max_val): + assert min_val < max_val + self.min = min_val + self.max = max_val + + def inrange(self, val): + return val >= self.min and val < self.max + + def sample(self): + return np.random.rand() * (self.max - self.min) + self.min + + +def sample_for_channel1(w_rangelist, joining_frequency): + assert len(w_rangelist) == 4 + if np.random.rand() > 0.5: + return w_rangelist[0].sample(), joining_frequency, w_rangelist[2].sample() + else: + return w_rangelist[1].sample(), joining_frequency, w_rangelist[3].sample() + + +def sample_for_channel2(w_rangelist, joining_frequency): + assert len(w_rangelist) == 4 + if np.random.rand() > 0.5: + return w_rangelist[0].sample(), joining_frequency, w_rangelist[3].sample() + else: + return w_rangelist[1].sample(), joining_frequency, w_rangelist[2].sample() + + +def spaced_out_vertical_shifts(max_value, num_curves, min_spacing): + """ + Sometimes the vertical shifts are too close.The idea is to generate them in such a way that they don't + overlap on each other + min_spacing: enforces the minimum distance between the start point of the curves + """ + if num_curves == 1: + return np.random.rand() * max_value + + bucket_size = 1 / num_curves + # normalizing min_spacing + min_spacing = min_spacing / max_value + + assert bucket_size > min_spacing, 'min_spacing is too small' + + # adding bucket_size/10 ensures that 1 also comes in this range. + disjoint_ranges = np.arange(0, 1 + bucket_size / 10, bucket_size) + output = [] + range_s = 0 + for range_e in disjoint_ranges[1:]: + # generate a value between [start_s+min_spacing/2, end_s-min_spacing/2] + norm_shift = np.random.rand() * (bucket_size - min_spacing) + range_s + min_spacing / 2 + output.append(norm_shift * max_value) + range_s = range_e + assert len(output) == num_curves + return output + + +def generate_dataset( + w_rangelist, + size, + img_sz, + num_curves=3, + curve_amplitude=64, + max_rotation=math.pi / 8, + max_vertical_shift_factor=0.8, + max_horizontal_shift_factor=0.3, + flip_w12_randomly=False, + curve_thickness=31, + encourage_non_overlap_single_channel=False, + vertical_min_spacing=0, + joining_frequency=0.01, + connecting_w_len=0.5, + curve_initial_phase=None, +): + """ + + Args: + w_rangelist: + size: + img_sz: + num_curves: + curve_amplitude: + max_rotation: + max_vertical_shift_factor: + max_horizontal_shift_factor: + flip_w12_randomly: + encourage_non_overlap_single_channel: If True, curves of a single channel are well spaced vertically to prevent + overlap. Note that there is overlap of curves between the two channels. + curve_thickness: + + Returns: + + """ + ch1_dset = [] + ch2_dset = [] + + def sample_angle(): + return 2 * np.random.rand() * max_rotation - max_rotation + + def get_random_w12_flips(): + if flip_w12_randomly: + random_w12_flips = [np.random.rand() > 0.5 for _ in range(num_curves)] + else: + random_w12_flips = [False] * num_curves + return random_w12_flips + + def get_shifts(): + if encourage_non_overlap_single_channel: + rand_vertical_shifts = spaced_out_vertical_shifts(img_sz * max_vertical_shift_factor, num_curves, + vertical_min_spacing) + else: + rand_vertical_shifts = [np.random.rand() * img_sz * max_vertical_shift_factor for _ in range(num_curves)] + rand_horizontal_shifts = [np.random.rand() * img_sz * max_horizontal_shift_factor for _ in range(num_curves)] + rand_horizontal_shifts = [x * -1 if np.random.rand() > 0.5 else x for x in rand_horizontal_shifts] + return rand_vertical_shifts, rand_horizontal_shifts + + for _ in tqdm(range(size)): + w1_list = [sample_for_channel1(w_rangelist, joining_frequency) for _ in range(num_curves)] + rotate_radians = [sample_angle() for _ in range(num_curves)] + vertical_shifts, horizontal_shifts = get_shifts() + img1 = get_img(w1_list, + img_sz, + vertical_shifts, + horizontal_shifts, + rotate_radians, [curve_amplitude] * num_curves, + get_random_w12_flips(), + curve_thickness, + connecting_w_len, + curve_initial_phase=curve_initial_phase) + + w2_list = [sample_for_channel2(w_rangelist, joining_frequency) for _ in range(num_curves)] + vertical_shifts, horizontal_shifts = get_shifts() + rotate_radians = [sample_angle() for _ in range(num_curves)] + img2 = get_img(w2_list, + img_sz, + vertical_shifts, + horizontal_shifts, + rotate_radians, [curve_amplitude] * num_curves, + get_random_w12_flips(), + curve_thickness, + connecting_w_len, + curve_initial_phase=curve_initial_phase) + + ch1_dset.append(img1[None]) + ch2_dset.append(img2[None]) + return np.concatenate(ch1_dset, axis=0), np.concatenate(ch2_dset, axis=0) + + +class CustomDataManager: + """ + A class to manage(load/save) the data. + """ + + def __init__(self, data_dir, data_config): + self._dir = data_dir + self._dconfig = data_config + + def fname(self): + fname = 'sin' + fname += f'_N-{self._dconfig.total_size}' + fname += f'_Fsz-{self._dconfig.frame_size}' + fname += f'_CA-{np.round(self._dconfig.curve_amplitude, 2)}' + fname += f'_CT-{self._dconfig.curve_thickness}' + fname += f'_CN-{self._dconfig.num_curves}' + fname += f'_MR-{self._dconfig.max_rotation}' + fname += f'_VF-{self._dconfig.max_vshift_factor}' + fname += f'_HF-{self._dconfig.max_hshift_factor}' + fname += f'_CfL-{self._dconfig.connecting_w_len}' + + if self._dconfig.encourage_non_overlap_single_channel: + fname += f'_NO-{self._dconfig.vertical_min_spacing}' + if self._dconfig.curve_initial_phase is not None: + fname += f'_ph-{self._dconfig.curve_initial_phase}' + + fr = self._dconfig.frequency_range_list + diff = [fr[i][1] - fr[i][0] for i in range(len(fr))] + gap = [fr[i + 1][0] - fr[i][1] for i in range(len(fr) - 1)] + + diff = int(np.mean(diff) * 100) + gap = int(np.mean(gap) * 100) + fname += f'_FR-{diff}.{gap}' + fname += '.xz' + return fname + + def exists(self): + return os.path.exists(os.path.join(self._dir, self.fname())) + + def load(self, fname: Union[str, None] = None): + fpath = os.path.join(self._dir, self.fname()) + if not os.path.exists(fpath): + print(f'File {fpath} does not exist.') + return None + + with lzma.open(fpath, 'rb') as f: + data_dict = pickle.load(f) + print(f'Loaded from file {fpath}') + + # Note that simpler arguments are already included in the name itself. + assert tuple(data_dict['frequency_range_list']) == tuple(self._dconfig.frequency_range_list) + return data_dict + + def save(self, data_dict): + data_dict['frequency_range_list'] = self._dconfig.frequency_range_list + fpath = os.path.join(self._dir, self.fname()) + with lzma.open(fpath, 'wb') as f: + pickle.dump(data_dict, f) + print(f'File {fpath} saved.') + + def remove(self): + fpath = os.path.join(self._dir, self.fname()) + if os.path.exists(fpath): + os.remove(fpath) + + +def train_val_data(data_dir, + data_config, + datasplit_type, + val_fraction=None, + test_fraction=None, + allow_generation=False): + assert isinstance(allow_generation, bool) + datamanager = CustomDataManager(data_dir, data_config) + total_size = data_config.total_size + frequency_range_list = data_config.frequency_range_list + frame_size = data_config.frame_size + curve_amplitude = data_config.curve_amplitude + num_curves = data_config.num_curves + max_rotation = data_config.max_rotation + curve_thickness = data_config.curve_thickness + max_vertical_shift_factor = data_config.max_vshift_factor + max_horizontal_shift_factor = data_config.max_hshift_factor + encourage_non_overlap_single_channel = data_config.encourage_non_overlap_single_channel + connecting_w_len = data_config.connecting_w_len + curve_initial_phase = data_config.curve_initial_phase + if encourage_non_overlap_single_channel: + vertical_min_spacing = data_config.vertical_min_spacing + else: + vertical_min_spacing = 0 + # I think this needs to be True for the data to be only dependant on the pairing. And not who is on left/right. + flip_w12_randomly = True + if datamanager.exists(): + data_dict = datamanager.load() + else: + data_dict = None + fpath = os.path.join(data_dir, datamanager.fname()) + assert allow_generation is True, f"{fpath} does not exist and Data generation is not allowed" + + if data_dict is None: + print('Data not found in the file. generating the data') + w_rangelist = [Range(x[0], x[1]) for x in frequency_range_list] + imgs1, imgs2 = generate_dataset(w_rangelist, + total_size, + frame_size, + num_curves=num_curves, + curve_amplitude=curve_amplitude, + max_rotation=max_rotation, + max_vertical_shift_factor=max_vertical_shift_factor, + max_horizontal_shift_factor=max_horizontal_shift_factor, + flip_w12_randomly=flip_w12_randomly, + curve_thickness=curve_thickness, + encourage_non_overlap_single_channel=encourage_non_overlap_single_channel, + vertical_min_spacing=vertical_min_spacing, + connecting_w_len=connecting_w_len, + curve_initial_phase=curve_initial_phase) + imgs1 = imgs1[..., None] + imgs2 = imgs2[..., None] + data = np.concatenate([imgs1, imgs2], axis=3) + # test, val, train + + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, len(data)) + data_dict = { + 'train': data[train_idx], + 'val': data[val_idx], + 'test': data[test_idx], + 'frequency_range_list': frequency_range_list + } + datamanager.save(data_dict) + + if datasplit_type == DataSplitType.Train: + return data_dict['train'] + elif datasplit_type == DataSplitType.Val: + return data_dict['val'] + elif datasplit_type == DataSplitType.Test: + return data_dict['test'] + + +if __name__ == '__main__': + w1 = 0.05 + w2 = 0.15 + max_angle = 100 + # curve, x = generate_one_curve(w1, w2, max_angle) + # x = 2 * x / max_angle - 1 + # # x = np.arange(len(curve)) + # xy = np.concatenate([x.reshape(1, -1), curve.reshape(1, -1)], axis=0) + # rotated = apply_rotation(xy, math.pi / 200) + # print(curve.shape) + import matplotlib.pyplot as plt + + # img = np.zeros((512, 512)) + # vshift = np.random.rand() * img.shape[-1] + # max_rotate = math.pi / 8 + # rotate = 2 * np.random.rand() * max_rotate - max_rotate + # add_to_img(img, w1, w2, vertical_shift=vshift, rotate_radian=rotate) + # + # vshift = np.random.rand() * img.shape[-1] + # rotate = 2 * np.random.rand() * max_rotate - max_rotate + # add_to_img(img, w1, w2, vertical_shift=vshift, rotate_radian=rotate) + # plt.imshow(img) + # plt.plot(x, curve) + # plt.plot(rotated[0], rotated[1], color='r') + w_rangelist = [Range(0.05, 0.1), Range(0.15, 0.2), Range(0.25, 0.3), Range(0.35, 0.4)] + size = 10 + img_sz = 512 + imgs1, imgs2 = generate_dataset(w_rangelist, + size, + img_sz, + num_curves=3, + curve_amplitude=64, + max_rotation=math.pi / 8, + flip_w12_randomly=True) + plt.imshow(imgs1[0]) + plt.show() diff --git a/denoisplit/data_loader/sox2golgi_rawdata_loader.py b/denoisplit/data_loader/sox2golgi_rawdata_loader.py new file mode 100644 index 0000000..dc50105 --- /dev/null +++ b/denoisplit/data_loader/sox2golgi_rawdata_loader.py @@ -0,0 +1,66 @@ +import os +from ast import literal_eval as make_tuple +from collections.abc import Sequence +from random import shuffle +from typing import List + +import numpy as np + +from denoisplit.core.custom_enum import Enum +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from denoisplit.core.tiff_reader import load_tiff +from denoisplit.data_loader.multifile_raw_dloader import SubDsetType +from denoisplit.data_loader.multifile_raw_dloader import get_train_val_data as get_train_val_data_twochannels + + +def get_two_channel_files(): + arr = [71, 89, 92, 93, 94, 95, 96, 97, 98, 99, 100, 1752, 1757, 1758, 1760, 1761] + sox2 = [f'SOX2/C2-Experiment-{i}.tif' for i in arr] + golgi = [f'GOLGI/C1-Experiment-{i}.tif' for i in arr] + return sox2, golgi + + +def get_one_channel_files(): + c2exp = [1267, 1268, 1269, 1270, 1272, 1273, 1274] + fpaths = [f'SOX2-Golgi/C2-Experiment-{i}.tif' for i in c2exp] + + c2osvz = [1294, 1295, 1296, 1297] + fpaths += [f'SOX2-Golgi/C2-oSVZ-Experiment-{i}.tif' for i in c2osvz] + + c2Osvz = [1286, 1287] + fpaths += [f'SOX2-Golgi/C2-OSVZ-Experiment-{i}.tif' for i in c2Osvz] + + c2svz = [1290, 1291, 1292, 1293] + fpaths += [f'SOX2-Golgi/C2-SVZ-Experiment-{i}.tif' for i in c2svz] + + fpaths += [ + 'SOX2-Golgi/C2-SVZ-Experiment-1282-Substack-9-12.tif', 'SOX2-Golgi/C2-SVZ-Experiment-1283-Substack-8-20.tif', + 'SOX2-Golgi/C2-SVZ-Experiment-1285-Substack-13-32.tif' + ] + return fpaths + + +def get_train_val_data(datadir, data_config, datasplit_type: DataSplitType, val_fraction=None, test_fraction=None): + if data_config.subdset_type == SubDsetType.OneChannel: + files_fn = get_one_channel_files + elif data_config.subdset_type == SubDsetType.TwoChannel: + files_fn = get_two_channel_files + + return get_train_val_data_twochannels(datadir, + data_config, + datasplit_type, + files_fn, + val_fraction=val_fraction, + test_fraction=test_fraction) + + +if __name__ == '__main__': + from denoisplit.data_loader.multifile_raw_dloader import SubDsetType + from ml_collections.config_dict import ConfigDict + data_config = ConfigDict() + data_config.subdset_type = SubDsetType.OneChannel + datadir = '/group/jug/ashesh/data/TavernaSox2Golgi/' + data = get_train_val_data(datadir, data_config, DataSplitType.Train, val_fraction=0.1, test_fraction=0.1) + print(len(data)) + # for i in range(len(data)): + # print(i, data[i].shape) diff --git a/denoisplit/data_loader/sox2golgi_v2_rawdata_loader.py b/denoisplit/data_loader/sox2golgi_v2_rawdata_loader.py new file mode 100644 index 0000000..5d3e4b2 --- /dev/null +++ b/denoisplit/data_loader/sox2golgi_v2_rawdata_loader.py @@ -0,0 +1,124 @@ +import os +from functools import partial + +import numpy as np + +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.data_loader.multifile_raw_dloader import get_train_val_data as get_train_val_data_multichannel +from nd2reader import ND2Reader + + +def get_start_end_index(key): + """ + Few start and end frames are not good in some of the files. So, we need to exclude them. + """ + start_index_dict = { + 'Test1_Slice1/1.nd2': 8, + 'Test1_Slice1/2.nd2': 1, + 'Test1_Slice1/3.nd2': 3, + 'Test1_Slice2_a/4.nd2': 10, + 'Test1_Slice2_a/5.nd2': 10, + 'Test1_Slice2_a/6.nd2': 10, + 'Test1_Slice2_b/7.nd2': 1, + 'Test1_Slice3_b/4.nd2': 1, + 'Test1_Slice3_b/5.nd2': 1, + 'Test1_Slice3_b/6.nd2': 1, + 'Test1_Slice4_a/1.nd2': 1, + 'Test1_Slice4_a/2.nd2': 1, + 'Test1_Slice4_a/3.nd2': 1, + 'Test1_Slice4_b/4.nd2': 1, + 'Test1_Slice4_b/5.nd2': 1, + 'Test1_Slice4_b/6.nd2': 1, + } + # excluding this index + end_index_dict = { + 'Test1_Slice2_b/7.nd2': 18, + 'Test1_Slice2_b/8.nd2': 18, + 'Test1_Slice2_b/9.nd2': 18, + 'Test1_Slice3_a/1.nd2': 15, + 'Test1_Slice3_a/2.nd2': 15, + 'Test1_Slice3_a/3.nd2': 15, + 'Test1_Slice3_b/4.nd2': 18, + 'Test1_Slice3_b/5.nd2': 18, + 'Test1_Slice3_b/6.nd2': 18, + 'Test1_Slice4_a/1.nd2': 19, + 'Test1_Slice4_a/2.nd2': 19, + 'Test1_Slice4_a/3.nd2': 19, + } + return start_index_dict.get(key), end_index_dict.get(key) + + +def load_nd2(fpath, channel_names=None, multiplicative_factor=1): + fname = os.path.basename(fpath) + parent_dir = os.path.basename(os.path.dirname(fpath)) + key = os.path.join(parent_dir, fname) + start_z, end_z = get_start_end_index(key) + with ND2Reader(fpath) as reader: + data = [] + if start_z is None: + start_z = 0 + if end_z is None: + end_z = reader.metadata['total_images_per_channel'] + + all_channels = reader.metadata['channels'] + relevant_channel_indices = [all_channels.index(c) for c in channel_names] + + for z in range(start_z, end_z): + channels = [] + for c in relevant_channel_indices: + img = reader.get_frame_2D(c=c, z=z) + img = img * multiplicative_factor + channels.append(img[..., None]) + img = np.concatenate(channels, axis=-1) + data.append(img[None]) + data = np.concatenate(data, axis=0) + return data + + +def get_files(): + rel_fpaths = [] + rel_fpaths += ['Test1_Slice1/1.nd2', 'Test1_Slice1/2.nd2', 'Test1_Slice1/3.nd2'] + rel_fpaths += ['Test1_Slice2_a/4.nd2', 'Test1_Slice2_a/5.nd2', 'Test1_Slice2_a/6.nd2'] + rel_fpaths += ['Test1_Slice2_b/7.nd2', 'Test1_Slice2_b/8.nd2', 'Test1_Slice2_b/9.nd2'] + rel_fpaths += ['Test1_Slice3_a/1.nd2', 'Test1_Slice3_a/2.nd2', 'Test1_Slice3_a/3.nd2'] + rel_fpaths += ['Test1_Slice3_b/4.nd2', 'Test1_Slice3_b/5.nd2', 'Test1_Slice3_b/6.nd2'] + rel_fpaths += ['Test1_Slice4_a/1.nd2', 'Test1_Slice4_a/2.nd2', 'Test1_Slice4_a/3.nd2'] + rel_fpaths += ['Test1_Slice4_b/4.nd2', 'Test1_Slice4_b/5.nd2', 'Test1_Slice4_b/6.nd2'] + return rel_fpaths + + +def get_train_val_data(datadir, data_config, datasplit_type: DataSplitType, val_fraction=None, test_fraction=None): + channel_names = [data_config.channel_1, + data_config.channel_2] # There are 3 channels ['555-647', 'GT_Cy5', 'GT_TRITC'] + load_data_fn = partial(load_nd2, channel_names=channel_names) + + if set(channel_names) == set(['555-647']) and data_config.input_is_sum == False: + # input is (C1 + C2 )/2. So, we need to divide by 2 for the input as well + load_data_fn = partial(load_nd2, channel_names=channel_names, multiplicative_factor=0.5) + + print( + f'Loading data from {datadir} with channel names {channel_names}, datasplit_type {DataSplitType.name(datasplit_type)}' + ) + return get_train_val_data_multichannel(datadir, + data_config, + datasplit_type, + get_files, + load_data_fn=partial(load_nd2, channel_names=channel_names), + val_fraction=val_fraction, + test_fraction=test_fraction) + + +if __name__ == '__main__': + import ml_collections + from denoisplit.data_loader.multifile_raw_dloader import SubDsetType + + config = ml_collections.ConfigDict() + config.subdset_type = SubDsetType.MultiChannel + config.channel_1 = 'GT_Cy5' + config.channel_2 = 'GT_TRITC' + data = get_train_val_data('/group/jug/ashesh/data/TavernaSox2Golgi/acquisition2/', + config, + DataSplitType.Train, + val_fraction=0.1, + test_fraction=0.1) + print(len(data)) diff --git a/denoisplit/data_loader/target_index_switcher.py b/denoisplit/data_loader/target_index_switcher.py new file mode 100644 index 0000000..662d8a7 --- /dev/null +++ b/denoisplit/data_loader/target_index_switcher.py @@ -0,0 +1,176 @@ +import numpy as np + + +class IndexSwitcher: + """ + The idea is to switch from valid indices for target to invalid indices for target. + If index in invalid for the target, then we return all zero vector as target. + This combines both logic: + 1. Using less amount of total data. + 2. Using less amount of target data but using full data. + """ + + def __init__(self, idx_manager, data_config, patch_size) -> None: + self.idx_manager = idx_manager + self._data_shape = self.idx_manager.get_data_shape() + self._training_validtarget_fraction = data_config.get('training_validtarget_fraction', 1.0) + self._validtarget_ceilT = int(np.ceil(self._data_shape[0] * self._training_validtarget_fraction)) + self._patch_size = patch_size + assert data_config.deterministic_grid is True, "This only works when the dataset has deterministic grid. Needed randomness comes from this class." + assert 'grid_size' in data_config and data_config.grid_size == 1, "We need a one to one mapping between index and h,w,t" + + self._h_validmax, self._w_validmax = self.get_reduced_frame_size(self._data_shape[:3], + self._training_validtarget_fraction) + if self._h_validmax < self._patch_size or self._w_validmax < self._patch_size: + print( + "WARNING: The valid target size is smaller than the patch size. This will result in all zero target. so, we are ignoring this frame for target." + ) + self._h_validmax = 0 + self._w_validmax = 0 + + print( + f'[{self.__class__.__name__}] Target Indices: [0,{self._validtarget_ceilT-1}]. Index={self._validtarget_ceilT-1} has shape [:{self._h_validmax},:{self._w_validmax}]. Available data: {self._data_shape[0]}' + ) + + def get_valid_target_index(self): + """ + Returns an index which corresponds to a frame which is expected to have a target. + """ + + _, h, w, _ = self._data_shape + framepixelcount = h * w + targetpixels = np.array([framepixelcount] * (self._validtarget_ceilT - 1) + + [self._h_validmax * self._w_validmax]) + targetpixels = targetpixels / np.sum(targetpixels) + t = np.random.choice(self._validtarget_ceilT, p=targetpixels) + # t = np.random.randint(0, self._validtarget_ceilT) if self._validtarget_ceilT >= 1 else 0 + h, w = self.get_valid_target_hw(t) + index = self.idx_manager.idx_from_hwt(h, w, t) + # print('Valid', index, h,w,t) + return index + + def get_invalid_target_index(self): + # if self._validtarget_ceilT == 0: + #TODO: There may not be enough data for this to work. The better way is to skip using 0 for invalid target. + # t = np.random.randint(1, self._data_shape[0]) + # elif self._validtarget_ceilT < self._data_shape[0]: + # t = np.random.randint(self._validtarget_ceilT, self._data_shape[0]) + # else: + # t = self._validtarget_ceilT - 1 + # 5 + # 1.2 => 2 + total_t, h, w, _ = self._data_shape + framepixelcount = h * w + available_h = h - self._h_validmax + if available_h < self._patch_size: + available_h = 0 + available_w = w - self._w_validmax + if available_w < self._patch_size: + available_w = 0 + + targetpixels = np.array([available_h * available_w] + [framepixelcount] * (total_t - self._validtarget_ceilT)) + t_probab = targetpixels / np.sum(targetpixels) + t = np.random.choice(np.arange(self._validtarget_ceilT - 1, total_t), p=t_probab) + + h, w = self.get_invalid_target_hw(t) + index = self.idx_manager.idx_from_hwt(h, w, t) + # print('Invalid', index, h,w,t) + return index + + def get_valid_target_hw(self, t): + """ + This is the opposite of get_invalid_target_hw. It returns a h,w which is valid for target. + This is only valid for single frame setup. + """ + if t == self._validtarget_ceilT - 1: + h = np.random.randint(0, self._h_validmax - self._patch_size) + w = np.random.randint(0, self._w_validmax - self._patch_size) + else: + h = np.random.randint(0, self._data_shape[1] - self._patch_size) + w = np.random.randint(0, self._data_shape[2] - self._patch_size) + return h, w + + def get_invalid_target_hw(self, t): + """ + This is the opposite of get_valid_target_hw. It returns a h,w which is not valid for target. + This is only valid for single frame setup. + """ + if t == self._validtarget_ceilT - 1: + h = np.random.randint(self._h_validmax, self._data_shape[1] - self._patch_size) + w = np.random.randint(self._w_validmax, self._data_shape[2] - self._patch_size) + else: + h = np.random.randint(0, self._data_shape[1] - self._patch_size) + w = np.random.randint(0, self._data_shape[2] - self._patch_size) + return h, w + + def _get_tidx(self, index): + if isinstance(index, int) or isinstance(index, np.int64): + idx = index + else: + idx = index[0] + return self.idx_manager.get_t(idx) + + def index_should_have_target(self, index): + tidx = self._get_tidx(index) + if tidx < self._validtarget_ceilT - 1: + return True + elif tidx > self._validtarget_ceilT - 1: + return False + else: + h, w, _ = self.idx_manager.hwt_from_idx(index) + return h + self._patch_size < self._h_validmax and w + self._patch_size < self._w_validmax + + @staticmethod + def get_reduced_frame_size(data_shape_nhw, fraction): + n, h, w = data_shape_nhw + + framepixelcount = h * w + targetpixelcount = int(n * framepixelcount * fraction) + + # We are currently supporting this only when there is just one frame. + # if np.ceil(pixelcount / framepixelcount) > 1: + # return None, None + + lastframepixelcount = targetpixelcount % framepixelcount + assert data_shape_nhw[1] == data_shape_nhw[2] + if lastframepixelcount > 0: + new_size = int(np.sqrt(lastframepixelcount)) + return new_size, new_size + else: + assert targetpixelcount / framepixelcount >= 1, 'This is not possible in euclidean space :D (so this is a bug)' + return h, w + + +if __name__ == '__main__': + import pandas as pd + + from denoisplit.configs.biosr_sparsely_supervised_config import get_config + from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager + + config = get_config() + data_shape = (15, 499, 499, 2) + config.data.training_validtarget_fraction = 0.16 + print(config.data.training_validtarget_fraction) + + grid_size = config.data.grid_size + patch_size = config.data.image_size + manager = GridIndexManager(data_shape, grid_size, patch_size, GridAlignement.LeftTop) + switcher = IndexSwitcher(manager, config.data, patch_size) + + valid_target = [] + for _ in range(10000): + idx = switcher.get_valid_target_index() + valid_target.append(switcher._get_tidx(idx)) + assert switcher.index_should_have_target(idx) + print(pd.Series(valid_target).value_counts(normalize=True)) + + invalid_target = [] + for _ in range(10000): + idx = switcher.get_invalid_target_index() + assert not switcher.index_should_have_target(idx) + invalid_target.append(switcher._get_tidx(idx)) + print(pd.Series(invalid_target).value_counts(normalize=True).sort_index()) + +# 5 ele +# 1.5 => ceilT = 2 +# [1] + [2,3,4] diff --git a/denoisplit/data_loader/tiff_dloader.py b/denoisplit/data_loader/tiff_dloader.py new file mode 100644 index 0000000..e95ffd7 --- /dev/null +++ b/denoisplit/data_loader/tiff_dloader.py @@ -0,0 +1,137 @@ +import os +from typing import Tuple + +import numpy as np +from skimage.io import imread +from tqdm import tqdm + +from denoisplit.core.tiff_reader import load_tiff + + +class TiffLoader: + def __init__(self, + img_sz: int, + enable_flips: bool = False, + thresh: float = None, + repeat_factor: int = 1, + normalized_input=None): + """ + Args: + repeat_factor: Since we are doing a random crop, repeat_factor is + given which can repeatedly sample from the same image. If self.N=12 + and repeat_factor is 5, then index upto 12*5 = 60 is allowed. + normalized_input: whether to normalize the input or not + """ + assert isinstance(normalized_input, bool) + self._img_sz = img_sz + + self._enable_flips = enable_flips + self.N = 0 + self._avg_cropped_count = 1 + self._called_count = 0 + self._thresh = thresh + self._repeat_factor = repeat_factor + self._normalized_input = normalized_input + assert self._thresh is not None + + def _crop_random(self, img1: np.ndarray, img2: np.ndarray): + h, w = img1.shape[-2:] + if self._img_sz is None: + return img1, img2, {'h': [0, h], 'w': [0, w], 'hflip': False, 'wflip': False} + + h_start, w_start, h_flip, w_flip = self._get_random_hw(h, w) + if self._enable_flips is False: + h_flip = False + w_flip = False + + img1 = self._crop_img(img1, h_start, w_start, h_flip, w_flip) + img2 = self._crop_img(img2, h_start, w_start, h_flip, w_flip) + + return img1, img2, { + 'h': [h_start, h_start + self._img_sz], + 'w': [w_start, w_start + self._img_sz], + 'hflip': h_flip, + 'wflip': w_flip, + } + + def _crop_img(self, img: np.ndarray, h_start: int, w_start: int, h_flip: bool, w_flip: bool): + new_img = img[..., h_start:h_start + self._img_sz, w_start:w_start + self._img_sz] + if h_flip: + new_img = new_img[..., ::-1, :] + if w_flip: + new_img = new_img[..., :, ::-1] + + return new_img.astype(np.float32) + + def _get_random_hw(self, h: int, w: int): + """ + Random starting position for the crop for the img with index `index`. + """ + h_start = np.random.choice(h - self._img_sz) + w_start = np.random.choice(w - self._img_sz) + h_flip, w_flip = np.random.choice(2, size=2) == 1 + return h_start, w_start, h_flip, w_flip + + def metric(self, img: np.ndarray): + return np.std(img) + + def in_allowed_range(self, metric_val: float): + return metric_val >= self._thresh + + def __len__(self): + return self.N * self._repeat_factor + + def _is_content_present(self, img1: np.ndarray, img2: np.ndarray): + met1 = self.metric(img1) + met2 = self.metric(img2) + # print('Metric', met1, met2) + if self.in_allowed_range(met1) or self.in_allowed_range(met2): + return True + return False + + def _load_img(self, index: int): + """ + It must return the two images which would be mixed. + """ + return None, None + + def _get_img(self, index: int): + """ + Loads an image. + Crops the image such that cropped image has content. + """ + img1, img2 = self._load_img(index) + cropped_img1, cropped_img2 = self._crop_random(img1, img2)[:2] + self._called_count += 1 + cropped_count = 1 + while (not self._is_content_present(cropped_img1, cropped_img2)): + cropped_img1, cropped_img2 = self._crop_random(img1, img2)[:2] + cropped_count += 1 + + self._avg_cropped_count = ( + (self._called_count - 1) * self._avg_cropped_count + cropped_count) / self._called_count + return cropped_img1, cropped_img2 + + def normalize_img(self, img1, img2): + mean, std = self.get_mean_std() + mean = mean.squeeze() + std = std.squeeze() + img1 = (img1 - mean[0]) / std[0] + img2 = (img2 - mean[1]) / std[1] + return img1, img2 + + def __getitem__(self, index: int) -> Tuple[np.ndarray, np.ndarray]: + + assert index < self._repeat_factor * self.N + index = index % self.N + + img1, img2 = self._get_img(index) + target = np.concatenate([img1, img2], axis=0) + if self._normalized_input: + img1, img2 = self.normalize_img(img1, img2) + + inp = (0.5 * img1 + 0.5 * img2).astype(np.float32) + return inp, target + + def get_mean_std(self): + return 0.0, 255.0 diff --git a/denoisplit/data_loader/train_val_data.py b/denoisplit/data_loader/train_val_data.py new file mode 100644 index 0000000..f5155c4 --- /dev/null +++ b/denoisplit/data_loader/train_val_data.py @@ -0,0 +1,138 @@ +""" +Here, the idea is to load the data from different data dtypes into a single interface. +""" +from typing import Union + +from denoisplit.config_utils import get_configdir_from_saved_predictionfile, load_config +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.core.data_type import DataType +from denoisplit.data_loader.allencell_rawdata_loader import get_train_val_data as _loadallencellmito +from denoisplit.data_loader.dao_3ch_rawdata_loader import get_train_val_data as _loaddao3ch +from denoisplit.data_loader.embl_semisup_rawdata_loader import get_train_val_data as _loadembl2_semisup +from denoisplit.data_loader.exp_microscopyv2_rawdata_loader import get_train_val_data as _loadexp_microscopyv2 +from denoisplit.data_loader.ht_iba1_ki67_rawdata_loader import get_train_val_data as _load_ht_iba1_ki67 +from denoisplit.data_loader.multi_channel_train_val_data import train_val_data as _load_tiff_train_val +from denoisplit.data_loader.pavia2_rawdata_loader import get_train_val_data as _loadpavia2 +from denoisplit.data_loader.pavia2_rawdata_loader import get_train_val_data_vanilla as _loadpavia2_vanilla +from denoisplit.data_loader.pavia3_rawdata_loader import get_train_val_data as _loadpavia3 +from denoisplit.data_loader.raw_mrc_dloader import get_train_val_data as _loadmrc +from denoisplit.data_loader.schroff_rawdata_loader import get_train_val_data as _loadschroff_mito_er +from denoisplit.data_loader.sinosoid_dloader import train_val_data as _loadsinosoid +from denoisplit.data_loader.sinosoid_threecurve_dloader import train_val_data as _loadsinosoid3curve +from denoisplit.data_loader.sox2golgi_rawdata_loader import get_train_val_data as _loadsox2golgi +from denoisplit.data_loader.sox2golgi_v2_rawdata_loader import get_train_val_data as _loadsox2golgi_v2 +from denoisplit.data_loader.two_tiff_rawdata_loader import get_train_val_data as _loadseparatetiff + + +def get_train_val_data(data_config, + fpath, + datasplit_type: DataSplitType, + val_fraction=None, + test_fraction=None, + allow_generation=None, + ignore_specific_datapoints=None): + """ + Ensure that the shape of data should be N*H*W*C: N is number of data points. H,W are the image dimensions. + C is the number of channels. + """ + assert isinstance(datasplit_type, int), f'datasplit_type should be an integer, but is {datasplit_type}' + if data_config.data_type == DataType.OptiMEM100_014: + return _load_tiff_train_val(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + elif data_config.data_type == DataType.CustomSinosoid: + return _loadsinosoid(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + allow_generation=allow_generation) + + elif data_config.data_type == DataType.CustomSinosoidThreeCurve: + return _loadsinosoid3curve(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + allow_generation=allow_generation) + + elif data_config.data_type == DataType.Prevedel_EMBL: + return _load_tiff_train_val(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + elif data_config.data_type == DataType.AllenCellMito: + return _loadallencellmito(fpath, data_config, datasplit_type, val_fraction, test_fraction) + elif data_config.data_type in [DataType.SeparateTiffData, DataType.PredictedTiffData]: + if data_config.data_type == DataType.PredictedTiffData: + cfg1 = load_config(get_configdir_from_saved_predictionfile(data_config.ch1_fname)) + cfg2 = load_config(get_configdir_from_saved_predictionfile(data_config.ch2_fname)) + cfg3 = load_config(get_configdir_from_saved_predictionfile(data_config.ch_input_fname)) + msg = '' + if 'poisson_noise_factor' in cfg1.data or 'poisson_noise_factor' in cfg2.data or 'poisson_noise_factor' in cfg3.data: + msg = f'p1:{cfg1.data.poisson_noise_factor} p2:{cfg2.data.poisson_noise_factor} p3:{cfg3.data.poisson_noise_factor}' + assert cfg1.data.poisson_noise_factor == cfg2.data.poisson_noise_factor == cfg3.data.poisson_noise_factor, msg + + if 'enable_gaussian_noise' in cfg1.data or 'enable_gaussian_noise' in cfg2.data or 'enable_gaussian_noise' in cfg3.data: + assert cfg1.data.enable_gaussian_noise == cfg2.data.enable_gaussian_noise == cfg3.data.enable_gaussian_noise + if cfg1.data.enable_gaussian_noise: + msg = f'g1:{cfg1.data.synthetic_gaussian_scale} g2:{cfg2.data.synthetic_gaussian_scale} g3:{cfg3.data.synthetic_gaussian_scale}' + assert cfg1.data.synthetic_gaussian_scale == cfg2.data.synthetic_gaussian_scale == cfg3.data.synthetic_gaussian_scale, msg + + return _loadseparatetiff(fpath, data_config, datasplit_type, val_fraction, test_fraction) + elif data_config.data_type == DataType.Pavia2: + return _loadpavia2(fpath, data_config, datasplit_type, val_fraction=val_fraction, test_fraction=test_fraction) + elif data_config.data_type == DataType.Pavia2VanillaSplitting: + return _loadpavia2_vanilla(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + elif data_config.data_type == DataType.SemiSupBloodVesselsEMBL: + return _loadembl2_semisup(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + + elif data_config.data_type == DataType.ShroffMitoEr: + return _loadschroff_mito_er(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + elif data_config.data_type == DataType.HTIba1Ki67: + return _load_ht_iba1_ki67(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + elif data_config.data_type == DataType.BioSR_MRC: + return _loadmrc(fpath, data_config, datasplit_type, val_fraction=val_fraction, test_fraction=test_fraction) + elif data_config.data_type == DataType.TavernaSox2Golgi: + return _loadsox2golgi(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + elif data_config.data_type == DataType.TavernaSox2GolgiV2: + return _loadsox2golgi_v2(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + elif data_config.data_type == DataType.Dao3Channel: + return _loaddao3ch(fpath, data_config, datasplit_type, val_fraction=val_fraction, test_fraction=test_fraction) + elif data_config.data_type == DataType.ExpMicroscopyV2: + return _loadexp_microscopyv2(fpath, + data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction) + elif data_config.data_type == DataType.Pavia3SeqData: + return _loadpavia3(fpath, data_config, datasplit_type, val_fraction=val_fraction, test_fraction=test_fraction) + else: + raise NotImplementedError(f'{DataType.name(data_config.data_type)} is not implemented') diff --git a/denoisplit/data_loader/two_dset_dloader.py b/denoisplit/data_loader/two_dset_dloader.py new file mode 100644 index 0000000..bcb0a97 --- /dev/null +++ b/denoisplit/data_loader/two_dset_dloader.py @@ -0,0 +1,242 @@ +import numpy as np +import torch + +import ml_collections +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.core.loss_type import LossType +from denoisplit.data_loader.base_data_loader import BaseDataLoader +from denoisplit.data_loader.lc_multich_dloader import LCMultiChDloader +from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager +from denoisplit.data_loader.vanilla_dloader import MultiChDloader + + +class TwoDsetDloader(BaseDataLoader): + """ + Here, we have 2 datasets. We want to get the data from 2 datasets. + """ + + def __init__( + self, + dset0, + dset1, + data_config, + use_one_mu_std=None, + ) -> None: + + # self._enable_random_cropping = enable_random_cropping + self._dset0 = dset0 + self._dset1 = dset1 + self._use_one_mu_std = use_one_mu_std + + self._mean = None + self._std = None + # assert normalized_input is True, "We are doing the normalization in this dataloader.So you better pass it as True" + # use_LC = 'multiscale_lowres_count' in data_config and data_config.multiscale_lowres_count is not None + # data_class = LCMultiChDloader if use_LC else MultiChDloader + + # kwargs = { + # 'normalized_input': normalized_input, + # 'enable_rotation_aug': enable_rotation_aug, + # 'use_one_mu_std': use_one_mu_std, + # 'allow_generation': allow_generation, + # 'datasplit_type': datasplit_type, + # 'grid_alignment': grid_alignment, + # 'overlapping_padding_kwargs': overlapping_padding_kwargs, + # } + # if use_LC: + # padding_kwargs = {'mode': data_config.padding_mode} + # if 'padding_value' in data_config and data_config.padding_value is not None: + # padding_kwargs['constant_values'] = data_config.padding_value + # kwargs['padding_kwargs'] = padding_kwargs + # kwargs['num_scales'] = data_config.multiscale_lowres_count + # self._subdset_types = data_config.subdset_types + # empty_patch_replacement_enabled = data_config.empty_patch_replacement_enabled_list + + self._subdset_types_prob = data_config.subdset_types_probab + assert sum(self._subdset_types_prob) == 1 + print(f'[{self.__class__.__name__}] Probabs:{self._subdset_types_prob}') + + def sum_channels(self, data, first_index_arr, second_index_arr): + fst_channel = data[..., first_index_arr].sum(axis=-1, keepdims=True) + scnd_channel = data[..., second_index_arr].sum(axis=-1, keepdims=True) + return np.concatenate([fst_channel, scnd_channel], axis=-1) + + # def set_img_sz(self, image_size, grid_size, alignment=None): + # """ + # Needed just for the notebooks + # If one wants to change the image size on the go, then this can be used. + # Args: + # image_size: size of one patch + # grid_size: frame is divided into square grids of this size. A patch centered on a grid having size `image_size` is returned. + # """ + # self._img_sz = image_size + # self._grid_sz = grid_size + + # if self._dset0 is not None: + # self._dset0.set_img_sz(image_size, grid_size, alignment=alignment) + + # if self._dset1 is not None: + # self._dset1.set_img_sz(image_size, grid_size, alignment=alignment) + + # self.idx_manager = GridIndexManager(self.get_data_shape(), self._grid_sz, self._img_sz, alignment) + + def get_mean_std(self): + """ + Needed just for running the notebooks + """ + return self._mean, self._std + + # def get_data_shape(self): + # N = 0 + # default_shape = None + + # if self._dset0 is not None: + # default_shape = self._dset0.get_data_shape() + # N += default_shape[0] + + # if self._dset1 is not None: + # default_shape = self._dset1.get_data_shape() + # N += default_shape[0] + + # default_shape = list(default_shape) + # default_shape[0] = N + # return tuple(default_shape) + + def __len__(self): + sz = 0 + if self._dset0 is not None: + sz += int(self._subdset_types_prob[0] * len(self._dset0)) + if self._dset1 is not None: + sz += int(self._subdset_types_prob[1] * len(self._dset1)) + return sz + + def compute_mean_std_for_input(self, dloader): + mean_for_input, std_for_input = dloader.compute_mean_std() + mean_for_input = mean_for_input.squeeze() + assert mean_for_input[0] == mean_for_input[1] + mean_for_input = np.array(mean_for_input[0], dtype=np.float32) + + std_for_input = std_for_input.squeeze() + assert std_for_input[0] == std_for_input[1] + std_for_input = np.array([std_for_input[0]], dtype=np.float32) + return mean_for_input, std_for_input + + def compute_individual_mean_std(self): + mean_dict = {'subdset_0': {}, 'subdset_1': {}} + std_dict = {'subdset_0': {}, 'subdset_1': {}} + + if self._dset0 is not None: + mean_, std_ = self._dset0.compute_individual_mean_std() + mean_for_input, std_for_input = self.compute_mean_std_for_input(self._dset0) + mean_dict['subdset_0'] = {'target': mean_, 'input': mean_for_input} + std_dict['subdset_0'] = {'target': std_, 'input': std_for_input} + + if self._dset1 is not None: + mean_, std_ = self._dset1.compute_individual_mean_std() + mean_for_input, std_for_input = self.compute_mean_std_for_input(self._dset1) + mean_dict['subdset_1'] = {'target': mean_, 'input': mean_for_input} + std_dict['subdset_1'] = {'target': std_, 'input': std_for_input} + + # assert LossType.ElboMixedReconstruction in [self.get_loss_idx(0), self.get_loss_idx(1)] + # if self.get_loss_idx(0) == LossType.ElboMixedReconstruction: + # # we are doing this for the model, not for the validation dadtaloader. + # mean_dict['subdset_0']['target'] = mean_dict['subdset_1']['target'] + # mean_dict['subdset_0']['input'] = mean_dict['subdset_1']['input'] + # else: + # mean_dict['subdset_1']['target'] = mean_dict['subdset_0']['target'] + # mean_dict['subdset_1']['input'] = mean_dict['subdset_0']['input'] + + return mean_dict, std_dict + + # def _compute_mean_std(self, allow_for_validation_data=False): + # mean_dict = {'subdset_0': {}, 'subdset_1': {}} + # std_dict = {'subdset_0': {}, 'subdset_1': {}} + + # if self._dset0 is not None: + # mean_, std_ = self._dset0.compute_mean_std(allow_for_validation_data=allow_for_validation_data) + # mean_dict['subdset_0'] = {'target': mean_} + # std_dict['subdset_0'] = {'target': std_} + + # if self._dset1 is not None: + # mean_, std_ = self._dset1.compute_mean_std(allow_for_validation_data=allow_for_validation_data) + # mean_dict['subdset_1'] = {'target': mean_} + # std_dict['subdset_1'] = {'target': std_} + # return mean_dict, std_dict + + def compute_mean_std(self, allow_for_validation_data=False): + assert self._use_one_mu_std is True, "We are not supporting separate mean and std for creating the input." + return self.compute_individual_mean_std() + + def set_mean_std(self, mean_val, std_val): + # NOTE: + self._mean = mean_val + self._std = std_val + + def per_side_overlap_pixelcount(self): + if self._dset0 is not None: + return self._dset0.per_side_overlap_pixelcount() + if self._dset1 is not None: + return self._dset1.per_side_overlap_pixelcount() + + def get_idx_manager(self): + d0_active = self._dset0 is not None + d1_active = self._dset1 is not None + assert d0_active or d1_active + assert not (d0_active and d1_active) + if d0_active: + return self._dset0.idx_manager + else: + return self._dset1.idx_manager + + def get_grid_size(self): + d0_active = self._dset0 is not None + d1_active = self._dset1 is not None + assert d0_active or d1_active + assert not (d0_active and d1_active) + if d0_active: + return self._dset0.get_grid_size() + else: + return self._dset1.get_grid_size() + + def get_loss_idx(self, dset_idx): + if dset_idx == 0: + return LossType.Elbo + elif dset_idx == 1: + return LossType.ElboMixedReconstruction + else: + raise NotImplementedError("Not implemented") + + def __getitem__(self, index): + """ + Returns: + (inp,tar,dset_label,loss_idx) + """ + + if self._subdset_types_prob[0] == 0 or self._subdset_types_prob[1] == 0: + # This is typically only true when we are handling validation.`` + if self._subdset_types_prob[0] == 0: + dset_idx = 1 + return (*self._dset1[index], dset_idx, self.get_loss_idx(dset_idx)) + elif self._subdset_types_prob[1] == 0: + dset_idx = 0 + return (*self._dset0[index], dset_idx, self.get_loss_idx(dset_idx)) + else: + raise ValueError("This is invalid state.") + else: + prob_list = np.cumsum(self._subdset_types_prob) + coin_flip = np.random.rand() + if coin_flip <= prob_list[0]: + dset_idx = 0 + elif coin_flip > prob_list[0] and coin_flip <= prob_list[1]: + dset_idx = 1 + + loss_idx = self.get_loss_idx(dset_idx) + + dset = getattr(self, f'_dset{dset_idx}') + idx = np.random.randint(len(dset)) + return (*dset[idx], dset_idx, loss_idx) + + def get_max_val(self): + max_val0 = self._dset0.get_max_val() + max_val1 = self._dset1.get_max_val() + return [max_val0, max_val1] diff --git a/denoisplit/data_loader/two_tiff_rawdata_loader.py b/denoisplit/data_loader/two_tiff_rawdata_loader.py new file mode 100644 index 0000000..aadedea --- /dev/null +++ b/denoisplit/data_loader/two_tiff_rawdata_loader.py @@ -0,0 +1,69 @@ +import os + +import numpy as np + +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from denoisplit.core.data_type import DataType +from denoisplit.core.tiff_reader import load_tiff + + +def get_train_val_data(dirname, data_config, datasplit_type, val_fraction, test_fraction): + # actin-60x-noise2-highsnr.tif mito-60x-noise2-highsnr.tif + fpath1 = os.path.join(dirname, data_config.ch1_fname) + fpath2 = os.path.join(dirname, data_config.ch2_fname) + fpaths = [fpath1, fpath2] + fpath0 = '' + if 'ch_input_fname' in data_config: + fpath0 = os.path.join(dirname, data_config.ch_input_fname) + fpaths = [fpath0] + fpaths + + print(f'Loading from {dirname} Channels: ' + f'{fpath1},{fpath2}, inp:{fpath0} Mode:{DataSplitType.name(datasplit_type)}') + + data = np.concatenate([load_tiff(fpath)[..., None] for fpath in fpaths], axis=3) + if data_config.data_type == DataType.PredictedTiffData: + assert len(data.shape) == 5 and data.shape[-1] == 1 + data = data[..., 0].copy() + # data = data[::3].copy() + # NOTE: This was not the correct way to do it. It is so because the noise present in the input was directly related + # to the noise present in the channels and so this is not the way we would get the data. + # We need to add the noise independently to the input and the target. + + # if data_config.get('poisson_noise_factor', False): + # data = np.random.poisson(data) + # if data_config.get('enable_gaussian_noise', False): + # synthetic_scale = data_config.get('synthetic_gaussian_scale', 0.1) + # print('Adding Gaussian noise with scale', synthetic_scale) + # noise = np.random.normal(0, synthetic_scale, data.shape) + # data = data + noise + + if datasplit_type == DataSplitType.All: + return data.astype(np.float32) + + train_idx, val_idx, test_idx = get_datasplit_tuples(val_fraction, test_fraction, len(data), starting_test=True) + if datasplit_type == DataSplitType.Train: + return data[train_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Val: + return data[val_idx].astype(np.float32) + elif datasplit_type == DataSplitType.Test: + return data[test_idx].astype(np.float32) + + +if __name__ == '__main__': + import matplotlib.pyplot as plt + + from denoisplit.configs.twotiff_config import get_config + from denoisplit.core.data_type import DataType + from denoisplit.core.loss_type import LossType + from denoisplit.core.model_type import ModelType + from denoisplit.core.sampler_type import SamplerType + + config = get_config() + config.data.enable_gaussian_noise = False + # config.data.synthetic_gaussian_scale = 1000 + data = get_train_val_data('/group/jug/ashesh/data/ventura_gigascience/', config.data, DataSplitType.Train, + config.training.val_fraction, config.training.test_fraction) + + _, ax = plt.subplots(figsize=(6, 3), ncols=2) + ax[0].imshow(data[0, ..., 0]) + ax[1].imshow(data[0, ..., 1]) diff --git a/denoisplit/data_loader/vanilla_dloader.py b/denoisplit/data_loader/vanilla_dloader.py new file mode 100644 index 0000000..f0aaf6e --- /dev/null +++ b/denoisplit/data_loader/vanilla_dloader.py @@ -0,0 +1,688 @@ +from typing import Tuple, Union + +import albumentations as A +import numpy as np + +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.core.data_type import DataType +from denoisplit.core.empty_patch_fetcher import EmptyPatchFetcher +from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager +from denoisplit.data_loader.target_index_switcher import IndexSwitcher +from denoisplit.data_loader.train_val_data import get_train_val_data + + +class MultiChDloader: + + def __init__(self, + data_config, + fpath: str, + datasplit_type: DataSplitType = None, + val_fraction=None, + test_fraction=None, + normalized_input=None, + enable_rotation_aug: bool = False, + enable_random_cropping: bool = False, + use_one_mu_std=None, + allow_generation=False, + max_val=None, + grid_alignment=GridAlignement.LeftTop, + overlapping_padding_kwargs=None, + print_vars=True): + """ + Here, an image is split into grids of size img_sz. + Args: + repeat_factor: Since we are doing a random crop, repeat_factor is + given which can repeatedly sample from the same image. If self.N=12 + and repeat_factor is 5, then index upto 12*5 = 60 is allowed. + use_one_mu_std: If this is set to true, then one mean and stdev is used + for both channels. Otherwise, two different meean and stdev are used. + + """ + self._fpath = fpath + self._data = self.N = self._noise_data = None + # by default, if the noise is present, add it to the input and target. + self._disable_noise = False + self._poisson_noise_factor = None + self._train_index_switcher = None + # NOTE: Input is the sum of the different channels. It is not the average of the different channels. + self._input_is_sum = data_config.get('input_is_sum', False) + self._num_channels = data_config.get('num_channels', 2) + if datasplit_type == DataSplitType.Train: + self._datausage_fraction = data_config.get('trainig_datausage_fraction', 1.0) + # assert self._datausage_fraction == 1.0, 'Not supported. Use validtarget_random_fraction and training_validtarget_fraction to get the same effect' + self._validtarget_rand_fract = data_config.get('validtarget_random_fraction', None) + # self._validtarget_random_fraction_final = data_config.get('validtarget_random_fraction_final', None) + # self._validtarget_random_fraction_stepepoch = data_config.get('validtarget_random_fraction_stepepoch', None) + # self._idx_count = 0 + elif datasplit_type == DataSplitType.Val: + self._datausage_fraction = data_config.get('validation_datausage_fraction', 1.0) + else: + self._datausage_fraction = 1.0 + + self.load_data(data_config, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + allow_generation=allow_generation) + self._normalized_input = normalized_input + self._quantile = data_config.get('clip_percentile', 0.995) + self._channelwise_quantile = data_config.get('channelwise_quantile', False) + self._background_quantile = data_config.get('background_quantile', 0.0) + self._clip_background_noise_to_zero = data_config.get('clip_background_noise_to_zero', False) + self._skip_normalization_using_mean = data_config.get('skip_normalization_using_mean', False) + + self._background_values = None + + self._grid_alignment = grid_alignment + self._overlapping_padding_kwargs = overlapping_padding_kwargs + if self._grid_alignment == GridAlignement.LeftTop: + assert self._overlapping_padding_kwargs is None or data_config.multiscale_lowres_count is not None, "Padding is not used with this alignement style" + elif self._grid_alignment == GridAlignement.Center: + assert self._overlapping_padding_kwargs is not None, 'With Center grid alignment, padding is needed.' + + self._is_train = datasplit_type == DataSplitType.Train + + # input = alpha * ch1 + (1-alpha)*ch2. + # alpha is sampled randomly between these two extremes + self._start_alpha_arr = self._end_alpha_arr = self._return_alpha = self._alpha_weighted_target = None + + self._img_sz = self._grid_sz = self._repeat_factor = self.idx_manager = None + if self._is_train: + self._start_alpha_arr = data_config.get('start_alpha', None) + self._end_alpha_arr = data_config.get('end_alpha', None) + self._alpha_weighted_target = data_config.get('alpha_weighted_target', False) + + self.set_img_sz(data_config.image_size, + data_config.grid_size if 'grid_size' in data_config else data_config.image_size) + + if self._validtarget_rand_fract is not None: + self._train_index_switcher = IndexSwitcher(self.idx_manager, data_config, self._img_sz) + self._std_background_arr = data_config.get('std_background_arr', None) + + else: + + self.set_img_sz(data_config.image_size, + data_config.val_grid_size if 'val_grid_size' in data_config else data_config.image_size) + + self._return_alpha = data_config.get('return_alpha', False) + self._return_index = data_config.get('return_index', False) + + self._empty_patch_replacement_enabled = data_config.get("empty_patch_replacement_enabled", + False) and self._is_train + if self._empty_patch_replacement_enabled: + self._empty_patch_replacement_channel_idx = data_config.empty_patch_replacement_channel_idx + self._empty_patch_replacement_probab = data_config.empty_patch_replacement_probab + data_frames = self._data[..., self._empty_patch_replacement_channel_idx] + # NOTE: This is on the raw data. So, it must be called before removing the background. + self._empty_patch_fetcher = EmptyPatchFetcher(self.idx_manager, + self._img_sz, + data_frames, + max_val_threshold=data_config.empty_patch_max_val_threshold) + + self.rm_bkground_set_max_val_and_upperclip_data(max_val, datasplit_type) + + # For overlapping dloader, image_size and repeat_factors are not related. hence a different function. + + self._mean = None + self._std = None + self._use_one_mu_std = use_one_mu_std + self._enable_rotation = enable_rotation_aug + self._enable_random_cropping = enable_random_cropping + # Randomly rotate [-90,90] + + self._rotation_transform = None + if self._enable_rotation: + self._rotation_transform = A.Compose([A.Flip(), A.RandomRotate90()]) + + if print_vars: + msg = self._init_msg() + print(msg) + + def disable_noise(self): + assert self._poisson_noise_factor is None, "This is not supported. Poisson noise is added to the data itself and so the noise cannot be disabled." + self._disable_noise = True + + def enable_noise(self): + self._disable_noise = False + + def get_data_shape(self): + return self._data.shape + + def load_data(self, data_config, datasplit_type, val_fraction=None, test_fraction=None, allow_generation=None): + self._data = get_train_val_data(data_config, + self._fpath, + datasplit_type, + val_fraction=val_fraction, + test_fraction=test_fraction, + allow_generation=allow_generation) + + old_shape = self._data.shape + if self._datausage_fraction < 1.0: + framepixelcount = np.prod(self._data.shape[1:3]) + pixelcount = int(len(self._data) * framepixelcount * self._datausage_fraction) + frame_count = int(np.ceil(pixelcount / framepixelcount)) + last_frame_reduced_size, _ = IndexSwitcher.get_reduced_frame_size(self._data.shape[:3], + self._datausage_fraction) + self._data = self._data[:frame_count].copy() + if frame_count == 1: + self._data = self._data[:, :last_frame_reduced_size, :last_frame_reduced_size].copy() + print(f'[{self.__class__.__name__}] New data shape: {self._data.shape} Old: {old_shape}') + + msg = '' + if data_config.get('poisson_noise_factor', -1) > 0: + self._poisson_noise_factor = data_config.poisson_noise_factor + msg += f'Adding Poisson noise with factor {self._poisson_noise_factor}.\t' + self._data = np.random.poisson(self._data / self._poisson_noise_factor) * self._poisson_noise_factor + + if data_config.get('enable_gaussian_noise', False): + synthetic_scale = data_config.get('synthetic_gaussian_scale', 0.1) + msg += f'Adding Gaussian noise with scale {synthetic_scale}' + # 0 => noise for input. 1: => noise for all targets. + shape = self._data.shape + self._noise_data = np.random.normal(0, synthetic_scale, (*shape[:-1], shape[-1] + 1)) + if data_config.get('input_has_dependant_noise', False): + msg += '. Moreover, input has dependent noise' + self._noise_data[..., 0] = np.mean(self._noise_data[..., 1:], axis=-1) + print(msg) + + self.N = len(self._data) + assert self._data.shape[-1] == self._num_channels, 'Number of channels in data and config do not match.' + + def save_background(self, channel_idx, frame_idx, background_value): + self._background_values[frame_idx, channel_idx] = background_value + + def get_background(self, channel_idx, frame_idx): + return self._background_values[frame_idx, channel_idx] + + def remove_background(self): + + self._background_values = np.zeros((self._data.shape[0], self._data.shape[-1])) + + if self._background_quantile == 0.0: + assert self._clip_background_noise_to_zero is False, 'This operation currently happens later in this function.' + return + + if self._data.dtype in [np.uint16]: + # unsigned integer creates havoc + self._data = self._data.astype(np.int32) + + for ch in range(self._data.shape[-1]): + for idx in range(self._data.shape[0]): + qval = np.quantile(self._data[idx, ..., ch], self._background_quantile) + assert np.abs( + qval + ) > 20, "We are truncating the qval to an integer which will only make sense if it is large enough" + # NOTE: Here, there can be an issue if you work with normalized data + qval = int(qval) + self.save_background(ch, idx, qval) + self._data[idx, ..., ch] -= qval + + if self._clip_background_noise_to_zero: + self._data[self._data < 0] = 0 + + def rm_bkground_set_max_val_and_upperclip_data(self, max_val, datasplit_type): + self.remove_background() + self.set_max_val(max_val, datasplit_type) + self.upperclip_data() + + def upperclip_data(self): + if isinstance(self.max_val, list): + chN = self._data.shape[-1] + assert chN == len(self.max_val) + for ch in range(chN): + ch_data = self._data[..., ch] + ch_q = self.max_val[ch] + ch_data[ch_data > ch_q] = ch_q + self._data[..., ch] = ch_data + else: + self._data[self._data > self.max_val] = self.max_val + + def compute_max_val(self): + if self._channelwise_quantile: + max_val_arr = [np.quantile(self._data[..., i], self._quantile) for i in range(self._data.shape[-1])] + return max_val_arr + else: + return np.quantile(self._data, self._quantile) + + def set_max_val(self, max_val, datasplit_type): + + if max_val is None: + assert datasplit_type == DataSplitType.Train + self.max_val = self.compute_max_val() + else: + assert max_val is not None + self.max_val = max_val + + def get_max_val(self): + return self.max_val + + def get_img_sz(self): + return self._img_sz + + def reduce_data(self, t_list=None, h_start=None, h_end=None, w_start=None, w_end=None): + if t_list is None: + t_list = list(range(self._data.shape[0])) + if h_start is None: + h_start = 0 + if h_end is None: + h_end = self._data.shape[1] + if w_start is None: + w_start = 0 + if w_end is None: + w_end = self._data.shape[2] + + self._data = self._data[t_list, h_start:h_end, w_start:w_end, :].copy() + if self._noise_data is not None: + self._noise_data = self._noise_data[t_list, h_start:h_end, w_start:w_end, :].copy() + + self.N = len(t_list) + self.set_img_sz(self._img_sz, self._grid_sz) + print(f'[{self.__class__.__name__}] Data reduced. New data shape: {self._data.shape}') + + def set_img_sz(self, image_size, grid_size): + """ + If one wants to change the image size on the go, then this can be used. + Args: + image_size: size of one patch + grid_size: frame is divided into square grids of this size. A patch centered on a grid having size `image_size` is returned. + """ + + self._img_sz = image_size + self._grid_sz = grid_size + self.idx_manager = GridIndexManager(self._data.shape, self._grid_sz, self._img_sz, self._grid_alignment) + self.set_repeat_factor() + + def set_repeat_factor(self): + if self._grid_sz > 1: + self._repeat_factor = self.idx_manager.grid_rows(self._grid_sz) * self.idx_manager.grid_cols(self._grid_sz) + else: + self._repeat_factor = self.idx_manager.grid_rows(self._img_sz) * self.idx_manager.grid_cols(self._img_sz) + + def _init_msg(self, ): + msg = f'[{self.__class__.__name__}] Sz:{self._img_sz}' + msg += f' Train:{int(self._is_train)} N:{self.N} NumPatchPerN:{self._repeat_factor}' + msg += f' NormInp:{self._normalized_input}' + msg += f' SingleNorm:{self._use_one_mu_std}' + msg += f' Rot:{self._enable_rotation}' + msg += f' RandCrop:{self._enable_random_cropping}' + msg += f' Q:{self._quantile}' + msg += f' SummedInput:{self._input_is_sum}' + msg += f' ReplaceWithRandSample:{self._empty_patch_replacement_enabled}' + if self._empty_patch_replacement_enabled: + msg += f'-{self._empty_patch_replacement_channel_idx}-{self._empty_patch_replacement_probab}' + + msg += f' BckQ:{self._background_quantile}' + if self._start_alpha_arr is not None: + msg += f' Alpha:[{self._start_alpha_arr},{self._end_alpha_arr}]' + return msg + + def _crop_imgs(self, index, *img_tuples: np.ndarray): + h, w = img_tuples[0].shape[-2:] + if self._img_sz is None: + return (*img_tuples, {'h': [0, h], 'w': [0, w], 'hflip': False, 'wflip': False}) + + if self._enable_random_cropping: + h_start, w_start = self._get_random_hw(h, w) + else: + h_start, w_start = self._get_deterministic_hw(index) + + cropped_imgs = [] + for img in img_tuples: + img = self._crop_flip_img(img, h_start, w_start, False, False) + cropped_imgs.append(img) + + return (*tuple(cropped_imgs), { + 'h': [h_start, h_start + self._img_sz], + 'w': [w_start, w_start + self._img_sz], + 'hflip': False, + 'wflip': False, + }) + + def _crop_img(self, img: np.ndarray, h_start: int, w_start: int): + if self._grid_alignment == GridAlignement.LeftTop: + # In training, this is used. + # NOTE: It is my opinion that if I just use self._crop_img_with_padding, it will work perfectly fine. + # The only benefit this if else loop provides is that it makes it easier to see what happens during training. + new_img = img[..., h_start:h_start + self._img_sz, w_start:w_start + self._img_sz] + return new_img + elif self._grid_alignment == GridAlignement.Center: + # During evaluation, this is used. In this situation, we can have negative h_start, w_start. Or h_start +self._img_sz can be larger than frame + # In these situations, we need some sort of padding. This is not needed in the LeftTop alignement. + return self._crop_img_with_padding(img, h_start, w_start) + + def get_begin_end_padding(self, start_pos, max_len): + """ + The effect is that the image with size self._grid_sz is in the center of the patch with sufficient + padding on all four sides so that the final patch size is self._img_sz. + """ + pad_start = 0 + pad_end = 0 + if start_pos < 0: + pad_start = -1 * start_pos + + pad_end = max(0, start_pos + self._img_sz - max_len) + + return pad_start, pad_end + + def _crop_img_with_padding(self, img: np.ndarray, h_start: int, w_start: int): + _, H, W = img.shape + h_on_boundary = self.on_boundary(h_start, H) + w_on_boundary = self.on_boundary(w_start, W) + + assert h_start < H + assert w_start < W + + assert h_start + self._img_sz <= H or h_on_boundary + assert w_start + self._img_sz <= W or w_on_boundary + # max() is needed since h_start could be negative. + new_img = img[..., max(0, h_start):h_start + self._img_sz, max(0, w_start):w_start + self._img_sz] + padding = np.array([[0, 0], [0, 0], [0, 0]]) + + if h_on_boundary: + pad = self.get_begin_end_padding(h_start, H) + padding[1] = pad + if w_on_boundary: + pad = self.get_begin_end_padding(w_start, W) + padding[2] = pad + + if not np.all(padding == 0): + new_img = np.pad(new_img, padding, **self._overlapping_padding_kwargs) + + return new_img + + def _crop_flip_img(self, img: np.ndarray, h_start: int, w_start: int, h_flip: bool, w_flip: bool): + new_img = self._crop_img(img, h_start, w_start) + if h_flip: + new_img = new_img[..., ::-1, :] + if w_flip: + new_img = new_img[..., :, ::-1] + + return new_img.astype(np.float32) + + def __len__(self): + return self.N * self._repeat_factor + + def _load_img(self, index: Union[int, Tuple[int, int]]) -> Tuple[np.ndarray, np.ndarray]: + """ + Returns the channels and also the respective noise channels. + """ + if isinstance(index, int) or isinstance(index, np.int64): + idx = index + else: + idx = index[0] + + imgs = self._data[self.idx_manager.get_t(idx)] + loaded_imgs = [imgs[None, ..., i] for i in range(imgs.shape[-1])] + noise = [] + if self._noise_data is not None and not self._disable_noise: + noise = [ + self._noise_data[self.idx_manager.get_t(idx)][None, ..., i] for i in range(self._noise_data.shape[-1]) + ] + return tuple(loaded_imgs), tuple(noise) + + def get_mean_std(self): + return self._mean, self._std + + def set_mean_std(self, mean_val, std_val): + self._mean = mean_val + self._std = std_val + + def normalize_img(self, *img_tuples): + mean, std = self.get_mean_std() + mean = mean.squeeze() + std = std.squeeze() + normalized_imgs = [] + for i, img in enumerate(img_tuples): + img = (img - mean[i]) / std[i] + normalized_imgs.append(img) + return tuple(normalized_imgs) + + def get_grid_size(self): + return self._grid_sz + + def get_idx_manager(self): + return self.idx_manager + + def per_side_overlap_pixelcount(self): + return (self._img_sz - self._grid_sz) // 2 + + def on_boundary(self, cur_loc, frame_size): + return cur_loc + self._img_sz > frame_size or cur_loc < 0 + + def _get_deterministic_hw(self, index: Union[int, Tuple[int, int]]): + """ + It returns the top-left corner of the patch corresponding to index. + """ + if isinstance(index, int) or isinstance(index, np.int64): + idx = index + grid_size = self._grid_sz + else: + idx, grid_size = index + + h_start, w_start = self.idx_manager.get_deterministic_hw(idx, grid_size=grid_size) + if self._grid_alignment == GridAlignement.LeftTop: + return h_start, w_start + elif self._grid_alignment == GridAlignement.Center: + pad = self.per_side_overlap_pixelcount() + return h_start - pad, w_start - pad + + def compute_individual_mean_std(self): + # numpy 1.19.2 has issues in computing for large arrays. https://github.com/numpy/numpy/issues/8869 + # mean = np.mean(self._data, axis=(0, 1, 2)) + # std = np.std(self._data, axis=(0, 1, 2)) + mean_arr = [] + std_arr = [] + for ch_idx in range(self._data.shape[-1]): + mean_ = 0.0 if self._skip_normalization_using_mean else self._data[..., ch_idx].mean() + if self._noise_data is not None: + std_ = (self._data[..., ch_idx] + self._noise_data[..., ch_idx + 1]).std() + else: + std_ = self._data[..., ch_idx].std() + + mean_arr.append(mean_) + std_arr.append(std_) + + mean = np.array(mean_arr) + std = np.array(std_arr) + + return mean[None, :, None, None], std[None, :, None, None] + + def compute_mean_std(self, allow_for_validation_data=False): + """ + Note that we must compute this only for training data. + """ + assert self._is_train is True or allow_for_validation_data, 'This is just allowed for training data' + if self._use_one_mu_std is True: + if self._input_is_sum: + assert self._noise_data is None, "This is not supported with noise" + mean = [np.mean(self._data[..., k:k + 1], keepdims=True) for k in range(self._num_channels)] + mean = np.sum(mean, keepdims=True)[0] + std = np.linalg.norm( + [np.std(self._data[..., k:k + 1], keepdims=True) for k in range(self._num_channels)], + keepdims=True)[0] + else: + mean = np.mean(self._data, keepdims=True).reshape(1, 1, 1, 1) + if self._noise_data is not None: + std = np.std(self._data + self._noise_data[..., 1:], keepdims=True).reshape(1, 1, 1, 1) + else: + std = np.std(self._data, keepdims=True).reshape(1, 1, 1, 1) + + mean = np.repeat(mean, self._num_channels, axis=1) + std = np.repeat(std, self._num_channels, axis=1) + + if self._skip_normalization_using_mean: + mean = np.zeros_like(mean) + + return mean, std + + elif self._use_one_mu_std is False: + return self.compute_individual_mean_std() + + elif self._use_one_mu_std is None: + return (np.array([0.0, 0.0]).reshape(1, self._num_channels, 1, + 1), np.array([1.0, 1.0]).reshape(1, self._num_channels, 1, 1)) + + def _get_random_hw(self, h: int, w: int): + """ + Random starting position for the crop for the img with index `index`. + """ + if h != self._img_sz: + h_start = np.random.choice(h - self._img_sz) + w_start = np.random.choice(w - self._img_sz) + else: + h_start = 0 + w_start = 0 + return h_start, w_start + + def _get_img(self, index: Union[int, Tuple[int, int]]): + """ + Loads an image. + Crops the image such that cropped image has content. + """ + img_tuples, noise_tuples = self._load_img(index) + cropped_img_tuples = self._crop_imgs(index, *img_tuples, *noise_tuples)[:-1] + cropped_noise_tuples = cropped_img_tuples[len(img_tuples):] + cropped_img_tuples = cropped_img_tuples[:len(img_tuples)] + return cropped_img_tuples, cropped_noise_tuples + + def replace_with_empty_patch(self, img_tuples): + empty_index = self._empty_patch_fetcher.sample() + empty_img_tuples = self._get_img(empty_index) + final_img_tuples = [] + for tuple_idx in range(len(img_tuples)): + if tuple_idx == self._empty_patch_replacement_channel_idx: + final_img_tuples.append(empty_img_tuples[tuple_idx]) + else: + final_img_tuples.append(img_tuples[tuple_idx]) + return tuple(final_img_tuples) + + def get_mean_std_for_input(self): + return self.get_mean_std() + + def _compute_input_with_alpha(self, img_tuples, alpha): + assert self._normalized_input is True, "normalization should happen here" + inp = 0 + for alpha, img in zip(alpha, img_tuples): + inp += img * alpha + + mean, std = self.get_mean_std_for_input() + mean = mean.squeeze() + std = std.squeeze() + if mean.size == 1: + mean = mean.reshape(1, ) + std = std.reshape(1, ) + + assert len(mean) == len(img_tuples) + for i in range(len(mean)): + assert mean[0] == mean[i] + assert std[0] == std[i] + + inp = (inp - mean[0]) / std[0] + return inp.astype(np.float32) + + def _sample_alpha(self): + alpha_pos = np.random.rand() + alpha_arr = [] + for i in range(self._num_channels): + alpha = self._start_alpha_arr[i] + alpha_pos * (self._end_alpha_arr[i] - self._start_alpha_arr[i]) + alpha_arr.append(alpha) + return alpha_arr + + def _compute_input(self, img_tuples): + alpha = [1 / len(img_tuples) for _ in range(len(img_tuples))] + if self._start_alpha_arr is not None: + alpha = self._sample_alpha() + + inp = self._compute_input_with_alpha(img_tuples, alpha) + if self._input_is_sum: + inp = len(img_tuples) * inp + return inp, alpha + + def _get_index_from_valid_target_logic(self, index): + if self._validtarget_rand_fract is not None: + if np.random.rand() < self._validtarget_rand_fract: + index = self._train_index_switcher.get_valid_target_index() + else: + index = self._train_index_switcher.get_invalid_target_index() + return index + + def __getitem__(self, index: Union[int, Tuple[int, int]]) -> Tuple[np.ndarray, np.ndarray]: + if self._train_index_switcher is not None: + index = self._get_index_from_valid_target_logic(index) + + img_tuples, noise_tuples = self._get_img(index) + assert self._empty_patch_replacement_enabled != True, "This is not supported with noise" + + if self._empty_patch_replacement_enabled: + if np.random.rand() < self._empty_patch_replacement_probab: + img_tuples = self.replace_with_empty_patch(img_tuples) + + if self._enable_rotation: + # passing just the 2D input. 3rd dimension messes up things. + img_kwargs = {f'img{i}': img_tuples[i][0] for i in range(len(img_tuples))} + noise_kwargs = {f'noise{i}': noise_tuples[i][0] for i in range(len(noise_tuples))} + rot_dic = self._rotation_transform(image=img_tuples[0][0], **img_kwargs, **noise_kwargs) + img_tuples = [rot_dic[f'img{i}'][None] for i in range(len(img_tuples))] + noise_tuples = [rot_dic[f'noise{i}'][None] for i in range(len(noise_tuples))] + + # add noise to input + if len(noise_tuples) > 0: + factor = np.sqrt(2) if self._input_is_sum else 1.0 + input_tuples = [x + noise_tuples[0] * factor for x in img_tuples] + else: + input_tuples = img_tuples + inp, alpha = self._compute_input(input_tuples) + + # add noise to target. + if len(noise_tuples) >= 1: + img_tuples = [x + noise for x, noise in zip(img_tuples, noise_tuples[1:])] + + if self._alpha_weighted_target: + assert self._input_is_sum is False + target = [] + for i in range(len(img_tuples)): + target.append(img_tuples[i] * alpha[i]) + target = np.concatenate(target, axis=0) + else: + target = np.concatenate(img_tuples, axis=0) + + output = [inp, target] + + if self._return_alpha: + output.append(alpha) + + if self._return_index: + output.append(index) + + if isinstance(index, int) or isinstance(index, np.int64): + return tuple(output) + + _, grid_size = index + output.append(grid_size) + return tuple(output) + + +if __name__ == '__main__': + # from denoisplit.configs.microscopy_multi_channel_lvae_config import get_config + from denoisplit.configs.twotiff_config import get_config + config = get_config() + dset = MultiChDloader( + config.data, + # '/group/jug/ashesh/data/microscopy/OptiMEM100x014.tif', + '/group/jug/ashesh/data/ventura_gigascience_small/', + DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=config.data.normalized_input, + enable_rotation_aug=config.data.normalized_input, + enable_random_cropping=config.data.deterministic_grid is False, + use_one_mu_std=config.data.use_one_mu_std, + allow_generation=False, + max_val=None, + grid_alignment=GridAlignement.LeftTop, + overlapping_padding_kwargs=None) + + mean, std = dset.compute_mean_std() + dset.set_mean_std(mean, std) + + inp, target = dset[0] diff --git a/denoisplit/loss/__pycache__/exclusive_loss.cpython-39.pyc b/denoisplit/loss/__pycache__/exclusive_loss.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6af7fa964b15a221fe32128cc5345b01f1f6ed98 GIT binary patch literal 1666 zcmZ`(OOM+&5ay7SEX$8Lo5gn9ZF?wksDZ%7?jfh3U7(NSqCjp!3Pm;PN2`Y;$*u)R zy=;06&`a<3vHzxLUfYZRLND!*l6Re;p)oTb$HO5t^N~TX=Mo%${{qwBZ9@LiljFf~ za*dL`L?wuTka)F)h*AP1Vjc$~I)VxQ8azvMg(Yl6wrC0GHSt=~5$&I7`a+UzTev&$ z+&k2fmULz3mU>+Q&&ja2$6d(HUhg{5>M-zV#6tNBC3}i0CnYICfS_;K3tF*?=dh(E z+ks#g#9&_I4@hN|mf#lzH?VF}imQj9tWd6HIKv4J=X!74Onov*qU9==zT8a0RklcC zKTNXBU&~3Jq{>1ynJbp9qM@z$BAQ(qeU<9ddaj9`rGeNS;lk_O`-?wFs!RUQH{*E{ z$#Ia)Wi}txW;{uR919sIi|5O5k=HOYP^TC-r&>#Ms?oAgXa9d-U93!3jlcLrHD{D{NOS#9**fwFTsK%TRb}?_dX~ z%yNy;eMuL9AHtL#A5UViqL}p`2(H=8I)mC_8(#3R0=~ zdLe&SER?abgXL1jLczDn4c0S%nIz$rP;3(9!-uJZIn%aQHM6;o zR_^^g{Yd99DRr^$c8h~Z`o7{wLUGRy#r4~CbZY%&sqT<+o<)gRh4Kqs_-ug6ffMH1 M?x&9JfQ!HX0E*^~#{d8T literal 0 HcmV?d00001 diff --git a/denoisplit/loss/__pycache__/nbr_consistency_loss.cpython-39.pyc b/denoisplit/loss/__pycache__/nbr_consistency_loss.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e465ccecd24f0f4df721e393bb1ee4b85ed8dce GIT binary patch literal 7666 zcmd5>TW=f372cV>@FJ3;Wa{pVe2H!5BFA>pG;W$0&BbV%DnV?tDVt=w;tZvg$t5$p zjBS-ffXYE%sy6R!0Vz+_OP~8wibY?FJ_*Qk9|E-LcV;PxluX$%9H3n7*|TTQ&d!|s z9C`VC*1+$p&sgn07YyTHbkqM!8C;oSYJ+8AD8n zNinryG6VE!O)njy&uIF@A^NPQvqSVbO`kkK*K%DwE=%ILI3Z4Mm|G08+@((RQ787O ztdGj}sFQuv$vx^+A9YGvt0!bhPDm!F3;O@`qbsfwwq10k*1rRSjo>5Y?tC8OfzGlB%%YHQfhOFICzPPrQo?l#2 zH)V8fZEXInX0;u@8@$_U-B6wguaz?~4}v)L)0=P7GUAaspxcm<@~iQs~P%{1h*%As634Amh!=raouX&!@zEw zcHO{hNY^b}u@%aCEzax@o*x{0?uenc4K)dAe*Ke6E6s+y3Sfi4jjTK8yje&9#0O9>_{02r*m9Ol>#r+ql>c<$yAX8tQMc zwTr_hb?~Js^5Ndk2A0C9Cl>(e7@I~1u|pMMY^=*880V_F&blUD1)IV2apg0{Z602E z+xQLJqjO|0bJpluk+o`LaaIS%i19h6t1zd4)l9r^3LBix1|r6GYH{Zq{C56JfL5}w zL!#Jbu_^qLTn7cfA58%I{ow-mF03iBqFuY{E#8DR+1i?% zMKwpOK2G2Sz=AqO=%dM_P4ajS{EsOQ{r+%yJb8oYH-up_QO`WO00ar(r3VP$5j{e` zKalq*yzF_z$GFiRfpV=EUMQ$=9aKn(oPtM(BlGnK4r?!Ppdi?PB0%r=f@wt3ZM$ax ziSAG0gWKkQ2vKD0=P?rF9rId=A zEiI(%QZtI0jiaS>;^5jol`8V9JsI7=xPvl!@ljqes5qu@zGDH&bf;hRRpI(!{f*cK-%6sE8!jFe$TWI8&Q+(JU0$4#8NEoBQiscgp9 zr@p+S&JfjVNG~XxIs;V-sB)yL%6eiGmHa?0bkL+`s?A2LjY4UFiz=o?j2!CnkzHhK zmxl>y==%dPh>UViK=*NjyiOvaOpYDl21jN`rU!*`b3&nl6M0`#_BqWi_C8$)&rJ0m z9NFsFTa4~E?T!soLRu2m9CoGMR429RM1T;k4dJGRjeO6D-f?Oq;#5-dY_r7Ww7AJ> zllV)CjFA^9baFqZlLA?M_PA7E}S^-J%1h90fnOrJ7Vf#}*ZX2Q`*oM!~CxqNnfUOCi;21|LV!FwHI0h*@4j394$$B2$!r)b|Oz zOyEETQy>W@0h^TYE3hO=fC>&M;rvlb*dOAFX@UIbJM|VtTG*k8cUTqA5|xSJyD(QC1)rmYV^*m)D_zu@hjx7#5CoGz@PVmyPi4 z=MAQhUjPc)7w_g_UBm0bo?=niQRi@pQ$bUgUa?vAB1K*in+-pRO?kJqn~{tCLEZI~ zs^t4Aha&uGGz5kuWw+*4vFrRTz7tYOONCy6t-U-ff{9(ZOkc0YVO!2lwAp=@{_vFT?cb>Pzjjm82m$b3>@kobRA)#A~06-G$;BFstCK+ zC&2TLL%X^Uc{kn7fQ#BCM{#AlBj6f+2v@F~2UqbST!rpvC*8?T8J!%?!jz%sIrarp ze?zr1-pO=EI{D7%vW3+ZQTe1g#gg$7HZPz2h3*n8I<{Ft-viA$lF6Kbj7!}^bUdgW zOVTRUJhcR&U)56c7n1jUK6h;A(+8GfJl}l-gt?Eh562@ z{+aHXv2nHP)V=5apL_o9x$V!-moz*-{hrwRj}1-xPs$vA3}l|e8(#yEniO5FA^58| zbp9GUX2TRzrgyC!yI~_;l$NybiALe;nk-1?o+h0=z2Qi4U8|QqL{HjAU1SR{1-^=- z@cBro=c8cjgQxlVm#ZKA`Jd7AqpM9Ce)JTOF!2&DZULl1id57zU3*J=OT3}Ip>OF@ zm&QG3V7wtXXG#k>b6Xo&iI!@6;+po#g@K)jj=pakXwtr^sc)y&zL^?(+JO+-t*>y- zoa8X&!p4Um<7r~dsmDTY8E;$zNVJaF*Wc9M#HtLvGy6Zqk!tPm&Clfi9OM)jY6>tZX~2`>6^D~MaG`R8IYlEFn8 zgi-r?uiH-YWX#EK6vr1;5GShLOaketpc#e8?KYEk6na#=+Pj-A#QsjN8+cnP+VOf( zT)|ke4xowt`NL(~J3Fgax>3{b#?P)EE zi$H$1>7mg!8sYiL)w-2gp!as5ipVSC^~|IV$ZWsY3qn~hWL7iU4U^2IJ;-NMrMgR0 zw~((p&O|$(wxQ;!kY<(FJvwR7jg}cx2bx|nD@MgIMOjotMX%`UL12%NkBIXe-gqA% zU=f3OeNlpc-xJc7g?m=Rkd7?g(;B8M$vJ$jz?Nk>e-B*UC?NfqtjL9X0y#%k=(5`{UqB|8o6Bx}F>}0OSyn_UFUVHBtu}Z} z`G6#4xxhihvM--hf?5fxleo2$_U)j1*K0!Q1zjJ4nmv(cnu&)_sYkAhA^f9tSG;z} zO;H=X88lm--|e;h7}J`RL`h3cN~&J2a@zeMubeF(!i2j!xd1GAO$8m%Z24grba_r$ z)r;FZ?XIud$z5*;x+hy4uNaFDdQr1AjS4ZTIIA>w;{^JJl#aI*W>!zNA!9|)Yj%C0 zJdoC-s-9ObW@a38w;F{ZtsBmW)Q!_8P`dHV2?ZnK9ZTp&eMGrWrE_CphGdPU31UPs zbpZ^Vt1eP$x&Fes+F?8KJQt|=9Dr7|#c{u~u=W1KCkfK(sGlhtXrMdN)hs`xrdV=v zDS}xBSBs6huAV@N`Vv6hP*35LS^2hDykWCbc6WOcjOaxn_%eaD3B07;?RqzpR=&eu zMHexdUJVQBfAz#Ee_B6HGJ~Us($ps}g(#W8yC5O$=p?p3Fi235H>7b>k01G__L`8a z8hDx3hI$BX`WIetUkLph-FCR`hEe!rq>@&&9ff|^CEjzJ(N1qSfgr&YuC8y^P4y(2 zsZ|0O2|NN&7fhvDy3_*dIq=Z$q}yLY{g~9XCTgN$^q)MD8ppM6vZ1Bcc*uPiE5nzN zAs3xhzyC zh9Cu*-Sd^d6E_^H0nO6QDx8vSXiB2Ex`I}-R9)H*hKg=n?*&w2KSa|{2~#-um67Uy z=|tKd?W4(if{y5!!#k$zi{LcS(1ru3?+HL~)@jf>HHTk|zEXh8p86&@Z%@1?5|QeO zzNg2}65k=HCN-P)c?64_vR9mTIH+hWgjMZOYh{5#D@9sHL<7InmVr z9<32Br3EQ|K^qhfkDOYn#cindGe=w9Y8~6k23JA$h`9ZW*B}^)dn0hWe*f;Odp$_p zC=A?a%Y_zkZ$wcSE>-L%k-MpOgH`r|6>)vt$qcdwrFPtgi|U8XATz0cX7t-VW;S&h z^)f?7@XT(vgFE%PMwz+mHh3#iapQ~%wgMHPX>K;h+!Qw!{B9I(dt*#io5=43+c@`$ zR(Vuh?-7#Q<8hBzn<*7dz7#X@xddk& z_-^_N1ZNqHcpa*GpX`u+pkL4ZD}Ccb(snRGY$s_y)#)6;HpxhQm6<&i$XR+6hHk_6 zP>{VS_34N;4;BV*~RJ5;Xf%bTkNhl|&aaCWC_&oPpRw>`)2}YK$?H zau^}if!J$wZXD=jclV*BA+~5k-#tD54vg@TguPDg#k?;jEjlK8H}`ZXbb|z`|0gAP z_&m>sDuA>=bb9&07}hIy5}`{WX33o(2;JmP1c`!mdeEjDsp2`U=0y;Co!-ymvP$u5rIied+u(G5aYb}Sr<{0n#~-@-?I zo61eJi!%fCpQYIxtriNhry}_-st!$P6?(t{xrk`}M?aBN!^R){^FPt^Uss##2^~KAR|Ry0WaW(NWcq#p9E`;Lo$bg zULRQ4G3yMu(SSFNcs)<$SQG1q*gwa^sQxet5HUO<(jWm=-|JLJK2ir2t>AZMZfcVp3hna|R(>$}}{ z3^Tjs#yHMFLBQ6K3@0r&@SzieZm_m9z>eGK4K;&Tn*q*hI7_kMqBl9hjf~v|w~e-J?Mc7zSQAyU{sD-N=f_tSG1E3@ zv>*Td)H#6E2eH|8ym1v^8;bfBXMkP$WBnGw4HH&D&`4i>Dig0xQ2C*&bcLuwM(o)i zp@;v*tM$KjBF~WAkP`B4_;7lM2k1$xYtmW0#4@VBgZ?HFBt`CJW+xF1%JH1sJ+_#} zY7?apbmIQT!VC?^h!FwRDe9}po8qCpIzxGj^Rugb;MjTp6&i2=QnSblScB}JqE|1$ z3+S(YHX=-!e=^pzRFC`>Cj4iNG|oABnY2>7rmbi*<^W8!&vj_ zG8~bLbnff>3rJND#9*26wIldiy1c*05q%3QSWat)a;SaMj)4lxD_RZ4VOZk`_0w8S zJFN{K_=FnEhuR8wq)*!_%mPtw_0dT5YJ=@yUji_BiY}QM{XK9dg@WhJAPM_%R|Q z_(tj`Y{Jk)Q}ku~w`)KA`oH(@U4?gI$>c74IX;}32pF_3;ex<#lJY;4gVv(l+Em#v zhqC&zdJO%lI)UFL&?GSS{4=wi1Uu?HA$JHo4v?8Na#q;tMt<`2ntFk7cJ4Z=kTQA_ zWj3xw+RZ?{OwE2Bpnf{{FBbD_6c|J4y{T}h z5%l85GIcPk*MVF+4mqwlQux$-Tyu0p2I8p zgK*L4R0@yNtilGJ%6~Yc(wTGxKRU5q6W7FfaRF|833xsKee@|7>c~WB|%RFL&@;x$3SwS>sBt+4-%FnmPIrd!Z{W~ zb(gSxfJSM|ZZV~Y{1&T}Y77X_pNThbwD!g*o0l79;FnyD;;3Nb3{<} z93L4GPDE|A0nWsc5k~{uI@6&sXRjB*UN)SF5qsgb8cq?MhcQMl1`Gm|=J56-I5^%` zF3q?6)<$Y2a7Xq8Z6?MkVjQ}|CN}=8mS1(>^Q@TCSUjvlgv-uPc`PJF0z11pk z=-)MHud$01V?tN}ZYt4Pz!{`8Ie@x)6&O}Oz>sSw(m5_I69+-?=}RJOmBEYmP3i&o z(h)qlnK+Nbh1KCa+MPnjfrCO<2)I0vCN2>w!E*pF)fqYEJ_0c)BFafgL>Q@OoLf|ri zUnIcy1Yba^Ud?&sD$-f?kR5M_h(1kNC_6h_cF4p}luhPzBZ>nzlg5;-q|1sa4C$$E zqs;CZZdS?YHL9Z=M{=qB%x)O(_Hf5|tO?N#b5| zbF@W@_m=cBxYfp4j$*oGHBDiEWaF$iPTLd(9@$gdrbsa5Y+-(6+lSMi5;!|Nize~) z=vhEw%;*1zOv0BaWN6i+3HXez>JYvFw;hPKCe8PtB@)Cs|4NZK2-2wVBR$ z9IpKr#KUO?+H~G?fY&-DDnovVKRqfbrE~cV=^_Kf*7{FxAf(FfHiboTqu|Cj+r1t| zP?+!B=^f{r#qAMs5R^E>wT|NpME9cY`dl7B;G0Kg`rBxnThZUA)cCqK7X+7Zp9iQf zurxHvbbBkk{JKrOLB(T>tKOvS(*)KCkmRVh3H$+pw*YW&hxWLGr|Y^#?KsXn!j;3T zT;k_8-EV9YSCZ6f260Bg|+f67lXrUq=WWI2n@I^MI+W$p`V(x9;@Du(|*SO~E9?&bj|;*ZSX0RL(j z;vZvScA9fo8vfW7uPXfY1YtS4Ue&1&HoG*z<7S>YS91D2ON<_~i-Qd->t&;K>i+;g CZD3CT literal 0 HcmV?d00001 diff --git a/denoisplit/loss/exclusive_loss.py b/denoisplit/loss/exclusive_loss.py new file mode 100644 index 0000000..2212d80 --- /dev/null +++ b/denoisplit/loss/exclusive_loss.py @@ -0,0 +1,50 @@ +import torch +import torch.nn.functional as F + + +def compute_exclusion_loss(img1, img2, level=3): + loss_gradx, loss_grady = compute_exclusion_loss_vector(img1, img2, level=3) + loss_gradxy = torch.sum(loss_gradx) / 3. + torch.sum(loss_grady) / 3. + return loss_gradxy / 2 + + +def compute_exclusion_loss_vector(img1, img2, level=3): + gradx_loss = [] + grady_loss = [] + + for l in range(level): + gradx1, grady1 = compute_gradient(img1) + gradx2, grady2 = compute_gradient(img2) + + alphax = 2.0 * torch.mean(torch.abs(gradx1)) / torch.mean(torch.abs(gradx2)) + alphay = 2.0 * torch.mean(torch.abs(grady1)) / torch.mean(torch.abs(grady2)) + + gradx1_s = (torch.sigmoid(gradx1) * 2) - 1 + grady1_s = (torch.sigmoid(grady1) * 2) - 1 + gradx2_s = (torch.sigmoid(gradx2 * alphax) * 2) - 1 + grady2_s = (torch.sigmoid(grady2 * alphay) * 2) - 1 + + prod = torch.multiply(torch.square(gradx1_s), torch.square(gradx2_s)) + prod = prod.view((len(prod), -1)) + gradx_loss.append(torch.mean(prod, dim=1)**0.25) + + prod = torch.multiply(torch.square(grady1_s), torch.square(grady2_s)) + prod = prod.view((len(prod), -1)) + grady_loss.append(torch.mean(prod, dim=1)**0.25) + + img1 = F.avg_pool2d(img1, 2) + img2 = F.avg_pool2d(img2, 2) + + return torch.cat(gradx_loss), torch.cat(grady_loss) + + +def compute_gradient(img): + gradx = img[..., 1:, :] - img[..., :-1, :, ] + grady = img[..., :, 1:] - img[..., :, :-1, ] + return gradx, grady + + +if __name__ == '__main__': + img1 = torch.rand((12, 1, 64, 64)) + img2 = torch.rand((12, 1, 64, 64)) + loss = compute_exclusion_loss(img1, img2) diff --git a/denoisplit/loss/nbr_consistency_loss.py b/denoisplit/loss/nbr_consistency_loss.py new file mode 100644 index 0000000..11a717d --- /dev/null +++ b/denoisplit/loss/nbr_consistency_loss.py @@ -0,0 +1,214 @@ +from turtle import right +import numpy as np + +import torch +import torch.nn as nn +from denoisplit.core.stable_exp import StableExponential + + +class NeighborConsistencyLoss: + def __init__(self, grid_size, nbr_set_count=None, focus_on_opposite_gradients=False) -> None: + self.loss_metric = nn.MSELoss(reduction='none') + self._default_grid_size = grid_size + self._nbr_set_count = nbr_set_count + # Here, the idea is that if in one channel we've a positive gradient and in other channel we have negative gradient, + # then that is a sure case of neighbor consistency + # if any of the four gradients indicate that there is an issue, then we need to compute the loss for all four. + # If none of the four gradients flag any issue, then we can simply ignore that sample from loss computation. + self._focus_on_opposite_gradients = focus_on_opposite_gradients + print( + f'[{self.__class__.__name__}] DefGrid:{self._default_grid_size} NbrSet:{self._nbr_set_count} FocusOnOppGrads:{focus_on_opposite_gradients}' + ) + + def use_default_grid(self, grid_size): + return grid_size is None or grid_size < 0 + + def on_boundary_lgrad(self, imgs, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + nD = len(imgs.shape) + assert imgs.shape[-1] == imgs.shape[-2] + pad = (imgs.shape[-1] - grid_size) // 2 + return torch.diff(imgs[..., pad:-pad, pad:pad + 2], dim=nD - 1) + + def on_boundary_rgrad(self, imgs, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + nD = len(imgs.shape) + assert imgs.shape[-1] == imgs.shape[-2] + pad = (imgs.shape[-1] - grid_size) // 2 + + return torch.diff(imgs[..., pad:-pad, -(pad + 2):-pad], dim=nD - 1) + + def on_boundary_ugrad(self, imgs, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + nD = len(imgs.shape) + assert imgs.shape[-1] == imgs.shape[-2] + pad = (imgs.shape[-1] - grid_size) // 2 + + return torch.diff(imgs[..., pad:pad + 2, pad:-pad], dim=nD - 2) + + def on_boundary_dgrad(self, imgs, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + nD = len(imgs.shape) + assert imgs.shape[-1] == imgs.shape[-2] + pad = (imgs.shape[-1] - grid_size) // 2 + return torch.diff(imgs[..., -(pad + 2):-pad, pad:-pad], dim=nD - 2) + + def across_boundary_horizontal_grad(self, left_img, right_img, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + pad = (left_img.shape[-1] - grid_size) // 2 + return right_img[..., pad:-pad, pad:pad + 1] - left_img[..., pad:-pad, -(pad + 1):-pad] + + def across_boundary_vertical_grad(self, top_img, bottom_img, grid_size=None): + if self.use_default_grid(grid_size): + grid_size = self._default_grid_size + + pad = (top_img.shape[-1] - grid_size) // 2 + return bottom_img[..., pad:(pad + 1), pad:-pad] - top_img[..., -(pad + 1):-pad, pad:-pad] + + def compute_opposite_gradient(self, intercell_grad): + opposite_grad = intercell_grad[:, :1] * intercell_grad[:, 1:] + return opposite_grad.view(len(opposite_grad), -1).mean(dim=1, keepdim=True) + + def get_left_loss(self, imgs, grid_size=None): + # center-left + ref_lgrad = self.on_boundary_lgrad(imgs[0], grid_size=grid_size) + left_rgrad = self.on_boundary_rgrad(imgs[1], grid_size=grid_size) + across_horizontal_grad = self.across_boundary_horizontal_grad(imgs[1], imgs[0], grid_size=grid_size) + + grad_product = None + if self._focus_on_opposite_gradients: + grad_product = self.compute_opposite_gradient(across_horizontal_grad) + + loss = self.loss_metric(across_horizontal_grad, (left_rgrad + ref_lgrad) / 2) + loss = loss.view(len(loss), -1).mean(dim=-1) + return loss, grad_product + + def get_right_loss(self, imgs, grid_size=None): + ref_rgrad = self.on_boundary_rgrad(imgs[0], grid_size=grid_size) + left_lgrad = self.on_boundary_lgrad(imgs[2], grid_size=grid_size) + across_horizontal_grad = self.across_boundary_horizontal_grad(imgs[0], imgs[2], grid_size=grid_size) + + grad_product = None + if self._focus_on_opposite_gradients: + grad_product = self.compute_opposite_gradient(across_horizontal_grad) + + loss = self.loss_metric(across_horizontal_grad, (left_lgrad + ref_rgrad) / 2) + loss = loss.view(len(loss), -1).mean(dim=-1) + return loss, grad_product + + def get_top_loss(self, imgs, grid_size=None): + ref_ugrad = self.on_boundary_ugrad(imgs[0], grid_size=grid_size) + up_dgrad = self.on_boundary_dgrad(imgs[3], grid_size=grid_size) + across_vertical_grad = self.across_boundary_vertical_grad(imgs[3], imgs[0], grid_size=grid_size) + + grad_product = None + if self._focus_on_opposite_gradients: + grad_product = self.compute_opposite_gradient(across_vertical_grad) + + loss = self.loss_metric(across_vertical_grad, (up_dgrad + ref_ugrad) / 2) + loss = loss.view(len(loss), -1).mean(dim=-1) + return loss, grad_product + + def get_bottom_loss(self, imgs, grid_size=None): + ref_dgrad = self.on_boundary_dgrad(imgs[0], grid_size=grid_size) + down_ugrad = self.on_boundary_ugrad(imgs[4], grid_size=grid_size) + across_vertical_grad = self.across_boundary_vertical_grad(imgs[0], imgs[4], grid_size=grid_size) + + grad_product = None + if self._focus_on_opposite_gradients: + grad_product = self.compute_opposite_gradient(across_vertical_grad) + + loss = self.loss_metric(across_vertical_grad, (ref_dgrad + down_ugrad) / 2) + loss = loss.view(len(loss), -1).mean(dim=-1) + return loss, grad_product + + def _compute_opposite_gradient_factor(self, grad_product_arr): + with torch.no_grad(): + grad_products = torch.cat(grad_product_arr, dim=1) + return StableExponential(-1 * torch.min(grad_products, dim=1)[0]).exp() + + def get(self, imgs, grid_sizes=None): + if grid_sizes is not None: + grid_sizes = grid_sizes.detach().cpu().numpy() + else: + grid_sizes = np.ones(len(imgs)) * self._default_grid_size + + relevant_imgs = 5 * (len(imgs) // 5) + if self._nbr_set_count is not None: + relevant_imgs = min(relevant_imgs, 5 * self._nbr_set_count) + + imgs = imgs[:relevant_imgs] + if len(imgs) == 0: + return None + + imgs = imgs.view(5, relevant_imgs // 5, *imgs.shape[1:]) + loss = 0 + for idx in range(0, relevant_imgs // 5): + grid_size = np.unique(grid_sizes[5 * idx:5 * idx + 5]) + assert len(grid_size) == 1 + grid_size = grid_size[0] + idx_loss = 0.0 + temp_loss1, grad_product1 = self.get_left_loss(imgs[:, idx:idx + 1], grid_size=grid_size) + temp_loss2, grad_product2 = self.get_right_loss(imgs[:, idx:idx + 1], grid_size=grid_size) + temp_loss3, grad_product3 = self.get_top_loss(imgs[:, idx:idx + 1], grid_size=grid_size) + temp_loss4, grad_product4 = self.get_bottom_loss(imgs[:, idx:idx + 1], grid_size=grid_size) + idx_loss = temp_loss1 + temp_loss2 + temp_loss3 + temp_loss4 + if self._focus_on_opposite_gradients: + grad_factor = self._compute_opposite_gradient_factor( + [grad_product1, grad_product2, grad_product3, grad_product4]) + loss += idx_loss * grad_factor + else: + loss += idx_loss + + return torch.mean(loss / (4 * relevant_imgs / 5)) + + +if __name__ == '__main__': + import numpy as np + import matplotlib.pyplot as plt + grid_size = 20 + factor = 0.01 + loss = NeighborConsistencyLoss(grid_size, focus_on_opposite_gradients=True) + center = factor * torch.Tensor(np.arange(grid_size)[None, None, None]).repeat(1, 2, grid_size, 1) + left = factor * torch.Tensor(np.arange(-grid_size - 10, -10)[None, None, None]).repeat(1, 2, grid_size, 1) + right = factor * torch.Tensor(np.arange(grid_size, 2 * grid_size)[None, None, None]).repeat(1, 2, grid_size, 1) + bottom = factor * torch.Tensor(np.arange(grid_size)[None, None, :, None]).repeat(1, 2, 1, grid_size) + top = factor * torch.Tensor(np.arange(grid_size)[None, None, None]).repeat(1, 2, grid_size, 1) + + _, ax = plt.subplots(figsize=(9, 9), ncols=3, nrows=3) + ax[0, 1].imshow(top[0, 0], vmin=-20, vmax=49) + ax[1, 1].imshow(center[0, 0], vmin=-20, vmax=49) + ax[1, 0].imshow(left[0, 0], vmin=-20, vmax=49) + ax[1, 2].imshow(right[0, 0], vmin=-20, vmax=49) + ax[2, 1].imshow(bottom[0, 0], vmin=-20, vmax=49) + + center = torch.Tensor(np.pad(center, ((0, 0), (0, 0), (6, 6), (6, 6)), mode='linear_ramp')) + left = torch.Tensor(np.pad(left, ((0, 0), (0, 0), (6, 6), (6, 6)), mode='linear_ramp')) + right = torch.Tensor(np.pad(right, ((0, 0), (0, 0), (6, 6), (6, 6)), mode='linear_ramp')) + bottom = torch.Tensor(np.pad(bottom, ((0, 0), (0, 0), (6, 6), (6, 6)), mode='linear_ramp')) + top = torch.Tensor(np.pad(top, ((0, 0), (0, 0), (6, 6), (6, 6)), mode='linear_ramp')) + + imgs = torch.cat([center, left, right, top, bottom], dim=0) + _, ax = plt.subplots(figsize=(9, 9), ncols=3, nrows=3) + ax[0, 1].imshow(top[0, 0], vmin=-20, vmax=49) + ax[1, 1].imshow(center[0, 0], vmin=-20, vmax=49) + ax[1, 0].imshow(left[0, 0], vmin=-20, vmax=49) + ax[1, 2].imshow(right[0, 0], vmin=-20, vmax=49) + ax[2, 1].imshow(bottom[0, 0], vmin=-20, vmax=49) + grid_sizes = torch.Tensor(np.repeat([16, 18, 20, 22], repeats=5)).type(torch.int32) + out = loss.get(imgs, grid_sizes=grid_sizes) + # out = loss.get_left_loss(imgs, grid_size=grid_size) + + loss = NeighborConsistencyLoss(grid_size, focus_on_opposite_gradients=True) + center = torch.Tensor(np.arange(grid_size)[None, None, None]).repeat(1, 2, grid_size, 1) + left = torch.Tensor(np.arange(-grid_size - 10, -10)[None, None, None]).repeat(1, 2, grid_size, 1) diff --git a/denoisplit/loss/restricted_reconstruction_loss.py b/denoisplit/loss/restricted_reconstruction_loss.py new file mode 100644 index 0000000..3d7b51a --- /dev/null +++ b/denoisplit/loss/restricted_reconstruction_loss.py @@ -0,0 +1,384 @@ +import numpy as np +import torch +import torch.nn as nn + +from torchmetrics.regression import PearsonCorrCoef + + +def sample_from_gmm(count, mean=0.3, std_dev=0.1): + # Set the parameters of the GMM + mean1, mean2 = mean, -1 * mean + + # np.random.seed(42) + + def sample_from_pos(): + return np.random.normal(mean1, std_dev, 1)[0] + + def sample_from_neg(): + return np.random.normal(mean2, std_dev, 1)[0] + + samples = [] + for i in range(count): + if np.random.rand() < 0.5: + samples.append(sample_from_pos()) + else: + samples.append(sample_from_neg()) + + return samples + + +class RestrictedReconstruction: + + def __init__(self, + w_split, + w_recons, + finegrained_restriction=True, + finegrained_restriction_retain_positively_correlated=False, + correct_grad_retain_negatively_correlated=False, + randomize_alpha=True, + randomize_numcount=8, + custom_loss_fn=None) -> None: + self._w_split = w_split + self._w_recons = w_recons + self._finegrained_restriction = finegrained_restriction + self._finegrained_restriction_retain_positively_correlated = finegrained_restriction_retain_positively_correlated + self._correct_grad_retain_negatively_correlated = correct_grad_retain_negatively_correlated + self._incorrect_samech_alphas = None #[0.5, 0.8, 0.8, 0.5] + self._incorrect_othrch_alphas = None #[0.5, 0.2, -0.2 - 0.5] + self._randomize_alpha = randomize_alpha + self._randomize_numcount = randomize_numcount + self._crosschannel_corr = None + self._similarity_mode = None #'dot' + self._restricted_epoch = self._restricted_names = None + self.custom_loss_fn = custom_loss_fn + + print(f'[{self.__class__.__name__}] w_split: {self._w_split}, w_recons: {self._w_recons}') + + def update_only_these_till_kth_epoch(self, names, epoch): + self._restricted_epoch = epoch + self._restricted_names = names + + def enable_nonorthogonal(self): + print(f'[{self.__class__.__name__}] Enabling non-orthogonal loss computations.') + assert self._finegrained_restriction_retain_positively_correlated == False + # assert self._correct_grad_retain_negatively_correlated == False + + self._finegrained_restriction_retain_positively_correlated = True + # self._correct_grad_retain_negatively_correlated = True + + @staticmethod + def get_grad_direction(score, params): + grad_all = torch.autograd.grad(score, params, create_graph=False, retain_graph=True, allow_unused=True) + grad_direction = [] + for grad in grad_all: + if grad is None: + grad_direction.append(None) + else: + grad_direction.append(grad / torch.norm(grad)) + return grad_direction + + @staticmethod + def get_grad_component(grad_vectors, + reference_grad_directions, + along_direction=False, + orthogonal_direction=False, + retain_positively_correlated=False, + retain_negatively_correlated=False): + grad_components = [] + assert int(along_direction) + int(orthogonal_direction) + int(retain_positively_correlated) + int( + retain_negatively_correlated) == 1, 'Donot be lazy. Set one of the booleans to True.' + assert isinstance(along_direction, bool) + assert isinstance(orthogonal_direction, bool) + assert isinstance(retain_positively_correlated, bool) + # assert orthogonal_direction == True, 'For now, only orthogonal direction is supported.' + neg_corr_count = 0 + for grad_vector, grad_direction in zip(grad_vectors, reference_grad_directions): + if grad_vector is None: + grad_components.append(None) + elif grad_direction is None: + grad_components.append(grad_vector) + else: + component = torch.dot(grad_vector.view(-1), grad_direction.view(-1)) + if along_direction: + grad_components.append(grad_direction * component) + elif orthogonal_direction: + grad_components.append(grad_vector - grad_direction * component) + elif retain_positively_correlated: + if component < 0: + grad_components.append(grad_vector - grad_direction * component) + else: + neg_corr_count += 1 + grad_components.append(grad_vector) + elif retain_negatively_correlated: + if component > 0: + grad_components.append(grad_vector - grad_direction * component) + else: + neg_corr_count += 1 + grad_components.append(grad_vector) + + # print('Retained neg corr fraction', neg_corr_count / len(grad_vectors)) + + # check one grad for norm + # assert torch.norm(grad_direction) - 1 < 1e-6 + + return grad_components + + def loss_fn(self, tar, pred): + if self.custom_loss_fn is None: + return torch.mean((tar - pred)**2) + else: + return self.custom_loss_fn(tar, pred) + + # return torch.mean(torch.abs(tar - pred)) + + @staticmethod + def get_pearson_corr(tensor1, tensor2): + """ + Computes the pearson correlation between two torch tensors. + These tensors are of shape (batch, channels, height, width). + """ + assert tensor1.shape == tensor2.shape + # assert len(tensor1.shape) == 4 + # assert tensor1.shape[1] == 1 + # assert tensor2.shape[1] == 1 + tensor1 = tensor1.reshape(tensor1.shape[0], -1) + tensor2 = tensor2.reshape(tensor2.shape[0], -1) + if tensor1.shape[0] == 1: + pearson_corr = PearsonCorrCoef().cuda() + corr = pearson_corr(tensor1.reshape(-1, ), tensor2.reshape(-1, )).reshape(-1, ) + else: + pearson_corr = PearsonCorrCoef(num_outputs=tensor1.shape[0]).cuda() + corr = pearson_corr(tensor1.T, tensor2.T) + + return corr + + @staticmethod + def get_dotprod(tensor1, tensor2): + assert tensor1.shape == tensor2.shape + dims = tuple(range(1, len(tensor1.shape))) + out = tensor1 * tensor2 + out = torch.mean(out, dim=dims) + out = out / torch.norm(tensor1, dim=dims) + out = out / torch.norm(tensor2, dim=dims) + return out + + def exp_moving_avg(self, new_val, old_val, beta=0.9): + if old_val is None: + return new_val + return beta * old_val + (1 - beta) * new_val + + def get_corr_based_alphas(self, excess_pos_corr, excess_neg_corr, count): + """ + Returns a list of size count, with each element being an N sized array of alphas. + Here, N is the length of excess_pos_corr and excess_neg_corr, ie, the batch size. + """ + alpha_arr = [] + for i in range(len(excess_pos_corr)): + assert (excess_pos_corr[i] != excess_neg_corr[i]) or (excess_neg_corr[i] == excess_pos_corr[i] == False) + if excess_pos_corr[i]: + alpha = np.random.normal(0.25, 0.1, count).tolist() + elif excess_neg_corr[i]: + alpha = np.random.normal(-0.25, 0.1, count).tolist() + else: + alpha = sample_from_gmm(count, 0.25) + alpha_arr.append(alpha) + return [x for x in np.array(alpha_arr).T] + + def get_incorrect_loss_v3(self, normalized_target, normalized_target_prediction): + """ + Here, we take into account the correlation between the prediction and the target to account for which direction is incorrect. + """ + assert self._randomize_alpha == True + assert self._similarity_mode != 'dot', 'dot was not working' + # ch1_incorrect_corr = self.get_dotprod(normalized_target[:, 1, :, :], normalized_target_prediction[:, + # 0, :, :]) + # ch2_incorrect_corr = self.get_dotprod(normalized_target[:, 0, :, :], normalized_target_prediction[:, + # 1, :, :]) + # cross_channel_corr = self.get_dotprod(normalized_target[:, 0, :, :], normalized_target[:, 1, :, :]) + # print(torch.max(cross_channel_corr).item(), + # torch.max(ch1_incorrect_corr).item(), torch.max(ch2_incorrect_corr).item()) + ch1_incorrect_corr = self.get_pearson_corr(normalized_target[:, 1, :, :], normalized_target_prediction[:, + 0, :, :]) + ch2_incorrect_corr = self.get_pearson_corr(normalized_target[:, 0, :, :], normalized_target_prediction[:, + 1, :, :]) + cross_channel_corr = self.get_pearson_corr(normalized_target[:, 0, :, :], normalized_target[:, 1, :, :]) + + self._crosschannel_corr = self.exp_moving_avg(torch.mean(cross_channel_corr).item(), self._crosschannel_corr) + eps = 1e-2 + ch1_excess_pos_corr = ch1_incorrect_corr > self._crosschannel_corr + eps + ch2_excess_pos_corr = ch2_incorrect_corr > self._crosschannel_corr + eps + ch1_excess_neg_corr = ch1_incorrect_corr < self._crosschannel_corr - 1 * eps + ch2_excess_neg_corr = ch2_incorrect_corr < self._crosschannel_corr - 1 * eps + # if ch1_excess_pos_corr is set, then ch2 is more in the predicted ch1. so, we need +ve ch2 alpha. + # similarly, if ch1_excess_neg_corr is set, then ch2 is more in the predicted ch2 in negative way. so, we need -ve ch2 alpha. + # important point is pos_corr and neg_corr of one channel are used to set alpha of the other channel. + ch2_bled_alphas = self.get_corr_based_alphas(ch1_excess_pos_corr, ch1_excess_neg_corr, self._randomize_numcount) + ch1_bled_alphas = self.get_corr_based_alphas(ch2_excess_pos_corr, ch2_excess_neg_corr, self._randomize_numcount) + ch2_frac_pos = torch.mean(ch1_excess_pos_corr.type(torch.float32)).item() + ch2_frac_neg = torch.mean(ch1_excess_neg_corr.type(torch.float32)).item() + ch1_frac_pos = torch.mean(ch2_excess_pos_corr.type(torch.float32)).item() + ch1_frac_neg = torch.mean(ch2_excess_neg_corr.type(torch.float32)).item() + # print(f'Ch1 pos:{ch1_frac_pos:.1f} neg:{ch1_frac_neg:.1f} avg:{torch.mean(ch1_incorrect_corr).item():.1f} \t Ch2 pos:{ch2_frac_pos:.1f} neg:{ch2_frac_neg:.1f}') + incorrect_c1loss = 0 + incorrect_c2loss = 0 + for ch1_alpha, ch2_alpha in zip(ch1_bled_alphas, ch2_bled_alphas): + ch1_alpha = torch.tensor(ch1_alpha, dtype=normalized_target.dtype).to(normalized_target.device) + ch2_alpha = torch.tensor(ch2_alpha, dtype=normalized_target.dtype).to(normalized_target.device) + ch1_alpha = ch1_alpha.reshape(-1, 1, 1) + ch2_alpha = ch2_alpha.reshape(-1, 1, 1) + + tar1 = normalized_target[:, 0, :, :] * (1 - ch1_alpha) + normalized_target[:, 1, :, :] * ch2_alpha + tar2 = normalized_target[:, 1, :, :] * ch1_alpha + normalized_target[:, 0, :, :] * (1 - ch2_alpha) + incorrect_c1loss += self.loss_fn(tar1, normalized_target_prediction[:, 0, :, :]) + incorrect_c2loss += self.loss_fn(tar2, normalized_target_prediction[:, 1, :, :]) + incorrect_c1loss /= self._randomize_numcount + incorrect_c2loss /= self._randomize_numcount + return incorrect_c1loss, incorrect_c2loss, { + 'ch1_frac_pos': ch1_frac_pos, + 'ch1_frac_neg': ch1_frac_neg, + 'ch2_frac_pos': ch2_frac_pos, + 'ch2_frac_neg': ch2_frac_neg + } + + # ch1_alphas = sample_from_gmm(self._randomize_numcount, mean=0.25) + # ch2_alphas = sample_from_gmm(self._randomize_numcount, mean=0.25) + # incorrect_c1loss = 0 + # incorrect_c2loss = 0 + # # import pdb; pdb.set_trace() + # for ch1_alpha, ch2_alpha in zip(ch1_alphas, ch2_alphas): + # tar1 = normalized_target[:, 0, :, :] * (1 - ch1_alpha) + normalized_target[:, 1, :, :] * ch2_alpha + # tar2 = normalized_target[:, 1, :, :] * ch1_alpha + normalized_target[:, 0, :, :] * (1 - ch2_alpha) + # incorrect_c1loss += self.loss_fn(tar1, normalized_target_prediction[:, 0, :, :]) + # incorrect_c2loss += self.loss_fn(tar2, normalized_target_prediction[:, 1, :, :]) + # incorrect_c1loss /= self._randomize_numcount + # incorrect_c2loss /= self._randomize_numcount + # return incorrect_c1loss, incorrect_c2loss + + def get_incorrect_loss_v2(self, normalized_target, normalized_target_prediction): + assert self._randomize_alpha == True + + ch1_alphas = sample_from_gmm(self._randomize_numcount, mean=0.25) + ch2_alphas = sample_from_gmm(self._randomize_numcount, mean=0.25) + incorrect_c1loss = 0 + incorrect_c2loss = 0 + # import pdb; pdb.set_trace() + for ch1_alpha, ch2_alpha in zip(ch1_alphas, ch2_alphas): + tar1 = normalized_target[:, 0, :, :] * (1 - ch1_alpha) + normalized_target[:, 1, :, :] * ch2_alpha + tar2 = normalized_target[:, 1, :, :] * ch1_alpha + normalized_target[:, 0, :, :] * (1 - ch2_alpha) + incorrect_c1loss += self.loss_fn(tar1, normalized_target_prediction[:, 0, :, :]) + incorrect_c2loss += self.loss_fn(tar2, normalized_target_prediction[:, 1, :, :]) + incorrect_c1loss /= self._randomize_numcount + incorrect_c2loss /= self._randomize_numcount + return incorrect_c1loss, incorrect_c2loss + + def get_incorrect_loss(self, normalized_target, normalized_target_prediction): + othrch_alphas = [1] + samech_alphas = [0] + if self._incorrect_othrch_alphas is not None: + othrch_alphas = self._incorrect_othrch_alphas + samech_alphas = self._incorrect_samech_alphas + elif self._randomize_alpha: + othrch_alphas = sample_from_gmm(self._randomize_numcount) + # othrch_alphas = [ + # torch.Tensor(sample_from_gmm(len(normalized_target))).view(-1, 1, 1).type(normalized_input.dtype).to( + # normalized_input.device) for _ in range(self._randomize_numcount) + # ] + samech_alphas = [1] * self._randomize_numcount + + incorrect_c1loss = 0 + for alpha1, alpha2 in zip(othrch_alphas, samech_alphas): + tar = normalized_target[:, 0] * alpha1 + normalized_target[:, 1] * alpha2 + incorrect_c1loss += self.loss_fn(tar, normalized_target_prediction[:, 1]) + incorrect_c1loss /= len(samech_alphas) + + incorrect_c2loss = 0 + for alpha1, alpha2 in zip(samech_alphas, othrch_alphas): + tar = normalized_target[:, 0] * alpha1 + normalized_target[:, 1] * alpha2 + incorrect_c2loss += self.loss_fn(tar, normalized_target_prediction[:, 0]) + incorrect_c2loss /= len(samech_alphas) + return incorrect_c1loss, incorrect_c2loss + + def get_correct_grad(self, params, normalized_input, normalized_target, normalized_target_prediction, + normalized_input_prediction): + # tar = normalized_target.detach().cpu().numpy() + # pred = normalized_target_prediction.detach().cpu().numpy() + # import numpy as np + # tar1 = tar[:, 0].reshape(-1,) + # tar2 = tar[:, 1].reshape(-1,) + # pred1 = pred[:, 0].reshape(-1,) + # pred2 = pred[:, 1].reshape(-1,) + # c0 = np.round(np.corrcoef(tar1, tar2), 2)[0,1] + # c1 = np.round(np.corrcoef(tar1, pred2), 2)[0,1] + # c2 = np.round(np.corrcoef(tar2, pred1), 2)[0,1] + # c1_res = np.round(np.corrcoef(tar1, (pred2 - tar2)) , 2)[0,1] + # c2_res = np.round(np.corrcoef(tar2, (pred1 - tar1)), 2)[0,1] + # print(f'c0: {c0} c1: {c1}, c2: {c2}, c1_res: {c1_res}, c2_res: {c2_res}') + + # incorrect_c2loss = self.loss_fn(normalized_target[:, 1], normalized_target_prediction[:, 0]) + incorrect_c1loss, incorrect_c2loss, log_dict = self.get_incorrect_loss_v3(normalized_target, + normalized_target_prediction) + incorrect_c1_all = self.get_grad_direction(incorrect_c1loss, params) + incorrect_c2_all = self.get_grad_direction(incorrect_c2loss, params) + + if self._finegrained_restriction: + correct_loss = self.loss_fn(normalized_target, normalized_target_prediction) + correct_grad_all = self.get_grad_direction(correct_loss, params) + incorrect_c1_all = self.get_grad_component( + incorrect_c1_all, + correct_grad_all, + retain_negatively_correlated=self._finegrained_restriction_retain_positively_correlated, + orthogonal_direction=not self._finegrained_restriction_retain_positively_correlated) + incorrect_c2_all = self.get_grad_component( + incorrect_c2_all, + correct_grad_all, + retain_negatively_correlated=self._finegrained_restriction_retain_positively_correlated, + orthogonal_direction=not self._finegrained_restriction_retain_positively_correlated) + + unsup_reconstruction_loss = self.loss_fn(normalized_input, normalized_input_prediction) + unsup_grad_all = torch.autograd.grad(unsup_reconstruction_loss, + params, + create_graph=False, + retain_graph=True, + allow_unused=True) + + incorrect_c2_all = self.get_grad_component(incorrect_c2_all, incorrect_c1_all, orthogonal_direction=True) + corrected_unsup_grad_all = self.get_grad_component( + unsup_grad_all, + incorrect_c1_all, + orthogonal_direction=not self._correct_grad_retain_negatively_correlated, + retain_negatively_correlated=self._correct_grad_retain_negatively_correlated) + + corrected_unsup_grad_all = self.get_grad_component( + corrected_unsup_grad_all, + incorrect_c2_all, + orthogonal_direction=not self._correct_grad_retain_negatively_correlated, + retain_negatively_correlated=self._correct_grad_retain_negatively_correlated) + + return corrected_unsup_grad_all, unsup_reconstruction_loss, log_dict + + def update_gradients(self, named_params, normalized_input, normalized_target, normalized_target_prediction, + normalized_input_prediction, epoch): + + if len(normalized_target) == 0: + print('No target, hence skipping input reconstruction loss') + return {'input_reconstruction_loss': torch.tensor(0.0), 'log': {}} + + names, params = zip(*named_params) + + corrected_unsup_grad_all, input_reconstruction_loss, log_dict = self.get_correct_grad( + params, normalized_input, normalized_target, normalized_target_prediction, normalized_input_prediction) + # split_grad_all, split_loss = self.get_split_grad(params, normalized_target, normalized_target_prediction) + + for name, param, corrected_unsup_grad in zip(names, params, corrected_unsup_grad_all): + if corrected_unsup_grad is None: + continue + elif self._restricted_epoch is not None and epoch < self._restricted_epoch: + if name not in self._restricted_names: + continue + + if param.grad is None: + param.grad = self._w_recons * corrected_unsup_grad + else: + param.grad = self._w_split * param.grad + self._w_recons * corrected_unsup_grad + + return {'input_reconstruction_loss': input_reconstruction_loss, 'log': log_dict} diff --git a/denoisplit/losses.py b/denoisplit/losses.py new file mode 100644 index 0000000..60bb807 --- /dev/null +++ b/denoisplit/losses.py @@ -0,0 +1,163 @@ +import datetime +import os +import time +from collections import OrderedDict +from typing import List + +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +from torch.autograd import Variable +from torch.nn import init + +from denoisplit import utils + + +def free_bits_kl(kl, free_bits, batch_average=False, eps=1e-6) -> torch.Tensor: + """Computes free-bits version of KL divergence. + Takes in the KL with shape (batch size, layers), returns the KL with + free bits (for optimization) with shape (layers,), which is the average + free-bits KL per layer in the current batch. + If batch_average is False (default), the free bits are per layer and + per batch element. Otherwise, the free bits are still per layer, but + are assigned on average to the whole batch. In both cases, the batch + average is returned, so it's simply a matter of doing mean(clamp(KL)) + or clamp(mean(KL)). + Args: + kl (torch.Tensor) + free_bits (float) + batch_average (bool, optional)) + eps (float, optional) + Returns: + The KL with free bits + """ + + assert kl.dim() == 2 + if free_bits < eps: + return kl.mean(0) + if batch_average: + return kl.mean(0).clamp(min=free_bits) + return kl.clamp(min=free_bits).mean(0) + + +def lossFunctionKLD(mu, logvar): + """Compute KL divergence loss. + Parameters + ---------- + mu: Tensor + Latent space mean of encoder distribution. + logvar: Tensor + Latent space log variance of encoder distribution. + """ + kl_error = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp()) + return kl_error + + +def recoLossGaussian(predicted_x, x, gaussian_noise_std, data_std): + """ + Compute reconstruction loss for a Gaussian noise model. + This is essentially the MSE loss with a factor depending on the standard deviation. + Parameters + ---------- + predicted_x: Tensor + Predicted signal by disentangle decoder. + x: Tensor + Noisy observation image. + gaussian_noise_std: float + Standard deviation of Gaussian noise. + data_std: float + Standard deviation of training and validation data combined (used for normailzation). + """ + reconstruction_error = torch.mean((predicted_x - x)**2) / (2.0 * (gaussian_noise_std / data_std)**2) + return reconstruction_error + + +def recoLoss(predicted_x, x, data_mean, data_std, noiseModel): + """Compute reconstruction loss for an arbitrary noise model. + Parameters + ---------- + predicted_x: Tensor + Predicted signal by disentangle decoder. + x: Tensor + Noisy observation image. + data_mean: float + Mean of training and validation data combined (used for normailzation). + data_std: float + Standard deviation of training and validation data combined (used for normailzation). + device: GPU device + torch cuda device + """ + predicted_x_denormalized = predicted_x * data_std + data_mean + x_denormalized = x * data_std + data_mean + predicted_x_cloned = predicted_x_denormalized + predicted_x_reduced = predicted_x_cloned.permute(1, 0, 2, 3) + + x_cloned = x_denormalized + x_cloned = x_cloned.permute(1, 0, 2, 3) + x_reduced = x_cloned[0, ...] + + likelihoods = noiseModel.likelihood(x_reduced, predicted_x_reduced) + log_likelihoods = torch.log(likelihoods) + + # Sum over pixels and batch + reconstruction_error = -torch.mean(log_likelihoods) + return reconstruction_error + + +def vanilla_vae_loss_fn(predicted_x, x, mu, logvar): + """Compute VAE elbo loss. + Parameters + ---------- + predicted_x: Tensor + Predicted signal by disentangle decoder. + x: Tensor + Noisy observation image. + mu: Tensor + Latent space mean of encoder distribution. + logvar: Tensor + Latent space logvar of encoder distribution. + """ + kl_loss = lossFunctionKLD(mu, logvar) + reconstruction_loss = recoLossGaussian(predicted_x, x, 1, 1) + return kl_loss / float(x.numel()), reconstruction_loss + + +def disentangle_loss_fn(predicted_x, x, mu, logvar, gaussian_noise_std, data_mean, data_std, noiseModel): + """Compute disentangle loss. + Parameters + ---------- + predicted_x: Tensor + Predicted signal by disentangle decoder. + x: Tensor + Noisy observation image. + mu: Tensor + Latent space mean of encoder distribution. + logvar: Tensor + Latent space logvar of encoder distribution. + gaussian_noise_std: float + Standard deviation of Gaussian noise (required when using Gaussian reconstruction loss). + data_mean: float + Mean of training and validation data combined (used for normailzation). + data_std: float + Standard deviation of training and validation data combined (used for normailzation). + device: GPU device + torch cuda device + noiseModel: NoiseModel object + Distribution of noisy pixel values corresponding to clean signal (required when using general reconstruction loss). + """ + kl_loss = lossFunctionKLD(mu, logvar) + + if noiseModel is not None: + reconstruction_loss = recoLoss(predicted_x, x, data_mean, data_std, noiseModel) + else: + reconstruction_loss = recoLossGaussian(predicted_x, x, gaussian_noise_std, data_std) + #print(float(x.numel())) + return reconstruction_loss, kl_loss / float(x.numel()) + + +class Elbo(nn.Module): + def forward(self, predicted_x, x, mu, logvar): + kl, recons = vanilla_vae_loss_fn(predicted_x, x, mu, logvar) + return {'kl': kl, 'recons': recons} diff --git a/denoisplit/metrics/__pycache__/running_psnr.cpython-39.pyc b/denoisplit/metrics/__pycache__/running_psnr.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5758dcc5d544aaa7613f63c03e262c2e5a765f6c GIT binary patch literal 1375 zcmZ`&!Hy#}5G}Xeou14r!!9{Q%Ss4|OC&S_3283~tpI_3`G3+SsYF?Ycg_SkaY}kQj^0(O!Bd zw@dy%&qvs11ZSBnh`h@)<(JJI6Ejhck8n(o%h~X;u4Kb$_2!V#0ES(jSCA<1UEbfn zRib6Vk!~Ar;ZTYCUjPE#h%VcTn`}#05+nJ~NOiQtH8wkzA%HoUB%PB{Kkt5|FosO>0&1FSf%$i7E3Uvfd|cHWy%hNY2D7^?KhhI-RwaiLY=H=Uty|^sr Ulkl6i#`4qt?9W(5p0||pFB|D3M*si- literal 0 HcmV?d00001 diff --git a/denoisplit/metrics/calibration.py b/denoisplit/metrics/calibration.py new file mode 100644 index 0000000..04c5076 --- /dev/null +++ b/denoisplit/metrics/calibration.py @@ -0,0 +1,114 @@ +""" +Here, we define the calibration metric. This metric measures the calibration of the model's predictions. A model is well-calibrated if the predicted probabilities are close to the true probabilities. We use the Expected Calibration Error (ECE) to measure the calibration of the model. The ECE is defined as the expected value of the difference between the predicted and true probabilities, where the expectation is taken over the bins of the predicted probabilities. The ECE is a scalar value that ranges from 0 to 1, where 0 indicates perfect calibration and 1 indicates the worst calibration. We also provide a function to plot the reliability diagram, which is a visual representation of the calibration of the model. +""" +import math + +import numpy as np +import torch + + +class Calibration: + + def __init__(self, num_bins=15, mode='pixelwise'): + self._bins = num_bins + self._bin_boundaries = None + self._mode = mode + assert mode in ['pixelwise', 'patchwise'] + self._boundary_mode = 'uniform' + assert self._boundary_mode in ['quantile', 'uniform'] + # self._bin_boundaries = {} + + def logvar_to_std(self, logvar): + return np.exp(logvar / 2) + + def compute_bin_boundaries(self, predict_logvar): + if self._boundary_mode == 'quantile': + boundaries = np.quantile(self.logvar_to_std(predict_logvar), np.linspace(0, 1, self._bins + 1)) + return boundaries + else: + min_logvar = np.min(predict_logvar) + max_logvar = np.max(predict_logvar) + min_std = self.logvar_to_std(min_logvar) + max_std = self.logvar_to_std(max_logvar) + return np.linspace(min_std, max_std, self._bins + 1) + + def compute_stats(self, pred, pred_logvar, target): + """ + Args: + pred: np.ndarray, shape (n, h, w, c) + pred_logvar: np.ndarray, shape (n, h, w, c) + target: np.ndarray, shape (n, h, w, c) + """ + self._bin_boundaries = {} + stats = {} + for ch_idx in range(pred.shape[-1]): + stats[ch_idx] = {'bin_count': [], 'rmv': [], 'rmse': [], 'bin_boundaries': None, 'bin_matrix': []} + pred_ch = pred[..., ch_idx] + logvar_ch = pred_logvar[..., ch_idx] + std_ch = self.logvar_to_std(logvar_ch) + print(std_ch.shape) + target_ch = target[..., ch_idx] + if self._mode == 'pixelwise': + boundaries = self.compute_bin_boundaries(logvar_ch) + stats[ch_idx]['bin_boundaries'] = boundaries + bin_matrix = np.digitize(std_ch.reshape(-1), boundaries) + bin_matrix = bin_matrix.reshape(std_ch.shape) + stats[ch_idx]['bin_matrix'] = bin_matrix + error = (pred_ch - target_ch)**2 + for bin_idx in range(self._bins): + bin_mask = bin_matrix == bin_idx + bin_error = error[bin_mask] + bin_size = np.sum(bin_mask) + bin_error = np.sqrt(np.sum(bin_error) / bin_size) if bin_size > 0 else None + bin_var = np.mean((std_ch[bin_mask]**2)) + stats[ch_idx]['rmse'].append(bin_error) + stats[ch_idx]['rmv'].append(np.sqrt(bin_var)) + stats[ch_idx]['bin_count'].append(bin_size) + else: + raise NotImplementedError(f'Patchwise mode is not implemented yet.') + return stats + + +def nll(x, mean, logvar): + """ + Log of the probability density of the values x untder the Normal + distribution with parameters mean and logvar. + :param x: tensor of points, with shape (batch, channels, dim1, dim2) + :param mean: tensor with mean of distribution, shape + (batch, channels, dim1, dim2) + :param logvar: tensor with log-variance of distribution, shape has to be + either scalar or broadcastable + """ + var = torch.exp(logvar) + log_prob = -0.5 * (((x - mean)**2) / var + logvar + torch.tensor(2 * math.pi).log()) + nll = -log_prob + return nll + + +def get_calibrated_factor_for_stdev(pred, pred_logvar, target, batch_size=32, epochs=500, lr=0.01): + """ + Here, we calibrate with multiplying the predicted std (computed from logvar) with a scalar. + We return the calibrated scalar. This needs to be multiplied with the std. + Why is the input logvar and not std? because the model typically predicts logvar and not std. + """ + import torch + from tqdm import tqdm + + # create a learnable scalar + scalar = torch.nn.Parameter(torch.tensor(2.0)) + optimizer = torch.optim.Adam([scalar], lr=lr) + # tqdm with text description as loss + bar = tqdm(range(epochs)) + for _ in bar: + optimizer.zero_grad() + mask = np.random.randint(0, pred.shape[0], batch_size) + pred_batch = torch.Tensor(pred[mask]).cuda() + pred_logvar_batch = torch.Tensor(pred_logvar[mask]).cuda() + target_batch = torch.Tensor(target[mask]).cuda() + + loss = torch.mean(nll(target_batch, pred_batch, pred_logvar_batch + torch.log(scalar))) + loss.backward() + optimizer.step() + bar.set_description(f'nll: {loss.item()} scalar: {scalar.item()}') + + return np.sqrt(scalar.item()) diff --git a/denoisplit/metrics/running_psnr.py b/denoisplit/metrics/running_psnr.py new file mode 100644 index 0000000..5b1a37c --- /dev/null +++ b/denoisplit/metrics/running_psnr.py @@ -0,0 +1,35 @@ +import torch + + +class RunningPSNR: + + def __init__(self): + self.N = self.mse_sum = self.max = self.min = None + self.reset() + + def reset(self): + self.mse_sum = 0 + self.N = 0 + self.max = self.min = None + + def update(self, rec, tar): + ins_max = torch.max(tar).item() + ins_min = torch.min(tar).item() + if self.max is None: + assert self.min is None + self.max = ins_max + self.min = ins_min + else: + self.max = max(self.max, ins_max) + self.min = min(self.min, ins_min) + + mse = (rec - tar)**2 + elementwise_mse = torch.mean(mse.view(len(mse), -1), dim=1) + self.mse_sum += torch.nansum(elementwise_mse) + self.N += len(elementwise_mse) - torch.sum(torch.isnan(elementwise_mse)) + + def get(self): + if self.N == 0 or self.N is None: + return None + rmse = torch.sqrt(self.mse_sum / self.N) + return 20 * torch.log10((self.max - self.min) / rmse) diff --git a/denoisplit/nets/__pycache__/brave_net.cpython-39.pyc b/denoisplit/nets/__pycache__/brave_net.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ff59e4472d10027624ec54b50f15eedb26420ae GIT binary patch literal 4907 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 J&;SJj^FJ^Fk{$p6 literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/context_transfer_module.cpython-39.pyc b/denoisplit/nets/__pycache__/context_transfer_module.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..681b00d938487d1e2ea9dcb3d39ae574d97b4ab1 GIT binary patch literal 4511 zcmcIn-H#kc5%2Dq+3(%^@O?UtSqLB&?7P^;goINtI3fWhCuBQ1G;uVVo9^A4_3X^L zd)8;4<^X(+IOQy$J!UhS@rG@@OSr+!r-Yk=bQ-IjY5yPD6c*>zs98^RI|UgV`?X3q&@IM2%+DjI*LcgTp^3%nv0 zIOFVh@Mu~^+BUX`m>VvNg%KTI7?I%;Jhc(AmqoR^!fU+D>&NUqvsdjkQR=RPj>b9> zYn-kVK6ec3*1h%NMX`({ys`>kgYn9EoU^;6HGlBO%IzqO#pAenPr9LM3)$>Nd=QAH z7jeOx?I;MMeLw6p_u{y(-rC&U-{0SmLJ3!TdmT3x8=;6d`-9!U_uSZz!p$2uu3fwN z=8ZRQI=SkrKiPMsa6Y`cEn=q~N$012)Ds-!1Lx;GwPsrU*W6J);}R8u^X^Y>*;cC%XpVQ(3>PFti>}XmWg}`9&FVg zfW+j84C#nalF<7`LL3GUwq|T~3ki#hL-3r0bfK?nwv7>8B52Ps%9UelSOK}JmS9T+ zWEfh>3&%LWru~YJP_`a7cp1j$y7Qj`-U$U-P1vX8PlY229!bEC+V&}Kry-% z_yDBSkuE<)L$oz8RP4K)1LQwL-VghM>xpOdqXYJF^BHZn7E((M`a-59$MHiycAS*n zPU(9o-AP#(rsZF{((Q>DB&;|BFGyOk?)C= z#ZimNS8!N3cR!!tszs1cm_G?^!2jU- zY_mU4g@>*;{vnSZs<#4iHEhKYgM(pW8&NQoZEH6@F*5Ut%J1|dpKFT&W;ATtf>H-8 z81$W;RTxxy=g$RbEc)`Rvhd5_M)I8*Yp9@N9_@$D&c%sUG-vPE3*nbu$0^$Pf7TI* zcI@oD`o-3f3BUY0(4)^^M-@$!m<*hq=EOq2e*T8!(q}@a2vhOV{_+=K5;`O!a>x?a zrRX#0I}ez;^b7J^s{5GkGobJF=Y59mGokMt-A9HN=rH0!mY9#&JLKc=&`cPIGztf` zrU@kLb)vs!B}QU$x<)|HlnnNc$y}YdBIz(m>Jzl3I|eI-*s~BHe&2o*L00PU(J1{j?ed z+<7FVg7Z49hGKvGG95Y<2pccUey@RAwE~3D5?#{&5}l_P=?1OQHF|K4E5A^11~@z; zp9A+-c=%oz~s-mx4&SO5r%+)9cG zPz_=6vswYdT@7Jj8p6~6!Y{{BVzQUlkW69tUF^FKVv*eIz%5q(vzL$LEjb z53uVEBtJwlmAh*?u!vU73VfN_nZ+(K>&o_dzj za(vzfiJAB`=@x|8WqR=1Y<$jWIUk^Zfc`HPAc|3@Q>3X=&STzm;_FegpMej zTv+iS2N!}N)0_#Mp*bryyWszL-XvBB&K%B;86+<UBidNvzC%e}Oi@4>Y17U3cX*E(*)B!$_FK=GUX zSLng3vpqGR)1p}doRe4!r4=VHsG+{EInKj@8)P-UuCC>`Kt>;GQfEbtn~tj&_Gt5N zq1?Nuu%6!+JP`zrGqG|kc_db~600OkUHU{Tu|}z6m5lsfFE#M5W$?n$bNvu69H+Nn z!s%~-$PbXik{?XDgdO^b)`#_vu$P^pa%pHjEw=rR@(OhNJIH8(}EtP(@b6=hsbL+u@$sMYw?PMl!Sw6{>Wh=f?dYiUWTaE+xpNg}gQT zK@8s=^!iWWcGlOYjcs_3q4PkRGsYtoV$?4mZ6Qb*o_@215) z;l@1|s)-=#Ozf=AZ2G=X+RAQ6Z=;P0`%R-pOUB|yB`6$_Gl4F$i`EKTgwyAL(z+h; literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/denoiser_splitter.cpython-39.pyc b/denoisplit/nets/__pycache__/denoiser_splitter.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7007cf23961b48710cbdd75c4af483ff2abc7e18 GIT binary patch literal 9247 zcmaJ`+ixS+d7mpe99|_+*S(m&ht5K_75BE?8osPIcIqf@tlH_+?s&vAqDT#g+%v=7 zl`xEfXw$ftZMOm1ht>wjw;CvdJ{CnE`_#XnIFD@~vgu2K0znbLc7NZQ5lLya=78Uv z^PT&5zWaFPvaR6v-yf@c|MNSF@}E?h|K(A61^>v<6on~F4HSpoTA=ncM^jUr?&z}3 za16Zl!0hFmoNP0Ke9v+$SvG@0&vxuy(JA&yPD$c&LAh6PDys5rh2@!bS7DZKAL~xl zud%{`c3-h~{aA69{l)PLQ`+i89j~%t`b>-z3%r)$OVlzk zSou@US(B~BbH||9xntJ-s=wy1`^(thhQHjs(7njip>kj4msv5iGfZ(+aW47#_%bW` zmn8176z&-l)oI9<%EK)w9%E?UxeZ}+2U=WyURby0ZRW6bC8z50e&{Js~q{kOtf9`ATz z{7w{dQI7k(weN;r*z>&*V;83Vulr%Y6ZyPFE6)FntP≤46;G6h~vKqqo7Cd)iNw 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 literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/discriminator.cpython-39.pyc b/denoisplit/nets/__pycache__/discriminator.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62dfd384f6871242ba204b08bbc9ab6ded855cc2 GIT binary patch literal 7526 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 PYpJqSX`X4muyp%hClHqO literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/gmm_nnbased_noise_model.cpython-39.pyc b/denoisplit/nets/__pycache__/gmm_nnbased_noise_model.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac59d4c022e1ce6ff1075189618cc006407fc25b GIT binary patch literal 4343 zcmcIn&2JmW6`z^?;F6RSSye1cPLpl=k+MkXBK<(?xJGNIb`KE|L{1MZjMauaB3Ig7 zQnO1(CaCrx7nTn$TA;VKfC%IwpogCO7vyi)Yfnad>n*2!rc){eGH;ezF-JWPK$Y-7uA#-9SbyS~vSy<4*b}5XqW6U`>G&d0_mB zKV~~zbGXR(2e+bbYp-z!N83u`#H2OZm$oOIG-#lu z9e|7-u@gRGoDGeD^_lwSkOzE^DL3GUM&h6+R@tGEi4$t(kYk=PBHS7=KznG6xTY9G zF{O;GA@ju01S|y%JerMXF3x)<2ylR!lUr%OCspovUYLZL=j9?v^2(On?-%;ZZIbA% zATPfw{k@0p%XdG>tGE2D)oFB9jB!WFGz|LCw3VBwjCS&Bn0T#@pCmF$^M!6doA#EW zA*sUnY(y=CjZ>bNJ+Bq{Y3g~W?9;}zPB)g<{Iny}PQCcM)`G#V1v2S|TfHdE3N+Pd zBD3^bJC401`Or^g;9*iKy_if~?>$tcZEEQT0OJ+z;Aaa*n0$fTzyY7zrNP>H3)Uw( zX_3MvAK~QUx6#tq0fuassZ|&SMjY}HUxTVA_!gXf3-UE;LQATuSa2#7;)dn?K&|1w z09Rmi$JEu0;F7aat+f_Ugx*rj~;CcJ7N>~$3Vg%+R zHWMUPUfS#zk#|w03)n+P#4mtMBLZG+WG3PdejS)k2^aWT{|TpmC7z`vHTTzeK^;aO@OL#JHP_KN&@#)A56GIAX))f(o5mnNr; zoko56{GzGZ$(gB*&Aw1k)O)enzX$5)nH^TLVSXzp1rGjgohwT^S6+HY%HG}0&6!k8 z`DpSH>!f*#mh^7`ME#MCWkO+q-OgWI(Cs{k2pb|{bU zia+8$|FdxfqXaOBhdWH)HJ|cd4qmM5LQh5D7ORoAZ$sD`3I9Rk#%z;>qcXP zHmj|E;Cq=&(yqEFaXIUH#TE?`ma-V*OMDr>!PR+z&t{*Km68b+A0%)32N<-?4h5Ql zW};b-`D0^8Pz*hCGIk89kN7+62t`OHj`@jkj56bhpO_=|L}b>keT>oFQeZq4)IV{K z#fU!KIqra(HAt`94?&Eo9F0@nr;mj&*+1pK;V@8U%@o*>$)*@ zvyMC$I!NMfJA5D$xA3gA;$HaP^A(B#R9W++Z=Zd0tH!&z*WIkETAe!iV*O6k^|O20 zA?Fs*sUIYPRMA5U?-y}1mSb-Dn3K72ohEdJaNUir!6gJ-iXd~?JzkbM%*$IMV zgf~LKej{*AqiSCRwj~Lbtkc z?`8{2{)NT{Z_fvKTV|6-&D7rY8+dm>j+;OxyWkCCAP>D*AgUv@K(CNMFBV089}^2s ze*g^ombFUn$+$NaKwSr|Lo?q7_`jU0jhD@zx;r^lk@0E^xuyK1EsGnLY^Z7gxgigF zxuu;vxA5eMd(HAVQO7Y2jr})dABJm`NF1+&% z{nXR%yLzjuWIfd{dk^MQWX=4wnF;g&tm_Bh^x>!In#*nE61<0W313uPbmk0;XGMGN a+(31Lxi`swQYt_3Fcc`8jFpX*<$nXOjL{YV literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/gmm_noise_model.cpython-39.pyc b/denoisplit/nets/__pycache__/gmm_noise_model.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e8d6b34c23a3d56c0e40a5c267f870701540fcdc GIT binary patch literal 9892 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 literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/hist_gmm_noise_model.cpython-39.pyc b/denoisplit/nets/__pycache__/hist_gmm_noise_model.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ba25e11804dbcf74e71df9338d7eea2b6cc69ab GIT binary patch literal 3343 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 literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/lvae_bleedthrough.cpython-39.pyc b/denoisplit/nets/__pycache__/lvae_bleedthrough.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0459e922272028c4f479ebaff63aaee7f63bfe2 GIT binary patch literal 8061 zcma)BO^hSQb?)kJHk-|#;cz&=yV|8zo3*IOv(nm8tc8%Qq)4$Gd!R@QJD{X=dRa9y zoN0D*tDCdClV+@VRxpBK0UeAWuqB%V*fwz<}+1ubSj= zCZ2UT!(!E|SJhSZ-uvFG*Fm-F8TkC?ciHw|f7vkpgBtUnA{uw_O&&AD;6}&bjGH0r zn;nx;-3qO~-LZAu4hwy!dL#p zK`*%V#@tGXzYA5GeW-5Y`zF3g1x03zjbo_RzKPA6hj+XdKJSTiD5Ip6%AsiWwrPV> zv;usixFtf-7g3tDdJ#HsAgPFwSZ=oTP)Sdq~2aBp%E#l80jVK2?AiLOQ>O>Tw<0gh*GW1E9Vsv`P>^pT%GzD66Oof)>Q zqU=(2{$o!XNr;LtIt=Dza@MhS3~p|l-#4~lUfh0M>e#%%9T-P}7rBdHhp%#vmmjlE zkym&X6qm2@8eagV#Mj9HQ1kc_Z=$cvq2TzfeBZE*P8FxRq1I-?{!TC5{Z{Xx;O`0O zL~{6V`q18bc)OJguf>BjNCb3;h8U+q$JWT1h;VU6E|I-i~D} zj>J4wkJt?kpp-F2bfKjX26*+HG=LNqT|#Qsy_{KZv>jsO?z?F3ZbQ&o_^Aag_G_&b3&jxK^%1?|9~Pjj*LB)vCPb@%+3m& zJt;6FH8W$+O6?;vx$zC-dn_%C9inh^9R{4&UNdG?YeuzZ)Z&a6wK?jPx5&YpS$pod z#BFXIRG8_o0T;K0S zz0~)W*Gqa)k_J&%s1hkgjtw^NbyHQ)2%((2+WM5M`;(L_o1UmFEJ#)77T`Zng@Nov zSg!AP!vL%D=~+?G7rx(il%0rhTdqMW@-h`J7-vG)yV2Xut9bz_aFu-SFv z63N5dl1tzOnAW3M_Jgo@C^*gz`g*#Jwke+jlVT6^rO(!{7G{I;G0)SZwYD;c+3fK7 z3wLmC;KduE!_>mM_3aVMLLc6-Ex)TQJtb5##p0nY=;9 znmOPotQ*^KD4FvyYS-cqq#!LOdG&X+&p06!IMLq2(g?1u`eamR z@g+B>19;b1Dk~IGyO_(jc9u^Say`%|`2uEEPCQJZ8LFfWk{*8kgjX+k+)EgqkSGo2 zGTU^RNq@g^?7C?~)hp)VOBWvh1ygoO*QcKnDkKOkguh4SRAri42&6o##>h&|Ju3qW zlAn5FX{*3NYpX!8LRK-dQ*&%*<}rh?2+OqM>0jN?oh74bjNsWuP701ahj8+U{ekgO zYgE*tgTOv9vtkC^Tt#gg{l9CBock$e1_x$#fz&REx9x7_s`?@peHY+p@m^mQ_k|ds zqK#AjHoEedz|CPr1Iz}f%1VZPWr>FaRge_V004J`fq+=!opvb~t2a>;xE8f|T8A3! zAox+b8*mKsS9R@=rkX_qEMh6;WU8{Ba`J)aMc*VjogaS(i%dv?40FxAZhGu83;#ex@@vM{qe4_uoR{DFlPatz+{;b3|69;cm#}_jJwNxAPhV1P964CxAdI zNl4|1u;_Q&UWaHihwPK1{+oEGoN$jO9ABXcMHso-@mZV=4f*5DjZAL#*r=4kIqyMj zCdwj59@+h59Udu3nMRkha#rGQ2FJ-upOcFvx6QDZpQhS{AF=5?bjwH#jTj~F6pVGv zn|b&xH;uGNBahf6D4%7#X59ZN+AjBo21dQ2M;YVNbO#ud@4AdofKIV8s%GY>hB3z2 z%W7FAtMbZc=CL_i(0g5=y<(+RtkA}7=Lgx`TpGDbQ19B|U+F-GLb2E7PI7zJBFe8r zvfHh9wp$3_=yGru!SjncP`W3Q9v29d5q1&!e!Hx^u(vP5 z-fkRobv4=V4gBa{JdAiCANd2sbz$Of%eb#6ljJevRVuzl#j8|oQt=83RToi!(0pP( z*p(z8Q#DwcfBKYmT^qE#N#h7nbL7y_Y=$9V84L1tWMd5iuFCoGhXu2 za{jA(rn@3!P?hNp2^u<+)+8QV$or;~hUWl4k~95dd=olIqgZE61OeCCSIvsq_?2xn zbWr254R*t>vleim$?EU~b@T9R7b3xLa9?-3(<=!*lA@`ZCvL$PX6!?21fNTI0DLGM zGe$_kG8+&K>lnlSG#DFWD=Qu|XnkqqLE~*1WhK}uE;ygSE;IMEzHiAWbpYe;JO`}8 z&79QTEA5-GV1&J}2Jn!hd16nj$=EB)e@0&!R^@W-B=Qp0RnsUm`PC@oa(lFpRk#7m z|5;WZS8&C&fnz^Qt7BLrIjf9pm4VCHTS)7Bi-;foN85FUJL|@{c5IC58TB@@dXwDW zBKEwLc^K2ksNOs_vWD(i$}HIMe}i|K7qdFn?LM(^jabP%UYa1*-(erkk*#^Wtck$h z%{%%rdE%qD41zE>j(jnQffh9`?hSYR`!E>4A3QuPO>4K|#>3pimUd*oeR8or z?vp7%VK`8YQ(_tqd>%iDlo?93G`;CeEsgFXi#isYL~{A0)l>$!T`lFK z&a78{fc>-==#sysV>T)S2%xWH-h-hse95x2R?8BFN;9Z=q;8A~D>_Ju@(N!h(r^yP>2 z@Qzoun^+xdk9oVU%x8y6z@nPr@b*$J*^LEI0gaIFCw z(1f632G1)Md&H(WvPA^_|&C{62G^@xoZ$wi=Eo7CYH_7-^Q48$&Q zFI${KY-Z9m6(IUIkU|68fK_Vk7^6noVI)kJ6w2p_Lx z&0}15v92aydNpfugsvoQ0QkS8YkTW(AvUi*G2y1@85_K|jyo4>m#79u2Kx9i*4_a3 zGgEFo<1*HD1(aNJHs-02q%xZ?pj_5Lef=2e|8snW8Q-GjgL~x-;?tM!r7cO;Gw&!U z%E=+uJqU7~mwy79DpPZSe6k{Bv5AXSa8HCUPl@z^ zDe+eOs_YWy45THerl3LxliO6=p<)KTs+>=#7o(iv0H`A-#9NvuT?|l#ZiuX<22V-x zlZ=V#4dMqt_ITUBrK;VbltB92<>evlH;AdMFMWh!;em3H*Ax-gV6Uuhke=RF(HsnO z2e3gwtq#?Jnz5YZp6|u*Hxn3^2`wU}Vg|P|qb9+ad`QJ3Dh{dma}>&(z$axw2sJz9 zTmbq&=Nq?j6#bY+{w0kp2VqE_a1e?_qp5Q8mU1zf-|r{lJhU!Az&)HL?#DiX>px}GgtG%+SCPdernP?D=yXP&>)QNkrO$wyOIqD{)%FQ`Vs(yLX~Nou((pqT#LhOQG!g$mlt zGQLR@1@dXdM%gX6mRENdy&K-E?n|13GShuTh{#Mc<&mN0uh0l2^k-7Jen($@b($$B zef+^49J9{*ErD~w_g}w%LbupS>(x7L`=o`o9(;0#YGV{_TmFRVI%!1&P1UqR`}Htv zwZ9~P2y$nQ_mXs&_V88(FYo$zSAt)9#iz68s(>JF@JL!&=KM^$pI{K6fF93ax&9OyTKJ_VJD4sms6 zRiALK0A@7kwB`oqyGW)3C!6}5mRAU*3?3oA#@y*wZmFWg3q0iOPSe+_pkI&&m07Y-T75yuEnrjNAMo&c#EefRR@6AfGl=#pk=FQBTnK$pf zd0z}$tp>yQ_h0hVR+UFNryn9fVK z!DoEhk@fO7bNvO2um1qQsA_6KEvh!|SyJu6^58Kk#!UZ7)|1BGyndYd$8i3*Y^Y-v zw^G8sJLCQdwWLn$@{b(EgU8jW!Q;Dvvkm5-Rp(?~oyUo#!4tb&g4(XQ z&OZLJ|71zUzhKv%8eH^$gd3h*V*bYMx6zG z7VSAXci;I)_?P@u!po*?-DB$Pb+*gDw_^=E#PqVdB-_hOt*tQVYJJA0S7ywAUOg}8 zw?IAn^H15Y=;RC27uBU1KcGzWH9P-*=!nd-bVz%hA8OCa*n!lf`9oR-eqPNDUK+eC z7i32+-WM~zkDIIhu*S>%XFwrmw13B%49&7{7KfJ|mZR$@av1tozslvePa% zHL297myYhG-sj9^eicm3nWcAe_XknFc^zE6os?JZUqLrj z&}wK7TJ{%!oK1P*%=pB~Md9r7iCef+XU2YWjkCfTxP!{TE8Iafs7Yq~y5#8HpdkhI zgSnt79gAsw0Katc+jTfgI_oU^uJ?iBefrpveIEmBVmXfA2#4E<8s!H9O zdJ^=bI9EC|t_<_g)IccJplgl~$8jEIy)afmoNj{)Try5_Q?Xo_sw_5%pS*?8ig8S1WBrgVI1v*#I!lDlJFL8ijvVd55jn~ z8D`^QkoLh!m?SFB%&{a*f-Fyg$nvNc+y>V;s>v2iOWnzJ80^W_tr#~`ao^NQs9>nV z1eQ+2ESJXXS^bzsqP8Iu>FO(}GzfZem}Nom75mRSYn$m%t%cd9$~ITaZjH=wO{ye~ z-W$bHUJf%mOjMq&#kWHhkU#Blu{ye|kAt};T6PkE@dmGH|u>941 z<@M+l_djw664|-{Q7zb%6$tYmiHU$4aG0qm5GG(q{6^Q&r?5vK12ENos<%TeyRJS> zbAD&v5~SgQK2IB;ByfSiQvkFrvknNRcTPQu$vv7kdc@HFSH*yQ)iRl5kTbBwiOq>q zuz}E{LP&msG9mkn@*sYF_XLCgItMuMndplX@Y`iJsT|<3yTp?RuQ056IXteY6yAoA zLOS=MhQfjP?u`eexd$8oPUFaE*sYYR=C3mFuQ* zE6lO9uxG~y=iyY=TzwZS>lR-5zAB#s?Q>{Z8-Vd9_rwZc;ivf`-?{K8r5;e<R#aeb&ZIi2P3oA}i)v9TyqPm;fO}~)2#&M{O_Det7ySkIyZC|3e{vR`Wb+mU7?>vZ>n4H zY1qy;|JeNci$DJRuUEB4=p~H+m}I#g+qjD$nPsrD8lsdMAxhy~Y>}pg(1b9UY?MM3)KPCyVDA>M8v zvQak3GSk|_Z>wlyGdE70Zs=Eujn@dgZplfNhsaQE>qz=C;p*0lf=J%c7ir@fA)9v& zvVoF%9Vp*JLJ8vaz5a@+<}$DeYOdtoGGX;$Y6!k1Pjm?Bql{q(f$Wg_vs{hnX|tCA z81EqVHWAns`Qmp?F21Wd6puZ=4F7B(Hg~Y2L#upI2;jYMy~@t{NBQf)1Jex@c59US zl5nVy`Wiuiv^z$23rsTzK1D7sS8R5$4^zJ2&%l&v?d74KisK+SB+GfMmXVnvEB&{~ zs1&M+W~b@48=A0m>kzgU1hB-0tq^Q}vj%PLyDQB6zHtR{c$ZTDaz9E?UmQjE$PxBG z3Zs+;Y{puYrF8RvxUwwc8nJr0d}I3(51*s)MjT~%FCC7q zM%eyOG^T$+;6nm006gdrpnD*On?*Y+`kMpkV9vVxx^byswWW=j%qv=0@zDD3p08>No z0WbZ&--@Fx6-S$CDv8}WGE6GUpgrS}{OJ(dLJtXToY2-4<{@DOuSb=K!cC11Im1J9 zs=ZM<*HyCD>=S^dsEHaJyXkbUQNaZd5gyX*3UH_SNjQAlb Zv7;Q(E^>bKE}eXWH@*}9bzM*u{{x2|L>>SD literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/lvae_denoiser.cpython-39.pyc b/denoisplit/nets/__pycache__/lvae_denoiser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a4b6770569029673c0ec243f0a2e9f7cbca0eef GIT binary patch literal 3621 zcmbVOPmkNi6`wz(L}|6_&3d!DUOP6OxGt0$TBPvN4H6`E(4g2uWAs269nhSSM42Mx z8OmNSv?$QEkzNA$0~CdnTkib;J@(w=poaqOWzlcYL(unzk}P|-4Nwvs4&VG{-kUe? z{T}1>^(KMqU%#c@CzlEN2Y#$xb@=!M9`kofh$NC`B*Hh#=#WK>k}rtl(tAOqr`Rcv zxbmd`n7yLavr)TeV$pMx!0Isdi53Ll*5ud+LhX9qgY{SQqil^Y}^*E1|BHb-FCNsy3(B z)Ky7l;7jPgx9pSYb-4z*Zh$mYH=uVDG~JX`(w9t#L3{9y<0CJL1I#OAhtFY)U7Wmo6W|XBc(=D9% zE4!*eA7h=vV6nU{kdoMqRbHd-!(RE*J;-J@Sg?0bsZc zoCp8t=7FVe%&)#3KDQ3t05sFB3Uvip>HpHcnD5@fYir>f{B@7y8T7bpI&DV_^jw?s z$N$*t>bSFgG2gu}&?X6_!`k5)&@E{*yEQgSjPs<(r5F}ciMX_lDgi{&Z+q5vIbr!{ z{g1HuspWB&X(aXIC-(~-R@gh?GZm_%kxI%iEyJ=1AE|Jh=Y<}|S$eEwCq%FrC;d>X z*c7>0onqpl3K!tGOp8410^F$%<6O?QbZo6scLoVWH0F~IuxUWk4ynW%klM!C^;no`ZmADz^<8m$4YCIJb54WUSP&vVoJCQnqW>Gb-!qEnI&a8e0P= zb<>{4w6=U`dfx$!36W&6F+zMt{{8tuzZj~6*z}d@cdFMx0u~%N{a+zBR9#0C2e~TE zLH0COVs4-AjGpTaSbhy2a~B%Ic4(7r&=&RRb$W;1Vc2$PNN<5`lWsv9!oAu%-akim zorOmdbll>?ji3)dgU4KlfS5ouRSfZvov;(+AgIKTnLeDb0hJtbfCG0xUINFkDVvcK zZ-Pw3C1m3^=97oLU6AL0akGK5^wESbbBDiV7|k$`O#KPex)YXTJ`$|z`r9QEW?XK3@FiaV@Q zuY=DegmyVaEtl!A9q3I!KuGrEk+Oc06}fV8A}iNaq2gSle+-8GcPC&t+=s^?Wug)S(TZXD`%K|ZSTzGD>i2#G#XVqDsKDTQ0XAL%qN^?PUsrj1L1>L5H|B4b&W**$@Ne5TS~ zzf@9W>0|h#?H7f#H8>-n6YIJ1$e|#v9N03iY;doNgpZN=T)_%hi*J6>qydmki`9T! c?qVOP<{I6Hw#oMB-uIr@qDVqb`XSu^0a>4Oz5oCK literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/lvae_layers.cpython-39.pyc b/denoisplit/nets/__pycache__/lvae_layers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b28b0aa87a2ef72ab28710a1ebd5f65507b0775b GIT binary patch literal 20328 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 T?-<7xzdT=>FD-t2{^b7!=WRSV literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/lvae_multidset_multi_input_branches.cpython-39.pyc b/denoisplit/nets/__pycache__/lvae_multidset_multi_input_branches.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89c15b5149998369987ce7f6611999315b46ee4c GIT binary patch literal 7176 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 M{;{oNK{}ZK3-n5P)c^nh literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/lvae_multidset_multi_optim.cpython-39.pyc b/denoisplit/nets/__pycache__/lvae_multidset_multi_optim.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..691d9e72dff7e0d9fbadc5d790091e0c17e35c55 GIT binary patch literal 5511 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 I{I#tA0SU)A9{>OV literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/lvae_multires_target.cpython-39.pyc b/denoisplit/nets/__pycache__/lvae_multires_target.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..709d31b1ef037def0812e4cb077693593f209365 GIT binary patch literal 4061 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 U`VWjhCFjP0+fqYGF3c+XKktOFf&c&j literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/lvae_twindecoder.cpython-39.pyc b/denoisplit/nets/__pycache__/lvae_twindecoder.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1b857d1011352f52a9291211bbb0c47d2622b65 GIT binary patch literal 8249 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 literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/lvae_twodset.cpython-39.pyc b/denoisplit/nets/__pycache__/lvae_twodset.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2d054dfae003f1a77e04d6a47debcd6cd07400c GIT binary patch literal 9029 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 G8U7#jt(oiq literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/lvae_with_critic.cpython-39.pyc b/denoisplit/nets/__pycache__/lvae_with_critic.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86aa94f1f822a207c463a605a2fdf4840cc46426 GIT binary patch literal 5106 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 K!^LA7y8j1UM+*`F literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/model_utils.cpython-39.pyc b/denoisplit/nets/__pycache__/model_utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e32719267febf851e32086e544fff7b7b1e8359 GIT binary patch literal 5191 zcmb7H&2JmW72jPhDUy;XO0pzNwk%5iq#aZKNSelRKJ3VD9mq-$xlTK1u~>0N;!3m2 z?d;GW0)+x`P6dJ*J@k;afL!#@-g@q#haP(DAF$}D?Iq|xP#8J%y|?6&l%*hDg0pYt z_hxoJf4?{G=xEV^=RZF)H?N*BjDKOK|H(n-efURTnufs*Zc2kCZMoHoc3qf4B16_+@EE$WDml07cZ`RCbrvM1yPzsjm)Ps)q_C3cDIWAZisGP_Lnl&ty7Y?OZ;^dM-tgaMZ-afBpXBqO zo9re(#TPy|*gO1;cvrj!KYROqUipp97x~iXS$2z?>qhnLSGa0xRWqL06545n+|`0R z^=7c?Z9!>%#ntYEr=dW5wHZYnyKukBh3sUCx0U-ytO@<`D!7$bM9}miq1Hp`X)P3# z6;@r&g?f1F4rGp}nNL04xbHm?{1X9Ri~yTl1s^P45hA=3)Zr^we>|IfU}X zwEPnhY30>nN|O<4)v9Z+8GzGF>a;F=Z@m=?^$2E-548K>u@|hs+$6J5?o@HbgU8Jk z7%TYB9W1-+1wyw1FTmyNO;M-D!484XSlW>fl&8Hq6iuf^k6|g+wWsTiq`{MiBiGio zyM=qC++Fm(b+Uf|Tcd8{M(aGt9YgT{0R9on7)IOJHnvS|ZD)2Yb(fo%e`Kg7D!2FS zpafQSKgTVed139@dZ=x-t+vs&+Zk?uk=@Haw}M}#t>mESik1NVhaMY1dt)mD`cjwsP&4>vT6cWMdTy#YJu!g) zHN__hzoCx};J-`pDZ-ha9>70K@fpH*_3;6GBgJP4|5DEl;I~u!1mS->o)qgETFB1B9eW?#E>DPEJ@pxu^Mtd1{ z?hrR#SkE)+At9Ida=Ny^+|Io)_lB?pJo3B%dpqCGgIBFR#EY}W{uMs_!ZeLEH$u7W z_SK|>7x?HG)?PthFh4Ogpkt-dKKXH6FfHMv3t195MJ9#ev#N!nonZKez6K=#ap%PlTKsnrb zEWE9Tj-1fd4YqU$5bb!OBfT9Vy+*Ui@5aSQgW5P82y%C!2h>7WxxN79aDd8cNxQrA zM>=eHF0yehq1u;ot4)`SZa+6w)34NbLS5mWdReTvx+216y>TPX(z|*+&eDkDBE1|O zn99P4Q_*sTI*EB3w9$<-!0{@N`7Zq<9j7#{CIM12h)<@}yq;>A8bi2@@To)KbzoU3 zNPJWYJt4L-;(S+M6^2zQVY?z>W_27(d%fvXR8>HzD>YDIKx)(kqEo$o5YZ=Gu4WPI z4FUB7hQAJjKZZ!J_Z?(VdesOz&8JNta7soviasY+AG)GX?e7Iz1d*qo-fC?r6bgtz zIst_mhO9#2P;;1!Bid7>UKdg2NO09Ox^%m7>rT(5CzEOleF}G;)CEKY%|I<;KC7Dw zPJ=CBGsT&(8OCF1I=w9$XG7%$x>}5LNw^djaDzC$aDzBcW~4bC9<=~Xs`J=x5%;3A ziH8L2hJb7nT47@cPDgAye>BwhpvueJ%Z;Wlmfff!qDC!wEn`fu%yD8!aT7Dbh-(=R zO|+bB=9czkR12TRBXuS4tWohVnnkN*O@mcF^k0VZqko6hn&`F!?Uv0v ze4%9K;9s&P%xO#AgYVYiR**iR{{}_}6b-C^v1RO;+Smu>WQ^Sc)LFw_z!&nK(~t1bh+ank^l+be!MxzyU~!RwPNjkL^uj)QsN% z>g=v%1AvIGN2YB~m?P$#sn+SE>SK7R+nC^B;~cPOO9geLo9=@ZkzQyveh&tRaY|z^ z+qSvYGSoI`6uuv7ikJ3nm?embxc$uf#T=*#L`kG7nNQ&cWy8dx5(MR|MzngxFzNRr zNFjpCJTvz)I^Tx5YlB`uR8?pjP&TBC(8drbQ@(BQ54ZC?I}57-Dl>w*#)qIJ-={J* z%ywb-MzI3VJzc?L5><3Vbd-V^7_+?@LM|3{IAKqz5-rKvZZSDVwQxtqmfBEDFnDza z6Wp-s93<7zxa3Q?o=6Gx;jl)r-Gl{k+(XOLaP&YCA z9wzTYQY{`>6m<(BJge#Or zZC-$Mq;npoP4#2Is^(hNT3f5$R;!RxKg5JV5|4*ZiGV;aK~yoCkF8Kr-{U+XwE#v9 z{~00yI{CF^0v$T_H0*eG09B$!yhIv@$L>{J!W}QsKpXM7gY^%HBIUd?}8}Y zBvx#(uK~i7JZL+08AP54ogF*qCm(_C;z4+|351*tDFlc0Znm}>By+5CSQ8G1i=;>{ zk|ZZ={s_0^(n=b`t{>{-<293m&^cr|UI5(Sz<}YdDI$_QcJW))Y~tNhq5iQeM^}K` zrqk)V6H#Q~Kt&1+*tu_2EuwgXojKZB30Q6l4Jj&NwL@LOt8t19@gO6xG zf?&gm(u*xc8%HdXh5(8u_go5~*vUh?p&vJK`Y8fo=fBCt*-Wp&r0?wVH+uKRmkf{M zh9mllS7N75S7nOxzR4}3h>8NVBl=6NC2r0&2reMv#>nf{P2W8(u%SCU6=R@R&rJ)D z9)^uQ%8N6wUU7C4h)P5B*kzRaP2K{IL>}tnG-5Z>w){;v?BMY(DrSVz1x!X<20Uhs Y0GIurzfAFi{4i+G*S2YymSunaKe5~NkpKVy literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/noise_model.cpython-39.pyc b/denoisplit/nets/__pycache__/noise_model.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..70c7202d751147a4a19db10f4ac6017313ae79ba GIT binary patch literal 4326 zcmb7H&5t8T74NG4aNA>hJl@$Mvk2A^A&XJu$qXnWs}QY{g@sjigtQS6eQA1K?QwhB zZByM|vR03f)*A&O1@?#(MVh%F1?9vafO0^bIdJMj6p7P{3+E_e_`T{LPtWW`3AU>G z)vNba@4b3etS_Vb7~4U!j*B|sVmqF8{?+aRInAUj$2NPX}2^{5%wcZ*uFJd zTj)+(R7LHP=3El1Vnx&+F=t&gL=%|Hg5A}+ttYTf+wHQfdS@d1@XZHPAA_}JF&7~Ub6{?3fk*v@t@J9Y=nHAJRG-b};U|d3B=c-2vz#vA+kQk{h_=5l83PNoj zTB&iw4$QZZHU|C+ooP{PTZ?bJh|Ng1@5q0iG*w-W*Qv?(iRtu~t*04Ssm|9v*Yx_F%d<;9< zX;s-;gRKVHl&q%J1w&t3V7o)d$5_uPjq*X%1m~rcgNL82qr1L4U+GVxL9o{w#giyw z(%JBYaQBKT@8%UMPDFOukGy-x`?FJT&cAVTB6JjOCx`(got#=^&%_U+WauYB|CBTC zd!au!I?w*FldVrt1EIRmH1PV^-%pUq$IeC~y&!U@IA)4jRVnA+`WY~VHiaRb_xvE* z>&#+bVCL67Bs=ZPOp{blC2gjxBD};Cft*+0@?-?^>z(<_ORzumqR0>3egDD98U~YD zBsxKKMpy2x>z!^(UM0~T>S*ggejt@nV>0z4>^}0S5l%dj8Khc1Po&p~RNwQH%$&*~ zN-|6OzL(?dU!FAxcBzV3>%RyrPBwRbZs*Y2#8tj+28|XB)!RqWg z+}4|Hoi`b0{FpQA*kbF)25@zDg}0c^48D%OhJPF14fHj(&Ysuh%aC!VUecMlte0=& zY!r0HY1oRoOb8mWCBzebWY9*D|5P)k;5a2eRj?&=z+qBBIU+9mWWyxY!&;6(Nn^=M z$`kwlX=vsvJn~upP zrvn{zKki=6Ol70Ij^dKl6znE=9!a_;W%fQWL+xJhGpstl&OTI*N zCM|c{sYGfWOJFCT*m3IlM4|5N?KxY;iB&#@-+;vUcj%~+w@|O^>OO7b&2kZhn>Olq zQ&CzM!g%fQ4a~Gz8|MMh){9Y#wG_ryeGNU)tm7QOj6tVFjoG}${qZ(ykcIZi;;RG+i)Qot8)sa`s?ksZPc#)4-$B5&j0`b literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/splitter_denoiser.cpython-39.pyc b/denoisplit/nets/__pycache__/splitter_denoiser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a07539bc340b2a9c2cdea7342c2c09f7b9951839 GIT binary patch literal 3268 zcmZuz-H+Tz5$|q$JhpdccW<-oN0Lj-B^MYFvzKrJgt!xsz#Zt6mz+3Z9kLvE&yHt3 zw$tv}uq%&{*r0nt@D4~bkNKDSm8aFc@_-ORRJFYy$?kZ%U9PUKE?51k%5lH%6Zn1o z2RizBkC1=j!{uKW9)1d=`Zpzn6HYS{;+rYq1RZ7I_2?^IkZ?VqFK3&qq zJKSrorQL9W&sx5ZD@&WN{GEjxX4SiP4@h0R=Z5gahPWZtz`jkfHu=V6i_;mA|K(op zx6j@-3Acr{*x|m|HoV7=zSJ*F63{1 z_KO6iFaPZJq53rtf`pWlkZ~GX`+%eo`-+Sxx48Yv1N<12gdN`H?kf^HX3gXND>v-& z72X4$`xUWC=z(2*z5cAsQl*4^BJv`wgp3~mQ2hXYzfu8jm{p+0BB&Zk9uzZG&eSmY ze4JJR{LP|(_uxULL>Z*HVU=kqvNRV#F>3aH^l__iX!L&}f^mE(f=5A7sy8CltDBS=Te|B+g%tIjA{gv zB8o0pZ7t~uojbL&u$JU6JBW(fnb=Y13&?*Pt`m!reElJ*KKy`CbNv=(<(!a3x283# zo!YKD%MK+qS-7<|@h1L~)+Act1meh^N;G58lW3A&on`>5EE9?GtM(roj6F#crQKPc z70H3%+UBu}wF`oUjFPeL7@ui3iqbq)QKb6@pKaKs?wEHE@0LP=i+6X zB(EV!qA1DYs*0l5tAy#>3{emw<{rgCGO#hBU_Q!H8^w@7;F)R-;CuF7pWH6G&G(aE*Je9|O5JPg8 zMKb=e?wI>8q0DtuApuJ^xba&OrYL01&bG$~dYmm>{sk0DvkAm4_kyj7UV< zz|uD`AzMW}YMOwAZyut%P`F>lk^{UAr0MVF4)8DVD<8t+9*oL#GBEsj=Zc}Nk~d65 zaWwBS?hRl%GZC-{h{QCTV1WfRa=P1;LTzKA8CY^1GAz5hF{~Cfsb_*K?QZxkFc)IGNgM^^kNog?MgR_ zc#%YrsXqZ3zyp64bOGle$O^5XvY+a zbreAY`KG3tW^f8^o-|#9=}wwMN7qhMbx+Z81N#*98Hv*XDU5-(rm-A+Ti!?7#_t%@ zaU_CLV)xVAOtH#WScQo{t#7k^4YXJ(kw5-?_QE` zv{l11ET0$fwmZm=&758;@lxQ&2sF|Ql!gvO8hV~Y*l7zY{iUd1bOiS&4W>TE xI95M`$)!E!GMH)4TK}F8)xc#v=nWsj)uXrRO_+VQLwEjX+aSYyNW<^I^?wLAZcYFI literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/unet.cpython-39.pyc b/denoisplit/nets/__pycache__/unet.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1612677aa9db9441ab57e6d8440c82240fcec33b GIT binary patch literal 8698 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

    )u0FC{LTqY&CxkI5I^bttkIxYMxkD z(gL~a_A2R~ESkLShu4}WV*ciY zEcxA+JQT@Gt<#@HH!R799GRaG{}Fw=?nk?ME>Ef%19x4Fl6k!;-Z)X`_E&Q5e4d0j jc?yN0S2ao{RpG=|5ermN63^TE(p$<~$~-|Vc^mS-fcW`W literal 0 HcmV?d00001 diff --git a/denoisplit/nets/__pycache__/unet_parts.cpython-39.pyc b/denoisplit/nets/__pycache__/unet_parts.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6bfed471528e6e17f53bd3ec04920f023423b5a GIT binary patch literal 2927 zcmb7GUvC>l5Z~R~J3F@17MDM1C~z$m)D?{(s(7fNf~Eo z8~&p(bq6v_++m)N)a`C}JIaUSt(724x=9p=D)Qs*gJ*drgW=6hc(uC~XItIGS9vJA z;}jGqyb;=189i$p!(~Y?Ksn#g8Q9bf5Fr64kUkT%Z;9FqGN9(l3w>T*v~Ry4ob(;I zKwUTPW#g?lT+7lYlPlK)7_xYrM_KBAeaHRnZto8qe-3}#?6^1F)m~6pLTfm0LARi* zA&8vpkpp@N&Mqv~F4(S>vjgZ4c|i*c1A`~ow?S(c)**#|96ZxL&Uj%JaOP9bu=!^W zoq~8ZLEzlA-Z2_IrXarSSi1QrlxY}yDw>44Hu8mt(rwMRB42HEsIEonDE5O8?rW>@ zD3rSHc~KhWo~K!w>c)EbcpRoVL_<61idCVTcl|sV_A;5kf};m?Qy5=)=%o(VT!ryK zH>1=GhJFg>m2PF@d~TIQ;$(G1^@8UGv9FZp9g%;(?GCdf?D}dLs^LmGbOQiRSA=O6 zt&id;FQ>{(0S4+c7$hdhIq2#F2tpf_!|z?%#@~OFi?hhCRJRQnJ~?eTM=!2HSGZR} z4oE={={h;0y$+SQ?Gcl2!Jz4md=JJ_ETN`0$mCOB3REkzFP*gKY)=2~(B4rE{hj(r z2>xz(9;C-O#(B&09*_Na`cKXCL>73SxtF|*HWsHI3&J>tKV~O*2hW1XkZ8FHT{$4? zl(TaSMi;>HRKu%cQ`bSv=ZMJ=K<4v0WC-NQb2679j^_8Wr|G1FQU!htz;d5L7Q2bR zGs?0U(>`@eWVncopfZHUaE=GV(HNekNSPW3T!6=O8xn-=u|ozBcMQZ??-;MvsmTQx zN}u38C1#vnxbN>g0PCy5TvoTHr!m+(vP{fm8y~-j!nn(L&-e_3{ULN^vKfFgS;XtT zF-+to*aU#`3EEgjF^iBfgh9Lty~0P!n3*C&esKDYSxi5MKiGM)w0qGhs&8YjI5Pt_pG zMh7%Ug}u*b&+g44@ATv~u%YW)5uh#f&^g2*WtQ;GKxdZ#-kE8909A(Bjs&KKUJelg{z{&&*G;88@~!fs8}PE@4U^H=%l$hnn4MXUp4e0qInIv`U^zGIJJ^g;wOxLkXZ%aIxevru+znivnrX)G2utXEW}bF&W 0: + branch.append(nn.Dropout(p=dropout)) + + return nn.Sequential(*branch) + + +def lowres_output_branches(num_kernels, final_activation, dropout): + blocks = nn.ModuleList([]) + N = len(num_kernels) + for i in range(N - 2): + branch = convolution_layer( + num_kernels[N - i - 2], + 2, + 1, + stride=1, + padding=0, #TODO: check + activation=final_activation, + dropout=dropout, + bn=False) #TODO: check this + blocks.append(branch) + return blocks + + +def up_scale_path(num_kernels, kernel_size, strides, padding, activation, dropout, bn): + blocks = nn.ModuleList([]) + input_ch_N = num_kernels[-1] + for i in range(len(num_kernels) - 1): + out_ch_N = num_kernels[len(num_kernels) - i - 2] + blocks.append( + downscale_upscale_conv_block(2 * input_ch_N, out_ch_N, kernel_size, strides, padding, activation, dropout, + bn)) + input_ch_N = out_ch_N + return blocks + + +class BraveNet(nn.Module): + + def __init__(self, num_kernels, kernel_size, strides, padding, activation, dropout, bn, final_activation): + super().__init__() + self.num_kernels = num_kernels + self.input_bn = nn.BatchNorm2d(1) + self.lowres_input_bn = nn.BatchNorm2d(1) + + self.bottom_up_layers = down_scale_path(num_kernels, kernel_size, strides, padding, activation, dropout, bn) + self.lowres_bottom_up_layers = down_scale_path(num_kernels, kernel_size, strides, padding, activation, dropout, + bn) + + # Merging bu layer output with lowres bu layer output + self.merge_block = merge_conv_block(num_kernels[-1]) + self.lowres_output_branches = lowres_output_branches(num_kernels, final_activation, dropout) + self.output_branch = convolution_layer(num_kernels[0], + 2, + 1, + stride=1, + activation=final_activation, + dropout=dropout, + padding=0, + bn=False) + self.num_kernels = num_kernels + self.top_down_layers = up_scale_path(num_kernels, kernel_size, strides, padding, activation, dropout, bn) + + def bottom_up(self, input, bu_layers): + residuals = {} + conv_down = input + for i in range(len(self.num_kernels)): + # level i + conv_down = bu_layers[i](conv_down) + residuals[f"conv_{i}"] = conv_down + if i < len(self.num_kernels) - 1: + conv_down = nn.MaxPool2d(2, stride=2)(conv_down) + + return conv_down, residuals + + def top_down(self, bu_output, residuals, output_dim): + """ + Returns a list of predictions. + first element will be the primary output. + """ + outputs = [] + conv_up = bu_output + for i in range(len(self.num_kernels) - 1): + conv_up = nn.Upsample(scale_factor=2, mode='nearest')(conv_up) + bu_tensor = residuals["conv_" + str(len(self.num_kernels) - i - 2)] + conv_up = torch.cat([conv_up, bu_tensor], dim=1) + conv_up = self.top_down_layers[i](conv_up) + if i < len(self.num_kernels) - 2: + temp_output = nn.Upsample(size=output_dim, mode='nearest')(conv_up) + temp_output = self.lowres_output_branches[i](temp_output) + outputs.append(temp_output) + + output = self.output_branch(conv_up) + outputs.append(output) + return outputs[::-1] + + def get_merged_residuals(self, bu_res, lr_bu_res): + ### CONCAT/PREPARE RESIDUALS + merged_residuals = {} + for key in bu_res.keys(): + merged_residuals[key] = torch.cat([bu_res[key], lr_bu_res[key]], dim=1) + return merged_residuals + + def forward(self, input, lowres_input): + output_dim = input.shape[-2:] + input = self.input_bn(input) + lowres_input = self.lowres_input_bn(lowres_input) + + bu_out, bu_res = self.bottom_up(input, self.bottom_up_layers) + lr_bu_out, lr_bu_res = self.bottom_up(lowres_input, self.lowres_bottom_up_layers) + bu_out = torch.cat([bu_out, lr_bu_out], dim=1) + bu_out = self.merge_block(bu_out) + residuals = self.get_merged_residuals(bu_res, lr_bu_res) + outputs = self.top_down(bu_out, residuals, output_dim) + return outputs + + +if __name__ == '__main__': + num_kernels = [32, 64, 128, 256] + kernel_size = 3 + padding = 1 + activation = 'relu' + final_activation = 'relu' + dropout = 0.1 + bn = True + strides = 1 + model = BraveNet(num_kernels, kernel_size, strides, padding, activation, dropout, bn) + inp = torch.randn(5, 1, 64, 64) + lowres_inp = torch.randn(5, 1, 64, 64) + out = model(inp, lowres_inp) + import pdb + pdb.set_trace() + # print(model) diff --git a/denoisplit/nets/cellpose_segmentation.py b/denoisplit/nets/cellpose_segmentation.py new file mode 100644 index 0000000..7cdce0b --- /dev/null +++ b/denoisplit/nets/cellpose_segmentation.py @@ -0,0 +1,51 @@ +from cellpose import models +from czifile import imread as imread_czi +import numpy as np +import os + +def load_czi(fpaths): + imgs = [] + for fpath in fpaths: + img = imread_czi(fpath) + assert img.shape[3] == 1 + img = np.swapaxes(img, 0, 3) + # the first dimension of img stored in imgs will have dim of 1, where the contenation will happen + imgs.append(img) + return imgs +def extension(fpath): + return os.path.basename(fpath).split('.')[-1] + +def load_data(fpaths): + exts = set([ extension(fpath) for fpath in fpaths]) + assert len(exts) ==1, f'In one call, pass only files with one extension. Found:{exts}' + if extension(fpaths[0]) == 'czi': + data = load_czi(fpaths) + return data + +def segment(imgs_2D, use_GPU=True, model_type='nuclei'): + model = models.Cellpose(gpu=use_GPU, model_type='nuclei') + + # define CHANNELS to run segementation on + # grayscale=0, R=1, G=2, B=3 + # channels = [cytoplasm, nucleus] + # if NUCLEUS channel does not exist, set the second channel to 0 + # channels = [0,0] + # IF ALL YOUR IMAGES ARE THE SAME TYPE, you can give a list with 2 elements + # channels = [0,0] # IF YOU HAVE GRAYSCALE + # channels = [2,3] # IF YOU HAVE G=cytoplasm and B=nucleus + # channels = [2,1] # IF YOU HAVE G=cytoplasm and R=nucleus + + # or if you have different types of channels in each image + # channels = [[2,3], [0,0], [0,0]] + channels = [0,0] + + # sanity checks on the input. Otherwise, one needs to update channels variable. + assert isinstance(imgs_2D,list) + assert all([len(x.shape)==2 for x in imgs_2D]) + + # if diameter is set to None, the size of the cells is estimated on a per image basis + # you can set the average cell `diameter` in pixels yourself (recommended) + # diameter can be a list or a single number for all images + + masks, flows, styles, diams = model.eval(imgs_2D, diameter=None, flow_threshold=None, channels=channels) + return masks, flows, styles, diams \ No newline at end of file diff --git a/denoisplit/nets/context_transfer_module.py b/denoisplit/nets/context_transfer_module.py new file mode 100644 index 0000000..fc04d21 --- /dev/null +++ b/denoisplit/nets/context_transfer_module.py @@ -0,0 +1,122 @@ +""" +Context Transfer module coded following https://www.researchgate.net/publication/331159375_Context-Aware_U-Net_for_Biomedical_Image_Segmentation +""" +import torch.nn as nn +import torch + + +class ContextTransferModule(nn.Module): + + def __init__(self, tensor_shape, initial_weight_factor=0): + super().__init__() + self.C, self.H, self.W = tensor_shape + # UP, DOWN, LEFT, RIGHT + self.ct_weights = nn.Parameter(initial_weight_factor * torch.ones((4, self.H, self.W)), requires_grad=True) + self.final_layer = nn.Sequential(nn.Conv2d(4 * self.C, self.C, 1, padding=0), nn.ReLU(inplace=False)) + print(f'[{self.__class__.__name__}] {tensor_shape} {initial_weight_factor}') + + def set_params_to_same_device_as(self, correct_device_tensor): + if isinstance(self.ct_weights, torch.Tensor): + if self.ct_weights.device != correct_device_tensor.device: + self.ct_weights = self.ct_weights.to(correct_device_tensor.device) + + def get_up_W(self): + return torch.sigmoid(self.ct_weights[0]) + + def get_down_W(self): + return torch.sigmoid(self.ct_weights[1]) + + def get_left_W(self): + return torch.sigmoid(self.ct_weights[2]) + + def get_right_W(self): + return torch.sigmoid(self.ct_weights[3]) + + def up_context(self, inp): + out = inp.clone() + assert out.shape[1] == self.C + assert out.shape[2] == self.H + assert out.shape[3] == self.W + w = self.get_up_W() + for i in range(1, self.H): + old_version = out[:, :, i].clone() + new_version = w[i - 1] * out[:, :, i - 1].clone() + old_version + new_version[new_version < 0] = 0 + out[:, :, i] = new_version + return out + + def down_context(self, inp): + out = inp.clone() + assert out.shape[1] == self.C + assert out.shape[2] == self.H + assert out.shape[3] == self.W + w = self.get_down_W() + rel_idx = -1 + for i in range(self.H - 2, -1, -1): + old_version = out[:, :, i].clone() + new_version = w[i - rel_idx] * out[:, :, i - rel_idx].clone() + old_version + new_version[new_version < 0] = 0 + out[:, :, i] = new_version + return out + + def right_context(self, inp): + out = inp.clone() + assert out.shape[1] == self.C + assert out.shape[2] == self.H + assert out.shape[3] == self.W + w = self.get_right_W() + rel_idx = -1 + for i in range(self.W - 2, -1, -1): + old_version = out[:, :, :, i].clone() + new_version = w[:, i - rel_idx] * out[:, :, :, i - rel_idx].clone() + old_version + new_version[new_version < 0] = 0 + out[:, :, :, i] = new_version + return out + + def left_context(self, inp): + out = inp.clone() + assert out.shape[1] == self.C + assert out.shape[2] == self.H + assert out.shape[3] == self.W + w = self.get_left_W() + rel_idx = 1 + for i in range(1, self.W): + old_version = out[:, :, :, i].clone() + new_version = w[:, i - rel_idx] * out[:, :, :, i - rel_idx].clone() + old_version + new_version[new_version < 0] = 0 + out[:, :, :, i] = new_version + return out + + def forward(self, inp): + lc = self.left_context(inp) + rc = self.right_context(inp) + uc = self.up_context(inp) + dc = self.down_context(inp) + context = torch.cat([lc, rc, uc, dc], dim=1) + return self.final_layer(context) + + +if __name__ == '__main__': + import seaborn as sns + import matplotlib.pyplot as plt + import numpy as np + # from denoisplit.nets.context_transfer_module import ContextTransferModule + + shape = (64, 128, 128) + cxt = ContextTransferModule(shape, initial_weight_factor=10) + inp = torch.zeros((2, *shape)) + # inp[:, :, :1] = 1 + inp[:, :, -1:] = 1 + # inp[:, :, :, :1] = 1 + # inp[:, :, :, -1:] = 1 + + # out = cxt(inp).detach().cpu().numpy() + out = cxt.down_context(inp).detach().cpu().numpy() + # out = out / out.max() + _, ax = plt.subplots(figsize=(8, 4), ncols=2) + sns.heatmap(inp[0, 0], ax=ax[0]) + sns.heatmap(np.log(out[0, 0] + 1), ax=ax[1]) + # import pdb;pdb.set_trace() + # out1 = cxt(inp) + # import pdb + # pdb.set_trace() diff --git a/denoisplit/nets/denoiser_splitter.py b/denoisplit/nets/denoiser_splitter.py new file mode 100644 index 0000000..e08600c --- /dev/null +++ b/denoisplit/nets/denoiser_splitter.py @@ -0,0 +1,313 @@ +import os +from copy import deepcopy + +import torch + +import ml_collections +from denoisplit.config_utils import load_config +from denoisplit.core.loss_type import LossType +from denoisplit.nets.lvae import LadderVAE, RangeInvariantPsnr, torch_nanmean +from denoisplit.nets.lvae_denoiser import LadderVAEDenoiser + + +class DenoiserSplitter(LadderVAE): + """ + It denoises the input and optionally the target. And then it splits the denoised input. + """ + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + self._denoiser_mmse = config.model.get('denoiser_mmse', 1) + self._denoiser_kinput_samples = config.model.get('denoiser_kinput_samples', None) + if self._denoiser_kinput_samples is not None: + assert self._denoiser_kinput_samples >= 1 + assert self._denoiser_mmse == 1 + + self._synchronized_input_target = config.model.get('synchronized_input_target', False) + self._use_noisy_input = config.model.get('use_noisy_input', False) + self._use_noisy_target = config.model.get('use_noisy_target', False) + self._use_both_noisy_clean_input = config.model.get('use_both_noisy_clean_input', False) + + new_config = deepcopy(ml_collections.ConfigDict(config)) + with new_config.unlocked(): + new_config.data.image_size = new_config.data.image_size // 2 + if self._use_both_noisy_clean_input: + new_config.data.color_ch = new_config.data.get('color_ch', 1) + 1 + if self._denoiser_kinput_samples is not None: + new_config.data.color_ch += (self._denoiser_kinput_samples - 1) + super().__init__(data_mean, data_std, new_config, use_uncond_mode_at, target_ch) + + self._denoiser_ch1, config_ch1 = self.load_denoiser(config.model.get('pre_trained_ckpt_fpath_ch1', None)) + self._denoiser_ch2, config_ch2 = self.load_denoiser(config.model.get('pre_trained_ckpt_fpath_ch2', None)) + self._denoiser_input, config_inp = self.load_denoiser(config.model.get('pre_trained_ckpt_fpath_input', None)) + self._denoiser_all, config_all = self.load_denoiser(config.model.get('pre_trained_ckpt_fpath_all', None)) + + # Same noise level for all denoisers + if 'synthetic_gaussian_scale' in config.data: + assert config_ch1 is None or ('synthetic_gaussian_scale' in config_ch1.data + and config_ch1.data.synthetic_gaussian_scale + == config.data.synthetic_gaussian_scale) + assert config_ch2 is None or ('synthetic_gaussian_scale' in config_ch2.data + and config_ch2.data.synthetic_gaussian_scale + == config.data.synthetic_gaussian_scale) + assert config_inp is None or ('synthetic_gaussian_scale' in config_inp.data + and config_inp.data.synthetic_gaussian_scale + == config.data.synthetic_gaussian_scale) + assert config_all is None or ('synthetic_gaussian_scale' in config_all.data + and config_all.data.synthetic_gaussian_scale + == config.data.synthetic_gaussian_scale) + + if self._denoiser_all is not None: + self._denoiser_ch1 = self._denoiser_all + self._denoiser_ch2 = self._denoiser_all + self._denoiser_input = self._denoiser_all + else: + if self._denoiser_ch1 is not None: + idx = ['Ch1', 'Ch2'].index(self._denoiser_ch1.denoise_channel) + fname = config_ch1.data[f'ch{idx+1}_fname'] + assert config.data['ch1_fname'] == fname + if self._denoiser_ch2 is not None: + idx = ['Ch1', 'Ch2'].index(self._denoiser_ch2.denoise_channel) + fname = config_ch2.data[f'ch{idx+1}_fname'] + assert config.data['ch2_fname'] == fname + + den_ch1 = self._denoiser_ch1 is not None + den_ch2 = self._denoiser_ch2 is not None + den_input = self._denoiser_input is not None + assert self._denoiser_input is None or (self._use_noisy_input == False + or self._use_both_noisy_clean_input == True) + print(f'[{self.__class__}] Denoisers Ch1:{den_ch1}, Ch2:{den_ch2}, Input:{den_input} All:{den_input}') + + def load_data_mean_std(self, checkpoint): + # TODO: save the mean and std in the checkpoint. + data_mean = deepcopy(self.data_mean) + data_std = deepcopy(self.data_std) + return data_mean, data_std + + def load_denoiser(self, pre_trained_ckpt_fpath): + if pre_trained_ckpt_fpath is None: + return None, None + checkpoint = torch.load(pre_trained_ckpt_fpath) + config_fpath = os.path.join(os.path.dirname(pre_trained_ckpt_fpath), 'config.pkl') + config = load_config(config_fpath) + data_mean, data_std = self.load_data_mean_std(checkpoint) + + model = LadderVAEDenoiser(data_mean, data_std, config) + _ = model.load_state_dict(checkpoint['state_dict'], strict=True) + print('Loaded model from ckpt dir', pre_trained_ckpt_fpath, f' at epoch:{checkpoint["epoch"]}') + + for param in model.parameters(): + param.requires_grad = False + return model, config + + def denoise_one_channel(self, normalized_x, denoiser, mmse_count=1, k_samples=None): + if k_samples is None: + output = 0 + for i in range(mmse_count): + out, _ = denoiser(normalized_x) + output += denoiser.likelihood.distr_params(out)['mean'] + return output / mmse_count + else: + output = [] + for i in range(k_samples): + out, _ = denoiser(normalized_x) + output.append(denoiser.likelihood.distr_params(out)['mean']) + # batch * k_samples * ch * H * W + return output + + def trim_to_half(self, x): + H = x.shape[-1] // 2 + return x[:, :, H // 2:-H // 2, H // 2:-H // 2] + + def denoise_target(self, target_normalized): + ch1 = target_normalized[:, :1] + ch2 = target_normalized[:, 1:] + ch1_denoised = self.denoise_one_channel(ch1, self._denoiser_ch1, mmse_count=self._denoiser_mmse) + ch2_denoised = self.denoise_one_channel(ch2, self._denoiser_ch2, mmse_count=self._denoiser_mmse) + + ch1_denoised = self.trim_to_half(ch1_denoised) + ch2_denoised = self.trim_to_half(ch2_denoised) + return torch.cat([ch1_denoised, ch2_denoised], dim=1) + + def denoise_input(self, x_normalized): + x_normalized = self.denoise_one_channel(x_normalized, + self._denoiser_input, + mmse_count=self._denoiser_mmse, + k_samples=self._denoiser_kinput_samples) + if self._denoiser_kinput_samples is not None: + assert isinstance(x_normalized, list) + return [self.trim_to_half(x) for x in x_normalized] + return self.trim_to_half(x_normalized) + + def compute_input(self, target_normalized): + return torch.mean(target_normalized, dim=1, keepdim=True) + + def get_normalized_input_target(self, batch): + """ + Optionally denoise the input and target. For conssistency, we also trim them to half their spatial size. + """ + x, noisy_target = batch[:2] + noisy_target_normalized = self.normalize_target(noisy_target) + denoised_target_normalized = self.denoise_target(noisy_target_normalized) + + if self._use_noisy_target: + target_normalized = self.trim_to_half(noisy_target_normalized) + else: + target_normalized = denoised_target_normalized + + # inputs + if self._use_both_noisy_clean_input: + x_normalized = self.normalize_input(x) + denoised_x = self.denoise_input(x_normalized) + x_normalized = self.trim_to_half(x_normalized) + assert isinstance(denoised_x, list) + x_normalized = torch.cat([x_normalized] + denoised_x, dim=1) + elif self._use_noisy_input: + x_normalized = self.normalize_input(x) + x_normalized = self.trim_to_half(x_normalized) + assert self._synchronized_input_target != True + elif self._synchronized_input_target: + x_normalized = torch.mean(target_normalized, dim=1, keepdim=True) + elif self._denoiser_input is not None: + x_normalized = self.denoise_input(x) + else: + raise ValueError('Not clear how input needs to be computed.') + return x_normalized, target_normalized + + def training_step(self, batch, batch_idx, enable_logging=True): + x_normalized, target_normalized = self.get_normalized_input_target(batch) + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, imgs = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + return_predicted_img=True) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = recons_loss_dict['loss'] + if self.loss_type == LossType.ElboMixedReconstruction: + recons_loss += self.mixed_rec_w * recons_loss_dict['mixed_loss'] + if enable_logging: + self.log('mixed_reconstruction_loss', recons_loss_dict['mixed_loss'], on_epoch=True) + elif self.loss_type == LossType.ElboWithNbrConsistency: + assert len(batch) == 4 + grid_sizes = batch[-1] + nbr_cons_loss = self.nbr_consistency_w * self.nbr_consistency_loss.get(imgs, grid_sizes=grid_sizes) + # print(recons_loss, nbr_cons_loss) + self.log('nbr_cons_loss', nbr_cons_loss.item(), on_epoch=True) + recons_loss += nbr_cons_loss + + if self.non_stochastic_version: + kl_loss = torch.Tensor([0.0]).cuda() + net_loss = recons_loss + else: + kl_loss = self.get_kl_divergence_loss( + td_data) if self.kl_loss_formulation != 'usplit' else self.get_kl_divergence_loss_usplit(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + if enable_logging: + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + # self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + # self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach(), + 'kl_loss': kl_loss.detach(), + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def validation_step(self, batch, batch_idx): + self.set_params_to_same_device_as(batch[0]) + x_normalized, target_normalized = self.get_normalized_input_target(batch) + + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, recons_img = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + return_predicted_img=True) + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + channels_rinvpsnr = [] + for i in range(recons_img.shape[1]): + self.channels_psnr[i].update(recons_img[:, i], target_normalized[:, i]) + psnr = RangeInvariantPsnr(target_normalized[:, i].clone(), recons_img[:, i].clone()) + channels_rinvpsnr.append(psnr) + psnr = torch_nanmean(psnr).item() + self.log(f'val_psnr_l{i+1}', psnr, on_epoch=True) + + # self.label1_psnr.update(recons_img[:, 0], target_normalized[:, 0]) + # self.label2_psnr.update(recons_img[:, 1], target_normalized[:, 1]) + + # psnr_label1 = RangeInvariantPsnr(target_normalized[:, 0].clone(), recons_img[:, 0].clone()) + # psnr_label2 = RangeInvariantPsnr(target_normalized[:, 1].clone(), recons_img[:, 1].clone()) + recons_loss = recons_loss_dict['loss'] + # kl_loss = self.get_kl_divergence_loss(td_data) + # net_loss = recons_loss + self.get_kl_weight() * kl_loss + self.log('val_loss', recons_loss, on_epoch=True) + # val_psnr_l1 = torch_nanmean(psnr_label1).item() + # val_psnr_l2 = torch_nanmean(psnr_label2).item() + # self.log('val_psnr_l1', val_psnr_l1, on_epoch=True) + # self.log('val_psnr_l2', val_psnr_l2, on_epoch=True) + # self.log('val_psnr', (val_psnr_l1 + val_psnr_l2) / 2, on_epoch=True) + + # if batch_idx == 0 and self.power_of_2(self.current_epoch): + # all_samples = [] + # for i in range(20): + # sample, _ = self(x_normalized[0:1, ...]) + # sample = self.likelihood.get_mean_lv(sample)[0] + # all_samples.append(sample[None]) + + # all_samples = torch.cat(all_samples, dim=0) + # all_samples = all_samples * self.data_std['target'] + self.data_mean['target'] + # all_samples = all_samples.cpu() + # img_mmse = torch.mean(all_samples, dim=0)[0] + # self.log_images_for_tensorboard(all_samples[:, 0, 0, ...], noisy_target[0, 0, ...], img_mmse[0], 'label1') + # self.log_images_for_tensorboard(all_samples[:, 0, 1, ...], noisy_target[0, 1, ...], img_mmse[1], 'label2') + + +if __name__ == '__main__': + import numpy as np + import torch + + from denoisplit.configs.denoiser_splitting_config import get_config + + config = get_config() + data_mean = {'input': np.array([0]).reshape(1, 1, 1, 1), 'target': np.array([0, 0]).reshape(1, 2, 1, 1)} + data_std = {'input': np.array([1]).reshape(1, 1, 1, 1), 'target': np.array([1, 1]).reshape(1, 2, 1, 1)} + model = DenoiserSplitter(data_mean, data_std, config) + mc = 1 if config.data.multiscale_lowres_count is None else config.data.multiscale_lowres_count + 1 + inp = torch.rand((2, mc, config.data.image_size, config.data.image_size)) + # out, td_data = model(inp) + # print(out.shape) + batch = ( + torch.rand((16, mc, config.data.image_size, config.data.image_size)), + torch.rand((16, 2, config.data.image_size, config.data.image_size)), + ) + model.training_step(batch, 0) + model.validation_step(batch, 0) + + ll = torch.ones((12, 2, 32, 32)) + ll_new = model._get_weighted_likelihood(ll) + print(ll_new[:, 0].mean(), ll_new[:, 0].std()) + print(ll_new[:, 1].mean(), ll_new[:, 1].std()) + print('mar') diff --git a/denoisplit/nets/discriminator.py b/denoisplit/nets/discriminator.py new file mode 100644 index 0000000..7d2ed3c --- /dev/null +++ b/denoisplit/nets/discriminator.py @@ -0,0 +1,214 @@ +""" +This part of the code is built based on the project: +https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix +""" + +import functools +from operator import imod + +import torch +import torch.nn as nn + + +class Identity(nn.Module): + def forward(self, x): + return x + + +class Reshape(nn.Module): + def forward(self, inp): + return inp.view(inp.shape[0], -1) + + +def get_norm_layer(norm_type='instance'): + """Return a normalization layer + + Parameters: + norm_type (str) -- the name of the normalization layer: batch | instance | none + + For BatchNorm, we use learnable affine parameters and track running statistics (mean/stddev). + For InstanceNorm, we do not use learnable affine parameters. We do not track running statistics. + """ + if norm_type == 'batch': + norm_layer = functools.partial(nn.BatchNorm2d, affine=True, track_running_stats=True) + elif norm_type == 'instance': + norm_layer = functools.partial(nn.InstanceNorm2d, affine=False, track_running_stats=False) + elif norm_type == 'none': + norm_layer = lambda x: Identity() + else: + raise NotImplementedError('normalization layer [%s] is not found' % norm_type) + return norm_layer + + +def define_D(input_nc, ndf, netD, n_layers_D=3, norm='batch', input_hw=None, dense_ch_list=None, cnn_out_ch=None): + """Create a discriminator + + Parameters: + input_nc (int) -- the number of channels in input images + ndf (int) -- the number of filters in the first conv layer + netD (str) -- the architecture's name: basic | n_layers | pixel + n_layers_D (int) -- the number of conv layers in the discriminator; effective when netD=='n_layers' + norm (str) -- the type of normalization layers used in the network. + input_hw -- input spatial size. We assume a square image. + dense_ch_list -- list of dense channels + cnn_out_ch -- output channel of the CNN subunit. + Returns a discriminator + + Our current implementation provides three types of discriminators: + [basic]: 'PatchGAN' classifier described in the original pix2pix paper. + It can classify whether 70×70 overlapping patches are real or fake. + Such a patch-level discriminator architecture has fewer parameters + than a full-image discriminator and can work on arbitrarily-sized images + in a fully convolutional fashion. + + [n_layers]: With this mode, you cna specify the number of conv layers in the discriminator + with the parameter (default=3 as used in [basic] (PatchGAN).) + + [pixel]: 1x1 PixelGAN discriminator can classify whether a pixel is real or not. + It encourages greater color diversity but has no effect on spatial statistics. + + The discriminator has been initialized by . It uses Leakly RELU for non-linearity. + """ + net = None + norm_layer = get_norm_layer(norm_type=norm) + + if netD == 'basic': # default PatchGAN classifier + net = NLayerDiscriminator( + input_nc, + ndf, + n_layers=3, + norm_layer=norm_layer, + input_hw=input_hw, + dense_ch_list=dense_ch_list, + cnn_out_ch=cnn_out_ch, + ) + elif netD == 'n_layers': # more options + net = NLayerDiscriminator( + input_nc, + ndf, + n_layers_D, + norm_layer=norm_layer, + input_hw=input_hw, + dense_ch_list=dense_ch_list, + cnn_out_ch=cnn_out_ch, + ) + elif netD == 'pixel': # classify if each pixel is real or fake + net = PixelDiscriminator(input_nc, ndf, norm_layer=norm_layer) + else: + raise NotImplementedError('Discriminator model name [%s] is not recognized' % netD) + return net + + +class NLayerDiscriminator(nn.Module): + """Defines a PatchGAN discriminator""" + def __init__(self, + input_nc, + ndf=64, + n_layers=3, + norm_layer=nn.BatchNorm2d, + input_hw=None, + dense_ch_list=None, + cnn_out_ch: int = None): + """Construct a PatchGAN discriminator + + Parameters: + input_nc (int) -- the number of channels in input images + ndf (int) -- the number of filters in the last conv layer + n_layers (int) -- the number of conv layers in the discriminator + norm_layer -- normalization layer + dense_ch_list -- If we want to add a dense layer at the end, we provide here the list of channels for the dnese layer. + cnn_out_ch -- output channels for the CNN portion. + """ + super(NLayerDiscriminator, self).__init__() + self.input_hw = input_hw + self.dense_ch_list = dense_ch_list + + if type(norm_layer) == functools.partial: # no need to use bias as BatchNorm2d has affine parameters + use_bias = norm_layer.func == nn.InstanceNorm2d + else: + use_bias = norm_layer == nn.InstanceNorm2d + + kw = 4 + padw = 2 + sequence = [nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2, padding=padw), nn.LeakyReLU(0.2, True)] + nf_mult = 1 + nf_mult_prev = 1 + for n in range(1, n_layers): # gradually increase the number of filters + nf_mult_prev = nf_mult + nf_mult = min(2**n, 8) + sequence += [ + nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult, kernel_size=kw, stride=2, padding=padw, bias=use_bias), + norm_layer(ndf * nf_mult), + nn.LeakyReLU(0.2, True) + ] + + nf_mult_prev = nf_mult + nf_mult = min(2**n_layers, 8) + sequence += [ + nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult, kernel_size=kw, stride=1, padding=padw, bias=use_bias), + norm_layer(ndf * nf_mult), + nn.LeakyReLU(0.2, True) + ] + + sequence += [nn.Conv2d(ndf * nf_mult, cnn_out_ch, kernel_size=kw, stride=1, + padding=padw)] # output 1 channel prediction map + self.cnn_model = nn.Sequential(*sequence) + # dense portion now + if self.dense_ch_list is not None: + self.add_dense_layers(input_hw, input_nc, cnn_out_ch) + else: + self.model = self.cnn_model + + def add_dense_layers(self, input_hw, input_nc, cnn_out_ch): + # finding the shape of the output coming out of CNN module + with torch.no_grad(): + inp = torch.rand(1, input_nc, input_hw, input_hw) + hw = self.cnn_model(inp).shape[-1] + # the last channel is 1 + dense = self.get_dense(hw * hw * cnn_out_ch, self.dense_ch_list + [1]) + self.model = nn.Sequential(self.cnn_model, Reshape(), dense) + + def get_dense(self, in_channels, fc_list): + modules = [] + for i, fc in enumerate(fc_list): + modules.append(nn.Linear(in_channels, fc)) + if i < len(fc_list) - 1: + modules.append(nn.LeakyReLU(0.2, True)) + in_channels = fc + return nn.Sequential(*modules) + + def forward(self, input): + """Standard forward.""" + return self.model(input) + + +class PixelDiscriminator(nn.Module): + """Defines a 1x1 PatchGAN discriminator (pixelGAN)""" + def __init__(self, input_nc, ndf=64, norm_layer=nn.BatchNorm2d): + """Construct a 1x1 PatchGAN discriminator + + Parameters: + input_nc (int) -- the number of channels in input images + ndf (int) -- the number of filters in the last conv layer + norm_layer -- normalization layer + """ + super(PixelDiscriminator, self).__init__() + if type(norm_layer) == functools.partial: # no need to use bias as BatchNorm2d has affine parameters + use_bias = norm_layer.func == nn.InstanceNorm2d + else: + use_bias = norm_layer == nn.InstanceNorm2d + + self.net = [ + nn.Conv2d(input_nc, ndf, kernel_size=1, stride=1, padding=0), + nn.LeakyReLU(0.2, True), + nn.Conv2d(ndf, ndf * 2, kernel_size=1, stride=1, padding=0, bias=use_bias), + norm_layer(ndf * 2), + nn.LeakyReLU(0.2, True), + nn.Conv2d(ndf * 2, 1, kernel_size=1, stride=1, padding=0, bias=use_bias) + ] + + self.net = nn.Sequential(*self.net) + + def forward(self, input): + """Standard forward.""" + return self.net(input) diff --git a/denoisplit/nets/gmm_nnbased_noise_model.py b/denoisplit/nets/gmm_nnbased_noise_model.py new file mode 100644 index 0000000..d949c0a --- /dev/null +++ b/denoisplit/nets/gmm_nnbased_noise_model.py @@ -0,0 +1,129 @@ +import torch +import torch.nn as nn + +from denoisplit.core.stable_exp import StableExponential +from denoisplit.nets.gmm_noise_model import GaussianMixtureNoiseModel + + +class PointConvBlock(nn.Module): + + def __init__(self, in_channels, out_channels, interim_channels=None, residual=False) -> None: + super().__init__() + if interim_channels is None: + if in_channels < 32: + interim_channels = 32 + else: + interim_channels = in_channels * 2 + + self.nn = nn.Sequential( + nn.Conv2d(in_channels, interim_channels, 1), + nn.LeakyReLU(), + nn.BatchNorm2d(interim_channels), + nn.Conv2d(interim_channels, out_channels, 1), + nn.LeakyReLU(), + ) + self.residual = residual + + def forward(self, x): + if self.residual: + return x + self.nn(x) + else: + return self.nn(x) + + +class MuModel(nn.Module): + + def __init__(self, n_gaussian): + super().__init__() + self.mu_model = nn.Sequential( + PointConvBlock(1, 32, residual=False), + PointConvBlock(32, 32, residual=True), + PointConvBlock(32, 32, residual=True), + PointConvBlock(32, 32, residual=True), + PointConvBlock(32, n_gaussian, interim_channels=32, residual=False), + ) + + def forward(self, x): + return x + self.mu_model(x) + + +class DeepGMMNoiseModel(GaussianMixtureNoiseModel): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + del self.weight + self.mu_model = MuModel(self.n_gaussian) + + self.sigma_model = nn.Sequential( + PointConvBlock(1, 32, residual=False), + PointConvBlock(32, 32, residual=True), + PointConvBlock(32, 32, residual=True), + PointConvBlock(32, 32, residual=True), + PointConvBlock(32, self.n_gaussian, interim_channels=32, residual=False), + ) + self.alpha_model = nn.Sequential( + PointConvBlock(1, 32, residual=False), + PointConvBlock(32, 32, residual=True), + PointConvBlock(32, 32, residual=True), + PointConvBlock(32, 32, residual=True), + PointConvBlock(32, self.n_gaussian, interim_channels=32, residual=False), + ) + + def make_learnable(self): + print(f'[{self.__class__.__name__}] Making noise model learnable') + self._learnable = True + # for params in self.parameters(): + # params.requires_grad = True + + def to_device(self, cuda_tensor): + if self.min_signal.device != cuda_tensor.device: + self.max_signal = self.max_signal.to(cuda_tensor.device) + self.min_signal = self.min_signal.to(cuda_tensor.device) + self.tol = self.tol.to(cuda_tensor.device) + + def getGaussianParameters(self, signals): + """Returns the noise model for given signals + Parameters + ---------- + signals : torch.cuda.FloatTensor + Underlying signals + Returns + ------- + noiseModel: list of torch.cuda.FloatTensor + Contains a list of `mu`, `sigma` and `alpha` for the `signals` + """ + noiseModel = [] + mu = [] + sigma = [] + alpha = [] + mu = [self.mu_model(signals)[:, k:k + 1] for k in range(self.n_gaussian)] + + sigmaTemp = StableExponential(self.sigma_model(signals)).exp() + sigmaTemp = torch.clamp(sigmaTemp, min=self.min_sigma) + sigmaTemp = torch.sqrt(sigmaTemp) + sigma = [sigmaTemp[:, k:k + 1] for k in range(self.n_gaussian)] + alphatemp = StableExponential(self.alpha_model(signals)).exp() + self.tol + alpha = [alphatemp[:, k:k + 1] for k in range(self.n_gaussian)] + + sum_alpha = 0 + for al in range(self.n_gaussian): + sum_alpha = alpha[al] + sum_alpha + for ker in range(self.n_gaussian): + alpha[ker] = alpha[ker] / sum_alpha + + sum_means = 0 + for ker in range(self.n_gaussian): + sum_means = alpha[ker] * mu[ker] + sum_means + + mu_shifted = [] + for ker in range(self.n_gaussian): + mu[ker] = mu[ker] - sum_means + signals + + for i in range(self.n_gaussian): + noiseModel.append(mu[i]) + for j in range(self.n_gaussian): + noiseModel.append(sigma[j]) + for k in range(self.n_gaussian): + noiseModel.append(alpha[k]) + + return noiseModel diff --git a/denoisplit/nets/gmm_noise_model.py b/denoisplit/nets/gmm_noise_model.py new file mode 100644 index 0000000..6b7de1c --- /dev/null +++ b/denoisplit/nets/gmm_noise_model.py @@ -0,0 +1,345 @@ +""" +Taken from https://github.com/juglab/HDN/blob/main/lib/gaussianMixtureNoiseModel.py +""" +import torch +import torch.nn as nn + +dtype = torch.float +import pickle + +import matplotlib.pyplot as plt +import numpy as np +from scipy.stats import norm +from torch.distributions import normal + +from tifffile import imread + + +def fastShuffle(series, num): + length = series.shape[0] + for i in range(num): + series = series[np.random.permutation(length), :] + return series + + +MAX_VAR_W = 30 +MAX_ALPHA_W = 30 + + +class GaussianMixtureNoiseModel(nn.Module): + """The GaussianMixtureNoiseModel class describes a noise model which is parameterized as a mixture of gaussians. + If you would like to initialize a new object from scratch, then set `params`= None and specify the other parameters as keyword arguments. If you are instead loading a model, use only `params`. + Parameters + ---------- + **kwargs: keyworded, variable-length argument dictionary. + Arguments include: + min_signal : float + Minimum signal intensity expected in the image. + max_signal : float + Maximum signal intensity expected in the image. + path: string + Path to the directory where the trained noise model (*.npz) is saved in the `train` method. + weight : array + A [3*n_gaussian, n_coeff] sized array containing the values of the weights describing the noise model. + Each gaussian contributes three parameters (mean, standard deviation and weight), hence the number of rows in `weight` are 3*n_gaussian. + If `weight=None`, the weight array is initialized using the `min_signal` and `max_signal` parameters. + n_gaussian: int + Number of gaussians. + n_coeff: int + Number of coefficients to describe the functional relationship between gaussian parameters and the signal. + 2 implies a linear relationship, 3 implies a quadratic relationship and so on. + device: device + GPU device. + min_sigma: int + All values of sigma (`standard deviation`) below min_sigma are clamped to become equal to min_sigma. + params: dictionary + Use `params` if one wishes to load a model with trained weights. + While initializing a new object of the class `GaussianMixtureNoiseModel` from scratch, set this to `None`. + Example + ------- + >>> model = GaussianMixtureNoiseModel(min_signal = 484.85, max_signal = 3235.01, path='../../models/', weight = None, n_gaussian = 3, n_coeff = 2, min_sigma = 50, device = torch.device("cuda:0")) + """ + + def __init__(self, **kwargs): + super().__init__() + self._learnable = False + + if (kwargs.get('params') is None): + weight = kwargs.get('weight') + n_gaussian = kwargs.get('n_gaussian') + n_coeff = kwargs.get('n_coeff') + min_signal = kwargs.get('min_signal') + max_signal = kwargs.get('max_signal') + # self.device = kwargs.get('device') + self.path = kwargs.get('path') + self.min_sigma = kwargs.get('min_sigma') + if (weight is None): + weight = np.random.randn(n_gaussian * 3, n_coeff) + weight[n_gaussian:2 * n_gaussian, 1] = np.log(max_signal - min_signal) + weight = torch.from_numpy(weight.astype(np.float32)).float() #.to(self.device) + weight = nn.Parameter(weight, requires_grad=True) + + self.n_gaussian = weight.shape[0] // 3 + self.n_coeff = weight.shape[1] + self.weight = weight + self.min_signal = torch.Tensor([min_signal]) #.to(self.device) + self.max_signal = torch.Tensor([max_signal]) #.to(self.device) + self.tol = torch.Tensor([1e-10]) #.to(self.device) + else: + params = kwargs.get('params') + # self.device = kwargs.get('device') + + self.min_signal = torch.Tensor(params['min_signal']) #.to(self.device) + self.max_signal = torch.Tensor(params['max_signal']) #.to(self.device) + + self.weight = torch.nn.Parameter(torch.Tensor(params['trained_weight']), + requires_grad=False) #.to(self.device) + self.min_sigma = params['min_sigma'].item() + self.n_gaussian = self.weight.shape[0] // 3 + self.n_coeff = self.weight.shape[1] + self.tol = torch.Tensor([1e-10]) #.to(self.device) + self.min_signal = torch.Tensor([self.min_signal]) #.to(self.device) + self.max_signal = torch.Tensor([self.max_signal]) #.to(self.device) + + def make_learnable(self): + print(f'[{self.__class__.__name__}] Making noise model learnable') + + self._learnable = True + self.weight.requires_grad = True + + # + def to_device(self, cuda_tensor): + # move everything to GPU + if self.min_signal.device != cuda_tensor.device: + self.max_signal = self.max_signal.to(cuda_tensor.device) + self.min_signal = self.min_signal.to(cuda_tensor.device) + self.tol = self.tol.to(cuda_tensor.device) + self.weight = self.weight.to(cuda_tensor.device) + if self._learnable: + self.weight.requires_grad = True + + def polynomialRegressor(self, weightParams, signals): + """Combines `weightParams` and signal `signals` to regress for the gaussian parameter values. + Parameters + ---------- + weightParams : torch.cuda.FloatTensor + Corresponds to specific rows of the `self.weight` + signals : torch.cuda.FloatTensor + Signals + Returns + ------- + value : torch.cuda.FloatTensor + Corresponds to either of mean, standard deviation or weight, evaluated at `signals` + """ + value = 0 + for i in range(weightParams.shape[0]): + value += weightParams[i] * (((signals - self.min_signal) / (self.max_signal - self.min_signal))**i) + return value + + def normalDens(self, x, m_=0.0, std_=None): + """Evaluates the normal probability density at `x` given the mean `m` and standard deviation `std`. + Parameters + ---------- + x: torch.cuda.FloatTensor + Observations + m_: torch.cuda.FloatTensor + Mean + std_: torch.cuda.FloatTensor + Standard-deviation + Returns + ------- + tmp: torch.cuda.FloatTensor + Normal probability density of `x` given `m_` and `std_` + """ + + tmp = -((x - m_)**2) + tmp = tmp / (2.0 * std_ * std_) + tmp = torch.exp(tmp) + tmp = tmp / torch.sqrt((2.0 * np.pi) * std_ * std_) + return tmp + + def likelihood(self, observations, signals): + """Evaluates the likelihood of observations given the signals and the corresponding gaussian parameters. + Parameters + ---------- + observations : torch.cuda.FloatTensor + Noisy observations + signals : torch.cuda.FloatTensor + Underlying signals + Returns + ------- + value :p + self.tol + Likelihood of observations given the signals and the GMM noise model + """ + self.to_device(signals) + gaussianParameters = self.getGaussianParameters(signals) + p = 0 + for gaussian in range(self.n_gaussian): + p += self.normalDens( + observations, gaussianParameters[gaussian], + gaussianParameters[self.n_gaussian + gaussian]) * gaussianParameters[2 * self.n_gaussian + gaussian] + return p + self.tol + + def getGaussianParameters(self, signals): + """Returns the noise model for given signals + + Parameters + ---------- + signals : torch.cuda.FloatTensor + Underlying signals + Returns + ------- + noiseModel: list of torch.cuda.FloatTensor + Contains a list of `mu`, `sigma` and `alpha` for the `signals` + + """ + noiseModel = [] + mu = [] + sigma = [] + alpha = [] + kernels = self.weight.shape[0] // 3 + for num in range(kernels): + mu.append(self.polynomialRegressor(self.weight[num, :], signals)) + # expval = torch.exp(torch.clamp(self.weight[kernels + num, :], max=MAX_VAR_W)) + expval = torch.exp(self.weight[kernels + num, :]) + # self.maxval = max(self.maxval, expval.max().item()) + sigmaTemp = self.polynomialRegressor(expval, signals) + sigmaTemp = torch.clamp(sigmaTemp, min=self.min_sigma) + sigma.append(torch.sqrt(sigmaTemp)) + + # expval = torch.exp( + # torch.clamp( + # self.polynomialRegressor(self.weight[2 * kernels + num, :], signals) + self.tol, MAX_ALPHA_W)) + expval = torch.exp(self.polynomialRegressor(self.weight[2 * kernels + num, :], signals) + self.tol) + # self.maxval = max(self.maxval, expval.max().item()) + alpha.append(expval) + + sum_alpha = 0 + for al in range(kernels): + sum_alpha = alpha[al] + sum_alpha + + # sum of alpha is forced to be 1. + for ker in range(kernels): + alpha[ker] = alpha[ker] / sum_alpha + + sum_means = 0 + # sum_means is the alpha weighted average of the means + for ker in range(kernels): + sum_means = alpha[ker] * mu[ker] + sum_means + + mu_shifted = [] + # subtracting the alpha weighted average of the means from the means + # ensures that the GMM has the inclination to have the mean=signals. + # its like a residual conection. I don't understand why we need to learn the mean? + for ker in range(kernels): + mu[ker] = mu[ker] - sum_means + signals + + for i in range(kernels): + noiseModel.append(mu[i]) + for j in range(kernels): + noiseModel.append(sigma[j]) + for k in range(kernels): + noiseModel.append(alpha[k]) + + return noiseModel + + def getSignalObservationPairs(self, signal, observation, lowerClip, upperClip): + """Returns the Signal-Observation pixel intensities as a two-column array + Parameters + ---------- + signal : numpy array + Clean Signal Data + observation: numpy array + Noisy observation Data + lowerClip: float + Lower percentile bound for clipping. + upperClip: float + Upper percentile bound for clipping. + Returns + ------- + noiseModel: list of torch floats + Contains a list of `mu`, `sigma` and `alpha` for the `signals` + """ + lb = np.percentile(signal, lowerClip) + ub = np.percentile(signal, upperClip) + stepsize = observation[0].size + n_observations = observation.shape[0] + n_signals = signal.shape[0] + sig_obs_pairs = np.zeros((n_observations * stepsize, 2)) + + for i in range(n_observations): + j = i // (n_observations // n_signals) + sig_obs_pairs[stepsize * i:stepsize * (i + 1), 0] = signal[j].ravel() + sig_obs_pairs[stepsize * i:stepsize * (i + 1), 1] = observation[i].ravel() + sig_obs_pairs = sig_obs_pairs[(sig_obs_pairs[:, 0] > lb) & (sig_obs_pairs[:, 0] < ub)] + return fastShuffle(sig_obs_pairs, 2) + + # def train(self, + # signal, + # observation, + # learning_rate=1e-1, + # batchSize=250000, + # n_epochs=2000, + # name='GMMNoiseModel.npz', + # lowerClip=0, + # upperClip=100): + # """Training to learn the noise model from signal - observation pairs. + # Parameters + # ---------- + # signal: numpy array + # Clean Signal Data + # observation: numpy array + # Noisy Observation Data + # learning_rate: float + # Learning rate. Default = 1e-1. + # batchSize: int + # Nini-batch size. Default = 250000. + # n_epochs: int + # Number of epochs. Default = 2000. + # name: string + # Model name. Default is `GMMNoiseModel`. This model after being trained is saved at the location `path`. + # lowerClip : int + # Lower percentile for clipping. Default is 0. + # upperClip : int + # Upper percentile for clipping. Default is 100. + + # """ + # sig_obs_pairs = self.getSignalObservationPairs(signal, observation, lowerClip, upperClip) + # counter = 0 + # optimizer = torch.optim.Adam([self.weight], lr=learning_rate) + # for t in range(n_epochs): + + # jointLoss = 0 + # if (counter + 1) * batchSize >= sig_obs_pairs.shape[0]: + # counter = 0 + # sig_obs_pairs = fastShuffle(sig_obs_pairs, 1) + + # batch_vectors = sig_obs_pairs[counter * batchSize:(counter + 1) * batchSize, :] + # observations = batch_vectors[:, 1].astype(np.float32) + # signals = batch_vectors[:, 0].astype(np.float32) + # observations = torch.from_numpy(observations.astype(np.float32)).float().to(self.device) + # signals = torch.from_numpy(signals).float().to(self.device) + # p = self.likelihood(observations, signals) + # loss = torch.mean(-torch.log(p)) + # jointLoss = jointLoss + loss + + # if t % 100 == 0: + # print(t, jointLoss.item()) + + # if (t % (int(n_epochs * 0.5)) == 0): + # trained_weight = self.weight.cpu().detach().numpy() + # min_signal = self.min_signal.cpu().detach().numpy() + # max_signal = self.max_signal.cpu().detach().numpy() + # np.savez(self.path + name, + # trained_weight=trained_weight, + # min_signal=min_signal, + # max_signal=max_signal, + # min_sigma=self.min_sigma) + + # optimizer.zero_grad() + # jointLoss.backward() + # optimizer.step() + # counter += 1 + + # print("===================\n") + # print("The trained parameters (" + name + ") is saved at location: " + self.path) diff --git a/denoisplit/nets/hist_gmm_noise_model.py b/denoisplit/nets/hist_gmm_noise_model.py new file mode 100644 index 0000000..773a4e0 --- /dev/null +++ b/denoisplit/nets/hist_gmm_noise_model.py @@ -0,0 +1,112 @@ +import math + +import numpy as np +import torch +from scipy.optimize import curve_fit + + +def gaus(x, mu, sigma): + out = np.exp(-(x - mu)**2 / (2 * sigma**2)) * 1 / (sigma * np.sqrt(2 * math.pi)) + return out + + +def gaus_pytorch(x, mu, sigma): + out = torch.exp(-(x - mu)**2 / (2 * sigma**2)) * 1 / (sigma * np.sqrt(2 * math.pi)) + return out + + +def sigmoid(x): + return 1 / (1 + math.exp(-x)) + + +class HistGMMNoiseModel: + + def __init__(self, histdata) -> None: + self._histdata = histdata + bin_val = (self._histdata[1] + self._histdata[2]) / 2 + # midpoint of every bin + self._bin_val = bin_val[:, 0] + self._binsize = np.mean(self._histdata[2] - self._histdata[1]) + # probability density function. + self._bin_pdf = self._histdata[0] / self._binsize + self._params = [] + + self.minv = np.min(histdata[1, ...]) + + # The upper boundaries of each bin in y are stored in dimension 2 + self.maxv = np.max(histdata[2, ...]) + self.bins = histdata.shape[1] + self._min_valid_index = None + self._max_valid_index = None + self.tol = 1e-10 + + def fit_index(self, index): + x = self._bin_val + y = self._bin_pdf[index] + if y.sum() * self._binsize < 1e-5: + return torch.tensor([torch.nan, torch.nan]) + + if self._min_valid_index is not None: + self._min_valid_index = min(index, self._min_valid_index) + else: + self._min_valid_index = index + + if self._max_valid_index is not None: + self._max_valid_index = max(index, self._max_valid_index) + else: + self._max_valid_index = index + + assert abs(y.sum() * self._binsize - 1) < 1e-5 + + mean = self._bin_val[index] + sigma = sum(y * (x - mean)**2) + popt, pcov = curve_fit(gaus, x, y, p0=[x[index], sigma], maxfev=6000) + return torch.Tensor(popt) + + def fit(self): + for index in range(len(self._bin_pdf)): + popt = self.fit_index(index) + self._params.append(popt) + + self._params = torch.stack(self._params) + # manually adde after last and before first bin. + if self._min_valid_index > 0: + self._params[self._min_valid_index - 1] = self._params[self._min_valid_index] + self._params[self._min_valid_index - 1, 0] -= self._binsize + self._min_valid_index -= 1 + + if self._max_valid_index < self.bins - 1: + self._params[self._max_valid_index + 1] = self._params[self._max_valid_index] + self._params[self._max_valid_index + 1, 0] += self._binsize + self._max_valid_index += 1 + + self._params = self._params.cuda() + + def getIndexSignalFloat(self, x): + return torch.clamp(self.bins * (x - self.minv) / (self.maxv - self.minv), min=0.0, max=self.bins - 1 - 1e-3) + + def likelihood(self, obs, signal): + signalF = self.getIndexSignalFloat(signal) + signal_ = signalF.floor().long() + fact = signalF - signal_.float() + underflow_mask = signal_ < self._min_valid_index + signal_[underflow_mask] = self._min_valid_index + fact[underflow_mask] = 0.0 + + overflow_mask = signal_ > self._max_valid_index + signal_[overflow_mask] = self._max_valid_index + params1 = self._params[signal_] + mu1 = params1[..., 0] + sigma1 = params1[..., 1] + + # if the signal is in the last bin, we just need to ignore the first mu and sigma and go with the last one. + last_index_mask = signal_ == self._max_valid_index + signal_[last_index_mask] = self._max_valid_index - 1 + fact[last_index_mask] = 1.0 + + params2 = self._params[signal_ + 1] + mu2 = params2[..., 0] + sigma2 = params2[..., 1] + mu = mu1 * (1 - fact) + mu2 * fact + sigma = sigma1 * (1 - fact) + sigma2 * fact + return self.tol + gaus_pytorch(obs, mu, sigma) diff --git a/denoisplit/nets/hist_gmm_noise_model2.py b/denoisplit/nets/hist_gmm_noise_model2.py new file mode 100644 index 0000000..773a4e0 --- /dev/null +++ b/denoisplit/nets/hist_gmm_noise_model2.py @@ -0,0 +1,112 @@ +import math + +import numpy as np +import torch +from scipy.optimize import curve_fit + + +def gaus(x, mu, sigma): + out = np.exp(-(x - mu)**2 / (2 * sigma**2)) * 1 / (sigma * np.sqrt(2 * math.pi)) + return out + + +def gaus_pytorch(x, mu, sigma): + out = torch.exp(-(x - mu)**2 / (2 * sigma**2)) * 1 / (sigma * np.sqrt(2 * math.pi)) + return out + + +def sigmoid(x): + return 1 / (1 + math.exp(-x)) + + +class HistGMMNoiseModel: + + def __init__(self, histdata) -> None: + self._histdata = histdata + bin_val = (self._histdata[1] + self._histdata[2]) / 2 + # midpoint of every bin + self._bin_val = bin_val[:, 0] + self._binsize = np.mean(self._histdata[2] - self._histdata[1]) + # probability density function. + self._bin_pdf = self._histdata[0] / self._binsize + self._params = [] + + self.minv = np.min(histdata[1, ...]) + + # The upper boundaries of each bin in y are stored in dimension 2 + self.maxv = np.max(histdata[2, ...]) + self.bins = histdata.shape[1] + self._min_valid_index = None + self._max_valid_index = None + self.tol = 1e-10 + + def fit_index(self, index): + x = self._bin_val + y = self._bin_pdf[index] + if y.sum() * self._binsize < 1e-5: + return torch.tensor([torch.nan, torch.nan]) + + if self._min_valid_index is not None: + self._min_valid_index = min(index, self._min_valid_index) + else: + self._min_valid_index = index + + if self._max_valid_index is not None: + self._max_valid_index = max(index, self._max_valid_index) + else: + self._max_valid_index = index + + assert abs(y.sum() * self._binsize - 1) < 1e-5 + + mean = self._bin_val[index] + sigma = sum(y * (x - mean)**2) + popt, pcov = curve_fit(gaus, x, y, p0=[x[index], sigma], maxfev=6000) + return torch.Tensor(popt) + + def fit(self): + for index in range(len(self._bin_pdf)): + popt = self.fit_index(index) + self._params.append(popt) + + self._params = torch.stack(self._params) + # manually adde after last and before first bin. + if self._min_valid_index > 0: + self._params[self._min_valid_index - 1] = self._params[self._min_valid_index] + self._params[self._min_valid_index - 1, 0] -= self._binsize + self._min_valid_index -= 1 + + if self._max_valid_index < self.bins - 1: + self._params[self._max_valid_index + 1] = self._params[self._max_valid_index] + self._params[self._max_valid_index + 1, 0] += self._binsize + self._max_valid_index += 1 + + self._params = self._params.cuda() + + def getIndexSignalFloat(self, x): + return torch.clamp(self.bins * (x - self.minv) / (self.maxv - self.minv), min=0.0, max=self.bins - 1 - 1e-3) + + def likelihood(self, obs, signal): + signalF = self.getIndexSignalFloat(signal) + signal_ = signalF.floor().long() + fact = signalF - signal_.float() + underflow_mask = signal_ < self._min_valid_index + signal_[underflow_mask] = self._min_valid_index + fact[underflow_mask] = 0.0 + + overflow_mask = signal_ > self._max_valid_index + signal_[overflow_mask] = self._max_valid_index + params1 = self._params[signal_] + mu1 = params1[..., 0] + sigma1 = params1[..., 1] + + # if the signal is in the last bin, we just need to ignore the first mu and sigma and go with the last one. + last_index_mask = signal_ == self._max_valid_index + signal_[last_index_mask] = self._max_valid_index - 1 + fact[last_index_mask] = 1.0 + + params2 = self._params[signal_ + 1] + mu2 = params2[..., 0] + sigma2 = params2[..., 1] + mu = mu1 * (1 - fact) + mu2 * fact + sigma = sigma1 * (1 - fact) + sigma2 * fact + return self.tol + gaus_pytorch(obs, mu, sigma) diff --git a/denoisplit/nets/hist_noise_model.py b/denoisplit/nets/hist_noise_model.py new file mode 100644 index 0000000..ef4eb98 --- /dev/null +++ b/denoisplit/nets/hist_noise_model.py @@ -0,0 +1,289 @@ +# ############################################ +# # The Noise Model. Adapted from https://github.com/juglab/HDN/blob/main/lib/histNoiseModel.py +# ############################################ + +# import torch.optim as optim +# import os +# import torch +# import torch.nn as nn +# import torch.nn.functional as F +# from torch.autograd import Variable +# from collections import OrderedDict +# from torch.nn import init +# import numpy as np +# import torchvision +# from typing import Tuple +# #from unet.model import UNet +# #import pn2v.utils + +# def getNoiseModelFname(data_fpath): +# return f'HistNoiseModel_{os.path.basename(data_fpath)}' + +# def createHistogram(bins, obsMinMax: Tuple[float, float], sigMinMax: [float, float], observation, signal): +# ''' +# Creates a 2D histogram from 'observation' and 'signal' +# Parameters +# ---------- +# bins: int +# The number of bins in x and y. The total number of 2D bins is 'bins'**2. +# obsMinMax: minVal and maxVal: float +# the lower bound of the lowest bin and the highest bound of the highest bin for observation. +# sigMinMax: minVal and maxVal: float +# the lower bound of the lowest bin and the highest bound of the highest bin for observation. +# observation: numpy array +# A 3D numpy array that is interpretted as a stack of 2D images. +# The number of images has to be divisible by the number of images in 'signal'. +# It is assumed that n subsequent images in observation belong to one image image in 'signal'. +# signal: numpy array +# A 3D numpy array that is interpretted as a stack of 2D images. + +# Returns +# ---------- +# histogram: numpy array +# A 3D array: +# 'histogram[0,...]' holds the normalized 2D counts. +# Each row sums to 1, describing p(x_i|s_i). +# 'histogram[1,...]' holds the lower boundaries of each bin in signal. +# 'histogram[2,...]' holds the upper boundaries of each bin in signal. +# 'histogram[3,...]' holds the lower boundaries of each bin in observation. +# 'histogram[4,...]' holds the upper boundaries of each bin in observation. +# The values for x can be obtained by transposing 'histogram[1,...]' and 'histogram[2,...]'. +# ''' + +# imgFactor = int(observation.shape[0] / signal.shape[0]) +# histogram = np.zeros((5, bins, bins)) + +# for i in range(observation.shape[0]): +# observation_ = observation[i].copy().ravel() + +# signal_ = (signal[i // imgFactor].copy()).ravel() + +# a = np.histogram2d(signal_, observation_, bins=bins, range=[sigMinMax, obsMinMax]) +# histogram[0] = histogram[0] + a[0] + 1e-30 #This is for numerical stability + +# for i in range(bins): +# if np.sum(histogram[0, i, :]) > 1e-20: #We exclude empty rows from normalization +# histogram[0, i, :] /= np.sum(histogram[0, i, :]) # we normalize each non-empty row + +# for i in range(bins): +# histogram[1, :, i] = a[1][:-1] # The lower boundaries of each bin in signal are stored in dimension 1 +# histogram[2, :, i] = a[1][1:] # The upper boundaries of each bin in signal are stored in dimension 2 + +# histogram[3, :, i] = a[2][:-1] # The lower boundaries of each bin in observation are stored in dimension 1 +# histogram[4, :, i] = a[2][1:] # The upper boundaries of each bin in observation are stored in dimension 2 +# # The accordent numbers for x are just transopsed. + +# return histogram + +# class HistNoiseModel: + +# def __init__(self, histogram): +# ''' +# Creates a NoiseModel object. +# Parameters +# ---------- +# histogram: numpy array +# A histogram as create by the 'createHistogram(...)' method. +# device: +# The device your NoiseModel lives on, e.g. your GPU. +# ''' + +# # The number of bins is the same in x and y +# bins = histogram.shape[1] + +# # The lower boundaries of each bin in y are stored in dimension 1 +# self.minv_signal = np.min(histogram[1, ...]) + +# # The upper boundaries of each bin in y are stored in dimension 2 +# self.maxv_signal = np.max(histogram[2, ...]) + +# # The lower boundaries of each bin in y are stored in dimension 1 +# self.minv_observ = np.min(histogram[3, ...]) + +# # The upper boundaries of each bin in y are stored in dimension 2 +# self.maxv_observ = np.max(histogram[4, ...]) + +# self.bins = torch.Tensor(np.array(float(bins))) +# self.fullHist = torch.Tensor(histogram[0, ...].astype(np.float32)) + +# def to_device(self, cuda_tensor): +# # move everything to GPU +# if self.bins.device != cuda_tensor.device: +# self.bins = self.bins.to(cuda_tensor.device) +# self.fullHist = self.fullHist.to(cuda_tensor.device) + +# def likelihood(self, obs, signal): +# ''' +# Calculate the likelihood p(x_i|s_i) for every pixel in a tensor, using a histogram based noise model. +# To ensure differentiability in the direction of s_i, we linearly interpolate in this direction. +# Parameters +# ---------- +# obs: pytorch tensor +# tensor holding your observed intesities x_i. +# signal: pytorch tensor +# tensor holding hypotheses for the clean signal at every pixel s_i^k. + +# Returns +# ---------- +# Torch tensor containing the observation likelihoods according to the noise model. +# ''' +# self.to_device(obs) + +# obsF = self.getIndexObsFloat(obs) +# obs_ = obsF.floor().long() +# signalF = self.getIndexSignalFloat(signal) +# signal_ = signalF.floor().long() +# fact = signalF - signal_.float() + +# # Finally we are looking ud the values and interpolate +# return self.fullHist[signal_, obs_] * (1.0 - fact) + self.fullHist[torch.clamp( +# (signal_ + 1).long(), 0, self.bins.long()), obs_] * (fact) + +# def getIndexObsFloat(self, x): +# self.to_device(x) +# return torch.clamp(self.bins * (x - self.minv_observ) / (self.maxv_observ - self.minv_observ), +# min=0.0, +# max=self.bins - 1 - 1e-3) + +# def getIndexSignalFloat(self, x): +# self.to_device(x) +# return torch.clamp(self.bins * (x - self.minv_signal) / (self.maxv_signal - self.minv_signal), +# min=0.0, +# max=self.bins - 1 - 1e-3) + +############################################ +# The Noise Model +############################################ + +import numpy as np +import torch + + +def createHistogram(bins, minVal, maxVal, observation, signal): + ''' + Creates a 2D histogram from 'observation' and 'signal' + + Parameters + ---------- + bins: int + The number of bins in x and y. The total number of 2D bins is 'bins'**2. + minVal: float + the lower bound of the lowest bin in x and y. + maxVal: float + the highest bound of the highest bin in x and y. + observation: numpy array + A 3D numpy array that is interpretted as a stack of 2D images. + The number of images has to be divisible by the number of images in 'signal'. + It is assumed that n subsequent images in observation belong to one image image in 'signal'. + signal: numpy array + A 3D numpy array that is interpretted as a stack of 2D images. + + Returns + ---------- + histogram: numpy array + A 3D array: + 'histogram[0,...]' holds the normalized 2D counts. + Each row sums to 1, describing p(x_i|s_i). + 'histogram[1,...]' holds the lower boundaries of each bin in y. + 'histogram[2,...]' holds the upper boundaries of each bin in y. + The values for x can be obtained by transposing 'histogram[1,...]' and 'histogram[2,...]'. + ''' + + imgFactor = int(observation.shape[0] / signal.shape[0]) + histogram = np.zeros((3, bins, bins)) + ra = [minVal, maxVal] + + for i in range(observation.shape[0]): + observation_ = observation[i].copy().ravel() + + signal_ = (signal[i // imgFactor].copy()).ravel() + + a = np.histogram2d(signal_, observation_, bins=bins, range=[ra, ra]) + histogram[0] = histogram[0] + a[0] + 1e-30 #This is for numerical stability + + for i in range(bins): + if np.sum(histogram[0, i, :]) > 1e-20: #We exclude empty rows from normalization + histogram[0, i, :] /= np.sum(histogram[0, i, :]) # we normalize each non-empty row + + for i in range(bins): + histogram[1, :, i] = a[1][:-1] # The lower boundaries of each bin in y are stored in dimension 1 + histogram[2, :, i] = a[1][1:] # The upper boundaries of each bin in y are stored in dimension 2 + # The accordent numbers for x are just transopsed. + + return histogram + + +class HistNoiseModel: + + def __init__(self, histogram): + ''' + Creates a NoiseModel object. + + Parameters + ---------- + histogram: numpy array + A histogram as create by the 'createHistogram(...)' method. + device: + The device your NoiseModel lives on, e.g. your GPU. + ''' + + # The number of bins is the same in x and y + bins = histogram.shape[1] + + # The lower boundaries of each bin in y are stored in dimension 1 + self.minv = np.min(histogram[1, ...]) + + # The upper boundaries of each bin in y are stored in dimension 2 + self.maxv = np.max(histogram[2, ...]) + + # move everything to GPU + self.bins = torch.Tensor(np.array(float(bins))) + self.bin_size = (self.maxv - self.minv) / self.bins + for i in range(histogram.shape[1]): + msg = f'bin size is not constant for index:{i}: {self.bin_size} vs {histogram[2,i,0] - histogram[1,i,0]}' + assert histogram[2, i, 0] - histogram[1, i, 0] == self.bin_size, msg + + self.fullHist = torch.Tensor(histogram[0, ...].astype(np.float32)) + + def to_device(self, cuda_tensor): + # move everything to GPU + if self.bins.device != cuda_tensor.device: + self.bins = self.bins.to(cuda_tensor.device) + self.fullHist = self.fullHist.to(cuda_tensor.device) + + def likelihood(self, obs, signal): + ''' + Calculate the likelihood p(x_i|s_i) for every pixel in a tensor, using a histogram based noise model. + To ensure differentiability in the direction of s_i, we linearly interpolate in this direction. + + Parameters + ---------- + obs: pytorch tensor + tensor holding your observed intesities x_i. + + signal: pytorch tensor + tensor holding hypotheses for the clean signal at every pixel s_i^k. + + Returns + ---------- + Torch tensor containing the observation likelihoods according to the noise model. + ''' + obsF = self.getIndexObsFloat(obs) + obs_ = obsF.floor().long() + signalF = self.getIndexSignalFloat(signal) + signal_ = signalF.floor().long() + fact = signalF - signal_.float() + # fact = 0.0 + # Finally we are looking ud the values and interpolate + unscaled_likelihood = self.fullHist[signal_, obs_] * (1.0 - fact) + self.fullHist[torch.clamp( + (signal_ + 1).long(), 0, self.bins.long()), obs_] * (fact) + + return unscaled_likelihood / self.bin_size + + def getIndexObsFloat(self, x): + self.to_device(x) + return torch.clamp(self.bins * (x - self.minv) / (self.maxv - self.minv), min=0.0, max=self.bins - 1 - 1e-3) + + def getIndexSignalFloat(self, x): + self.to_device(x) + return torch.clamp(self.bins * (x - self.minv) / (self.maxv - self.minv), min=0.0, max=self.bins - 1 - 1e-3) diff --git a/denoisplit/nets/lvae.py b/denoisplit/nets/lvae.py new file mode 100644 index 0000000..4f6bda0 --- /dev/null +++ b/denoisplit/nets/lvae.py @@ -0,0 +1,1209 @@ +""" +Ladder VAE. Adapted from from https://github.com/juglab/HDN/blob/main/models/lvae.py +""" +import os + +import numpy as np +import pytorch_lightning as pl +import torch +import torch.optim as optim +import torchvision.transforms.functional as F +import wandb +from torch import nn +from torch.autograd import Variable + +from denoisplit.analysis.pred_frame_creator import PredFrameCreator +from denoisplit.core.data_utils import Interpolate, crop_img_tensor, pad_img_tensor +from denoisplit.core.likelihoods import GaussianLikelihood, NoiseModelLikelihood +from denoisplit.core.loss_type import LossType +from denoisplit.core.metric_monitor import MetricMonitor +from denoisplit.core.psnr import RangeInvariantPsnr +from denoisplit.core.sampler_type import SamplerType +from denoisplit.loss.exclusive_loss import compute_exclusion_loss +from denoisplit.loss.nbr_consistency_loss import NeighborConsistencyLoss +from denoisplit.losses import free_bits_kl +from denoisplit.metrics.running_psnr import RunningPSNR +from denoisplit.nets.lvae_layers import (BottomUpDeterministicResBlock, BottomUpLayer, TopDownDeterministicResBlock, + TopDownLayer) +from denoisplit.nets.noise_model import get_noise_model + + +def torch_nanmean(inp): + return torch.mean(inp[~inp.isnan()]) + + +def compute_batch_mean(x): + N = len(x) + return x.view(N, -1).mean(dim=1) + + +class LadderVAE(pl.LightningModule): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2, val_idx_manager=None): + super().__init__() + self.lr = config.training.lr + self.lr_scheduler_patience = config.training.lr_scheduler_patience + self.ch1_recons_w = config.loss.get('ch1_recons_w', 1) + self.ch2_recons_w = config.loss.get('ch2_recons_w', 1) + self._stochastic_use_naive_exponential = config.model.decoder.get('stochastic_use_naive_exponential', False) + self._enable_topdown_normalize_factor = config.model.get('enable_topdown_normalize_factor', True) + # can be used to tile the validation predictions + self._val_idx_manager = val_idx_manager + self._val_frame_creator = None + self._dump_kth_frame_prediction = config.training.get('dump_kth_frame_prediction') + if self._dump_kth_frame_prediction is not None: + assert self._val_idx_manager is not None + dir = os.path.join(config.workdir, 'pred_frames') + os.mkdir(dir) + self._dump_epoch_interval = config.training.get('dump_epoch_interval', 1) + self._val_frame_creator = PredFrameCreator(self._val_idx_manager, self._dump_kth_frame_prediction, dir) + + self._input_is_sum = config.data.input_is_sum + # grayscale input + self.color_ch = config.data.get('color_ch', 1) + self._tethered_ch1_scalar = self._tethered_ch2_scalar = None + self._tethered_to_input = config.model.get('tethered_to_input', False) + if self._tethered_to_input: + target_ch = 1 + requires_grad = config.model.get('tethered_learnable_scalar', False) + # a learnable scalar that is multiplied with one channel prediction. + self._tethered_ch1_scalar = nn.Parameter(torch.ones(1) * 0.5, requires_grad=requires_grad) + self._tethered_ch2_scalar = nn.Parameter(torch.ones(1) * 2.0, requires_grad=requires_grad) + + # disentangling two grayscale images. + self.target_ch = target_ch + + self.z_dims = config.model.z_dims + self.encoder_blocks_per_layer = config.model.encoder.blocks_per_layer + self.decoder_blocks_per_layer = config.model.decoder.blocks_per_layer + + self.kl_loss_formulation = config.loss.get('kl_loss_formulation', None) + assert self.kl_loss_formulation in [None, '', + 'usplit'], f'Invalid kl_loss_formulation. {self.kl_loss_formulation}' + self.n_layers = len(self.z_dims) + self.stochastic_skip = config.model.stochastic_skip + self.bottomup_batchnorm = config.model.encoder.batchnorm + self.topdown_batchnorm = config.model.decoder.batchnorm + + self.encoder_n_filters = config.model.encoder.n_filters + self.decoder_n_filters = config.model.decoder.n_filters + + self.encoder_dropout = config.model.encoder.dropout + self.decoder_dropout = config.model.decoder.dropout + self.skip_bottomk_buvalues = config.model.get('skip_bottomk_buvalues', 0) + + # whether or not to have bias with Conv2D layer. + self.topdown_conv2d_bias = config.model.decoder.conv2d_bias + + self.learn_top_prior = config.model.learn_top_prior + self.img_shape = (config.data.image_size, config.data.image_size) + self.res_block_type = config.model.res_block_type + self.encoder_res_block_kernel = config.model.encoder.res_block_kernel + self.decoder_res_block_kernel = config.model.decoder.res_block_kernel + + self.encoder_res_block_skip_padding = config.model.encoder.res_block_skip_padding + self.decoder_res_block_skip_padding = config.model.decoder.res_block_skip_padding + + self.reconstruction_mode = config.model.get('reconstruction_mode', False) + + self.gated = config.model.gated + if isinstance(data_mean, np.ndarray): + self.data_mean = torch.Tensor(data_mean) + self.data_std = torch.Tensor(data_std) + elif isinstance(data_mean, dict): + for k in data_mean.keys(): + data_mean[k] = torch.Tensor(data_mean[k]) if not isinstance(data_mean[k], dict) else data_mean[k] + data_std[k] = torch.Tensor(data_std[k]) if not isinstance(data_std[k], dict) else data_std[k] + self.data_mean = data_mean + self.data_std = data_std + else: + raise NotImplementedError('data_mean and data_std must be either a numpy array or a dictionary') + + self.noiseModel = get_noise_model(config) + self.merge_type = config.model.merge_type + self.analytical_kl = config.model.analytical_kl + self.no_initial_downscaling = config.model.no_initial_downscaling + self.mode_pred = config.model.mode_pred + self.use_uncond_mode_at = use_uncond_mode_at + self.nonlin = config.model.nonlin + self.kl_annealing = config.loss.kl_annealing + self.kl_annealtime = self.kl_start = None + + if self.kl_annealing: + self.kl_annealtime = config.loss.kl_annealtime + self.kl_start = config.loss.kl_start + + self.predict_logvar = config.model.predict_logvar + self.logvar_lowerbound = config.model.logvar_lowerbound + self.non_stochastic_version = config.model.get('non_stochastic_version', False) + self._var_clip_max = config.model.var_clip_max + # loss related + self.loss_type = config.loss.loss_type + self.kl_weight = config.loss.kl_weight + self.free_bits = config.loss.free_bits + self.reconstruction_weight = config.loss.get('reconstruction_weight', 1.0) + + self.encoder_no_padding_mode = config.model.encoder.res_block_skip_padding is True and config.model.encoder.res_block_kernel > 1 + self.decoder_no_padding_mode = config.model.decoder.res_block_skip_padding is True and config.model.decoder.res_block_kernel > 1 + + self.skip_nboundary_pixels_from_loss = config.model.skip_nboundary_pixels_from_loss + # initialize the learning rate scheduler params. + self.lr_scheduler_monitor = self.lr_scheduler_mode = None + self._init_lr_scheduler_params(config) + + # enabling reconstruction loss on mixed input + self.mixed_rec_w = 0 + self.mixed_rec_w_step = 0 + self.enable_mixed_rec = False + self.nbr_consistency_w = 0 + self._exclusion_loss_weight = config.loss.get('exclusion_loss_weight', 0) + + if self.loss_type in [ + LossType.ElboMixedReconstruction, LossType.ElboSemiSupMixedReconstruction, + LossType.ElboRestrictedReconstruction + ]: + + self.mixed_rec_w = config.loss.mixed_rec_weight + self.mixed_rec_w_step = config.loss.get('mixed_rec_w_step', 0) + self.enable_mixed_rec = True + if self.loss_type not in [ + LossType.ElboSemiSupMixedReconstruction, LossType.ElboMixedReconstruction, + LossType.ElboRestrictedReconstruction + ] and config.data.use_one_mu_std is False: + raise NotImplementedError( + "This cannot work since now, different channels have different mean. One needs to reweigh the " + "predicted channels and then take their sum. This would then be equivalent to the input.") + elif self.loss_type == LossType.ElboWithNbrConsistency: + self.nbr_consistency_w = config.loss.nbr_consistency_w + assert 'grid_size' in config.data or 'gridsizes' in config.training + self._grid_sz = config.data.grid_size if 'grid_size' in config.data else config.data.image_size + # NeighborConsistencyLoss assumes the batch to be a sequence of [center, left, right, top bottom] images. + self.nbr_consistency_loss = NeighborConsistencyLoss( + self._grid_sz, + nbr_set_count=config.data.get('nbr_set_count', None), + focus_on_opposite_gradients=config.model.offset_prediction_focus_on_opposite_gradients) + + self._global_step = 0 + + # normalized_input: If input is normalized, then we don't normalize the input. + # We then just normalize the target. Otherwise, both input and target are normalized. + self.normalized_input = config.data.normalized_input + + assert (self.data_std is not None) + assert (self.data_mean is not None) + if self.noiseModel is None: + self.likelihood_form = "gaussian" + else: + self.likelihood_form = "noise_model" + + self.downsample = [1] * self.n_layers + + # Downsample by a factor of 2 at each downsampling operation + self.overall_downscale_factor = np.power(2, sum(self.downsample)) + if not config.model.no_initial_downscaling: # by default do another downscaling + self.overall_downscale_factor *= 2 + + assert max(self.downsample) <= self.encoder_blocks_per_layer + assert len(self.downsample) == self.n_layers + + # Get class of nonlinear activation from string description + nonlin = self.get_nonlin() + + # First bottom-up layer: change num channels + downsample by factor 2 + # unless we want to prevent this + stride = 1 if config.model.no_initial_downscaling else 2 + self.first_bottom_up = self.create_first_bottom_up(stride) + self.multiscale_retain_spatial_dims = config.model.multiscale_retain_spatial_dims + self.lowres_first_bottom_ups = self._multiscale_count = None + self._init_multires(config) + + # Init lists of layers + + enable_multiscale = self._multiscale_count is not None and self._multiscale_count > 1 + self.multiscale_decoder_retain_spatial_dims = self.multiscale_retain_spatial_dims and enable_multiscale + self.bottom_up_layers = self.create_bottom_up_layers(config.model.multiscale_lowres_separate_branch) + self.top_down_layers = self.create_top_down_layers() + + # Final top-down layer + self.final_top_down = self.create_final_topdown_layer(not self.no_initial_downscaling) + + self.channel_1_w = config.loss.get('channel_1_w', 1) + self.channel_2_w = config.loss.get('channel_2_w', 1) + + self.likelihood = self.create_likelihood_module() + # gradient norms. updated while training. this is also logged. + self.grad_norm_bottom_up = 0.0 + self.grad_norm_top_down = 0.0 + # PSNR computation on validation. + # self.label1_psnr = RunningPSNR() + # self.label2_psnr = RunningPSNR() + self.channels_psnr = [RunningPSNR() for _ in range(target_ch)] + logvar_ch_needed = self.predict_logvar is not None + self.output_layer = self.parameter_net = nn.Conv2d(self.decoder_n_filters, + self.target_ch * (1 + logvar_ch_needed), + kernel_size=3, + padding=1, + bias=self.topdown_conv2d_bias) + + print( + f'[{self.__class__.__name__}] Stoc:{not self.non_stochastic_version} RecMode:{self.reconstruction_mode} TethInput:{self._tethered_to_input}' + ) + + def create_top_down_layers(self): + top_down_layers = nn.ModuleList([]) + nonlin = self.get_nonlin() + for i in range(self.n_layers): + # Add top-down stochastic layer at level i. + # The architecture when doing inference is roughly as follows: + # p_params = output of top-down layer above + # bu = inferred bottom-up value at this layer + # q_params = merge(bu, p_params) + # z = stochastic_layer(q_params): + # possibly get skip connection from previous top-down layer + # top-down deterministic ResNet + # + # When doing generation only, the value bu is not available, the + # merge layer is not used, and z is sampled directly from p_params. + # + # only apply this normalization with relatively deep networks. + # Whether this is the top layer + is_top = i == self.n_layers - 1 + if self._enable_topdown_normalize_factor: + normalize_latent_factor = 1 / np.sqrt(2 * (1 + i)) if len(self.z_dims) > 4 else 1.0 + else: + normalize_latent_factor = 1.0 + + top_down_layers.append( + TopDownLayer( + z_dim=self.z_dims[i], + n_res_blocks=self.decoder_blocks_per_layer, + n_filters=self.decoder_n_filters, + is_top_layer=is_top, + downsampling_steps=self.downsample[i], + nonlin=nonlin, + merge_type=self.merge_type, + batchnorm=self.topdown_batchnorm, + dropout=self.decoder_dropout, + stochastic_skip=self.stochastic_skip, + learn_top_prior=self.learn_top_prior, + top_prior_param_shape=self.get_top_prior_param_shape(), + res_block_type=self.res_block_type, + res_block_kernel=self.decoder_res_block_kernel, + res_block_skip_padding=self.decoder_res_block_skip_padding, + gated=self.gated, + analytical_kl=self.analytical_kl, + # in no_padding_mode, what gets passed from the encoder are not multiples of 2 and so merging operation does not work natively. + bottomup_no_padding_mode=self.encoder_no_padding_mode, + topdown_no_padding_mode=self.decoder_no_padding_mode, + retain_spatial_dims=self.multiscale_decoder_retain_spatial_dims, + non_stochastic_version=self.non_stochastic_version, + input_image_shape=self.img_shape, + normalize_latent_factor=normalize_latent_factor, + conv2d_bias=self.topdown_conv2d_bias, + stochastic_use_naive_exponential=self._stochastic_use_naive_exponential)) + return top_down_layers + + def get_other_channel(self, ch1, input): + assert self.data_std['target'].squeeze().shape == (2, ) + assert self.data_mean['target'].squeeze().shape == (2, ) + assert self.target_ch == 2 + ch1_un = ch1[:, :1] * self.data_std['target'][:, :1] + self.data_mean['target'][:, :1] + input_un = input * self.data_std['input'] + self.data_mean['input'] + ch2_un = self._tethered_ch2_scalar * (input_un - ch1_un * self._tethered_ch1_scalar) + ch2 = (ch2_un - self.data_mean['target'][:, -1:]) / self.data_std['target'][:, -1:] + return ch2 + + def create_bottom_up_layers(self, lowres_separate_branch): + bottom_up_layers = nn.ModuleList([]) + multiscale_lowres_size_factor = 1 + enable_multiscale = self._multiscale_count is not None and self._multiscale_count > 1 + nonlin = self.get_nonlin() + for i in range(self.n_layers): + # Whether this is the top layer + is_top = i == self.n_layers - 1 + layer_enable_multiscale = enable_multiscale and self._multiscale_count > i + 1 + # if multiscale is enabled, this is the factor by which the lowres tensor will be larger than + multiscale_lowres_size_factor *= (1 + int(layer_enable_multiscale)) + # Add bottom-up deterministic layer at level i. + # It's a sequence of residual blocks (BottomUpDeterministicResBlock) + # possibly with downsampling between them. + output_expected_shape = (self.img_shape[0] // 2**(i + 1), + self.img_shape[1] // 2**(i + 1)) if self._multiscale_count > 1 else None + bottom_up_layers.append( + BottomUpLayer(n_res_blocks=self.encoder_blocks_per_layer, + n_filters=self.encoder_n_filters, + downsampling_steps=self.downsample[i], + nonlin=nonlin, + batchnorm=self.bottomup_batchnorm, + dropout=self.encoder_dropout, + res_block_type=self.res_block_type, + res_block_kernel=self.encoder_res_block_kernel, + res_block_skip_padding=self.encoder_res_block_skip_padding, + gated=self.gated, + lowres_separate_branch=lowres_separate_branch, + enable_multiscale=enable_multiscale, + multiscale_retain_spatial_dims=self.multiscale_retain_spatial_dims, + multiscale_lowres_size_factor=multiscale_lowres_size_factor, + decoder_retain_spatial_dims=self.multiscale_decoder_retain_spatial_dims, + output_expected_shape=output_expected_shape)) + return bottom_up_layers + + def create_final_topdown_layer(self, upsample): + + # Final top-down layer + + modules = list() + if upsample: + modules.append(Interpolate(scale=2)) + for i in range(self.decoder_blocks_per_layer): + modules.append( + TopDownDeterministicResBlock( + c_in=self.decoder_n_filters, + c_out=self.decoder_n_filters, + nonlin=self.get_nonlin(), + batchnorm=self.topdown_batchnorm, + dropout=self.decoder_dropout, + res_block_type=self.res_block_type, + res_block_kernel=self.decoder_res_block_kernel, + skip_padding=self.decoder_res_block_skip_padding, + gated=self.gated, + conv2d_bias=self.topdown_conv2d_bias, + )) + return nn.Sequential(*modules) + + def create_likelihood_module(self): + # Define likelihood + if self.likelihood_form == 'gaussian': + likelihood = GaussianLikelihood(self.decoder_n_filters, + self.target_ch, + predict_logvar=self.predict_logvar, + logvar_lowerbound=self.logvar_lowerbound, + conv2d_bias=self.topdown_conv2d_bias) + elif self.likelihood_form == 'noise_model': + likelihood = NoiseModelLikelihood(self.decoder_n_filters, self.target_ch, self.data_mean, self.data_std, + self.noiseModel) + else: + msg = "Unrecognized likelihood '{}'".format(self.likelihood_form) + raise RuntimeError(msg) + return likelihood + + def create_first_bottom_up(self, init_stride, num_blocks=1): + nonlin = self.get_nonlin() + modules = [ + nn.Conv2d(self.color_ch, + self.encoder_n_filters, + self.encoder_res_block_kernel, + padding=0 if self.encoder_res_block_skip_padding else self.encoder_res_block_kernel // 2, + stride=init_stride), + nonlin() + ] + for _ in range(num_blocks): + modules.append( + BottomUpDeterministicResBlock( + c_in=self.encoder_n_filters, + c_out=self.encoder_n_filters, + nonlin=nonlin, + batchnorm=self.bottomup_batchnorm, + dropout=self.encoder_dropout, + res_block_type=self.res_block_type, + skip_padding=self.encoder_res_block_skip_padding, + res_block_kernel=self.encoder_res_block_kernel, + )) + return nn.Sequential(*modules) + + def _init_multires(self, config): + """ + Initialize everything related to multiresolution approach. + """ + stride = 1 if config.model.no_initial_downscaling else 2 + nonlin = self.get_nonlin() + self._multiscale_count = config.data.multiscale_lowres_count + if self._multiscale_count is None: + self._multiscale_count = 1 + + msg = "Multiscale count({}) should not exceed the number of bottom up layers ({}) by more than 1" + msg = msg.format(config.data.multiscale_lowres_count, len(config.model.z_dims)) + assert self._multiscale_count <= 1 or config.data.multiscale_lowres_count <= 1 + len(config.model.z_dims), msg + + msg = "if multiscale is enabled, then we are just working with monocrome images." + assert self._multiscale_count == 1 or self.color_ch == 1, msg + lowres_first_bottom_ups = [] + for _ in range(1, self._multiscale_count): + first_bottom_up = nn.Sequential( + nn.Conv2d(self.color_ch, self.encoder_n_filters, 5, padding=2, stride=stride), nonlin(), + BottomUpDeterministicResBlock( + c_in=self.encoder_n_filters, + c_out=self.encoder_n_filters, + nonlin=nonlin, + batchnorm=self.bottomup_batchnorm, + dropout=self.encoder_dropout, + res_block_type=self.res_block_type, + skip_padding=self.encoder_res_block_skip_padding, + )) + lowres_first_bottom_ups.append(first_bottom_up) + + self.lowres_first_bottom_ups = nn.ModuleList(lowres_first_bottom_ups) if len(lowres_first_bottom_ups) else None + + def get_nonlin(self): + nonlin = { + 'relu': nn.ReLU, + 'leakyrelu': nn.LeakyReLU, + 'elu': nn.ELU, + 'selu': nn.SELU, + } + return nonlin[self.nonlin] + + def increment_global_step(self): + """Increments global step by 1.""" + self._global_step += 1 + + @property + def global_step(self) -> int: + """Global step.""" + return self._global_step + + def _init_lr_scheduler_params(self, config): + self.lr_scheduler_monitor = config.model.get('monitor', 'val_loss') + self.lr_scheduler_mode = MetricMonitor(self.lr_scheduler_monitor).mode() + + def configure_optimizers(self): + optimizer = optim.Adamax(self.parameters(), lr=self.lr, weight_decay=0) + scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, + self.lr_scheduler_mode, + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + + return {'optimizer': optimizer, 'lr_scheduler': scheduler, 'monitor': self.lr_scheduler_monitor} + + def get_kl_weight(self): + if (self.kl_annealing == True): + # calculate relative weight + kl_weight = (self.current_epoch - self.kl_start) * (1.0 / self.kl_annealtime) + # clamp to [0,1] + kl_weight = min(max(0.0, kl_weight), 1.0) + + # if the final weight is given, then apply that weight on top of it + if self.kl_weight is not None: + kl_weight = kl_weight * self.kl_weight + + elif self.kl_weight is not None: + return self.kl_weight + else: + kl_weight = 1.0 + return kl_weight + + def get_reconstruction_loss(self, + reconstruction, + target, + input, + splitting_mask=None, + return_predicted_img=False, + likelihood_obj=None): + output = self._get_reconstruction_loss_vector(reconstruction, + target, + input, + return_predicted_img=return_predicted_img, + likelihood_obj=likelihood_obj) + loss_dict = output[0] if return_predicted_img else output + if splitting_mask is None: + splitting_mask = torch.ones_like(loss_dict['loss']).bool() + + # print(len(target) - (torch.isnan(loss_dict['loss'])).sum()) + + loss_dict['loss'] = loss_dict['loss'][splitting_mask].sum() / len(reconstruction) + for i in range(1, 1 + target.shape[1]): + key = 'ch{}_loss'.format(i) + loss_dict[key] = loss_dict[key][splitting_mask].sum() / len(reconstruction) + + if 'mixed_loss' in loss_dict: + loss_dict['mixed_loss'] = torch.mean(loss_dict['mixed_loss']) + if return_predicted_img: + assert len(output) == 2 + return loss_dict, output[1] + else: + return loss_dict + + def reset_for_different_output_size(self, output_size): + for i in range(self.n_layers): + sz = output_size // 2**(1 + i) + self.bottom_up_layers[i].output_expected_shape = (sz, sz) + self.top_down_layers[i].latent_shape = (output_size, output_size) + + def get_mixed_prediction(self, prediction, prediction_logvar, data_mean, data_std, channel_weights=None): + pred_unorm = prediction * data_std['target'] + data_mean['target'] + if channel_weights is None: + channel_weights = 1 + + if self._input_is_sum: + mixed_prediction = torch.sum(pred_unorm * channel_weights, dim=1, keepdim=True) + else: + mixed_prediction = torch.mean(pred_unorm * channel_weights, dim=1, keepdim=True) + + mixed_prediction = (mixed_prediction - data_mean['input'].mean()) / data_std['input'].mean() + + if prediction_logvar is not None: + if data_std['target'].shape == data_std['input'].shape and torch.all( + data_std['target'] == data_std['input']): + assert channel_weights == 1 + logvar = prediction_logvar + else: + var = torch.exp(prediction_logvar) + var = var * (data_std['target'] / data_std['input'])**2 + if channel_weights != 1: + var = var * torch.square(channel_weights) + + # sum of variance. + mixed_var = 0 + for i in range(var.shape[1]): + mixed_var += var[:, i:i + 1] + + logvar = torch.log(mixed_var) + else: + logvar = None + return mixed_prediction, logvar + + def _get_weighted_likelihood(self, ll): + """ + each of the channels gets multiplied with a different weight. + """ + if self.ch1_recons_w == 1 and self.ch2_recons_w == 1: + return ll + assert ll.shape[1] == 2, "This function is only for 2 channel images" + mask1 = torch.zeros((len(ll), ll.shape[1], 1, 1), device=ll.device) + mask1[:, 0] = 1 + + mask2 = torch.zeros((len(ll), ll.shape[1], 1, 1), device=ll.device) + mask2[:, 1] = 1 + return ll * mask1 * self.ch1_recons_w + ll * mask2 * self.ch2_recons_w + + def _get_reconstruction_loss_vector(self, + reconstruction, + target, + input, + return_predicted_img=False, + likelihood_obj=None): + """ + Args: + return_predicted_img: If set to True, the besides the loss, the reconstructed image is also returned. + """ + + output = { + 'loss': None, + 'mixed_loss': None, + } + for i in range(1, 1 + target.shape[1]): + output['ch{}_loss'.format(i)] = None + + if likelihood_obj is None: + likelihood_obj = self.likelihood + + # Log likelihood + ll, like_dict = likelihood_obj(reconstruction, target) + ll = self._get_weighted_likelihood(ll) + if self.skip_nboundary_pixels_from_loss is not None and self.skip_nboundary_pixels_from_loss > 0: + pad = self.skip_nboundary_pixels_from_loss + ll = ll[:, :, pad:-pad, pad:-pad] + like_dict['params']['mean'] = like_dict['params']['mean'][:, :, pad:-pad, pad:-pad] + + # assert ll.shape[1] == 2, f"Change the code below to handle >2 channels first. ll.shape {ll.shape}" + output = { + 'loss': compute_batch_mean(-1 * ll), + } + if ll.shape[1] > 1: + for i in range(1, 1 + target.shape[1]): + output['ch{}_loss'.format(i)] = compute_batch_mean(-ll[:, i - 1]) + else: + assert ll.shape[1] == 1 + output['ch1_loss'] = output['loss'] + output['ch2_loss'] = output['loss'] + + if self.channel_1_w is not None and self.channel_2_w is not None and (self.channel_1_w != 1 + or self.channel_2_w != 1): + assert ll.shape[1] == 2, "Only 2 channels are supported for now." + output['loss'] = (self.channel_1_w * output['ch1_loss'] + + self.channel_2_w * output['ch2_loss']) / (self.channel_1_w + self.channel_2_w) + + if self.enable_mixed_rec: + mixed_pred, mixed_logvar = self.get_mixed_prediction(like_dict['params']['mean'], + like_dict['params']['logvar'], self.data_mean, + self.data_std) + if self._multiscale_count is not None and self._multiscale_count > 1: + assert input.shape[1] == self._multiscale_count + input = input[:, :1] + + assert input.shape == mixed_pred.shape, "No fucking room for vectorization induced bugs." + mixed_recons_ll = self.likelihood.log_likelihood(input, {'mean': mixed_pred, 'logvar': mixed_logvar}) + output['mixed_loss'] = compute_batch_mean(-1 * mixed_recons_ll) + + if self._exclusion_loss_weight: + imgs = like_dict['params']['mean'] + exclusion_loss = compute_exclusion_loss(imgs[:, :1], imgs[:, 1:]) + output['exclusion_loss'] = exclusion_loss + + if return_predicted_img: + return output, like_dict['params']['mean'] + + return output + + def get_kl_divergence_loss_usplit(self, topdown_layer_data_dict): + kl = torch.cat([kl_layer.unsqueeze(1) for kl_layer in topdown_layer_data_dict['kl']], dim=1) + # kl.shape = (16,4) 16 is batch size. 4 is number of layers. Values are sum() and so are of the order 30000 + # Example values: 30626.6758, 31028.8145, 29509.8809, 29945.4922, 28919.1875, 29075.2988 + nlayers = kl.shape[1] + for i in range(nlayers): + # topdown_layer_data_dict['z'][2].shape[-3:] = 128 * 32 * 32 + kl[:, i] = kl[:, i] / np.prod(topdown_layer_data_dict['z'][i].shape[-3:]) + + kl_loss = free_bits_kl(kl, self.free_bits).mean() + return kl_loss + + def get_kl_divergence_loss(self, topdown_layer_data_dict): + # kl[i] for each i has length batch_size + # resulting kl shape: (batch_size, layers) + kl = torch.cat([kl_layer.unsqueeze(1) for kl_layer in topdown_layer_data_dict['kl']], dim=1) + # As compared to uSplit kl divergence, + # more by a factor of 4 just because we do sum and not mean. + kl_loss = free_bits_kl(kl, self.free_bits).sum() + # at each hierarchy, it is more by a factor of 128/i**2). + # 128/(2*2) = 32 (bottommost layer) + # 128/(4*4) = 8 + # 128/(8*8) = 2 + # 128/(16*16) = 0.5 (topmost layer) + kl_loss = kl_loss / np.prod(self.img_shape) + return kl_loss + + def training_step(self, batch, batch_idx, enable_logging=True): + if self.current_epoch == 0 and batch_idx == 0: + self.log('val_psnr', 1.0, on_epoch=True) + + x, target = batch[:2] + x_normalized = self.normalize_input(x) + if self.reconstruction_mode: + target_normalized = x_normalized[:, :1].repeat(1, 2, 1, 1) + target = None + mask = None + else: + target_normalized = self.normalize_target(target) + mask = ~((target == 0).reshape(len(target), -1).all(dim=1)) + + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + # mask = torch.isnan(target.reshape(len(x), -1)).all(dim=1) + recons_loss_dict, imgs = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + mask, + return_predicted_img=True) + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = recons_loss_dict['loss'] * self.reconstruction_weight + if torch.isnan(recons_loss).any(): + recons_loss = 0.0 + + if self.loss_type == LossType.ElboMixedReconstruction: + recons_loss += self.mixed_rec_w * recons_loss_dict['mixed_loss'] + + if enable_logging: + self.log('mixed_reconstruction_loss', recons_loss_dict['mixed_loss'], on_epoch=True) + + if self._exclusion_loss_weight: + exclusion_loss = recons_loss_dict['exclusion_loss'] + recons_loss += self._exclusion_loss_weight * exclusion_loss + if enable_logging: + self.log('exclusion_loss', exclusion_loss, on_epoch=True) + + elif self.loss_type == LossType.ElboWithNbrConsistency: + assert len(batch) == 4 + grid_sizes = batch[-1] + nbr_cons_loss = self.nbr_consistency_w * self.nbr_consistency_loss.get(imgs, grid_sizes=grid_sizes) + self.log('nbr_cons_loss', nbr_cons_loss.item(), on_epoch=True) + recons_loss += nbr_cons_loss + + if self.non_stochastic_version: + kl_loss = torch.Tensor([0.0]).cuda() + net_loss = recons_loss + else: + kl_loss = self.get_kl_divergence_loss( + td_data) if self.kl_loss_formulation != 'usplit' else self.get_kl_divergence_loss_usplit(td_data) + + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + # print(f'rec:{recons_loss_dict["loss"]:.3f} mix: {recons_loss_dict.get("mixed_loss",0):.3f} KL: {kl_loss:.3f}') + if enable_logging: + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + if self._tethered_ch2_scalar is not None: + self.log('tethered_ch2_scalar', self._tethered_ch2_scalar, on_epoch=True) + self.log('tethered_ch1_scalar', self._tethered_ch1_scalar, on_epoch=True) + + # self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + # self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach() if isinstance(recons_loss, torch.Tensor) else recons_loss, + 'kl_loss': kl_loss.detach(), + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def normalize_input(self, x): + if self.normalized_input: + return x + return (x - self.data_mean['input'].mean()) / self.data_std['input'].mean() + + def normalize_target(self, target, batch=None): + return (target - self.data_mean['target']) / self.data_std['target'] + + def unnormalize_target(self, target_normalized): + return target_normalized * self.data_std['target'] + self.data_mean['target'] + + def power_of_2(self, x): + assert isinstance(x, int) + if x == 1: + return True + if x == 0: + # happens with validation + return False + if x % 2 == 1: + return False + return self.power_of_2(x // 2) + + def set_params_to_same_device_as(self, correct_device_tensor): + self.likelihood.set_params_to_same_device_as(correct_device_tensor) + if isinstance(self.data_mean, torch.Tensor): + if self.data_mean.device != correct_device_tensor.device: + self.data_mean = self.data_mean.to(correct_device_tensor.device) + self.data_std = self.data_std.to(correct_device_tensor.device) + elif isinstance(self.data_mean, dict): + for k, v in self.data_mean.items(): + if v.device != correct_device_tensor.device: + self.data_mean[k] = v.to(correct_device_tensor.device) + self.data_std[k] = self.data_std[k].to(correct_device_tensor.device) + + def validation_step(self, batch, batch_idx): + x, target = batch[:2] + self.set_params_to_same_device_as(x) + x_normalized = self.normalize_input(x) + if self.reconstruction_mode: + target_normalized = x_normalized[:, :1].repeat(1, 2, 1, 1) + target = None + mask = None + else: + target_normalized = self.normalize_target(target) + mask = ~((target == 0).reshape(len(target), -1).all(dim=1)) + + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, recons_img = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + mask, + return_predicted_img=True) + if self._dump_kth_frame_prediction is not None: + if self.current_epoch == 0: + self._val_frame_creator.update_target(target.cpu().numpy().astype(np.int32), + batch[-1].cpu().numpy().astype(np.int32)) + if self.current_epoch == 0 or self.current_epoch % self._dump_epoch_interval == 0: + imgs = self.unnormalize_target(recons_img).cpu().numpy().astype(np.int32) + self._val_frame_creator.update(imgs, batch[-1].cpu().numpy().astype(np.int32)) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + channels_rinvpsnr = [] + for i in range(recons_img.shape[1]): + self.channels_psnr[i].update(recons_img[:, i], target_normalized[:, i]) + psnr = RangeInvariantPsnr(target_normalized[:, i].clone(), recons_img[:, i].clone()) + channels_rinvpsnr.append(psnr) + psnr = torch_nanmean(psnr).item() + self.log(f'val_psnr_l{i+1}', psnr, on_epoch=True) + + recons_loss = recons_loss_dict['loss'] + if torch.isnan(recons_loss).any(): + return + + self.log('val_loss', recons_loss, on_epoch=True) + # self.log('val_psnr', (val_psnr_l1 + val_psnr_l2) / 2, on_epoch=True) + + # if batch_idx == 0 and self.power_of_2(self.current_epoch): + # all_samples = [] + # for i in range(20): + # sample, _ = self(x_normalized[0:1, ...]) + # sample = self.likelihood.get_mean_lv(sample)[0] + # all_samples.append(sample[None]) + + # all_samples = torch.cat(all_samples, dim=0) + # all_samples = all_samples * self.data_std + self.data_mean + # all_samples = all_samples.cpu() + # img_mmse = torch.mean(all_samples, dim=0)[0] + # self.log_images_for_tensorboard(all_samples[:, 0, 0, ...], target[0, 0, ...], img_mmse[0], 'label1') + # self.log_images_for_tensorboard(all_samples[:, 0, 1, ...], target[0, 1, ...], img_mmse[1], 'label2') + + # return net_loss + + def on_validation_epoch_end(self): + psnr_arr = [] + for i in range(len(self.channels_psnr)): + psnr = self.channels_psnr[i].get() + if psnr is None: + psnr_arr = None + break + psnr_arr.append(psnr.cpu().numpy()) + self.channels_psnr[i].reset() + + if psnr_arr is not None: + psnr = np.mean(psnr_arr) + self.log('val_psnr', psnr, on_epoch=True) + else: + self.log('val_psnr', 0.0, on_epoch=True) + + if self._dump_kth_frame_prediction is not None: + if self.current_epoch == 1: + self._val_frame_creator.dump_target() + if self.current_epoch == 0 or self.current_epoch % self._dump_epoch_interval == 0: + self._val_frame_creator.dump(self.current_epoch) + self._val_frame_creator.reset() + + if self.mixed_rec_w_step: + self.mixed_rec_w = max(self.mixed_rec_w - self.mixed_rec_w_step, 0.0) + self.log('mixed_rec_w', self.mixed_rec_w, on_epoch=True) + + def forward(self, x): + img_size = x.size()[2:] + + # Pad input to make everything easier with conv strides + x_pad = self.pad_input(x) + + # Bottom-up inference: return list of length n_layers (bottom to top) + bu_values = self.bottomup_pass(x_pad) + for i in range(0, self.skip_bottomk_buvalues): + bu_values[i] = None + + mode_layers = range(self.n_layers) if self.non_stochastic_version else None + # Top-down inference/generation + out, td_data = self.topdown_pass(bu_values, mode_layers=mode_layers) + + if out.shape[-1] > img_size[-1]: + # Restore original image size + out = crop_img_tensor(out, img_size) + + out = self.output_layer(out) + if self._tethered_to_input: + assert out.shape[1] == 1 + ch2 = self.get_other_channel(out, x_pad) + out = torch.cat([out, ch2], dim=1) + + return out, td_data + + def bottomup_pass(self, inp): + return self._bottomup_pass(inp, self.first_bottom_up, self.lowres_first_bottom_ups, self.bottom_up_layers) + + def _bottomup_pass(self, inp, first_bottom_up, lowres_first_bottom_ups, bottom_up_layers): + + if self._multiscale_count > 1: + # Bottom-up initial layer. The first channel is the original input, what we want to reconstruct. + # later channels are simply to yield more context. + x = first_bottom_up(inp[:, :1]) + else: + x = first_bottom_up(inp) + + # Loop from bottom to top layer, store all deterministic nodes we + # need in the top-down pass + bu_values = [] + for i in range(self.n_layers): + lowres_x = None + if self._multiscale_count > 1 and i + 1 < inp.shape[1]: + lowres_x = lowres_first_bottom_ups[i](inp[:, i + 1:i + 2]) + + x, bu_value = bottom_up_layers[i](x, lowres_x=lowres_x) + bu_values.append(bu_value) + + return bu_values + + def sample_from_q(self, x, masks=None): + img_size = x.size()[2:] + + # Pad input to make everything easier with conv strides + x_pad = self.pad_input(x) + + # Bottom-up inference: return list of length n_layers (bottom to top) + bu_values = self.bottomup_pass(x_pad) + return self._sample_from_q(bu_values, masks=masks) + + def _sample_from_q(self, bu_values, top_down_layers=None, final_top_down_layer=None, masks=None): + if top_down_layers is None: + top_down_layers = self.top_down_layers + if final_top_down_layer is None: + final_top_down_layer = self.final_top_down + if masks is None: + masks = [None] * len(bu_values) + + msg = "Multiscale is not supported as of now. You need the output from the previous layers to do this." + assert self.n_layers == 1, msg + samples = [] + for i in reversed(range(self.n_layers)): + bu_value = bu_values[i] + + # Note that the first argument can be set to None since we are just dealing with one level + sample = top_down_layers[i].sample_from_q(None, bu_value, var_clip_max=self._var_clip_max, mask=masks[i]) + samples.append(sample) + + return samples + + def topdown_pass(self, + bu_values=None, + n_img_prior=None, + mode_layers=None, + constant_layers=None, + forced_latent=None, + top_down_layers=None, + final_top_down_layer=None): + """ + Args: + bu_values: Output of the bottom-up pass. It will have values from multiple layers of the ladder. + n_img_prior: bu_values needs to be none for this. This generates n images from the prior. So, it does + not use bottom up pass at all. + mode_layers: At these layers, sampling is disabled. Mean value is used directly. + constant_layers: Here, a single instance's z is copied over the entire batch. Also, bottom-up path is not used. + So, only prior is used here. + forced_latent: Here, latent vector is not sampled but taken from here. + """ + if top_down_layers is None: + top_down_layers = self.top_down_layers + if final_top_down_layer is None: + final_top_down_layer = self.final_top_down + + # Default: no layer is sampled from the distribution's mode + if mode_layers is None: + mode_layers = [] + if constant_layers is None: + constant_layers = [] + prior_experiment = len(mode_layers) > 0 or len(constant_layers) > 0 + + # If the bottom-up inference values are not given, don't do + # inference, sample from prior instead + inference_mode = bu_values is not None + + # Check consistency of arguments + if inference_mode != (n_img_prior is None): + msg = ("Number of images for top-down generation has to be given " + "if and only if we're not doing inference") + raise RuntimeError(msg) + if inference_mode and prior_experiment and (self.non_stochastic_version is False): + msg = ("Prior experiments (e.g. sampling from mode) are not" + " compatible with inference mode") + raise RuntimeError(msg) + + # Sampled latent variables at each layer + z = [None] * self.n_layers + + # KL divergence of each layer + kl = [None] * self.n_layers + + # mean from which z is sampled. + q_mu = [None] * self.n_layers + # log(var) from which z is sampled. + q_lv = [None] * self.n_layers + + # Spatial map of KL divergence for each layer + kl_spatial = [None] * self.n_layers + + debug_qvar_max = [None] * self.n_layers + + kl_channelwise = [None] * self.n_layers + if forced_latent is None: + forced_latent = [None] * self.n_layers + + # log p(z) where z is the sample in the topdown pass + # logprob_p = 0. + + # Top-down inference/generation loop + out = out_pre_residual = None + for i in reversed(range(self.n_layers)): + + # If available, get deterministic node from bottom-up inference + try: + bu_value = bu_values[i] + except TypeError: + bu_value = None + + # Whether the current layer should be sampled from the mode + use_mode = i in mode_layers + constant_out = i in constant_layers + use_uncond_mode = i in self.use_uncond_mode_at + + # Input for skip connection + skip_input = out # TODO or n? or both? + + # Full top-down layer, including sampling and deterministic part + out, out_pre_residual, aux = top_down_layers[i](out, + skip_connection_input=skip_input, + inference_mode=inference_mode, + bu_value=bu_value, + n_img_prior=n_img_prior, + use_mode=use_mode, + force_constant_output=constant_out, + forced_latent=forced_latent[i], + mode_pred=self.mode_pred, + use_uncond_mode=use_uncond_mode, + var_clip_max=self._var_clip_max) + z[i] = aux['z'] # sampled variable at this layer (batch, ch, h, w) + kl[i] = aux['kl_samplewise'] # (batch, ) + kl_spatial[i] = aux['kl_spatial'] # (batch, h, w) + q_mu[i] = aux['q_mu'] + q_lv[i] = aux['q_lv'] + + kl_channelwise[i] = aux['kl_channelwise'] + debug_qvar_max[i] = aux['qvar_max'] + # if self.mode_pred is False: + # logprob_p += aux['logprob_p'].mean() # mean over batch + # else: + # logprob_p = None + # Final top-down layer + out = final_top_down_layer(out) + + data = { + 'z': z, # list of tensors with shape (batch, ch[i], h[i], w[i]) + 'kl': kl, # list of tensors with shape (batch, ) + 'kl_spatial': kl_spatial, # list of tensors w shape (batch, h[i], w[i]) + 'kl_channelwise': kl_channelwise, # list of tensors with shape (batch, ch[i]) + # 'logprob_p': logprob_p, # scalar, mean over batch + 'q_mu': q_mu, + 'q_lv': q_lv, + 'debug_qvar_max': debug_qvar_max, + } + return out, data + + def pad_input(self, x): + """ + Pads input x so that its sizes are powers of 2 + :param x: + :return: Padded tensor + """ + size = self.get_padded_size(x.size()) + x = pad_img_tensor(x, size) + return x + + def get_padded_size(self, size): + """ + Returns the smallest size (H, W) of the image with actual size given + as input, such that H and W are powers of 2. + :param size: input size, tuple either (N, C, H, w) or (H, W) + :return: 2-tuple (H, W) + """ + + # Make size argument into (heigth, width) + if len(size) == 4: + size = size[2:] + if len(size) != 2: + msg = ("input size must be either (N, C, H, W) or (H, W), but it " + "has length {} (size={})".format(len(size), size)) + raise RuntimeError(msg) + + if self.multiscale_decoder_retain_spatial_dims is True: + # In this case, we can go much more deeper and so this is not required + # (in the way it is. ;). More work would be needed if this was to be correctly implemented ) + return list(size) + + # Overall downscale factor from input to top layer (power of 2) + dwnsc = self.overall_downscale_factor + + # Output smallest powers of 2 that are larger than current sizes + padded_size = list(((s - 1) // dwnsc + 1) * dwnsc for s in size) + + return padded_size + + def sample_prior(self, n_imgs, mode_layers=None, constant_layers=None): + + # Generate from prior + out, _ = self.topdown_pass(n_img_prior=n_imgs, mode_layers=mode_layers, constant_layers=constant_layers) + out = crop_img_tensor(out, self.img_shape) + + # Log likelihood and other info (per data point) + _, likelihood_data = self.likelihood(out, None) + + return likelihood_data['sample'] + + def get_top_prior_param_shape(self, n_imgs=1): + # TODO num channels depends on random variable we're using + + if self.multiscale_decoder_retain_spatial_dims is False: + dwnsc = self.overall_downscale_factor + else: + actual_downsampling = self.n_layers + 1 - self._multiscale_count + dwnsc = 2**actual_downsampling + + sz = self.get_padded_size(self.img_shape) + h = sz[0] // dwnsc + w = sz[1] // dwnsc + c = self.z_dims[-1] * 2 # mu and logvar + top_layer_shape = (n_imgs, c, h, w) + return top_layer_shape + + def log_images_for_tensorboard(self, pred, target, img_mmse, label): + clamped_pred = torch.clamp((pred - pred.min()) / (pred.max() - pred.min()), 0, 1) + clamped_mmse = torch.clamp((img_mmse - img_mmse.min()) / (img_mmse.max() - img_mmse.min()), 0, 1) + if target is not None: + clamped_input = torch.clamp((target - target.min()) / (target.max() - target.min()), 0, 1) + img = wandb.Image(clamped_input[None].cpu().numpy()) + self.logger.experiment.log({f'target_for{label}': img}) + # self.trainer.logger.experiment.add_image(f'target_for{label}', clamped_input[None], self.current_epoch) + for i in range(3): + # self.trainer.logger.experiment.add_image(f'{label}/sample_{i}', clamped_pred[i:i + 1], self.current_epoch) + img = wandb.Image(clamped_pred[i:i + 1].cpu().numpy()) + self.logger.experiment.log({f'{label}/sample_{i}': img}) + + img = wandb.Image(clamped_mmse[None].cpu().numpy()) + self.trainer.logger.experiment.log({f'{label}/mmse (100 samples)': img}) + + +if __name__ == '__main__': + import numpy as np + import torch + + # from denoisplit.configs.microscopy_multi_channel_lvae_config import get_config + from denoisplit.configs.biosr_supervised_config import get_config + config = get_config() + data_mean = torch.Tensor([0]).reshape(1, 1, 1, 1) + # copy twice along 2nd dimensiion + data_std = torch.Tensor([1]).reshape(1, 1, 1, 1) + model = LadderVAE({ + 'input': data_mean, + 'target': data_mean.repeat(1, 2, 1, 1) + }, { + 'input': data_std, + 'target': data_std.repeat(1, 2, 1, 1) + }, config) + mc = 1 if config.data.multiscale_lowres_count is None else config.data.multiscale_lowres_count + inp = torch.rand((2, mc, config.data.image_size, config.data.image_size)) + out, td_data = model(inp) + batch = ( + torch.rand((16, mc, config.data.image_size, config.data.image_size)), + torch.rand((16, 2, config.data.image_size, config.data.image_size)), + ) + model.training_step(batch, 0) + model.validation_step(batch, 0) + + ll = torch.ones((12, 2, 32, 32)) + ll_new = model._get_weighted_likelihood(ll) + print(ll_new[:, 0].mean(), ll_new[:, 0].std()) + print(ll_new[:, 1].mean(), ll_new[:, 1].std()) + print('mar') diff --git a/denoisplit/nets/lvae_bleedthrough.py b/denoisplit/nets/lvae_bleedthrough.py new file mode 100644 index 0000000..b7bc547 --- /dev/null +++ b/denoisplit/nets/lvae_bleedthrough.py @@ -0,0 +1,253 @@ +""" +This model is created to handle the bleedthrough effect. +""" +from distutils.command.config import config + +from numpy import dtype +from denoisplit.nets.lvae import LadderVAE, compute_batch_mean, torch_nanmean +import torch +from denoisplit.core.loss_type import LossType +from denoisplit.core.psnr import RangeInvariantPsnr +from denoisplit.data_loader.pavia2_enums import Pavia2BleedthroughType + + +def empty_tensor(tens): + """ + Returns true if there are no elements in this tensor. + """ + return tens.nelement() == 0 + + +class LadderVAEWithMixedRecons(LadderVAE): + """ + Ex: Pavia2 dataset. + Here, we work with 2 data sources. For one data source, we have both channels. + For the other, we just have one channel and the input. Here, we apply the mixed reconstruction loss. + + """ + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=3): + super().__init__(data_mean, data_std, config, use_uncond_mode_at=use_uncond_mode_at, target_ch=target_ch) + assert isinstance(self.data_mean, dict) + self.data_mean['target'] = torch.Tensor(self.data_mean['target']) + self.data_mean['mix'] = torch.Tensor(self.data_mean['mix']) + + self.data_std['target'] = torch.Tensor(self.data_std['target']) + self.data_std['mix'] = torch.Tensor(self.data_std['mix']) + self.rec_loss_ch_w = config.loss.get('rec_loss_channel_weights',None) + print(f'[{self.__class__.__name__}] Ch weights: {self.rec_loss_ch_w}') + + def normalize_input(self, x): + if self.normalized_input: + return x + return (x - self.data_mean['mix']) / self.data_std['mix'] + + def normalize_target(self, target): + return (target - self.data_mean['target']) / self.data_std['target'] + + def get_reconstruction_loss(self, reconstruction, input, target, return_predicted_img=False): + if empty_tensor(reconstruction): + return None, None + + output = self._get_reconstruction_loss_vector(reconstruction, + input, + target, + return_predicted_img=return_predicted_img) + loss_dict = output[0] if return_predicted_img else output + + if return_predicted_img: + assert len(output) == 2 + return loss_dict, output[1] + else: + return loss_dict + + def get_mixed_prediction(self, prediction, prediction_logvar): + + pred_unorm = prediction * self.data_std['target'] + self.data_mean['target'] + + mixed_prediction = (torch.sum(pred_unorm, dim=1, keepdim=True) - self.data_mean['mix']) / self.data_std['mix'] + + var = torch.exp(prediction_logvar) + var = var * (self.data_std['target'] / self.data_std['mix'])**2 + # sum of variance. + mixed_var = 0 + for i in range(var.shape[1]): + mixed_var += var[:, i:i + 1] + + logvar = torch.log(mixed_var) + + return mixed_prediction, logvar + + def _get_reconstruction_loss_vector(self, reconstruction, input, target, return_predicted_img=False): + """ + Args: + return_predicted_img: If set to True, the besides the loss, the reconstructed image is also returned. + """ + + # Log likelihood + ll, like_dict = self.likelihood(reconstruction, target) + if self.skip_nboundary_pixels_from_loss is not None and self.skip_nboundary_pixels_from_loss > 0: + pad = self.skip_nboundary_pixels_from_loss + ll = ll[:, :, pad:-pad, pad:-pad] + like_dict['params']['mean'] = like_dict['params']['mean'][:, :, pad:-pad, pad:-pad] + + recons_loss = compute_batch_mean(-1 * ll) + output = { + 'loss': recons_loss if self.rec_loss_ch_w is None else 0, + } + for ch_idx in range(ll.shape[1]): + ch_idx_loss = compute_batch_mean(-ll[:, ch_idx]) + output[f'ch{ch_idx}_loss'] = ch_idx_loss + if self.rec_loss_ch_w is not None: + assert len(self.rec_loss_ch_w) == ll.shape[1] + output['loss'] += (self.rec_loss_ch_w[ch_idx] * ch_idx_loss)/sum(self.rec_loss_ch_w) + + + + assert self.enable_mixed_rec is True + mixed_pred, mixed_logvar = self.get_mixed_prediction(like_dict['params']['mean'], like_dict['params']['logvar']) + + mixed_target = input + mixed_recons_ll = self.likelihood.log_likelihood(mixed_target, {'mean': mixed_pred, 'logvar': mixed_logvar}) + output['mixed_loss'] = compute_batch_mean(-1 * mixed_recons_ll) + + if return_predicted_img: + return output, like_dict['params']['mean'] + + return output + + def training_step(self, batch, batch_idx, enable_logging=True): + x, target, mixed_recons_flag = batch + self.set_params_to_same_device_as(target) + + x_normalized = self.normalize_input(x) + # TODO: check normalization. it is so because nucleus is from two datasets. + target_normalized = self.normalize_target(target) + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + clean_mask = mixed_recons_flag == Pavia2BleedthroughType.Clean + recons_loss_dict, _ = self.get_reconstruction_loss(out, + x_normalized, + target_normalized, + return_predicted_img=True) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + channel_recons_loss = 0 + if recons_loss_dict is not None and clean_mask.sum() > 0: + channel_recons_loss = torch.mean(recons_loss_dict['loss'][clean_mask]) + + assert self.loss_type == LossType.ElboMixedReconstruction + input_recons_loss = recons_loss_dict['mixed_loss'].mean() + recons_loss = channel_recons_loss + self.mixed_rec_w * input_recons_loss + + kl_loss = self.get_kl_divergence_loss(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + if enable_logging: + self.log('mixed_reconstruction_loss', input_recons_loss, on_epoch=True) + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + if channel_recons_loss != 0: + self.log('channel_recons_loss', channel_recons_loss, on_epoch=True) + self.log('input_recons_loss', input_recons_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach(), + 'kl_loss': kl_loss.detach(), + } + + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def validation_step(self, batch, batch_idx): + x, target, _ = batch + self.set_params_to_same_device_as(target) + + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, recons_img = self.get_reconstruction_loss(out, + x_normalized, + target_normalized, + return_predicted_img=True) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + self.label1_psnr.update(recons_img[:, 0], target_normalized[:, 0]) + self.label2_psnr.update(recons_img[:, 1], target_normalized[:, 1]) + + psnr_label1 = RangeInvariantPsnr(target_normalized[:, 0].clone(), recons_img[:, 0].clone()) + psnr_label2 = RangeInvariantPsnr(target_normalized[:, 1].clone(), recons_img[:, 1].clone()) + recons_loss = recons_loss_dict['loss'] + # kl_loss = self.get_kl_divergence_loss(td_data) + # net_loss = recons_loss + self.get_kl_weight() * kl_loss + self.log('val_loss', recons_loss, on_epoch=True) + val_psnr_l1 = torch_nanmean(psnr_label1).item() + val_psnr_l2 = torch_nanmean(psnr_label2).item() + self.log('val_psnr_l1', val_psnr_l1, on_epoch=True) + self.log('val_psnr_l2', val_psnr_l2, on_epoch=True) + # self.log('val_psnr', (val_psnr_l1 + val_psnr_l2) / 2, on_epoch=True) + + if batch_idx == 0 and self.power_of_2(self.current_epoch): + all_samples = [] + for i in range(20): + sample, _ = self(x_normalized[0:1, ...]) + sample = self.likelihood.get_mean_lv(sample)[0] + all_samples.append(sample[None]) + + all_samples = torch.cat(all_samples, dim=0) + all_samples = all_samples * self.data_std['target'] + self.data_mean['target'] + all_samples = all_samples.cpu() + img_mmse = torch.mean(all_samples, dim=0)[0] + self.log_images_for_tensorboard(all_samples[:, 0, 0, ...], target[0, 0, ...], img_mmse[0], 'label1') + self.log_images_for_tensorboard(all_samples[:, 0, 1, ...], target[0, 1, ...], img_mmse[1], 'label2') + + def set_params_to_same_device_as(self, correct_device_tensor): + if isinstance(self.data_mean['mix'], torch.Tensor): + if self.data_mean['mix'].device != correct_device_tensor.device: + self.data_mean['mix'] = self.data_mean['mix'].to(correct_device_tensor.device) + self.data_mean['target'] = self.data_mean['target'].to(correct_device_tensor.device) + self.data_std['mix'] = self.data_std['mix'].to(correct_device_tensor.device) + self.data_std['target'] = self.data_std['target'].to(correct_device_tensor.device) + + self.likelihood.set_params_to_same_device_as(correct_device_tensor) + + +if __name__ == '__main__': + import numpy as np + from denoisplit.configs.pavia2_config import get_config + data_mean = { + 'target': np.array([0.0, 10.0], dtype=np.float32).reshape(1, 2, 1, 1), + 'mix': np.array([110.0], dtype=np.float32).reshape(1, 1, 1, 1), + } + data_std = { + 'target': np.array([1.0, 5], dtype=np.float32).reshape(1, 2, 1, 1), + 'mix': np.array([25.0], dtype=np.float32).reshape(1, 1, 1, 1), + } + config = get_config() + model = LadderVAEWithMixedRecons(data_mean, data_std, config) + x = torch.rand((32, 1, 64, 64), dtype=torch.float32) + target = torch.rand((32, 2, 64, 64), dtype=torch.float32) + mixed_recons_flag = torch.Tensor(np.array([1] * 32)).type(torch.bool) + batch = (x, target, mixed_recons_flag) + output = model.training_step(batch, 0) + print('All ') \ No newline at end of file diff --git a/denoisplit/nets/lvae_deepencoder.py b/denoisplit/nets/lvae_deepencoder.py new file mode 100644 index 0000000..4b1fcb7 --- /dev/null +++ b/denoisplit/nets/lvae_deepencoder.py @@ -0,0 +1,126 @@ +from copy import deepcopy + +import torch + +import ml_collections +from denoisplit.nets.lvae import LadderVAE +from denoisplit.nets.lvae_twindecoder import LadderVAETwinDecoder + + +class LVAEWithDeepEncoder(LadderVAETwinDecoder): + + def __init__(self, data_mean, data_std, config): + config = ml_collections.ConfigDict(config) + new_config = deepcopy(config) + with new_config.unlocked(): + new_config.data.color_ch = config.model.encoder.n_filters + new_config.data.multiscale_lowres_count = None # multiscaleing is inside the extra encoder. + new_config.model.gated = False + new_config.model.decoder.dropout = 0. + new_config.model.merge_type = 'residual_ungated' + super().__init__(data_mean, data_std, new_config) + + self.enable_input_alphasum_of_channels = config.data.target_separate_normalization == False + with config.unlocked(): + config.model.non_stochastic_version = True + self.extra_encoder = LadderVAE(data_mean, data_std, config, target_ch=config.model.encoder.n_filters) + + def forward(self, x): + encoded, _ = self.extra_encoder(x) + return super().forward(encoded) + + def normalize_target(self, target, batch=None): + target_normalized = super().normalize_target(target) + if self.enable_input_alphasum_of_channels: + # adjust the targets for the alpha + alpha = batch[2][:, None, None, None] + tar1 = target_normalized[:, :1] * alpha + tar2 = target_normalized[:, 1:] * (1 - alpha) + target_normalized = torch.cat([tar1, tar2], dim=1) + return target_normalized + + def training_step(self, batch, batch_idx): + x, target = batch[:2] + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target, batch) + if batch_idx == 0 and self.enable_input_alphasum_of_channels: + assert torch.abs(torch.sum(target_normalized, dim=1, keepdim=True) - + x_normalized[:, :1]).max().item() < 1e-5 + + out_l1, out_l2, td_data = self.forward(x_normalized) + + recons_loss = self.get_reconstruction_loss(out_l1, out_l2, target_normalized) + if self.non_stochastic_version: + kl_loss = torch.Tensor([0.0]).to(target_normalized.device) + net_loss = recons_loss + else: + kl_loss = self.get_kl_divergence_loss(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + self.log('reconstruction_loss', recons_loss, on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach(), + 'kl_loss': kl_loss.detach(), + } + return output + + +if __name__ == '__main__': + import numpy as np + import torch + + from denoisplit.configs.deepencoder_lvae_config import get_config + + config = get_config() + data_mean = torch.Tensor([0]).reshape(1, 1, 1, 1) + data_std = torch.Tensor([1]).reshape(1, 1, 1, 1) + model = LVAEWithDeepEncoder(data_mean, data_std, config) + mc = 1 if config.data.multiscale_lowres_count is None else config.data.multiscale_lowres_count + 1 + inp = torch.rand((2, mc, config.data.image_size, config.data.image_size)) + out1, out2, td_data = model(inp) + print(out1.shape, out2.shape) + + # print(td_data) + # decoder invariance. + bu_values_l1 = [] + for i in range(1, len(config.model.z_dims) + 1): + isz = config.data.image_size + z = config.model.encoder.n_filters + pow = 2**(i) + bu_values_l1.append(torch.rand(2, z // 2, isz // pow, isz // pow)) + + out_l1_1x, _ = model.topdown_pass( + bu_values_l1, + top_down_layers=model.top_down_layers_l1, + final_top_down_layer=model.final_top_down_l1, + ) + + out_l1_10x, _ = model.topdown_pass( + [10 * x for x in bu_values_l1], + top_down_layers=model.top_down_layers_l1, + final_top_down_layer=model.final_top_down_l1, + ) + + max_diff = torch.abs(out_l1_1x * 10 - out_l1_10x).max().item() + assert max_diff < 1e-5 + out_l1_1x, _ = model.likelihood_l1.get_mean_lv(out_l1_1x) + out_l1_10x, _ = model.likelihood_l1.get_mean_lv(out_l1_10x) + max_diff = torch.abs(out_l1_1x * 10 - out_l1_10x).max().item() + assert max_diff < 1e-5 + # out_l1_1x = model.top_down_layers_l1[0](None, bu_value=bu_values_l1[0], inference_mode=True,use_mode=True) + # out_l1_10x = model.top_down_layers_l1[0](None, bu_value=10*bu_values_l1[0], inference_mode=True,use_mode=True) + # inp, target, alpha_val, ch1_idx, ch2_idx + batch = (torch.rand((16, mc, config.data.image_size, config.data.image_size)), + torch.rand((16, 2, config.data.image_size, config.data.image_size)), + torch.Tensor(np.random.randint(20, size=16)), torch.Tensor(np.random.randint(1000), + np.random.randint(1000))) + model.training_step(batch, 0) + model.validation_step(batch, 0) + + print('mar') diff --git a/denoisplit/nets/lvae_denoiser.py b/denoisplit/nets/lvae_denoiser.py new file mode 100644 index 0000000..88e87ac --- /dev/null +++ b/denoisplit/nets/lvae_denoiser.py @@ -0,0 +1,104 @@ +import torch + +from denoisplit.nets.lvae import LadderVAE + + +class LadderVAEDenoiser(LadderVAE): + """ + It denoises input/target. This is the first step in the pipeline of denoise=>split. + """ + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[]): + # since input is the target, we don't need to normalize it at all. + super().__init__(data_mean, data_std, config, use_uncond_mode_at=use_uncond_mode_at, target_ch=1) + self.denoise_channel = config.model.denoise_channel + + assert self.denoise_channel in ['input', 'Ch1', 'Ch2', 'all'] + if self.denoise_channel == 'all': + msg = 'For target, we expect it to be unnormalized. For such reasons, we expect same normalization for input and target.' + assert len(self.data_mean['target'].squeeze()) == 2, msg + assert self.data_mean['input'].squeeze() == self.data_mean['target'].squeeze()[:1], msg + assert self.data_mean['input'].squeeze() == self.data_mean['target'].squeeze()[1:], msg + + assert len(self.data_std['target'].squeeze()) == 2, msg + assert self.data_std['input'].squeeze() == self.data_std['target'].squeeze()[:1], msg + assert self.data_std['input'].squeeze() == self.data_std['target'].squeeze()[1:], msg + self.data_mean['target'] = self.data_mean['target'][:, :1] + self.data_std['target'] = self.data_std['target'][:, :1] + elif self.denoise_channel == 'input': + self.data_mean['target'] = self.data_mean['input'] + self.data_std['target'] = self.data_std['input'] + elif self.denoise_channel == 'Ch1': + self.data_mean['target'] = self.data_mean['target'][:, :1] + self.data_std['target'] = self.data_std['target'][:, :1] + self.data_mean['input'] = self.data_mean['target'] + self.data_std['input'] = self.data_std['target'] + elif self.denoise_channel == 'Ch2': + self.data_mean['target'] = self.data_mean['target'][:, 1:] + self.data_std['target'] = self.data_std['target'][:, 1:] + self.data_mean['input'] = self.data_mean['target'] + self.data_std['input'] = self.data_std['target'] + + def get_new_input_target(self, batch): + x, target = batch[:2] + if self.denoise_channel == 'input': + assert x.shape[1] == 1 + new_target = x.clone() + # Input is normalized, but target is not. So we need to un-normalize it. + new_target = new_target * self.data_std['input'] + self.data_mean['input'] + elif self.denoise_channel == 'Ch1': + new_target = target[:, :1] + # Input is normalized, but target is not. So we need to normalize it. + x = self.normalize_target(new_target) + + elif self.denoise_channel == 'Ch2': + new_target = target[:, 1:] + # Input is normalized, but target is not. So we need to normalize it. + x = self.normalize_target(new_target) + elif self.denoise_channel == 'all': + assert x.shape[1] == 1 + x = x * self.data_std['input'] + self.data_mean['input'] + new_target = torch.cat([x, target[:, :1], target[:, 1:]], dim=0) + x = self.normalize_target(new_target) + return x, new_target + + def training_step(self, batch, batch_idx, enable_logging=True): + x, new_target = self.get_new_input_target(batch) + batch = (x, new_target, *batch[2:]) + return super().training_step(batch, batch_idx, enable_logging) + + def validation_step(self, batch, batch_idx): + self.set_params_to_same_device_as(batch[0]) + x, new_target = self.get_new_input_target(batch) + batch = (x, new_target, *batch[2:]) + return super().validation_step(batch, batch_idx) + + +if __name__ == '__main__': + import numpy as np + import torch + + from denoisplit.configs.hdn_denoiser_config import get_config + + config = get_config() + data_mean = {'input': np.array([0]).reshape(1, 1, 1, 1), 'target': np.array([0, 0]).reshape(1, 2, 1, 1)} + data_std = {'input': np.array([1]).reshape(1, 1, 1, 1), 'target': np.array([1, 1]).reshape(1, 2, 1, 1)} + import pdb + pdb.set_trace() + model = LadderVAEDenoiser(data_mean, data_std, config) + mc = 1 if config.data.multiscale_lowres_count is None else config.data.multiscale_lowres_count + 1 + inp = torch.rand((2, mc, config.data.image_size, config.data.image_size)) + out, td_data = model(inp) + print(out.shape) + batch = ( + torch.rand((16, mc, config.data.image_size, config.data.image_size)), + torch.rand((16, 2, config.data.image_size, config.data.image_size)), + ) + model.training_step(batch, 0) + model.validation_step(batch, 0) + + ll = torch.ones((12, 2, 32, 32)) + ll_new = model._get_weighted_likelihood(ll) + print(ll_new[:, 0].mean(), ll_new[:, 0].std()) + print(ll_new[:, 1].mean(), ll_new[:, 1].std()) + print('mar') diff --git a/denoisplit/nets/lvae_layers.py b/denoisplit/nets/lvae_layers.py new file mode 100644 index 0000000..85263de --- /dev/null +++ b/denoisplit/nets/lvae_layers.py @@ -0,0 +1,722 @@ +""" +Taken from https://github.com/juglab/HDN/blob/main/models/lvae_layers.py +""" +from copy import deepcopy +from typing import Tuple, Union + +import torch +import torchvision.transforms.functional as F +from torch import nn + +from denoisplit.core.data_utils import crop_img_tensor, pad_img_tensor +from denoisplit.core.nn_submodules import ResidualBlock, ResidualGatedBlock +from denoisplit.core.non_stochastic import NonStochasticBlock2d +from denoisplit.core.stochastic import NormalStochasticBlock2d + + +class TopDownLayer(nn.Module): + """ + Top-down layer, including stochastic sampling, KL computation, and small + deterministic ResNet with upsampling. + The architecture when doing inference is roughly as follows: + p_params = output of top-down layer above + bu = inferred bottom-up value at this layer + q_params = merge(bu, p_params) + z = stochastic_layer(q_params) + possibly get skip connection from previous top-down layer + top-down deterministic ResNet + When doing generation only, the value bu is not available, the + merge layer is not used, and z is sampled directly from p_params. + If this is the top layer, at inference time, the uppermost bottom-up value + is used directly as q_params, and p_params are defined in this layer + (while they are usually taken from the previous layer), and can be learned. + """ + + def __init__(self, + z_dim: int, + n_res_blocks: int, + n_filters: int, + is_top_layer: bool = False, + downsampling_steps: int = None, + nonlin=None, + merge_type: str = None, + batchnorm: bool = True, + dropout: Union[None, float] = None, + stochastic_skip: bool = False, + res_block_type=None, + res_block_kernel=None, + res_block_skip_padding=None, + groups: int = 1, + gated=None, + learn_top_prior=False, + top_prior_param_shape=None, + analytical_kl=False, + bottomup_no_padding_mode=False, + topdown_no_padding_mode=False, + retain_spatial_dims: bool = False, + non_stochastic_version=False, + input_image_shape: Union[None, Tuple[int, int]] = None, + normalize_latent_factor=1.0, + conv2d_bias: bool = True, + stochastic_use_naive_exponential=False): + """ + Args: + z_dim: This is the dimension of the latent space. + n_res_blocks: Number of TopDownDeterministicResBlock blocks + n_filters: Number of channels which is present through out this layer. + is_top_layer: Whether it is top layer or not. + downsampling_steps: How many times upsampling has to be done in this layer. This is typically 1. + nonlin: What non linear activation is to be applied at various places in this module. + merge_type: In Top down layer, one merges the information passed from q() and upper layers. + This specifies how to mix these two tensors. + batchnorm: Whether to apply batch normalization at various places or not. + dropout: Amount of dropout to be applied at various places. + stochastic_skip: Previous layer's output is mixed with this layer's stochastic output. So, + the previous layer's output has a way to reach this level without going + through the stochastic process. However, technically, this is not a skip as + both are merged together. + res_block_type: Example: 'bacdbac'. It has the constitution of the residual block. + gated: This is also an argument for the residual block. At the end of residual block, whether + there should be a gate or not. + learn_top_prior: Whether we want to learn the top prior or not. If set to False, for the top-most + layer, p will be N(0,1). Otherwise, we will still have a normal distribution. It is + just that the mean and the stdev will be different. + top_prior_param_shape: This is the shape of the tensor which would contain the mean and the variance + of the prior (which is normal distribution) for the top most layer. + analytical_kl: If True, typical KL divergence is calculated. Otherwise, an approximate of it is + calculated. + retain_spatial_dims: If True, the the latent space of encoder remains at image_shape spatial resolution for each topdown layer. What this means for one topdown layer is that the input spatial size remains the output spatial size. + To achieve this, we centercrop the intermediate representation. + input_image_shape: This is the shape of the input patch. when retain_spatial_dims is set to True, then this is used to ensure that the output of this layer has this shape. + normalize_latent_factor: Divide the latent space (q_params) by this factor. + conv2d_bias: Whether or not bias should be present in the Conv2D layer. + """ + + super().__init__() + + self.is_top_layer = is_top_layer + self.z_dim = z_dim + self.stochastic_skip = stochastic_skip + self.learn_top_prior = learn_top_prior + self.analytical_kl = analytical_kl + self.bottomup_no_padding_mode = bottomup_no_padding_mode + self.topdown_no_padding_mode = topdown_no_padding_mode + self.retain_spatial_dims = retain_spatial_dims + self.latent_shape = input_image_shape if self.retain_spatial_dims else None + self.non_stochastic_version = non_stochastic_version + self.normalize_latent_factor = normalize_latent_factor + # Define top layer prior parameters, possibly learnable + if is_top_layer: + self.top_prior_params = nn.Parameter(torch.zeros(top_prior_param_shape), requires_grad=learn_top_prior) + + # Downsampling steps left to do in this layer + dws_left = downsampling_steps + + # Define deterministic top-down block: sequence of deterministic + # residual blocks with downsampling when needed. + block_list = [] + + for _ in range(n_res_blocks): + do_resample = False + if dws_left > 0: + do_resample = True + dws_left -= 1 + block_list.append( + TopDownDeterministicResBlock( + n_filters, + n_filters, + nonlin, + upsample=do_resample, + batchnorm=batchnorm, + dropout=dropout, + res_block_type=res_block_type, + res_block_kernel=res_block_kernel, + skip_padding=res_block_skip_padding, + gated=gated, + conv2d_bias=conv2d_bias, + groups=groups, + )) + self.deterministic_block = nn.Sequential(*block_list) + + # Define stochastic block with 2d convolutions + if self.non_stochastic_version: + self.stochastic = NonStochasticBlock2d( + c_in=n_filters, + c_vars=z_dim, + c_out=n_filters, + transform_p_params=(not is_top_layer), + groups=groups, + conv2d_bias=conv2d_bias, + ) + else: + self.stochastic = NormalStochasticBlock2d( + c_in=n_filters, + c_vars=z_dim, + c_out=n_filters, + transform_p_params=(not is_top_layer), + use_naive_exponential=stochastic_use_naive_exponential, + ) + + if not is_top_layer: + + # Merge layer, combine bottom-up inference with top-down + # generative to give posterior parameters + self.merge = MergeLayer( + channels=n_filters, + merge_type=merge_type, + nonlin=nonlin, + batchnorm=batchnorm, + dropout=dropout, + res_block_type=res_block_type, + res_block_kernel=res_block_kernel, + conv2d_bias=conv2d_bias, + ) + + # Skip connection that goes around the stochastic top-down layer + if stochastic_skip: + self.skip_connection_merger = SkipConnectionMerger( + channels=n_filters, + nonlin=nonlin, + batchnorm=batchnorm, + dropout=dropout, + res_block_type=res_block_type, + merge_type=merge_type, + conv2d_bias=conv2d_bias, + res_block_kernel=res_block_kernel, + res_block_skip_padding=res_block_skip_padding, + ) + print(f'[{self.__class__.__name__}] normalize_latent_factor:{self.normalize_latent_factor}') + + def sample_from_q(self, input_, bu_value, var_clip_max=None, mask=None): + """ + We sample from q + """ + if self.is_top_layer: + q_params = bu_value + else: + # NOTE: Here the assumption is that the vampprior is only applied on the top layer. + n_img_prior = None + p_params = self.get_p_params(input_, n_img_prior) + q_params = self.merge(bu_value, p_params) + + sample = self.stochastic.sample_from_q(q_params, var_clip_max) + if mask: + return sample[mask] + return sample + + def get_p_params(self, input_, n_img_prior): + p_params = None + # If top layer, define parameters of prior p(z_L) + if self.is_top_layer: + p_params = self.top_prior_params + + # Sample specific number of images by expanding the prior + if n_img_prior is not None: + p_params = p_params.expand(n_img_prior, -1, -1, -1) + + # Else the input from the layer above is the prior parameters + else: + p_params = input_ + + return p_params + + def align_pparams_buvalue(self, p_params, bu_value): + """ + In case the padding is not used either (or both) in encoder and decoder, we could have a mismatch. Doing a centercrop to ensure that both remain aligned. + """ + if bu_value.shape[-2:] != p_params.shape[-2:]: + assert self.bottomup_no_padding_mode is True + if self.topdown_no_padding_mode is False: + assert bu_value.shape[-1] > p_params.shape[-1] + bu_value = F.center_crop(bu_value, p_params.shape[-2:]) + else: + if bu_value.shape[-1] > p_params.shape[-1]: + bu_value = F.center_crop(bu_value, p_params.shape[-2:]) + else: + p_params = F.center_crop(p_params, bu_value.shape[-2:]) + return p_params, bu_value + + def forward(self, + input_: Union[None, torch.Tensor] = None, + skip_connection_input=None, + inference_mode=False, + bu_value=None, + n_img_prior=None, + forced_latent: Union[None, torch.Tensor] = None, + use_mode: bool = False, + force_constant_output=False, + mode_pred=False, + use_uncond_mode=False, + var_clip_max: Union[None, float] = None): + """ + Args: + input_: output from previous top_down layer. + skip_connection_input: Currently, this is output from the previous top down layer. + It is mixed with the output of the stochastic layer. + inference_mode: In inference mode, q_params is not None. Otherwise it is. When q_params is None, + everything is generated from the p_params. So, the encoder is not used at all. + bu_value: Output of the bottom-up pass layer of the same level as this top-down. + n_img_prior: This affects just the top most top-down layer. This is only present if inference_mode=False. + forced_latent: If this is a tensor, then in stochastic layer, we don't sample by using p() & q(). We simply + use this as the latent space sampling. + use_mode: If it is true, we still don't sample from the q(). We simply + use the mean of the distribution as the latent space. + force_constant_output: This ensures that only the first sample of the batch is used. Typically used + when infernce_mode is False + mode_pred: If True, then only prediction happens. Otherwise, KL divergence loss also gets computed. + use_uncond_mode: Used only when mode_pred=True + var_clip_max: This is the maximum value the log of the variance of the latent vector for any layer can reach. + """ + # Check consistency of arguments + inputs_none = input_ is None and skip_connection_input is None + if self.is_top_layer and not inputs_none: + raise ValueError("In top layer, inputs should be None") + + p_params = self.get_p_params(input_, n_img_prior) + + # In inference mode, get parameters of q from inference path, + # merging with top-down path if it's not the top layer + if inference_mode: + if self.is_top_layer: + q_params = bu_value + if mode_pred is False: + p_params, bu_value = self.align_pparams_buvalue(p_params, bu_value) + else: + if use_uncond_mode: + q_params = p_params + else: + p_params, bu_value = self.align_pparams_buvalue(p_params, bu_value) + q_params = self.merge(bu_value, p_params) + + # In generative mode, q is not used + else: + q_params = None + + # Sample from either q(z_i | z_{i+1}, x) or p(z_i | z_{i+1}) + # depending on whether q_params is None + + # This is done, purely for stablity. See Very deep VAEs generalize autoregressive models. + if self.normalize_latent_factor: + q_params = q_params / self.normalize_latent_factor + + x, data_stoch = self.stochastic(p_params=p_params, + q_params=q_params, + forced_latent=forced_latent, + use_mode=use_mode, + force_constant_output=force_constant_output, + analytical_kl=self.analytical_kl, + mode_pred=mode_pred, + use_uncond_mode=use_uncond_mode, + var_clip_max=var_clip_max) + + # Skip connection from previous layer + if self.stochastic_skip and not self.is_top_layer: + if self.topdown_no_padding_mode is True: + # the output of last TopDown layer was of size 64*64. Due to lack of padding, currecnt x has become, say 60*60. + skip_connection_input = F.center_crop(skip_connection_input, x.shape[-2:]) + + x = self.skip_connection_merger(x, skip_connection_input) + + # Save activation before residual block: could be the skip + # connection input in the next layer + x_pre_residual = x + if self.retain_spatial_dims: + # when we don't want to do padding in topdown as well, we need to spare some boundary pixels which would be used up. + extra_len = (self.topdown_no_padding_mode is True) * 3 + + # # this means that the x should be of the same size as config.data.image_size. So, we have to centercrop by a factor of 2 at this point. + # assert x.shape[-1] >= self.latent_shape[-1] // 2 + extra_len + # we assume that one topdown layer will have exactly one upscaling layer. + new_latent_shape = (self.latent_shape[0] // 2 + extra_len, self.latent_shape[1] // 2 + extra_len) + + # If the LC is not applied on all layers, then this can happen. + if x.shape[-1] > new_latent_shape[-1]: + x = F.center_crop(x, new_latent_shape) + + # Last top-down block (sequence of residual blocks) + x = self.deterministic_block(x) + + if self.topdown_no_padding_mode: + x = F.center_crop(x, self.latent_shape) + + keys = [ + 'z', + 'kl_samplewise', + 'kl_spatial', + 'kl_channelwise', + # 'logprob_p', + 'logprob_q', + 'qvar_max' + ] + data = {k: data_stoch.get(k, None) for k in keys} + data['q_mu'] = None + data['q_lv'] = None + if data_stoch['q_params'] is not None: + q_mu, q_lv = data_stoch['q_params'] + data['q_mu'] = q_mu + data['q_lv'] = q_lv + return x, x_pre_residual, data + + +class BottomUpLayer(nn.Module): + """ + Bottom-up deterministic layer for inference, roughly the same as the + small deterministic Resnet in top-down layers. Consists of a sequence of + bottom-up deterministic residual blocks with downsampling. + """ + + def __init__(self, + n_res_blocks: int, + n_filters: int, + downsampling_steps: int = 0, + nonlin=None, + batchnorm: bool = True, + dropout: Union[None, float] = None, + res_block_type: str = None, + res_block_kernel: int = None, + res_block_skip_padding: bool = False, + gated: bool = None, + multiscale_lowres_size_factor: int = None, + enable_multiscale: bool = False, + lowres_separate_branch=False, + multiscale_retain_spatial_dims: bool = False, + decoder_retain_spatial_dims: bool = False, + output_expected_shape=None): + """ + Args: + n_res_blocks: Number of BottomUpDeterministicResBlock blocks present in this layer. + n_filters: Number of channels which is present through out this layer. + downsampling_steps: How many times downsampling has to be done in this layer. This is typically 1. + nonlin: What non linear activation is to be applied at various places in this module. + batchnorm: Whether to apply batch normalization at various places or not. + dropout: Amount of dropout to be applied at various places. + res_block_type: Example: 'bacdbac'. It has the constitution of the residual block. + gated: This is also an argument for the residual block. At the end of residual block, whether + there should be a gate or not. + res_block_kernel:int => kernel size for the residual blocks in the bottom up layer. + multiscale_lowres_size_factor: How small is the bu_value when compared with low resolution tensor. + enable_multiscale: Whether to enable multiscale or not. + multiscale_retain_spatial_dims: typically the output of the bottom-up layer scales down spatially. + However, with this set, we return the same spatially sized tensor. + output_expected_shape: What should be the shape of the output of this layer. Only used if enable_multiscale is True. + """ + super().__init__() + self.enable_multiscale = enable_multiscale + self.lowres_separate_branch = lowres_separate_branch + self.multiscale_retain_spatial_dims = multiscale_retain_spatial_dims + self.output_expected_shape = output_expected_shape + self.decoder_retain_spatial_dims = decoder_retain_spatial_dims + assert self.output_expected_shape is None or self.enable_multiscale is True + + bu_blocks_downsized = [] + bu_blocks_samesize = [] + for _ in range(n_res_blocks): + do_resample = False + if downsampling_steps > 0: + do_resample = True + downsampling_steps -= 1 + block = BottomUpDeterministicResBlock( + c_in=n_filters, + c_out=n_filters, + nonlin=nonlin, + downsample=do_resample, + batchnorm=batchnorm, + dropout=dropout, + res_block_type=res_block_type, + res_block_kernel=res_block_kernel, + skip_padding=res_block_skip_padding, + gated=gated, + ) + if do_resample: + bu_blocks_downsized.append(block) + else: + bu_blocks_samesize.append(block) + + self.net_downsized = nn.Sequential(*bu_blocks_downsized) + self.net = nn.Sequential(*bu_blocks_samesize) + # using the same net for the lowresolution (and larger sized image) + self.lowres_net = self.lowres_merge = self.multiscale_lowres_size_factor = None + if self.enable_multiscale: + self._init_multiscale( + n_filters=n_filters, + nonlin=nonlin, + batchnorm=batchnorm, + dropout=dropout, + res_block_type=res_block_type, + multiscale_retain_spatial_dims=multiscale_retain_spatial_dims, + multiscale_lowres_size_factor=multiscale_lowres_size_factor, + ) + + msg = f'[{self.__class__.__name__}] McEnabled:{int(enable_multiscale)} ' + if enable_multiscale: + msg += f'McParallelBeam:{int(multiscale_retain_spatial_dims)} McFactor{multiscale_lowres_size_factor}' + print(msg) + + def _init_multiscale(self, + n_filters=None, + nonlin=None, + batchnorm=None, + dropout=None, + res_block_type=None, + multiscale_retain_spatial_dims=None, + multiscale_lowres_size_factor=None): + self.multiscale_lowres_size_factor = multiscale_lowres_size_factor + self.lowres_net = self.net + if self.lowres_separate_branch: + self.lowres_net = deepcopy(self.net) + + self.lowres_merge = MergeLowRes( + channels=n_filters, + merge_type='residual', + nonlin=nonlin, + batchnorm=batchnorm, + dropout=dropout, + res_block_type=res_block_type, + multiscale_retain_spatial_dims=multiscale_retain_spatial_dims, + multiscale_lowres_size_factor=self.multiscale_lowres_size_factor, + ) + + def forward(self, x, lowres_x=None): + primary_flow = self.net_downsized(x) + primary_flow = self.net(primary_flow) + + if self.enable_multiscale is False: + assert lowres_x is None + return primary_flow, primary_flow + + if lowres_x is not None: + lowres_flow = self.lowres_net(lowres_x) + merged = self.lowres_merge(primary_flow, lowres_flow) + else: + merged = primary_flow + + if self.multiscale_retain_spatial_dims is False or self.decoder_retain_spatial_dims is True: + return merged, merged + + if self.output_expected_shape is not None: + expected_shape = self.output_expected_shape + else: + fac = self.multiscale_lowres_size_factor + expected_shape = (merged.shape[-2] // fac, merged.shape[-1] // fac) + assert merged.shape[-2:] != expected_shape + + value_to_use_in_topdown = crop_img_tensor(merged, expected_shape) + return merged, value_to_use_in_topdown + + +class ResBlockWithResampling(nn.Module): + """ + Residual block that takes care of resampling steps (each by a factor of 2). + The mode can be top-down or bottom-up, and the block does up- and + down-sampling by a factor of 2, respectively. Resampling is performed at + the beginning of the block, through strided convolution. + The number of channels is adjusted at the beginning and end of the block, + through convolutional layers with kernel size 1. The number of internal + channels is by default the same as the number of output channels, but + min_inner_channels overrides this behaviour. + Other parameters: kernel size, nonlinearity, and groups of the internal + residual block; whether batch normalization and dropout are performed; + whether the residual path has a gate layer at the end. There are a few + residual block structures to choose from. + """ + + def __init__(self, + mode, + c_in, + c_out, + nonlin=nn.LeakyReLU, + resample=False, + res_block_kernel=None, + groups=1, + batchnorm=True, + res_block_type=None, + dropout=None, + min_inner_channels=None, + gated=None, + lowres_input=False, + skip_padding=False, + conv2d_bias=True): + super().__init__() + assert mode in ['top-down', 'bottom-up'] + if min_inner_channels is None: + min_inner_channels = 0 + inner_filters = max(c_out, min_inner_channels) + + # Define first conv layer to change channels and/or up/downsample + if resample: + if mode == 'bottom-up': # downsample + self.pre_conv = nn.Conv2d(in_channels=c_in, + out_channels=inner_filters, + kernel_size=3, + padding=1, + stride=2, + groups=groups, + bias=conv2d_bias) + elif mode == 'top-down': # upsample + self.pre_conv = nn.ConvTranspose2d(in_channels=c_in, + out_channels=inner_filters, + kernel_size=3, + padding=1, + stride=2, + groups=groups, + output_padding=1, + bias=conv2d_bias) + elif c_in != inner_filters: + self.pre_conv = nn.Conv2d(c_in, inner_filters, 1, groups=groups, bias=conv2d_bias) + else: + self.pre_conv = None + + # Residual block + self.res = ResidualBlock( + channels=inner_filters, + nonlin=nonlin, + kernel=res_block_kernel, + groups=groups, + batchnorm=batchnorm, + dropout=dropout, + gated=gated, + block_type=res_block_type, + skip_padding=skip_padding, + conv2d_bias=conv2d_bias, + ) + # Define last conv layer to get correct num output channels + if inner_filters != c_out: + self.post_conv = nn.Conv2d(inner_filters, c_out, 1, groups=groups, bias=conv2d_bias) + else: + self.post_conv = None + + def forward(self, x): + if self.pre_conv is not None: + x = self.pre_conv(x) + + x = self.res(x) + if self.post_conv is not None: + x = self.post_conv(x) + return x + + +class TopDownDeterministicResBlock(ResBlockWithResampling): + + def __init__(self, *args, upsample=False, **kwargs): + kwargs['resample'] = upsample + super().__init__('top-down', *args, **kwargs) + + +class BottomUpDeterministicResBlock(ResBlockWithResampling): + + def __init__(self, *args, downsample=False, **kwargs): + kwargs['resample'] = downsample + super().__init__('bottom-up', *args, **kwargs) + + +class MergeLayer(nn.Module): + """ + Merge two/more than two 4D input tensors by concatenating along dim=1 and passing the + result through 1) a convolutional 1x1 layer, or 2) a residual block + """ + + def __init__(self, + channels, + merge_type, + nonlin=nn.LeakyReLU, + batchnorm=True, + dropout=None, + res_block_type=None, + res_block_kernel=None, + conv2d_bias=True, + res_block_skip_padding=False): + super().__init__() + try: + iter(channels) + except TypeError: # it is not iterable + channels = [channels] * 3 + else: # it is iterable + if len(channels) == 1: + channels = [channels[0]] * 3 + + # assert len(channels) == 3 + + if merge_type == 'linear': + self.layer = nn.Conv2d(sum(channels[:-1]), channels[-1], 1, bias=conv2d_bias) + elif merge_type == 'residual': + self.layer = nn.Sequential( + nn.Conv2d(sum(channels[:-1]), channels[-1], 1, padding=0, bias=conv2d_bias), + ResidualGatedBlock( + channels[-1], + nonlin, + batchnorm=batchnorm, + dropout=dropout, + block_type=res_block_type, + kernel=res_block_kernel, + conv2d_bias=conv2d_bias, + skip_padding=res_block_skip_padding, + ), + ) + elif merge_type == 'residual_ungated': + self.layer = nn.Sequential( + nn.Conv2d(sum(channels[:-1]), channels[-1], 1, padding=0, bias=conv2d_bias), + ResidualBlock( + channels[-1], + nonlin, + batchnorm=batchnorm, + dropout=dropout, + block_type=res_block_type, + kernel=res_block_kernel, + conv2d_bias=conv2d_bias, + skip_padding=res_block_skip_padding, + ), + ) + + def forward(self, *args): + x = torch.cat(args, dim=1) + return self.layer(x) + + +class MergeLowRes(MergeLayer): + """ + Here, we merge the lowresolution input (which has higher size) + """ + + def __init__(self, *args, **kwargs): + self.retain_spatial_dims = kwargs.pop('multiscale_retain_spatial_dims') + self.multiscale_lowres_size_factor = kwargs.pop('multiscale_lowres_size_factor') + super().__init__(*args, **kwargs) + + def forward(self, latent, lowres): + if self.retain_spatial_dims: + latent = pad_img_tensor(latent, lowres.shape[2:]) + else: + lh, lw = lowres.shape[-2:] + h = lh // self.multiscale_lowres_size_factor + w = lw // self.multiscale_lowres_size_factor + h_pad = (lh - h) // 2 + w_pad = (lw - w) // 2 + lowres = lowres[:, :, h_pad:-h_pad, w_pad:-w_pad] + + return super().forward(latent, lowres) + + +class SkipConnectionMerger(MergeLayer): + """ + By default for now simply a merge layer. + """ + + def __init__(self, + channels, + nonlin, + batchnorm, + dropout, + res_block_type, + merge_type='residual', + conv2d_bias: bool = True, + res_block_kernel=None, + res_block_skip_padding=False): + super().__init__(channels, + merge_type, + nonlin, + batchnorm, + dropout=dropout, + res_block_type=res_block_type, + res_block_kernel=res_block_kernel, + conv2d_bias=conv2d_bias, + res_block_skip_padding=res_block_skip_padding) diff --git a/denoisplit/nets/lvae_multidset_multi_input_branches.py b/denoisplit/nets/lvae_multidset_multi_input_branches.py new file mode 100644 index 0000000..e27f629 --- /dev/null +++ b/denoisplit/nets/lvae_multidset_multi_input_branches.py @@ -0,0 +1,259 @@ +from typing import List + +import torch + +from denoisplit.core.data_utils import crop_img_tensor +from denoisplit.core.loss_type import LossType +from denoisplit.core.psnr import RangeInvariantPsnr +from denoisplit.nets.lvae import torch_nanmean +from denoisplit.nets.lvae_twodset import LadderVaeTwoDset + + +class LadderVaeMultiDatasetMultiBranch(LadderVaeTwoDset): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super().__init__(data_mean, data_std, config, use_uncond_mode_at, target_ch) + stride = 1 if config.model.no_initial_downscaling else 2 + del self.first_bottom_up + self._first_bottom_up_subdset0 = self.create_first_bottom_up(stride) + self._first_bottom_up_subdset1 = self.create_first_bottom_up(stride) + + def forward(self, x, loss_idx: int): + img_size = x.size()[2:] + + # Pad input to make everything easier with conv strides + x_pad = self.pad_input(x) + + # Bottom-up inference: return list of length n_layers (bottom to top) + bu_values = self.bottomup_pass(x_pad, loss_idx) + mode_layers = range(self.n_layers) if self.non_stochastic_version else None + # Top-down inference/generation + out, td_data = self.topdown_pass(bu_values, mode_layers=mode_layers) + + if out.shape[-1] > img_size[-1]: + # Restore original image size + out = crop_img_tensor(out, img_size) + + return out, td_data + + def bottomup_pass(self, inp, loss_idx): + if loss_idx == LossType.ElboMixedReconstruction: + return self._bottomup_pass(inp, self._first_bottom_up_subdset0, self.lowres_first_bottom_ups, + self.bottom_up_layers) + + elif loss_idx == LossType.Elbo: + return self._bottomup_pass(inp, self._first_bottom_up_subdset1, self.lowres_first_bottom_ups, + self.bottom_up_layers) + + def merge_td_data(self, td_data1, len1: int, td_data2, len2: int): + """ + merge the td data + """ + if td_data1 is None: + return td_data2 + if td_data2 is None: + return td_data1 + + output_td_data = {} + for key in ['z', 'kl']: + output_td_data[key] = [] + for i in range(len(td_data1[key])): + concat_value = torch.cat([td_data1[key][i], td_data2[key][i]], dim=0) + output_td_data[key].append(concat_value) + + for key in ['debug_qvar_max']: + output_td_data[key] = [] + for i in range(len(td_data1[key])): + merged_value = torch.max(td_data1[key][i], td_data2[key][i]) + output_td_data[key].append(merged_value) + + return output_td_data + + def merge_vectors(self, vector_tuple1: List[torch.Tensor], vector_tuple2: List[torch.Tensor]): + out_vectors = [] + for i in range(len(vector_tuple1)): + if vector_tuple1[i] is None or torch.numel(vector_tuple1[i]) == 0: + out_vectors.append(vector_tuple2[i]) + elif vector_tuple2[i] is None or torch.numel(vector_tuple2[i]) == 0: + out_vectors.append(vector_tuple1[i]) + else: + out_vectors.append(torch.cat([vector_tuple1[i], vector_tuple2[i]], dim=0)) + return out_vectors + + def training_step(self, batch, batch_idx, enable_logging=True): + x, target, dset_idx, loss_idx = batch + assert self.normalized_input == True + x_normalized = x + target_normalized = self.normalize_target(target, dset_idx) + + mask_mixrecons = loss_idx == LossType.ElboMixedReconstruction + mask_2ch = loss_idx == LossType.Elbo + assert torch.sum(mask_2ch) + torch.sum(mask_mixrecons) == len(target) + if mask_mixrecons.sum() > 0: + out_mixrecons, td_data_mixrecons = self.forward(x_normalized[mask_mixrecons], + LossType.ElboMixedReconstruction) + else: + out_mixrecons = None + td_data_mixrecons = None + + if mask_2ch.sum() > 0: + out_2ch, td_data_2ch = self.forward(x_normalized[mask_2ch], LossType.Elbo) + else: + out_2ch = None + td_data_2ch = None + + td_data = self.merge_td_data(td_data_mixrecons, mask_mixrecons.sum(), td_data_2ch, mask_2ch.sum()) + + assert self.encoder_no_padding_mode is False + + out, target_normalized, dset_idx, loss_idx = self.merge_vectors( + (out_mixrecons, target_normalized[mask_mixrecons], dset_idx[mask_mixrecons], loss_idx[mask_mixrecons]), + (out_2ch, target_normalized[mask_2ch], dset_idx[mask_2ch], loss_idx[mask_2ch]), + ) + + recons_loss_dict = self.get_reconstruction_loss(out, + target_normalized, + dset_idx, + loss_idx, + return_predicted_img=False) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = recons_loss_dict['loss'] + if self.loss_type == LossType.ElboMixedReconstruction: + recons_loss += self.mixed_rec_w * recons_loss_dict['mixed_loss'] + + if enable_logging: + self.log('mixed_reconstruction_loss', recons_loss_dict['mixed_loss'], on_epoch=True) + + if self.non_stochastic_version: + kl_loss = torch.Tensor([0.0]).cuda() + net_loss = recons_loss + else: + kl_loss = self.get_kl_divergence_loss(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + if enable_logging: + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + if self._interchannel_weights is not None: + self.log('interchannel_w0', self._interchannel_weights.squeeze()[0].item(), on_epoch=True) + self.log('interchannel_w1', self._interchannel_weights.squeeze()[1].item(), on_epoch=True) + + # self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + # self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss, + 'kl_loss': self.get_kl_weight() * kl_loss, + } + + if self.loss_type == LossType.ElboMixedReconstruction: + output['mixed_loss'] = self.mixed_rec_w * recons_loss_dict['mixed_loss'] + + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def validation_step(self, batch, batch_idx): + x, target, dset_idx, loss_idx = batch + self.set_params_to_same_device_as(target) + + x_normalized = x + target_normalized = self.normalize_target(target, dset_idx) + + mask_mixrecons = loss_idx == LossType.ElboMixedReconstruction + mask_2ch = loss_idx == LossType.Elbo + assert mask_2ch.sum() == len(x) + assert mask_mixrecons.sum() == 0 + out, td_data = self.forward(x_normalized, LossType.Elbo) + + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, recons_img = self.get_reconstruction_loss(out, + target_normalized, + dset_idx, + loss_idx, + return_predicted_img=True) + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + self.label1_psnr.update(recons_img[:, 0], target_normalized[:, 0]) + self.label2_psnr.update(recons_img[:, 1], target_normalized[:, 1]) + + psnr_label1 = RangeInvariantPsnr(target_normalized[:, 0].clone(), recons_img[:, 0].clone()) + psnr_label2 = RangeInvariantPsnr(target_normalized[:, 1].clone(), recons_img[:, 1].clone()) + recons_loss = recons_loss_dict['loss'] + # kl_loss = self.get_kl_divergence_loss(td_data) + # net_loss = recons_loss + self.get_kl_weight() * kl_loss + self.log('val_loss', recons_loss, on_epoch=True) + val_psnr_l1 = torch_nanmean(psnr_label1).item() + val_psnr_l2 = torch_nanmean(psnr_label2).item() + self.log('val_psnr_l1', val_psnr_l1, on_epoch=True) + self.log('val_psnr_l2', val_psnr_l2, on_epoch=True) + # self.log('val_psnr', (val_psnr_l1 + val_psnr_l2) / 2, on_epoch=True) + + if batch_idx == 0 and self.power_of_2(self.current_epoch): + all_samples = [] + for i in range(20): + sample, _ = self(x_normalized[0:1, ...], LossType.Elbo) + sample = self.likelihood.get_mean_lv(sample)[0] + all_samples.append(sample[None]) + + all_samples = torch.cat(all_samples, dim=0) + data_mean, data_std = self.get_mean_std_for_one_batch(dset_idx, self.data_mean, self.data_std) + all_samples = all_samples * data_std['target'] + data_mean['target'] + all_samples = all_samples.cpu() + img_mmse = torch.mean(all_samples, dim=0)[0] + self.log_images_for_tensorboard(all_samples[:, 0, 0, ...], target[0, 0, ...], img_mmse[0], 'label1') + self.log_images_for_tensorboard(all_samples[:, 0, 1, ...], target[0, 1, ...], img_mmse[1], 'label2') + + +if __name__ == '__main__': + from denoisplit.configs.ht_iba1_ki64_multidata_config import get_config + + data_mean = { + 'subdset_0': { + 'target': torch.Tensor([1.1, 3.2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([1366]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([15, 30]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([10]).reshape((1, 1, 1, 1)) + } + } + + data_std = { + 'subdset_0': { + 'target': torch.Tensor([21, 45]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([955]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([90, 2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([121]).reshape((1, 1, 1, 1)) + } + } + + config = get_config() + model = LadderVaeMultiDatasetMultiBranch(data_mean, data_std, config) + + dset_idx = torch.Tensor([0, 1, 0, 1]) + loss_idx = torch.Tensor( + [LossType.Elbo, LossType.ElboMixedReconstruction, LossType.Elbo, LossType.ElboMixedReconstruction]) + x = torch.rand((4, 1, 64, 64)) + target = torch.rand((4, 2, 64, 64)) + batch = (x, target, dset_idx, loss_idx) + model.training_step(batch, 0, enable_logging=True) + model.validation_step(batch, 0) diff --git a/denoisplit/nets/lvae_multidset_multi_optim.py b/denoisplit/nets/lvae_multidset_multi_optim.py new file mode 100644 index 0000000..5f62e97 --- /dev/null +++ b/denoisplit/nets/lvae_multidset_multi_optim.py @@ -0,0 +1,166 @@ +import torch.nn as nn +import torch.optim as optim + +from denoisplit.core.loss_type import LossType +from denoisplit.nets.lvae_multidset_multi_input_branches import LadderVaeMultiDatasetMultiBranch + + +class IntensityMap(nn.Module): + + def __init__(self): + super().__init__() + self._net = nn.Sequential( + nn.Conv2d(1, 64, 1), + nn.LeakyReLU(), + nn.Conv2d(64, 64, 1), + nn.LeakyReLU(), + nn.Conv2d(64, 64, 1), + nn.LeakyReLU(), + nn.Conv2d(64, 1, 1), + ) + + def forward(self, x): + return x + self._net(x) + + +class LadderVaeMultiDatasetMultiOptim(LadderVaeMultiDatasetMultiBranch): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super().__init__(data_mean, data_std, config, use_uncond_mode_at, target_ch) + + self.automatic_optimization = False + self._donot_keep_separate_firstbottomup = config.model.get('only_optimize_interchannel_weights', False) + if self._donot_keep_separate_firstbottomup is True: + del self._first_bottom_up_subdset0 + self._first_bottom_up_subdset0 = self._first_bottom_up_subdset1 + + learn_imap = config.model.get('learn_intensity_map', False) + self._intensity_map_net = None + if learn_imap: + self._intensity_map_net = IntensityMap() + self._first_bottom_up_subdset0 = nn.Sequential(self._intensity_map_net, self._first_bottom_up_subdset0) + + print( + f'[{self.__class__.__name__}] OnlyOptimizeInterchannelWeights:{self._donot_keep_separate_firstbottomup} IMap:{learn_imap}' + ) + + def get_encoder_params(self): + encoder_params = list(self._first_bottom_up_subdset1.parameters()) + list(self.bottom_up_layers.parameters()) + if self.lowres_first_bottom_ups is not None: + encoder_params.append(self.lowres_first_bottom_ups.parameters()) + return encoder_params + + def get_decoder_params(self): + decoder_params = list(self.top_down_layers.parameters()) + list(self.final_top_down.parameters()) + list( + self.likelihood.parameters()) + return decoder_params + + def get_mixrecons_extra_params(self): + if self._donot_keep_separate_firstbottomup: + params = [] + assert self._interchannel_weights is not None, "There would be nothing to optimize for the second optimizer." + else: + params = list(self._first_bottom_up_subdset0.parameters()) + + if self._intensity_map_net is not None: + params += list(self._intensity_map_net.parameters()) + + if self._interchannel_weights is not None: + params = params + [self._interchannel_weights] + + return params + + def get_scheduler(self, optimizer): + return optim.lr_scheduler.ReduceLROnPlateau(optimizer, + self.lr_scheduler_mode, + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + + def configure_optimizers(self): + + encoder_params = self.get_encoder_params() + decoder_params = self.get_decoder_params() + # channel 1 params + ch2_pathway = encoder_params + decoder_params + optimizer0 = optim.Adamax(ch2_pathway, lr=self.lr, weight_decay=0) + + optimizer1 = optim.Adamax(self.get_mixrecons_extra_params(), lr=self.lr, weight_decay=0) + + scheduler0 = self.get_scheduler(optimizer0) + scheduler1 = self.get_scheduler(optimizer1) + + return [optimizer0, optimizer1], [{ + 'scheduler': scheduler, + 'monitor': self.lr_scheduler_monitor, + } for scheduler in [scheduler0, scheduler1]] + + def training_step(self, batch, batch_idx, enable_logging=True): + x, target, dset_idx, loss_idx = batch + ch2_opt, mix_opt = self.optimizers() + mask_ch2 = loss_idx == LossType.Elbo + mask_mix = loss_idx == LossType.ElboMixedReconstruction + assert mask_ch2.sum() + mask_mix.sum() == len(x) + loss_dict = None + + if mask_ch2.sum() > 0: + batch = (x[mask_ch2], target[mask_ch2], dset_idx[mask_ch2], loss_idx[mask_ch2]) + loss_dict = super().training_step(batch, batch_idx, enable_logging=enable_logging) + if loss_dict is not None: + ch2_opt.zero_grad() + loss = loss_dict['kl_loss'] + loss_dict['reconstruction_loss'] + self.manual_backward(loss) + ch2_opt.step() + + if mask_mix.sum() > 0: + batch = (x[mask_mix], target[mask_mix], dset_idx[mask_mix], loss_idx[mask_mix]) + mix_loss_dict = super().training_step(batch, batch_idx, enable_logging=enable_logging) + if loss_dict is not None: + mix_opt.zero_grad() + loss = mix_loss_dict['kl_loss'] + mix_loss_dict['mixed_loss'] + self.manual_backward(loss) + mix_opt.step() + + if loss_dict is not None: + self.log_dict({"loss": loss}, prog_bar=True) + + +if __name__ == '__main__': + import torch + + from denoisplit.configs.ht_iba1_ki64_multidata_config import get_config + + data_mean = { + 'subdset_0': { + 'target': torch.Tensor([1.1, 3.2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([1366]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([15, 30]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([10]).reshape((1, 1, 1, 1)) + } + } + + data_std = { + 'subdset_0': { + 'target': torch.Tensor([21, 45]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([955]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([90, 2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([121]).reshape((1, 1, 1, 1)) + } + } + + config = get_config() + model = LadderVaeMultiDatasetMultiOptim(data_mean, data_std, config) + dset_idx = torch.Tensor([0, 1, 0, 1]) + loss_idx = torch.Tensor( + [LossType.Elbo, LossType.ElboMixedReconstruction, LossType.Elbo, LossType.ElboMixedReconstruction]) + x = torch.rand((4, 1, 64, 64)) + target = torch.rand((4, 2, 64, 64)) + batch = (x, target, dset_idx, loss_idx) + _ = model.forward(x, 2) + model.training_step(batch, 0, enable_logging=True) + model.validation_step(batch, 0) diff --git a/denoisplit/nets/lvae_multiple_encoder_single_opt.py b/denoisplit/nets/lvae_multiple_encoder_single_opt.py new file mode 100644 index 0000000..e586ad4 --- /dev/null +++ b/denoisplit/nets/lvae_multiple_encoder_single_opt.py @@ -0,0 +1,87 @@ +""" +here, using a single optimizer we want to train the model. +""" +import torch +import torch.optim as optim + +from denoisplit.core.mixed_input_type import MixedInputType +from denoisplit.nets.lvae_multiple_encoders import LadderVAEMultipleEncoders + + +class LadderVAEMulEncoder1Optim(LadderVAEMultipleEncoders): + def configure_optimizers(self): + encoder_params = self.get_encoder_params() + decoder_params = self.get_decoder_params() + encoder_ch1_params = self.get_ch1_branch_params() + encoder_ch2_params = self.get_ch2_branch_params() + optimizer = optim.Adamax(encoder_params + decoder_params + encoder_ch1_params + encoder_ch2_params, lr=self.lr, + weight_decay=0) + + scheduler = self.get_scheduler(optimizer) + + return {'optimizer': optimizer, 'lr_scheduler': scheduler, 'monitor': self.lr_scheduler_monitor} + + def training_step(self, batch, batch_idx, enable_logging=True): + + x, target, supervised_mask = batch + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + recons_loss = 0 + kl_loss = 0 + if supervised_mask.sum() > 0: + out, td_data = self._forward_mix(x_normalized[supervised_mask]) + recons_loss_dict = self._get_reconstruction_loss_vector(out, target_normalized[supervised_mask]) + recons_loss = recons_loss_dict['loss'].sum() + kl_loss = self.get_kl_divergence_loss(td_data) * supervised_mask.sum() + # todo: one can also apply mixed reconstruction loss here. input mix and reconstruct mix. + + if (~supervised_mask).sum() > 0: + target_indep = target_normalized[~supervised_mask] + out_ch0, td_data0 = self._forward_separate_ch(target_indep[:, :1], None) + out_ch1, td_data1 = self._forward_separate_ch(None, target_indep[:, 1:2]) + recons_loss_ch0 = self._get_reconstruction_loss_vector(out_ch0, target_indep)['ch1_loss'] + recons_loss_ch1 = self._get_reconstruction_loss_vector(out_ch1, target_indep)['ch2_loss'] + + kl_loss0 = self.get_kl_divergence_loss(td_data0) + kl_loss1 = self.get_kl_divergence_loss(td_data1) + + kl_loss_mix = None + recons_loss_mix = None + if self.mixed_input_type == MixedInputType.Aligned: + out_mix, td_datamix = self._forward_mix(x_normalized[~supervised_mask]) + recons_loss_mix = self._get_mixed_reconstruction_loss_vector(out_mix, x_normalized[~supervised_mask]) + kl_loss_mix = self.get_kl_divergence_loss(td_datamix) + recons_loss += (recons_loss_ch0.sum() + recons_loss_ch1.sum() + recons_loss_mix.sum()) / 3 + kl_loss += (kl_loss0 + kl_loss1 + kl_loss_mix) / 3 * len(target_indep) + else: + recons_loss += (recons_loss_ch0.sum() + recons_loss_ch1.sum()) / 2 + kl_loss += (kl_loss0 + kl_loss1) / 2 * len(target_indep) + + if enable_logging: + self.log(f'reconstruction_loss_ch0', recons_loss_ch0.mean(), on_epoch=True) + self.log(f'reconstruction_loss_ch1', recons_loss_ch1.mean(), on_epoch=True) + self.log(f'kl_loss_ch0', kl_loss0, on_epoch=True) + self.log(f'kl_loss_ch1', kl_loss1, on_epoch=True) + if self.mixed_input_type == MixedInputType.Aligned: + self.log(f'reconstruction_loss_mix', recons_loss_mix.mean(), on_epoch=True) + self.log(f'kl_loss_mix', kl_loss0, on_epoch=True) + + recons_loss = recons_loss / len(x) + kl_loss = kl_loss / len(x) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + if enable_logging: + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('reconstruction_loss', recons_loss, on_epoch=True) + + output = { + 'loss': net_loss, + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + # skipping inf loss + if torch.isinf(net_loss).any(): + return None + + return output diff --git a/denoisplit/nets/lvae_multiple_encoders.py b/denoisplit/nets/lvae_multiple_encoders.py new file mode 100644 index 0000000..667a3ae --- /dev/null +++ b/denoisplit/nets/lvae_multiple_encoders.py @@ -0,0 +1,286 @@ +import copy + +import torch +import torch.nn as nn +import torch.optim as optim + +from denoisplit.core.data_utils import crop_img_tensor +from denoisplit.core.mixed_input_type import MixedInputType +from denoisplit.nets.lvae import LadderVAE +from denoisplit.nets.lvae_layers import BottomUpLayer, MergeLayer + + +class LadderVAEMultipleEncoders(LadderVAE): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super().__init__(data_mean, data_std, config, use_uncond_mode_at=use_uncond_mode_at, target_ch=target_ch) + self.bottom_up_layers_ch1 = nn.ModuleList([]) + self.bottom_up_layers_ch2 = nn.ModuleList([]) + + fbu_num_blocks = config.model.fbu_num_blocks + del self.first_bottom_up + stride = 1 if config.model.no_initial_downscaling else 2 + self.first_bottom_up = self.create_first_bottom_up(stride, num_blocks=fbu_num_blocks) + self.first_bottom_up_ch1 = self.create_first_bottom_up(stride, num_blocks=fbu_num_blocks) + self.first_bottom_up_ch2 = self.create_first_bottom_up(stride, num_blocks=fbu_num_blocks) + shape = (1, config.data.image_size, config.data.image_size) + self._inp_tensor_ch1 = nn.Parameter(torch.zeros(shape, requires_grad=True)) + self._inp_tensor_ch2 = nn.Parameter(torch.zeros(shape, requires_grad=True)) + + self.lowres_first_bottom_ups_ch1 = self.lowres_first_bottom_ups_ch2 = None + self.share_bottom_up_starting_idx = config.model.share_bottom_up_starting_idx + self.mixed_input_type = config.data.mixed_input_type + self.separate_mix_branch_training = config.model.separate_mix_branch_training + if self.lowres_first_bottom_ups is not None: + self.lowres_first_bottom_ups_ch1 = copy.deepcopy(self.lowres_first_bottom_ups_ch1) + self.lowres_first_bottom_ups_ch2 = copy.deepcopy(self.lowres_first_bottom_ups_ch2) + + enable_multiscale = self._multiscale_count is not None and self._multiscale_count > 1 + multiscale_lowres_size_factor = 1 + + for i in range(self.n_layers): + # Whether this is the top layer + layer_enable_multiscale = enable_multiscale and self._multiscale_count > i + 1 + # if multiscale is enabled, this is the factor by which the lowres tensor will be larger than + multiscale_lowres_size_factor *= (1 + int(layer_enable_multiscale)) + # Add bottom-up deterministic layer at level i. + # It's a sequence of residual blocks (BottomUpDeterministicResBlock) + # possibly with downsampling between them. + if i >= self.share_bottom_up_starting_idx: + self.bottom_up_layers_ch1.append(self.bottom_up_layers[i]) + self.bottom_up_layers_ch2.append(self.bottom_up_layers[i]) + continue + + blayer = self.get_bottom_up_layer(i, config.model.multiscale_lowres_separate_branch, enable_multiscale, + multiscale_lowres_size_factor) + self.bottom_up_layers_ch1.append(blayer) + blayer = self.get_bottom_up_layer(i, config.model.multiscale_lowres_separate_branch, enable_multiscale, + multiscale_lowres_size_factor) + self.bottom_up_layers_ch2.append(blayer) + + msg = f'[{self.__class__.__name__}] ShareStartIdx:{self.share_bottom_up_starting_idx} ' + msg += f'SepMixedBranch:{self.separate_mix_branch_training} ' + print(msg) + + def get_bottom_up_layer(self, ith_layer, lowres_separate_branch, enable_multiscale, multiscale_lowres_size_factor): + return BottomUpLayer( + n_res_blocks=self.encoder_blocks_per_layer, + n_filters=self.encoder_n_filters, + downsampling_steps=self.downsample[ith_layer], + nonlin=self.get_nonlin(), + batchnorm=self.batchnorm, + dropout=self.encoder_dropout, + res_block_type=self.res_block_type, + gated=self.gated, + lowres_separate_branch=lowres_separate_branch, + enable_multiscale=enable_multiscale, + multiscale_retain_spatial_dims=self.multiscale_retain_spatial_dims, + multiscale_lowres_size_factor=multiscale_lowres_size_factor, + ) + + def get_scheduler(self, optimizer): + return optim.lr_scheduler.ReduceLROnPlateau(optimizer, + self.lr_scheduler_mode, + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + + def get_encoder_params(self): + encoder_params = list(self.first_bottom_up.parameters()) + list(self.bottom_up_layers.parameters()) + if self.lowres_first_bottom_ups is not None: + encoder_params.append(self.lowres_first_bottom_ups.parameters()) + return encoder_params + + def get_ch1_branch_params(self): + encoder_ch1_params = list(self.first_bottom_up_ch1.parameters()) + list(self.bottom_up_layers_ch1.parameters()) + if self.lowres_first_bottom_ups_ch1 is not None: + encoder_ch1_params.append(self.lowres_first_bottom_ups_ch1.parameters()) + encoder_ch1_params.append(self._inp_tensor_ch1) + return encoder_ch1_params + + def get_ch2_branch_params(self): + encoder_ch2_params = list(self.first_bottom_up_ch2.parameters()) + list(self.bottom_up_layers_ch2.parameters()) + if self.lowres_first_bottom_ups_ch2 is not None: + encoder_ch2_params.append(self.lowres_first_bottom_ups_ch2.parameters()) + encoder_ch2_params.append(self._inp_tensor_ch2) + return encoder_ch2_params + + def get_decoder_params(self): + decoder_params = list(self.top_down_layers.parameters()) + list(self.final_top_down.parameters()) + list( + self.likelihood.parameters()) + return decoder_params + + def configure_optimizers(self): + + encoder_params = self.get_encoder_params() + decoder_params = self.get_decoder_params() + encoder_ch1_params = self.get_ch1_branch_params() + encoder_ch2_params = self.get_ch2_branch_params() + # channel 1 params + + if self.separate_mix_branch_training: + optimizer0 = optim.Adamax(encoder_params, lr=self.lr, weight_decay=0) + else: + optimizer0 = optim.Adamax(encoder_params + decoder_params, lr=self.lr, weight_decay=0) + optimizer1 = optim.Adamax(encoder_ch1_params + encoder_ch2_params + decoder_params, lr=self.lr, weight_decay=0) + + scheduler0 = self.get_scheduler(optimizer0) + scheduler1 = self.get_scheduler(optimizer1) + + return [optimizer0, optimizer1], [{ + 'scheduler': scheduler, + 'monitor': self.lr_scheduler_monitor, + } for scheduler in [scheduler0, scheduler1]] + + def _forward_mix(self, x): + img_size = x.size()[2:] + + # Pad input to make everything easier with conv strides + x_pad = self.pad_input(x) + + # Bottom-up inference: return list of length n_layers (bottom to top) + bu_values = self.bottomup_pass(mix_inp=x_pad) + + # Top-down inference/generation + out, td_data = self.topdown_pass(bu_values) + # Restore original image size + out = crop_img_tensor(out, img_size) + + return out, td_data + + def _forward_separate_ch(self, ch1_inp, ch2_inp): + img_size = ch1_inp.size()[2:] if ch1_inp is not None else ch2_inp.size()[2:] + + # Pad input to make everything easier with conv strides + ch1_inp = self.pad_input(ch1_inp) if ch1_inp is not None else None + ch2_inp = self.pad_input(ch2_inp) if ch2_inp is not None else None + + # Bottom-up inference: return list of length n_layers (bottom to top) + bu_values = self.bottomup_pass(ch1_inp=ch1_inp, ch2_inp=ch2_inp) + + # Top-down inference/generation + out, td_data = self.topdown_pass(bu_values) + # Restore original image size + out = crop_img_tensor(out, img_size) + + return out, td_data + + def _bottomup_pass_ch(self, ch1_inp, ch2_inp): + if ch1_inp is None: + ch1_inp = self._inp_tensor_ch1[None] + assert ch2_inp is not None + ch1_inp = torch.tile(ch1_inp, (len(ch2_inp), 1, 1, 1)) + + if ch2_inp is None: + ch2_inp = self._inp_tensor_ch2[None] + assert ch1_inp is not None + ch2_inp = torch.tile(ch2_inp, (len(ch1_inp), 1, 1, 1)) + + x1 = self.first_bottom_up_ch1(ch1_inp) + x2 = self.first_bottom_up_ch2(ch2_inp) + # Loop from bottom to top layer, store all deterministic nodes we + # need in the top-down pass + bu_values = [] + + for i in range(self.n_layers): + + if self.share_bottom_up_starting_idx > i: + x1, bu_value1 = self.bottom_up_layers_ch1[i](x1, lowres_x=None) + x2, bu_value2 = self.bottom_up_layers_ch2[i](x2, lowres_x=None) + bu_values.append((bu_value1 + bu_value2) / 2) + else: + if self.share_bottom_up_starting_idx == i: + x = (x1 + x2) / 2 + + x, bu_value = self.bottom_up_layers[i](x, lowres_x=None) + + bu_values.append(bu_value) + + return bu_values + + def bottomup_pass(self, mix_inp=None, ch1_inp=None, ch2_inp=None): + # by default it is necessary to feed 0, since in validation step it is required. + if mix_inp is not None: + return super().bottomup_pass(mix_inp) + else: + return self._bottomup_pass_ch(ch1_inp, ch2_inp) + + def validation_step(self, batch, batch_idx): + x, target, supervised_mask = batch + assert supervised_mask.sum() == len(x) + return super().validation_step((x, target), batch_idx) + + # TODO: TRAINING STEP FOR semi_supervised_v3. I need to use this. + # def training_step(self, batch, batch_idx, optimizer_idx, enable_logging=True): + # + # x, target, supervised_mask = batch + # x_normalized = self.normalize_input(x) + # target_normalized = self.normalize_target(target) + # if optimizer_idx == 0: + # out, td_data = self.forward_ch(x_normalized, optimizer_idx) + # if self.mixed_input_type == MixedInputType.ConsistentWithSingleInputs: + # if self.skip_disentanglement_for_nonaligned_data: + # if supervised_mask.sum() > 0: + # recons_loss_dict = self._get_reconstruction_loss_vector(out[supervised_mask], + # target_normalized[supervised_mask]) + # recons_loss = recons_loss_dict['loss'].mean() + # else: + # recons_loss = 0.0 + # else: + # recons_loss_dict = self._get_reconstruction_loss_vector(out, target_normalized) + # recons_loss = recons_loss_dict['loss'].mean() + # else: + # assert self.mixed_input_type == MixedInputType.Aligned + # recons_loss = 0 + # if supervised_mask.sum() > 0: + # recons_loss_dict = self._get_reconstruction_loss_vector(out[supervised_mask], + # target_normalized[supervised_mask]) + # recons_loss = recons_loss_dict['loss'].sum() + # if (~supervised_mask).sum() > 0: + # # todo: check if x_normalized does not have any extra pre-processing. + # recons_loss += self._get_mixed_reconstruction_loss_vector(out[~supervised_mask], + # x_normalized[~supervised_mask]).sum() + # N = len(x) + # recons_loss = recons_loss / N + # else: + # out, td_data = self.forward_ch(target_normalized[:, optimizer_idx - 1:optimizer_idx], optimizer_idx) + # recons_loss_dict = self._get_reconstruction_loss_vector(out, target_normalized) + # if optimizer_idx == 1: + # recons_loss = recons_loss_dict['ch1_loss'].mean() + # elif optimizer_idx == 2: + # recons_loss = recons_loss_dict['ch2_loss'].mean() + # + def training_step(self, batch, batch_idx, optimizer_idx, enable_logging=True): + x, target, _ = batch + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + if optimizer_idx == 0: + out, td_data = self._forward_mix(x_normalized) + assert self.mixed_input_type == MixedInputType.ConsistentWithSingleInputs + recons_loss_dict = self._get_reconstruction_loss_vector(out, target_normalized) + recons_loss = recons_loss_dict['loss'].mean() + else: + out, td_data = self._forward_separate_ch(target_normalized[:, :1], target_normalized[:, 1:2]) + recons_loss_dict = self._get_reconstruction_loss_vector(out, target_normalized) + recons_loss = recons_loss_dict['loss'].mean() + + kl_loss = self.get_kl_divergence_loss(td_data) + + net_loss = recons_loss + self.get_kl_weight() * kl_loss + if enable_logging: + self.log(f'reconstruction_loss_ch{optimizer_idx}', recons_loss, on_epoch=True) + self.log(f'kl_loss_ch{optimizer_idx}', kl_loss, on_epoch=True) + + output = { + 'loss': net_loss, + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + # skipping inf loss + if torch.isinf(net_loss).any(): + return None + + return output diff --git a/denoisplit/nets/lvae_multires_target.py b/denoisplit/nets/lvae_multires_target.py new file mode 100644 index 0000000..417fcf6 --- /dev/null +++ b/denoisplit/nets/lvae_multires_target.py @@ -0,0 +1,117 @@ +from denoisplit.nets.lvae import LadderVAE +import torch.nn as nn +import torch +from denoisplit.core.loss_type import LossType + + +class LadderVAEMultiTarget(LadderVAE): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super(LadderVAEMultiTarget, self).__init__(data_mean, + data_std, + config, + use_uncond_mode_at=use_uncond_mode_at, + target_ch=target_ch) + self._lres_final_top_down = None + self._latent_dims = config.model.z_dims + self._lres_final_top_down = nn.ModuleList() + self._lres_conv_for_z = nn.ModuleList() + + for ith_res in range(self._multiscale_count - 1): + self._lres_conv_for_z.append( + nn.Conv2d(self._latent_dims[ith_res], config.model.decoder.n_filters, 3, padding=1)) + self._lres_final_top_down.append(self.create_final_topdown_layer(False)) + + self._lres_likelihoods = None + self._lres_likelihoods = nn.ModuleList() + for _ in range(self._multiscale_count - 1): + self._lres_likelihoods.append(self.create_likelihood_module()) + self._lres_recloss_w = config.loss.lres_recloss_w + assert len(self._lres_recloss_w) == config.data.multiscale_lowres_count + + print(f'[{self.__class__.__name__}] LowResSupLen:{len(self._lres_likelihoods)} rec_w:{self._lres_recloss_w}') + + def validation_step(self, batch, batch_idx): + x, target = batch + return super().validation_step((x, target[:, 0]), batch_idx) + + def get_allres_predictions(self, x_normalized): + """ + Get all disentangled predictions at all levels. + Args: + x_normalized: + + Returns: + + """ + out, td_data = self.forward(x_normalized) + lowres_outs = [self.likelihood.parameter_net(out)] + for l_to_h_idx in range(self._multiscale_count - 1): + out_temp = self._lres_conv_for_z[l_to_h_idx](td_data['z'][l_to_h_idx]) + lowres_out = self._lres_final_top_down[l_to_h_idx](out_temp) + lowres_out = self._lres_likelihoods[l_to_h_idx].parameter_net(lowres_out) + lowres_outs.append(lowres_out) + return lowres_outs + + def get_all_res_reconstruction_loss(self, out, td_data, target_normalized): + """ + Reconstruction loss from all resolutions + """ + lowres_outs = [] + for l_to_h_idx in range(self._multiscale_count - 1): + out_temp = self._lres_conv_for_z[l_to_h_idx](td_data['z'][l_to_h_idx]) + lowres_outs.append(self._lres_final_top_down[l_to_h_idx](out_temp)) + + recons_loss = 0 + assert self._multiscale_count == target_normalized.shape[1] + + for ith_res in range(self._multiscale_count): + if ith_res == 0: + recons_loss_dict = self.get_reconstruction_loss(out, target_normalized[:, 0]) + else: + new_sz = self.img_shape[0] // (2**ith_res) + skip_idx = (target_normalized.shape[-1] - new_sz) // 2 + tar_res = target_normalized[:, ith_res, :, skip_idx:-skip_idx, skip_idx:-skip_idx] + lowres_pred = lowres_outs[ith_res - 1] + if self.multiscale_decoder_retain_spatial_dims: + lowres_pred = lowres_pred[:, :, skip_idx:-skip_idx, skip_idx:-skip_idx] + + recons_loss_dict = self.get_reconstruction_loss(lowres_pred, + tar_res, + likelihood_obj=self._lres_likelihoods[ith_res - 1]) + recons_loss += recons_loss_dict['loss'] * self._lres_recloss_w[ith_res] + return recons_loss + + def training_step(self, batch, batch_idx, enable_logging=True): + x, target = batch + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + + out, td_data = self.forward(x_normalized) + recons_loss = self.get_all_res_reconstruction_loss(out, td_data, target_normalized) + kl_loss = self.get_kl_divergence_loss(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + assert self.loss_type not in [LossType.ElboMixedReconstruction, LossType.ElboWithNbrConsistency] + assert self.non_stochastic_version is False + + if enable_logging: + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss, on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach(), + 'kl_loss': kl_loss.detach(), + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output diff --git a/denoisplit/nets/lvae_restricted_reconstruction.py b/denoisplit/nets/lvae_restricted_reconstruction.py new file mode 100644 index 0000000..a2745a8 --- /dev/null +++ b/denoisplit/nets/lvae_restricted_reconstruction.py @@ -0,0 +1,114 @@ +import numpy as np + +from denoisplit.core.loss_type import LossType +from denoisplit.loss.restricted_reconstruction_loss import RestrictedReconstruction +from denoisplit.nets.lvae import LadderVAE + + +class LadderVAERestrictedReconstruction(LadderVAE): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2, val_idx_manager=None): + super().__init__(data_mean, data_std, config, use_uncond_mode_at, target_ch, val_idx_manager=val_idx_manager) + self.automatic_optimization = False + assert self.loss_type == LossType.ElboRestrictedReconstruction + self.mixed_rec_w = config.loss.mixed_rec_weight + self.split_w = config.loss.get('split_weight', 1.0) + self._switch_to_nonorthogonal_epoch = config.loss.get('switch_to_nonorthogonal_epoch', 100000) + + # note that split_s is directly multipled with the loss and not with the gradient. + self.grad_setter = RestrictedReconstruction(1, self.mixed_rec_w) + self._nonorthogonal_epoch_enabled = False + + def training_step(self, batch, batch_idx, enable_logging=True): + if self.current_epoch == 0 and batch_idx == 0: + self.log('val_psnr', 1.0, on_epoch=True) + + if self.current_epoch == self._switch_to_nonorthogonal_epoch and self._nonorthogonal_epoch_enabled == False: + self.grad_setter.enable_nonorthogonal() + self._nonorthogonal_epoch_enabled = True + + x, target = batch[:2] + x_normalized = self.normalize_input(x) + assert self.reconstruction_mode != True + target_normalized = self.normalize_target(target) + mask = ~((target == 0).reshape(len(target), -1).all(dim=1)) + out, td_data = self.forward(x_normalized) + assert self.loss_type == LossType.ElboRestrictedReconstruction + pred_x_normalized, _ = self.get_mixed_prediction(out, None, self.data_mean, self.data_std) + optim = self.optimizers() + optim.zero_grad() + split_loss = self.grad_setter.loss_fn(target_normalized[mask], out[mask]) + self.manual_backward(self.split_w * split_loss, retain_graph=True) + # add input reconstruction loss compoenent to the gradient. + loss_dict = self.grad_setter.update_gradients(list(self.named_parameters()), x_normalized, + target_normalized[mask], out[mask], pred_x_normalized, + self.current_epoch) + optim.step() + assert self.non_stochastic_version == True + if enable_logging: + training_loss = self.split_w * split_loss + self.mixed_rec_w * loss_dict['input_reconstruction_loss'] + self.log('training_loss', training_loss, on_epoch=True) + self.log('reconstruction_loss', split_loss, on_epoch=True) + self.log('input_reconstruction_loss', loss_dict['input_reconstruction_loss'], on_epoch=True) + for key in loss_dict['log']: + self.log(key, loss_dict['log'][key], on_epoch=True) + + def on_validation_epoch_end(self): + psnr_arr = [] + for i in range(len(self.channels_psnr)): + psnr = self.channels_psnr[i].get() + psnr_arr.append(psnr.cpu().numpy()) + self.channels_psnr[i].reset() + + psnr = np.mean(psnr_arr) + self.log('val_psnr', psnr, on_epoch=True) + + sch1 = self.lr_schedulers() + sch1.step(psnr) + + if self._dump_kth_frame_prediction is not None: + if self.current_epoch == 0 or self.current_epoch % self._dump_epoch_interval == 0: + self._val_frame_creator.dump(self.current_epoch) + self._val_frame_creator.reset() + if self.current_epoch == 1: + self._val_frame_creator.dump_target() + + if self.mixed_rec_w_step: + self.mixed_rec_w = max(self.mixed_rec_w - self.mixed_rec_w_step, 0.0) + self.log('mixed_rec_w', self.mixed_rec_w, on_epoch=True) + + +if __name__ == '__main__': + import numpy as np + import torch + + from denoisplit.configs.biosr_sparsely_supervised_config import get_config + config = get_config() + # config.loss.critic_loss_weight = 0.0 + data_mean = torch.Tensor([0]).reshape(1, 1, 1, 1) + data_std = torch.Tensor([1]).reshape(1, 1, 1, 1) + model = LadderVAERestrictedReconstruction({ + 'input': data_mean, + 'target': data_mean.repeat(1, 2, 1, 1) + }, { + 'input': data_std, + 'target': data_std.repeat(1, 2, 1, 1) + }, config) + model.configure_optimizers() + mc = 1 if config.data.multiscale_lowres_count is None else config.data.multiscale_lowres_count + inp = torch.rand((2, mc, config.data.image_size, config.data.image_size)) + out, td_data = model(inp) + batch = ( + torch.rand((16, mc, config.data.image_size, config.data.image_size)), + torch.rand((16, 2, config.data.image_size, config.data.image_size)), + ) + batch[1][::2] = 0 * batch[1][::2] + + model.validation_step(batch, 0) + model.training_step(batch, 0) + + ll = torch.ones((12, 2, 32, 32)) + ll_new = model._get_weighted_likelihood(ll) + print(ll_new[:, 0].mean(), ll_new[:, 0].std()) + print(ll_new[:, 1].mean(), ll_new[:, 1].std()) + print('mar') diff --git a/denoisplit/nets/lvae_semi_supervised.py b/denoisplit/nets/lvae_semi_supervised.py new file mode 100644 index 0000000..eb061ef --- /dev/null +++ b/denoisplit/nets/lvae_semi_supervised.py @@ -0,0 +1,230 @@ +from distutils.command.config import LANG_EXT +from statistics import mode +from turtle import pd +from denoisplit.nets.lvae import LadderVAE, compute_batch_mean, torch_nanmean +import torch +from denoisplit.core.loss_type import LossType +from denoisplit.core.psnr import RangeInvariantPsnr +from denoisplit.loss.exclusive_loss import compute_exclusion_loss +from denoisplit.data_loader.pavia2_enums import Pavia2BleedthroughType +import torch.nn as nn + + +class LadderVAESemiSupervised(LadderVAE): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super().__init__(data_mean, data_std, config, use_uncond_mode_at, target_ch) + assert self.enable_mixed_rec is True + self._exclusion_loss_w = config.loss.get('exclusion_loss_weight', None) + conv1 = nn.Conv2d(config.model.decoder.n_filters, 32, 5, stride=2, padding=2) + conv2 = nn.Conv2d(32, 16, 5, stride=2, padding=2) + conv3 = nn.Conv2d(16, 1, 5, stride=2, padding=2) + self._factor_branch = nn.Sequential(conv1, nn.LeakyReLU(), conv2, nn.LeakyReLU(), conv3, nn.ReLU(), + nn.AvgPool2d(8)) + print(f'[{self.__class__.__name__}] Exclusion Loss w', self._exclusion_loss_w) + + def get_factor(self, reconstruction): + factor = self._factor_branch(reconstruction) + 1 + return factor + + def get_mixed_prediction(self, reconstruction, channelwise_prediction, channelwise_logvar): + factor = self.get_factor(reconstruction) + + mixed_prediction = channelwise_prediction[:, :1] * factor + channelwise_prediction[:, 1:] + + var = torch.exp(channelwise_logvar) + # sum of variance. + var = var[:, :1] * (factor * factor) + var[:, 1:] + logvar = torch.log(var) + + return mixed_prediction, logvar + + def _get_reconstruction_loss_vector(self, reconstruction, input, target_ch1, return_predicted_img=False): + """ + Args: + return_predicted_img: If set to True, the besides the loss, the reconstructed image is also returned. + """ + + # Log likelihood + ll, like_dict = self.likelihood(reconstruction, target_ch1) + + # We just want to compute it for the first channel. + ll = ll[:, :1] + + if self.skip_nboundary_pixels_from_loss is not None and self.skip_nboundary_pixels_from_loss > 0: + pad = self.skip_nboundary_pixels_from_loss + ll = ll[:, :, pad:-pad, pad:-pad] + like_dict['params']['mean'] = like_dict['params']['mean'][:, :, pad:-pad, pad:-pad] + + recons_loss = compute_batch_mean(-1 * ll) + exclusion_loss = None + if self._exclusion_loss_w: + exclusion_loss = compute_exclusion_loss(reconstruction[:, :1], reconstruction[:, 1:]) + + output = { + 'loss': recons_loss, + 'ch1_loss': compute_batch_mean(-ll[:, 0]), + 'ch2_loss': None, + 'exclusion_loss': exclusion_loss + } + + mixed_target = input[:, :1] + mixed_prediction, mixed_logvar = self.get_mixed_prediction(reconstruction, like_dict['params']['mean'], + like_dict['params']['logvar']) + + # TODO: We must enable standard deviation here in some way. I think this is very much needed. + mixed_recons_ll = self.likelihood.log_likelihood(mixed_target, { + 'mean': mixed_prediction, + 'logvar': mixed_logvar + }) + output['mixed_loss'] = compute_batch_mean(-1 * mixed_recons_ll) + + if return_predicted_img: + return output, torch.cat([like_dict['params']['mean'], mixed_prediction], dim=1) + + return output + + def get_reconstruction_loss(self, reconstruction, input, target_ch1, return_predicted_img=False): + output = self._get_reconstruction_loss_vector(reconstruction, + input, + target_ch1, + return_predicted_img=return_predicted_img) + loss_dict = output[0] if return_predicted_img else output + loss_dict['loss'] = torch.mean(loss_dict['loss']) + loss_dict['ch1_loss'] = torch.mean(loss_dict['ch1_loss']) + loss_dict['ch2_loss'] = None + + if 'mixed_loss' in loss_dict: + loss_dict['mixed_loss'] = torch.mean(loss_dict['mixed_loss']) + if return_predicted_img: + assert len(output) == 2 + return loss_dict, output[1] + else: + return loss_dict + + def normalize_target(self, target, dataset_index): + mean_ = self.data_mean[dataset_index, :, 1:] + assert mean_.shape[-1] == 1 + mean_ = mean_[..., 0] + assert len(mean_) == len(target) + std_ = self.data_std[dataset_index, :, 1:] + return (target - mean_) / std_[..., 0] + + def normalize_input(self, x, dataset_index): + if self.normalized_input: + return x + return (x - self.data_mean[dataset_index].mean()) / self.data_std[dataset_index].mean() + + def training_step(self, batch, batch_idx, enable_logging=True): + x, target, dataset_index = batch + x_normalized = self.normalize_input(x, dataset_index) + target_normalized = self.normalize_target(target, dataset_index) + + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict = self.get_reconstruction_loss(out, + x_normalized, + target_normalized, + return_predicted_img=False) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = recons_loss_dict['loss'] + assert self.loss_type == LossType.ElboSemiSupMixedReconstruction + + recons_loss += self.mixed_rec_w * recons_loss_dict['mixed_loss'] + + if enable_logging: + self.log('mixed_reconstruction_loss', recons_loss_dict['mixed_loss'], on_epoch=True) + + kl_loss = self.get_kl_divergence_loss(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + if self._exclusion_loss_w: + excl_loss = self._exclusion_loss_w * recons_loss_dict['exclusion_loss'] + net_loss += net_loss + if enable_logging: + self.log('exclusion_loss', excl_loss, on_epoch=True) + + if enable_logging: + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach(), + 'kl_loss': kl_loss.detach(), + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def validation_step(self, batch, batch_idx): + x, target, dataset_index = batch + self.set_params_to_same_device_as(target) + + x_normalized = self.normalize_input(x, dataset_index) + target_normalized = self.normalize_target(target, dataset_index) + + out, td_data = self.forward(x_normalized) + + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, recons_img = self.get_reconstruction_loss(out, + x_normalized, + target_normalized, + return_predicted_img=True) + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + self.label1_psnr.update(recons_img[:, 0], target_normalized[:, 0]) + psnr_label1 = RangeInvariantPsnr(target_normalized[:, 0].clone(), recons_img[:, 0].clone()) + recons_loss = recons_loss_dict['loss'] + self.log('val_loss', recons_loss, on_epoch=True) + val_psnr_l1 = torch_nanmean(psnr_label1).item() + self.log('val_psnr_l1', val_psnr_l1, on_epoch=True) + + if batch_idx == 0 and self.power_of_2(self.current_epoch): + all_samples = [] + for i in range(20): + sample, _ = self(x_normalized[0:1, ...]) + sample = self.likelihood.get_mean_lv(sample)[0] + all_samples.append(sample[None]) + + all_samples = torch.cat(all_samples, dim=0) + all_samples = all_samples * self.data_std[dataset_index[0]] + self.data_mean[dataset_index[0]] + all_samples = all_samples.cpu() + img_mmse = torch.mean(all_samples, dim=0)[0] + self.log_images_for_tensorboard(all_samples[:, 0, 0, ...], target[0, 0, ...], img_mmse[0], 'label1') + + def on_validation_epoch_end(self): + psnrl1 = self.label1_psnr.get() + psnr = psnrl1 + self.log('val_psnr', psnr, on_epoch=True) + self.label1_psnr.reset() + + +if __name__ == '__main__': + from denoisplit.configs.semi_supervised_config import get_config + config = get_config() + data_mean = torch.ones([3, 1, 2, 1, 1]) + data_std = torch.ones([3, 1, 2, 1, 1]) + model = LadderVAESemiSupervised(data_mean, data_std, config) + inp = torch.rand((32, 1, 64, 64)) + tar = torch.rand(32, 1, 64, 64) + dset_index = torch.randint(low=0, high=3, size=(len(inp), )) + model.training_step((inp, tar, dset_index), 0) diff --git a/denoisplit/nets/lvae_twindecoder.py b/denoisplit/nets/lvae_twindecoder.py new file mode 100644 index 0000000..f1fd537 --- /dev/null +++ b/denoisplit/nets/lvae_twindecoder.py @@ -0,0 +1,287 @@ +from typing import List, Tuple + +import numpy as np +import pytorch_lightning as pl +import torch +import torch.optim as optim +from torch import nn + +from denoisplit.core.data_utils import Interpolate, crop_img_tensor, pad_img_tensor +from denoisplit.core.likelihoods import GaussianLikelihood, NoiseModelLikelihood +from denoisplit.core.loss_type import LossType +from denoisplit.losses import free_bits_kl +from denoisplit.nets.lvae import LadderVAE +from denoisplit.nets.lvae_layers import (BottomUpDeterministicResBlock, BottomUpLayer, TopDownDeterministicResBlock, + TopDownLayer) + + +class LadderVAETwinDecoder(LadderVAE): + + def __init__(self, data_mean, data_std, config): + super().__init__(data_mean, data_std, config, target_ch=1) + + del self.top_down_layers + self.top_down_layers = None + self.top_down_layers_l1 = nn.ModuleList([]) + self.top_down_layers_l2 = nn.ModuleList([]) + self.enable_input_alphasum_of_channels = config.get('enable_input_alphasum_of_channels', False) + nonlin = self.get_nonlin() + + for i in range(self.n_layers): + # Whether this is the top layer + is_top = i == self.n_layers - 1 + + self.top_down_layers_l1.append( + TopDownLayer( + z_dim=self.z_dims[i], + n_res_blocks=self.decoder_blocks_per_layer, + n_filters=self.decoder_n_filters // 2, + is_top_layer=is_top, + downsampling_steps=self.downsample[i], + nonlin=nonlin, + merge_type=self.merge_type, + batchnorm=self.topdown_batchnorm, + dropout=self.decoder_dropout, + stochastic_skip=self.stochastic_skip, + learn_top_prior=self.learn_top_prior, + top_prior_param_shape=self.get_top_prior_param_shape(), + res_block_type=self.res_block_type, + gated=self.gated, + analytical_kl=self.analytical_kl, + conv2d_bias=self.topdown_conv2d_bias, + non_stochastic_version=self.non_stochastic_version, + )) + + self.top_down_layers_l2.append( + TopDownLayer( + z_dim=self.z_dims[i], + n_res_blocks=self.decoder_blocks_per_layer, + n_filters=self.decoder_n_filters // 2, + is_top_layer=is_top, + downsampling_steps=self.downsample[i], + nonlin=nonlin, + merge_type=self.merge_type, + batchnorm=self.topdown_batchnorm, + dropout=self.decoder_dropout, + stochastic_skip=self.stochastic_skip, + learn_top_prior=self.learn_top_prior, + top_prior_param_shape=self.get_top_prior_param_shape(), + res_block_type=self.res_block_type, + gated=self.gated, + analytical_kl=self.analytical_kl, + conv2d_bias=self.topdown_conv2d_bias, + non_stochastic_version=self.non_stochastic_version, + )) + + # Final top-down layer + self.final_top_down_l1 = self.get_final_top_down() + self.final_top_down_l2 = self.get_final_top_down() + # Define likelihood + assert self.likelihood_form == 'gaussian' + del self.likelihood + self.likelihood = None + self.likelihood_l1 = GaussianLikelihood(self.decoder_n_filters // 2, + self.target_ch, + predict_logvar=self.predict_logvar, + conv2d_bias=self.topdown_conv2d_bias) + + self.likelihood_l2 = GaussianLikelihood(self.decoder_n_filters // 2, + self.target_ch, + predict_logvar=self.predict_logvar, + conv2d_bias=self.topdown_conv2d_bias) + print(f'[{self.__class__.__name__}]') + + def set_params_to_same_device_as(self, correct_device_tensor): + if isinstance(self.data_mean, torch.Tensor): + if self.data_mean.device != correct_device_tensor.device: + self.data_mean = self.data_mean.to(correct_device_tensor.device) + self.data_std = self.data_std.to(correct_device_tensor.device) + self.likelihood_l1.set_params_to_same_device_as(correct_device_tensor) + self.likelihood_l2.set_params_to_same_device_as(correct_device_tensor) + + def get_final_top_down(self): + modules = list() + nonlin = self.get_nonlin() + if not self.no_initial_downscaling: + modules.append(Interpolate(scale=2)) + for i in range(self.decoder_blocks_per_layer): + modules.append( + TopDownDeterministicResBlock( + c_in=self.decoder_n_filters // 2, + c_out=self.decoder_n_filters // 2, + nonlin=nonlin, + batchnorm=self.topdown_batchnorm, + dropout=self.decoder_dropout, + res_block_type=self.res_block_type, + gated=self.gated, + conv2d_bias=self.topdown_conv2d_bias, + )) + + return nn.Sequential(*modules) + + def sample_from_q(self, x, masks=None) -> Tuple[List[torch.Tensor], List[torch.Tensor]]: + img_size = x.size()[2:] + + # Pad input to make everything easier with conv strides + x_pad = self.pad_input(x) + + # Bottom-up inference: return list of length n_layers (bottom to top) + bu_values = self.bottomup_pass(x_pad) + bu_values_l1, bu_values_l2 = self.get_separate_bu_values(bu_values) + + sample1 = self._sample_from_q(bu_values_l1, + top_down_layers=self.top_down_layers_l1, + final_top_down_layer=self.final_top_down_l1, + masks=masks) + + sample2 = self._sample_from_q(bu_values_l2, + top_down_layers=self.top_down_layers_l2, + final_top_down_layer=self.final_top_down_l2, + masks=masks) + return sample1, sample2 + + @staticmethod + def get_separate_bu_values(bu_values): + """ + One bu_value list for each decoder + """ + bu_values_l1 = [] + bu_values_l2 = [] + + for one_level_bu in bu_values: + bu_l1, bu_l2 = one_level_bu.chunk(2, dim=1) + bu_values_l1.append(bu_l1) + bu_values_l2.append(bu_l2) + return bu_values_l1, bu_values_l2 + + def forward(self, x): + img_size = x.size()[2:] + + # Pad input to make everything easier with conv strides + x_pad = self.pad_input(x) + # Bottom-up inference: return list of length n_layers (bottom to top) + bu_values = self.bottomup_pass(x_pad) + bu_values_l1, bu_values_l2 = self.get_separate_bu_values(bu_values) + + # Top-down inference/generation + out_l1, td_data_l1 = self.topdown_pass( + bu_values_l1, + top_down_layers=self.top_down_layers_l1, + final_top_down_layer=self.final_top_down_l1, + ) + out_l2, td_data_l2 = self.topdown_pass( + bu_values_l2, + top_down_layers=self.top_down_layers_l2, + final_top_down_layer=self.final_top_down_l2, + ) + + # Restore original image size + out_l1 = crop_img_tensor(out_l1, img_size) + out_l2 = crop_img_tensor(out_l2, img_size) + + td_data = { + 'z': [torch.cat([td_data_l1['z'][i], td_data_l2['z'][i]], dim=1) for i in range(len(td_data_l1['z']))], + 'bu_values_l1': bu_values_l1, + 'bu_values_l2': bu_values_l2, + } + + if td_data_l2['kl'][0] is not None: + td_data['kl'] = [(td_data_l1['kl'][i] + td_data_l2['kl'][i]) / 2 for i in range(len(td_data_l1['kl']))] + return out_l1, out_l2, td_data + + def get_reconstruction_loss(self, reconstruction_l1, reconstruction_l2, target, return_predicted_img=False): + # Log likelihood + ll, like1_dict = self.likelihood_l1(reconstruction_l1, target[:, 0:1]) + recons_loss_l1 = -ll.mean() + + ll, like2_dict = self.likelihood_l2(reconstruction_l2, target[:, 1:]) + recons_loss_l2 = -ll.mean() + recon_loss = (self.ch1_recons_w * recons_loss_l1 + self.ch2_recons_w * recons_loss_l2) / 2 + if return_predicted_img: + rec_imgs = [like1_dict['params']['mean'], like2_dict['params']['mean']] + return recon_loss, rec_imgs + + return recon_loss + + def compute_gradient_norm(self): + grad_norm_bottom_up = self._compute_gradient_norm(self.bottom_up_layers) + grad_norm_top_down = 0.5 * self._compute_gradient_norm(self.top_down_layers_l1) + grad_norm_top_down += 0.5 * self._compute_gradient_norm(self.top_down_layers_l2) + return grad_norm_bottom_up, grad_norm_top_down + + def training_step(self, batch, batch_idx): + x, target = batch[:2] + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + + if self.enable_input_alphasum_of_channels: + # adjust the targets for the alpha + alpha = batch[2][:, None, None, None] + tar1 = target_normalized[:, :1] * alpha + tar2 = target_normalized[:, 1:] * (1 - alpha) + target_normalized = torch.cat([tar1, tar2], dim=1) + if batch_idx == 0: + assert torch.abs(torch.sum(target_normalized, dim=1, keepdim=True) - x_normalized).max().item() < 1e-5 + + out_l1, out_l2, td_data = self.forward(x_normalized) + + recons_loss = self.get_reconstruction_loss(out_l1, out_l2, target_normalized) + if self.non_stochastic_version: + kl_loss = torch.Tensor([0.0]).cuda() + net_loss = recons_loss + else: + kl_loss = self.get_kl_divergence_loss(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + self.log('reconstruction_loss', recons_loss, on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach(), + 'kl_loss': kl_loss.detach(), + } + return output + + def validation_step(self, batch, batch_idx): + x, target = batch[:2] + self.set_params_to_same_device_as(target) + + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target, batch=batch) + + out_l1, out_l2, td_data = self.forward(x_normalized) + + recons_loss, recons_img_list = self.get_reconstruction_loss(out_l1, + out_l2, + target_normalized, + return_predicted_img=True) + self.label1_psnr.update(recons_img_list[0][:, 0], target_normalized[:, 0]) + self.label2_psnr.update(recons_img_list[1][:, 0], target_normalized[:, 1]) + + self.log('val_loss', recons_loss, on_epoch=True) + if batch_idx == 0 and self.power_of_2(self.current_epoch): + all_samples_l1 = [] + all_samples_l2 = [] + for i in range(20): + sample_l1, sample_l2, _ = self(x_normalized[0:1, ...]) + sample_l1 = self.likelihood_l1.parameter_net(sample_l1) + sample_l2 = self.likelihood_l2.parameter_net(sample_l2) + all_samples_l1.append(sample_l1[None]) + all_samples_l2.append(sample_l2[None]) + + all_samples_l1 = torch.cat(all_samples_l1, dim=0) + all_samples_l1 = all_samples_l1 * self.data_std + self.data_mean + all_samples_l1 = all_samples_l1.cpu() + img_mmse_l1 = torch.mean(all_samples_l1, dim=0)[0] + + all_samples_l2 = torch.cat(all_samples_l2, dim=0) + all_samples_l2 = all_samples_l2 * self.data_std + self.data_mean + all_samples_l2 = all_samples_l2.cpu() + img_mmse_l2 = torch.mean(all_samples_l2, dim=0)[0] + + self.log_images_for_tensorboard(all_samples_l1[:, 0, 0, ...], target[0, 0, ...], img_mmse_l1[0], 'label1') + self.log_images_for_tensorboard(all_samples_l2[:, 0, 0, ...], target[0, 1, ...], img_mmse_l2[0], 'label2') diff --git a/denoisplit/nets/lvae_twodset.py b/denoisplit/nets/lvae_twodset.py new file mode 100644 index 0000000..522c564 --- /dev/null +++ b/denoisplit/nets/lvae_twodset.py @@ -0,0 +1,371 @@ +""" +Multi dataset based setup. +""" +import torch +import torch.nn as nn + +from denoisplit.core.loss_type import LossType +from denoisplit.core.psnr import RangeInvariantPsnr +from denoisplit.nets.lvae import LadderVAE, compute_batch_mean, torch_nanmean + + +class LadderVaeTwoDset(LadderVAE): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super().__init__(data_mean, data_std, config, use_uncond_mode_at, target_ch) + assert config.loss.loss_type == LossType.ElboMixedReconstruction, "This model only supports ElboMixedReconstruction loss type." + self._interchannel_weights = None + if config.model.get('enable_learnable_interchannel_weights', False): + # self._interchannel_weights = nn.Parameter(torch.ones((1, target_ch, 1, 1)), requires_grad=True) + self._interchannel_weights = nn.Conv2d(target_ch, target_ch, 1, bias=True, groups=target_ch) + + for dloader_key in self.data_mean.keys(): + assert dloader_key in ['subdset_0', 'subdset_1'] + for data_key in self.data_mean[dloader_key].keys(): + assert data_key in ['target', 'input'] + self.data_mean[dloader_key][data_key] = torch.Tensor(data_mean[dloader_key][data_key]) + self.data_std[dloader_key][data_key] = torch.Tensor(data_std[dloader_key][data_key]) + + self.data_mean[dloader_key]['input'] = self.data_mean[dloader_key]['input'].reshape(1, 1, 1, 1) + self.data_std[dloader_key]['input'] = self.data_std[dloader_key]['input'].reshape(1, 1, 1, 1) + + print(f'[{self.__class__.__name__}] Learnable Ch weights:', self._interchannel_weights is not None) + + def get_reconstruction_loss(self, + reconstruction, + target, + input, + dset_idx, + loss_type_idx, + return_predicted_img=False, + likelihood_obj=None): + output = self._get_reconstruction_loss_vector(reconstruction, + target, + input, + dset_idx, + return_predicted_img=return_predicted_img, + likelihood_obj=likelihood_obj) + loss_dict = output[0] if return_predicted_img else output + individual_ch_loss_mask = loss_type_idx == LossType.Elbo + mixed_reconstruction_mask = loss_type_idx == LossType.ElboMixedReconstruction + + if torch.sum(individual_ch_loss_mask) > 0: + loss_dict['loss'] = torch.mean(loss_dict['loss'][individual_ch_loss_mask]) + loss_dict['ch1_loss'] = torch.mean(loss_dict['ch1_loss'][individual_ch_loss_mask]) + loss_dict['ch2_loss'] = torch.mean(loss_dict['ch2_loss'][individual_ch_loss_mask]) + else: + loss_dict['loss'] = 0.0 + loss_dict['ch1_loss'] = 0.0 + loss_dict['ch2_loss'] = 0.0 + + if torch.sum(mixed_reconstruction_mask) > 0: + loss_dict['mixed_loss'] = torch.mean(loss_dict['mixed_loss'][mixed_reconstruction_mask]) + else: + loss_dict['mixed_loss'] = 0.0 + + if return_predicted_img: + assert len(output) == 2 + return loss_dict, output[1] + else: + return loss_dict + + def normalize_target(self, target, dataset_index): + dataset_index = dataset_index[:, None, None, None] + mean = self.data_mean['subdset_0']['target'] * ( + 1 - dataset_index) + self.data_mean['subdset_1']['target'] * dataset_index + std = self.data_std['subdset_0']['target'] * ( + 1 - dataset_index) + self.data_std['subdset_1']['target'] * dataset_index + return (target - mean) / std + + def _get_reconstruction_loss_vector(self, + reconstruction, + target, + input, + dset_idx, + return_predicted_img=False, + likelihood_obj=None): + """ + Args: + return_predicted_img: If set to True, the besides the loss, the reconstructed image is also returned. + """ + + output = { + 'loss': None, + 'mixed_loss': None, + } + for i in range(1, 1 + target.shape[1]): + output['ch{}_loss'.format(i)] = None + + if likelihood_obj is None: + likelihood_obj = self.likelihood + # Log likelihood + ll, like_dict = likelihood_obj(reconstruction, target) + ll = self._get_weighted_likelihood(ll) + if self.skip_nboundary_pixels_from_loss is not None and self.skip_nboundary_pixels_from_loss > 0: + pad = self.skip_nboundary_pixels_from_loss + ll = ll[:, :, pad:-pad, pad:-pad] + like_dict['params']['mean'] = like_dict['params']['mean'][:, :, pad:-pad, pad:-pad] + + assert ll.shape[1] == 2, f"Change the code below to handle >2 channels first. ll.shape {ll.shape}" + output = { + 'loss': compute_batch_mean(-1 * ll), + } + if ll.shape[1] > 1: + for i in range(1, 1 + target.shape[1]): + output['ch{}_loss'.format(i)] = compute_batch_mean(-ll[:, i - 1]) + else: + assert ll.shape[1] == 1 + output['ch1_loss'] = output['loss'] + output['ch2_loss'] = output['loss'] + + if self.channel_1_w is not None or self.channel_2_w is not None: + assert ll.shape[1] == 2, "Only 2 channels are supported for now." + output['loss'] = (self.channel_1_w * output['ch1_loss'] + + self.channel_2_w * output['ch2_loss']) / (self.channel_1_w + self.channel_2_w) + + if self.enable_mixed_rec: + data_mean, data_std = self.get_mean_std_for_one_batch(dset_idx, self.data_mean, self.data_std) + # NOTE: We should not have access to target data_mean, data_std of the dataset2. We should have access to + # input data_mean, data_std of the dataset2. + data_mean['target'] = self.data_mean['subdset_0']['target'] + data_std['target'] = self.data_std['subdset_0']['target'] + + # NOTE: here, we are using the same interchannel weights for both dataset types. However, + # we filter the loss on entries in get_reconstruction_loss() + mean_pred = like_dict['params']['mean'] + if self._interchannel_weights is not None: + mean_pred = self._interchannel_weights(mean_pred) + + mixed_pred, mixed_logvar = self.get_mixed_prediction(mean_pred, + like_dict['params']['logvar'], + data_mean, + data_std, + channel_weights=None) + if self._multiscale_count is not None and self._multiscale_count > 1: + assert input.shape[1] == self._multiscale_count + input = input[:, :1] + + assert input.shape == mixed_pred.shape, "No fucking room for vectorization induced bugs." + mixed_recons_ll = self.likelihood.log_likelihood(input, {'mean': mixed_pred, 'logvar': mixed_logvar}) + output['mixed_loss'] = compute_batch_mean(-1 * mixed_recons_ll) + + if return_predicted_img: + return output, like_dict['params']['mean'] + + return output + + @staticmethod + def get_mean_std_for_one_batch(dset_idx, data_mean, data_std): + """ + For each element in the batch, pick the relevant mean and stdev on the basis of which dataset it is coming from. + """ + # to make it work as an index + dset_idx = dset_idx.type(torch.long) + batch_data_mean = {} + batch_data_std = {} + for key in data_mean['subdset_0'].keys(): + assert key in ['target', 'input'] + combined = torch.cat([data_mean['subdset_0'][key], data_mean['subdset_1'][key]], dim=0) + batch_values = combined[dset_idx] + batch_data_mean[key] = batch_values + combined = torch.cat([data_std['subdset_0'][key], data_std['subdset_1'][key]], dim=0) + batch_values = combined[dset_idx] + batch_data_std[key] = batch_values + + return batch_data_mean, batch_data_std + + def training_step(self, batch, batch_idx, enable_logging=True): + x, target, dset_idx, loss_idx = batch + + assert self.normalized_input == True + x_normalized = x + target_normalized = self.normalize_target(target, dset_idx) + + out, td_data = self.forward(x_normalized) + + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + dset_idx, + loss_idx, + return_predicted_img=False) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = recons_loss_dict['loss'] + if self.loss_type == LossType.ElboMixedReconstruction: + recons_loss += self.mixed_rec_w * recons_loss_dict['mixed_loss'] + + if enable_logging: + self.log('mixed_reconstruction_loss', recons_loss_dict['mixed_loss'], on_epoch=True) + + if self.non_stochastic_version: + kl_loss = torch.Tensor([0.0]).cuda() + net_loss = recons_loss + else: + kl_loss = self.get_kl_divergence_loss(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + if enable_logging: + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + if self._interchannel_weights is not None: + self.log('interchannel_w0', + self._interchannel_weights.weight.squeeze()[0].item(), + on_epoch=False, + on_step=True) + self.log('interchannel_w1', + self._interchannel_weights.weight.squeeze()[1].item(), + on_epoch=False, + on_step=True) + self.log('interchannel_b0', + self._interchannel_weights.bias.squeeze()[0].item(), + on_epoch=False, + on_step=True) + self.log('interchannel_b1', + self._interchannel_weights.bias.squeeze()[1].item(), + on_epoch=False, + on_step=True) + + # self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + # self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach(), + 'kl_loss': kl_loss.detach(), + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def set_params_to_same_device_as(self, correct_device_tensor): + if isinstance(self._interchannel_weights, torch.Tensor): + if self._interchannel_weights.device != correct_device_tensor.device: + self._interchannel_weights = self._interchannel_weights.to(correct_device_tensor.device) + + for dataset_index in [0, 1]: + str_idx = f'subdset_{dataset_index}' + if str_idx in self.data_mean and isinstance(self.data_mean[str_idx]['target'], torch.Tensor): + if self.data_mean[str_idx]['target'].device != correct_device_tensor.device: + self.data_mean[str_idx]['target'] = self.data_mean[str_idx]['target'].to( + correct_device_tensor.device) + self.data_std[str_idx]['target'] = self.data_std[str_idx]['target'].to(correct_device_tensor.device) + + self.data_mean[str_idx]['input'] = self.data_mean[str_idx]['input'].to(correct_device_tensor.device) + self.data_std[str_idx]['input'] = self.data_std[str_idx]['input'].to(correct_device_tensor.device) + + self.likelihood.set_params_to_same_device_as(correct_device_tensor) + else: + return + + def validation_step(self, batch, batch_idx): + x, target = batch[:2] + dset_idx = torch.zeros((x.shape[0], ), dtype=torch.long).to(x.device) + loss_idx = torch.Tensor([LossType.Elbo] * x.shape[0]).type(torch.long).to(x.device) + self.set_params_to_same_device_as(target) + + x_normalized = x + target_normalized = self.normalize_target(target, dset_idx) + assert self.reconstruction_mode is False + + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, recons_img = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + dset_idx, + loss_idx, + return_predicted_img=True) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + channels_rinvpsnr = [] + for i in range(recons_img.shape[1]): + self.channels_psnr[i].update(recons_img[:, i], target_normalized[:, i]) + psnr = RangeInvariantPsnr(target_normalized[:, i].clone(), recons_img[:, i].clone()) + channels_rinvpsnr.append(psnr) + psnr = torch_nanmean(psnr).item() + self.log(f'val_psnr_l{i+1}', psnr, on_epoch=True) + + recons_loss = recons_loss_dict['loss'] + # kl_loss = self.get_kl_divergence_loss(td_data) + # net_loss = recons_loss + self.get_kl_weight() * kl_loss + self.log('val_loss', recons_loss, on_epoch=True) + + # if batch_idx == 0 and self.power_of_2(self.current_epoch): + # all_samples = [] + # for i in range(20): + # sample, _ = self(x_normalized[0:1, ...]) + # sample = self.likelihood.get_mean_lv(sample)[0] + # all_samples.append(sample[None]) + + # all_samples = torch.cat(all_samples, dim=0) + # data_mean, data_std = self.get_mean_std_for_one_batch(dset_idx, self.data_mean, self.data_std) + # all_samples = all_samples * data_std['target'] + data_mean['target'] + # all_samples = all_samples.cpu() + # img_mmse = torch.mean(all_samples, dim=0)[0] + # self.log_images_for_tensorboard(all_samples[:, 0, 0, ...], target[0, 0, ...], img_mmse[0], 'label1') + # self.log_images_for_tensorboard(all_samples[:, 0, 1, ...], target[0, 1, ...], img_mmse[1], 'label2') + + +if __name__ == '__main__': + data_mean = { + 'subdset_0': { + 'target': torch.Tensor([1.1, 3.2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([1366]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([15, 30]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([10]).reshape((1, 1, 1, 1)) + } + } + + data_std = { + 'subdset_0': { + 'target': torch.Tensor([21, 45]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([955]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([90, 2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([121]).reshape((1, 1, 1, 1)) + } + } + + # dset_idx = torch.Tensor([0, 0, 0, 1, 1, 0]) + + # mean, std = LadderVaeTwoDset.get_mean_std_for_one_batch(dset_idx, data_mean, data_std) + import numpy as np + import torch + + # from denoisplit.configs.microscopy_multi_channel_lvae_config import get_config + from denoisplit.configs.twodset_config import get_config + config = get_config() + model = LadderVaeTwoDset(data_mean, data_std, config) + mc = 1 if config.data.multiscale_lowres_count is None else config.data.multiscale_lowres_count + inp = torch.rand((2, mc, config.data.image_size, config.data.image_size)) + out, td_data = model(inp) + batch = ( + torch.rand((16, mc, config.data.image_size, config.data.image_size)), + torch.rand((16, 2, config.data.image_size, config.data.image_size)), + (torch.rand((16, )) > 0.5).type(torch.long), + torch.Tensor([LossType.Elbo] * 8 + [LossType.ElboMixedReconstruction] * 8).type(torch.long), + ) + model.training_step(batch, 0) + model.validation_step(batch, 0) diff --git a/denoisplit/nets/lvae_twodset_finetuning.py b/denoisplit/nets/lvae_twodset_finetuning.py new file mode 100644 index 0000000..3a1e01c --- /dev/null +++ b/denoisplit/nets/lvae_twodset_finetuning.py @@ -0,0 +1,388 @@ +from copy import deepcopy + +import torch +import torch.optim as optim + +import ml_collections +from denoisplit.core.likelihoods import GaussianLikelihood, NoiseModelLikelihood +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.psnr import RangeInvariantPsnr +from denoisplit.loss.restricted_reconstruction_loss import RestrictedReconstruction +from denoisplit.nets.lvae import compute_batch_mean, torch_nanmean +from denoisplit.nets.lvae_twodset_restrictedrecons import LadderVaeTwoDsetRestrictedRecons +from denoisplit.nets.noise_model import get_noise_model + + +class LadderVaeTwoDsetFinetuning(LadderVaeTwoDsetRestrictedRecons): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2, val_idx_manager=None): + super(LadderVaeTwoDsetRestrictedRecons, self).__init__(data_mean, + data_std, + config, + use_uncond_mode_at=use_uncond_mode_at, + target_ch=target_ch, + val_idx_manager=val_idx_manager) + self.rest_recons_loss = None + self.mixed_rec_w = config.loss.mixed_rec_weight + + self.split_w = config.loss.split_weight + self.init_normalization(data_mean, data_std) + self.likelihood_old = self.likelihood + new_config = ml_collections.ConfigDict() + new_config.data = ml_collections.ConfigDict() + for key in config.data.dset1: + new_config.data[key] = config.data.dset1[key] + + self._interchannel_weights = None + new_config.model = ml_collections.ConfigDict() + new_config.model.enable_noise_model = True + new_config.model.noise_model_ch1_fpath = config.model.finetuning_noise_model_ch1_fpath + new_config.model.noise_model_ch2_fpath = config.model.finetuning_noise_model_ch2_fpath + new_config.model.noise_model_type = config.model.finetuning_noise_model_type + new_config.model.model_type = ModelType.Denoiser + new_config.model.denoise_channel = 'input' + self.noiseModel_finetuning = get_noise_model(new_config) + mean_dict = deepcopy(self.data_mean['subdset_1']) + std_dict = deepcopy(self.data_std['subdset_1']) + mean_dict['target'] = mean_dict['input'] + std_dict['target'] = std_dict['input'] + self.likelihood_finetuning = NoiseModelLikelihood(self.decoder_n_filters, 1, mean_dict, std_dict, + self.noiseModel_finetuning) + assert self.likelihood_form == 'gaussian' + # self.likelihood = NoiseModelLikelihood(self.decoder_n_filters, self.target_ch, self.data_mean['subdset_0'], + # self.data_std['subdset_0'], self.noiseModel) + self.likelihood = GaussianLikelihood(self.decoder_n_filters, + self.target_ch, + predict_logvar=self.predict_logvar, + logvar_lowerbound=self.logvar_lowerbound, + conv2d_bias=self.topdown_conv2d_bias) + + if config.loss.loss_type == LossType.ElboRestrictedReconstruction: + self.rest_recons_loss = RestrictedReconstruction(1, + self.mixed_rec_w, + custom_loss_fn=self.get_loss_fn( + self.likelihood_finetuning)) + self.rest_recons_loss.enable_nonorthogonal() + + self.automatic_optimization = False + + @staticmethod + def get_loss_fn(likelihood_fn): + + def loss_fn(tar, pred): + """ + Batch * H * W shape for both inputs. + """ + mixed_recons_ll = likelihood_fn.log_likelihood(tar[:, None], {'mean': pred[:, None], 'logvar': None}) + nll = (-1 * mixed_recons_ll).mean() + return nll + + return loss_fn + + def configure_optimizers(self): + selected_params = [] + for name, param in self.named_parameters(): + # print(name) + # first_bottom_up + # final_top_down + name = name.split('.')[0] + if name in ['first_bottom_up', 'bottom_up_layers']: #, 'final_top_down']: + selected_params.append(param) + + optimizer = optim.Adamax(selected_params, lr=self.lr, weight_decay=0) + scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, + self.lr_scheduler_mode, + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + + return {'optimizer': optimizer, 'lr_scheduler': scheduler, 'monitor': self.lr_scheduler_monitor} + + def _training_manual_step(self, batch, batch_idx, enable_logging=True): + x, target, dset_idx, loss_idx = batch + # ensure that we have exactly 16 dset 0 examples. + csum = (dset_idx == 0).cumsum(dim=0) + if csum[-1] < 16: + return None + csum_mask = csum <= 16 + # csum_mask = dset_idx == 0 + x = x[csum_mask] + + target = target[csum_mask] + dset_idx = dset_idx[csum_mask] + loss_idx = loss_idx[csum_mask] + + assert len(torch.unique(loss_idx[dset_idx == 0])) <= 1 + assert len(torch.unique(loss_idx[dset_idx == 1])) <= 1 + assert len(torch.unique(loss_idx)) <= 2 + + optim = self.optimizers() + optim.zero_grad() + + assert self.normalized_input == True + x_normalized = x + target_normalized = self.normalize_target(target, dset_idx) + + out, td_data = self.forward(x_normalized) + + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + dset_idx, + loss_idx, + return_predicted_img=False) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = self.split_w * recons_loss_dict['loss'] + mask = loss_idx == LossType.Elbo + if self.non_stochastic_version: + kl_loss = torch.Tensor([0.0]).cuda() + net_loss = recons_loss + else: + kl_dict = {'kl': [kl_level[mask] for kl_level in td_data['kl']]} + kl_loss = self.get_kl_divergence_loss(kl_dict) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + if isinstance(net_loss, torch.Tensor): + self.manual_backward(net_loss, retain_graph=True) + else: + assert net_loss == 0.0 + return None + + if self.predict_logvar is not None: + assert target_normalized.shape[1] * 2 == out.shape[1] + out = out.chunk(2, dim=1)[0] + + assert target_normalized.shape[1] == out.shape[1] + mixed_loss = None + if (~mask).sum() > 0: + pred_x_normalized, _ = self.get_mixed_prediction(out[~mask], None, dset_idx[~mask]) + params = list(self.named_parameters()) + relevant_params = [] + for name, param in params: + if param.requires_grad == False: + pass + else: + relevant_params.append((name, param)) + + _ = self.rest_recons_loss.update_gradients(relevant_params, x_normalized[~mask], target_normalized[mask], + out[mask], pred_x_normalized, self.current_epoch) + optim.step() + + if enable_logging: + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + if mixed_loss is not None: + self.log('mixed_loss', mixed_loss) + # self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + # self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach() if isinstance(recons_loss, torch.Tensor) else recons_loss, + 'kl_loss': kl_loss.detach(), + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def training_step(self, batch, batch_idx, enable_logging=True): + if self.automatic_optimization is False: + return self._training_manual_step(batch, batch_idx, enable_logging=enable_logging) + + x, target, dset_idx, loss_idx = batch + + assert self.normalized_input == True + x_normalized = x + target_normalized = self.normalize_target(target, dset_idx) + + out, td_data = self.forward(x_normalized) + + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + dset_idx, + loss_idx, + return_predicted_img=False) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = self.split_w * recons_loss_dict['loss'] + if self.non_stochastic_version: + kl_loss = torch.Tensor([0.0]).cuda() + net_loss = recons_loss + else: + kl_loss = self.get_kl_divergence_loss(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + mask = loss_idx == LossType.Elbo + # if 2 * target_normalized.shape[1] == out.shape[1]: + # pred_mean, pred_logvar = out.chunk(2, dim=1) + assert target_normalized.shape[1] == out.shape[1] + mixed_loss = None + if (~mask).sum() > 0: + pred_x_normalized, _ = self.get_mixed_prediction(out[~mask], None, dset_idx[~mask]) + mixed_recons_ll = self.likelihood_finetuning.log_likelihood(x_normalized[~mask], { + 'mean': pred_x_normalized, + 'logvar': None + }) + mixed_loss = (-1 * mixed_recons_ll).mean() + net_loss += self.mixed_rec_w * mixed_loss + + if enable_logging: + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + if mixed_loss is not None: + self.log('mixed_loss', mixed_loss) + # self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + # self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach() if isinstance(recons_loss, torch.Tensor) else recons_loss, + 'kl_loss': kl_loss.detach(), + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def set_params_to_same_device_as(self, correct_device_tensor): + self.likelihood.set_params_to_same_device_as(correct_device_tensor) + self.likelihood_finetuning.set_params_to_same_device_as(correct_device_tensor) + for dataset_index in [0, 1]: + str_idx = f'subdset_{dataset_index}' + if str_idx in self.data_mean and isinstance(self.data_mean[str_idx]['target'], torch.Tensor): + if self.data_mean[str_idx]['target'].device != correct_device_tensor.device: + self.data_mean[str_idx]['target'] = self.data_mean[str_idx]['target'].to( + correct_device_tensor.device) + self.data_std[str_idx]['target'] = self.data_std[str_idx]['target'].to(correct_device_tensor.device) + + self.data_mean[str_idx]['input'] = self.data_mean[str_idx]['input'].to(correct_device_tensor.device) + self.data_std[str_idx]['input'] = self.data_std[str_idx]['input'].to(correct_device_tensor.device) + + def validation_step(self, batch, batch_idx): + x, target = batch[:2] + dset_idx = torch.zeros((x.shape[0], ), dtype=torch.long).to(x.device) + loss_idx = torch.Tensor([LossType.Elbo] * x.shape[0]).type(torch.long).to(x.device) + self.set_params_to_same_device_as(target) + + x_normalized = x + target_normalized = self.normalize_target(target, dset_idx) + assert self.reconstruction_mode is False + + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, recons_img = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + dset_idx, + loss_idx, + return_predicted_img=True) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + channels_rinvpsnr = [] + for i in range(recons_img.shape[1]): + self.channels_psnr[i].update(recons_img[:, i], target_normalized[:, i]) + psnr = RangeInvariantPsnr(target_normalized[:, i].clone(), recons_img[:, i].clone()) + channels_rinvpsnr.append(psnr) + psnr = torch_nanmean(psnr).item() + self.log(f'val_psnr_l{i+1}', psnr, on_epoch=True) + + recons_loss = recons_loss_dict['loss'] + # kl_loss = self.get_kl_divergence_loss(td_data) + # net_loss = recons_loss + self.get_kl_weight() * kl_loss + self.log('val_loss', recons_loss, on_epoch=True) + + # if batch_idx == 0 and self.power_of_2(self.current_epoch): + # all_samples = [] + # for i in range(20): + # sample, _ = self(x_normalized[0:1, ...]) + # sample = self.likelihood.get_mean_lv(sample)[0] + # all_samples.append(sample[None]) + + # all_samples = torch.cat(all_samples, dim=0) + # data_mean, data_std = self.get_mean_std_for_one_batch(dset_idx, self.data_mean, self.data_std) + # all_samples = all_samples * data_std['target'] + data_mean['target'] + # all_samples = all_samples.cpu() + # img_mmse = torch.mean(all_samples, dim=0)[0] + # self.log_images_for_tensorboard(all_samples[:, 0, 0, ...], target[0, 0, ...], img_mmse[0], 'label1') + # self.log_images_for_tensorboard(all_samples[:, 0, 1, ...], target[0, 1, ...], img_mmse[1], 'label2') + + +if __name__ == '__main__': + import numpy as np + import torch + + data_mean = { + 'subdset_0': { + 'target': torch.Tensor([1.1, 3.2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([1366]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([15, 30]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([10]).reshape((1, 1, 1, 1)) + } + } + + data_std = { + 'subdset_0': { + 'target': torch.Tensor([21, 45]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([955]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([90, 2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([121]).reshape((1, 1, 1, 1)) + } + } + + # dset_idx = torch.Tensor([0, 0, 0, 1, 1, 0]) + + # mean, std = LadderVaeTwoDset.get_mean_std_for_one_batch(dset_idx, data_mean, data_std) + + # from denoisplit.configs.microscopy_multi_channel_lvae_config import get_config + from denoisplit.configs.twodset_config import get_config + config = get_config() + model = LadderVaeTwoDsetFinetuning(data_mean, data_std, config) + mc = 1 if config.data.multiscale_lowres_count is None else config.data.multiscale_lowres_count + inp = torch.rand((2, mc, config.data.image_size, config.data.image_size)) + out, td_data = model(inp) + batch = ( + torch.rand((16, mc, config.data.image_size, config.data.image_size)), + torch.rand((16, 2, config.data.image_size, config.data.image_size)), + (torch.rand((16, )) > 0.5).type(torch.long), + torch.Tensor([LossType.Elbo] * 8 + [LossType.ElboMixedReconstruction] * 8).type(torch.long), + ) + model.validation_step(batch, 0) + model.training_step(batch, 0) diff --git a/denoisplit/nets/lvae_twodset_restrictedrecons.py b/denoisplit/nets/lvae_twodset_restrictedrecons.py new file mode 100644 index 0000000..6488837 --- /dev/null +++ b/denoisplit/nets/lvae_twodset_restrictedrecons.py @@ -0,0 +1,400 @@ +""" +Multi dataset based setup. +""" +import torch +import torch.nn as nn + +from denoisplit.core.loss_type import LossType +from denoisplit.core.psnr import RangeInvariantPsnr +from denoisplit.loss.exclusive_loss import compute_exclusion_loss +from denoisplit.loss.restricted_reconstruction_loss import RestrictedReconstruction +from denoisplit.nets.lvae import LadderVAE, compute_batch_mean, torch_nanmean + + +class LadderVaeTwoDsetRestrictedRecons(LadderVAE): + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super().__init__(data_mean, data_std, config, use_uncond_mode_at, target_ch) + self.automatic_optimization = False + assert config.loss.loss_type == LossType.ElboRestrictedReconstruction, "This model only supports ElboRestrictedReconstruction loss type." + self._interchannel_weights = None + self.split_w = config.loss.split_weight + + if config.model.get('enable_learnable_interchannel_weights', False): + # self._interchannel_weights = nn.Parameter(torch.ones((1, target_ch, 1, 1)), requires_grad=True) + self._interchannel_weights = nn.Conv2d(target_ch, target_ch, 1, bias=True, groups=target_ch) + self._interchannel_weights.weight.data.fill_(1.0 * 0.01) + self._interchannel_weights.bias.data.fill_(0.0) + + self.init_normalization(data_mean, data_std) + self.rest_recons_loss = RestrictedReconstruction(1, self.mixed_rec_w) + # self.rest_recons_loss.update_only_these_till_kth_epoch( + # ['_interchannel_weights.weight', '_interchannel_weights.bias'], 40) + + print(f'[{self.__class__.__name__}] Learnable Ch weights:', self._interchannel_weights is not None) + + def init_normalization(self, data_mean, data_std): + for dloader_key in self.data_mean.keys(): + assert dloader_key in ['subdset_0', 'subdset_1'] + for data_key in self.data_mean[dloader_key].keys(): + assert data_key in ['target', 'input'] + self.data_mean[dloader_key][data_key] = torch.Tensor(data_mean[dloader_key][data_key]) + self.data_std[dloader_key][data_key] = torch.Tensor(data_std[dloader_key][data_key]) + + self.data_mean[dloader_key]['input'] = self.data_mean[dloader_key]['input'].reshape(1, 1, 1, 1) + self.data_std[dloader_key]['input'] = self.data_std[dloader_key]['input'].reshape(1, 1, 1, 1) + + def get_reconstruction_loss(self, + reconstruction, + target, + input, + dset_idx, + loss_type_idx, + return_predicted_img=False, + likelihood_obj=None): + output = self._get_reconstruction_loss_vector(reconstruction, + target, + input, + dset_idx, + return_predicted_img=return_predicted_img, + likelihood_obj=likelihood_obj) + loss_dict = output[0] if return_predicted_img else output + individual_ch_loss_mask = loss_type_idx == LossType.Elbo + if torch.sum(individual_ch_loss_mask) > 0: + loss_dict['loss'] = torch.mean(loss_dict['loss'][individual_ch_loss_mask]) + loss_dict['ch1_loss'] = torch.mean(loss_dict['ch1_loss'][individual_ch_loss_mask]) + loss_dict['ch2_loss'] = torch.mean(loss_dict['ch2_loss'][individual_ch_loss_mask]) + else: + loss_dict['loss'] = 0.0 + loss_dict['ch1_loss'] = 0.0 + loss_dict['ch2_loss'] = 0.0 + + if return_predicted_img: + assert len(output) == 2 + return loss_dict, output[1] + else: + return loss_dict + + def normalize_target(self, target, dataset_index): + dataset_index = dataset_index[:, None, None, None] + mean0 = self.data_mean['subdset_0']['target'] + mean1 = self.data_mean['subdset_1']['target'] + std0 = self.data_std['subdset_0']['target'] + std1 = self.data_std['subdset_1']['target'] + + mean = mean0 * (1 - dataset_index) + mean1 * dataset_index + std = std0 * (1 - dataset_index) + std1 * dataset_index + return (target - mean) / std + + def _get_reconstruction_loss_vector(self, + reconstruction, + target, + input, + dset_idx, + return_predicted_img=False, + likelihood_obj=None): + """ + Args: + return_predicted_img: If set to True, the besides the loss, the reconstructed image is also returned. + """ + + output = { + 'loss': None, + 'mixed_loss': None, + } + for i in range(1, 1 + target.shape[1]): + output['ch{}_loss'.format(i)] = None + + if likelihood_obj is None: + likelihood_obj = self.likelihood + # Log likelihood + ll, like_dict = likelihood_obj(reconstruction, target) + ll = self._get_weighted_likelihood(ll) + if self.skip_nboundary_pixels_from_loss is not None and self.skip_nboundary_pixels_from_loss > 0: + pad = self.skip_nboundary_pixels_from_loss + ll = ll[:, :, pad:-pad, pad:-pad] + like_dict['params']['mean'] = like_dict['params']['mean'][:, :, pad:-pad, pad:-pad] + + assert ll.shape[1] == 2, f"Change the code below to handle >2 channels first. ll.shape {ll.shape}" + output = { + 'loss': compute_batch_mean(-1 * ll), + } + if ll.shape[1] > 1: + for i in range(1, 1 + target.shape[1]): + output['ch{}_loss'.format(i)] = compute_batch_mean(-ll[:, i - 1]) + else: + assert ll.shape[1] == 1 + output['ch1_loss'] = output['loss'] + output['ch2_loss'] = output['loss'] + + if self.channel_1_w is not None or self.channel_2_w is not None: + assert ll.shape[1] == 2, "Only 2 channels are supported for now." + output['loss'] = (self.channel_1_w * output['ch1_loss'] + + self.channel_2_w * output['ch2_loss']) / (self.channel_1_w + self.channel_2_w) + + # if self._multiscale_count is not None and self._multiscale_count > 1: + # assert input.shape[1] == self._multiscale_count + # input = input[:, :1] + + # assert input.shape == mixed_pred.shape, "No fucking room for vectorization induced bugs." + # mixed_recons_ll = self.likelihood.log_likelihood(input, {'mean': mixed_pred, 'logvar': mixed_logvar}) + # output['mixed_loss'] = compute_batch_mean(-1 * mixed_recons_ll) + + if return_predicted_img: + return output, like_dict['params']['mean'] + + return output + + @staticmethod + def get_mean_std_for_one_batch(dset_idx, data_mean, data_std): + """ + For each element in the batch, pick the relevant mean and stdev on the basis of which dataset it is coming from. + """ + # to make it work as an index + dset_idx = dset_idx.type(torch.long) + batch_data_mean = {} + batch_data_std = {} + for key in data_mean['subdset_0'].keys(): + assert key in ['target', 'input'] + combined = torch.cat([data_mean['subdset_0'][key], data_mean['subdset_1'][key]], dim=0) + batch_values = combined[dset_idx] + batch_data_mean[key] = batch_values + combined = torch.cat([data_std['subdset_0'][key], data_std['subdset_1'][key]], dim=0) + batch_values = combined[dset_idx] + batch_data_std[key] = batch_values + + return batch_data_mean, batch_data_std + + def get_mixed_prediction(self, prediction_mean, prediction_logvar, dset_idx): + data_mean, data_std = self.get_mean_std_for_one_batch(dset_idx, self.data_mean, self.data_std) + # NOTE: We should not have access to target data_mean, data_std of the dataset2. We should have access to + # input data_mean, data_std of the dataset2. + data_mean['target'] = self.data_mean['subdset_0']['target'] + data_std['target'] = self.data_std['subdset_0']['target'] + + # NOTE: here, we are using the same interchannel weights for both dataset types. However, + # we filter the loss on entries in get_reconstruction_loss() + if self._interchannel_weights is not None: + prediction_mean = self._interchannel_weights(prediction_mean) + + mixed_pred, mixed_logvar = super().get_mixed_prediction(prediction_mean, + prediction_logvar, + data_mean, + data_std, + channel_weights=None) + return mixed_pred, mixed_logvar + + def training_step(self, batch, batch_idx, enable_logging=True): + x, target, dset_idx, loss_idx = batch + optim = self.optimizers() + optim.zero_grad() + assert self.normalized_input == True + x_normalized = x + target_normalized = self.normalize_target(target, dset_idx) + + out, td_data = self.forward(x_normalized) + + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + dset_idx, + loss_idx, + return_predicted_img=False) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = self.split_w * recons_loss_dict['loss'] + if self.non_stochastic_version: + kl_loss = torch.Tensor([0.0]).cuda() + net_loss = recons_loss + else: + kl_loss = self.get_kl_divergence_loss(td_data) + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + mask = loss_idx == LossType.Elbo + exclusion_loss = None + if self._exclusion_loss_weight > 0 and torch.sum(~mask) > 0: + exclusion_loss = compute_exclusion_loss(out[~mask, 0], out[~mask, 1]) + net_loss += exclusion_loss * self._exclusion_loss_weight + + if isinstance(net_loss, torch.Tensor): + self.manual_backward(net_loss, retain_graph=True) + else: + assert net_loss == 0.0 + return None + + assert self.loss_type == LossType.ElboRestrictedReconstruction + if 2 * target_normalized.shape[1] == out.shape[1]: + pred_mean, pred_logvar = out.chunk(2, dim=1) + pred_x_normalized, _ = self.get_mixed_prediction(pred_mean[~mask], pred_logvar[~mask], dset_idx[~mask]) + params = list(self.named_parameters()) + loss_dict = self.rest_recons_loss.update_gradients(params, x_normalized[~mask], target_normalized[mask], + pred_mean[mask], pred_x_normalized, self.current_epoch) + optim.step() + if enable_logging: + if exclusion_loss is not None: + self.log('exclusive_loss', exclusion_loss.item(), on_epoch=True) + + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + if self._interchannel_weights is not None: + self.log('interchannel_w0', + self._interchannel_weights.weight.squeeze()[0].item(), + on_epoch=False, + on_step=True) + self.log('interchannel_w1', + self._interchannel_weights.weight.squeeze()[1].item(), + on_epoch=False, + on_step=True) + if self._interchannel_weights.bias is not None: + self.log('interchannel_b0', + self._interchannel_weights.bias.squeeze()[0].item(), + on_epoch=False, + on_step=True) + self.log('interchannel_b1', + self._interchannel_weights.bias.squeeze()[1].item(), + on_epoch=False, + on_step=True) + + # self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + # self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach() if isinstance(recons_loss, torch.Tensor) else recons_loss, + 'kl_loss': kl_loss.detach(), + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def set_params_to_same_device_as(self, correct_device_tensor): + if isinstance(self._interchannel_weights, torch.Tensor): + if self._interchannel_weights.device != correct_device_tensor.device: + self._interchannel_weights = self._interchannel_weights.to(correct_device_tensor.device) + + for dataset_index in [0, 1]: + str_idx = f'subdset_{dataset_index}' + if str_idx in self.data_mean and isinstance(self.data_mean[str_idx]['target'], torch.Tensor): + if self.data_mean[str_idx]['target'].device != correct_device_tensor.device: + self.data_mean[str_idx]['target'] = self.data_mean[str_idx]['target'].to( + correct_device_tensor.device) + self.data_std[str_idx]['target'] = self.data_std[str_idx]['target'].to(correct_device_tensor.device) + + self.data_mean[str_idx]['input'] = self.data_mean[str_idx]['input'].to(correct_device_tensor.device) + self.data_std[str_idx]['input'] = self.data_std[str_idx]['input'].to(correct_device_tensor.device) + + self.likelihood.set_params_to_same_device_as(correct_device_tensor) + else: + return + + def validation_step(self, batch, batch_idx): + x, target = batch[:2] + dset_idx = torch.zeros((x.shape[0], ), dtype=torch.long).to(x.device) + loss_idx = torch.Tensor([LossType.Elbo] * x.shape[0]).type(torch.long).to(x.device) + self.set_params_to_same_device_as(target) + + x_normalized = x + target_normalized = self.normalize_target(target, dset_idx) + assert self.reconstruction_mode is False + + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, recons_img = self.get_reconstruction_loss(out, + target_normalized, + x_normalized, + dset_idx, + loss_idx, + return_predicted_img=True) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + channels_rinvpsnr = [] + for i in range(recons_img.shape[1]): + self.channels_psnr[i].update(recons_img[:, i], target_normalized[:, i]) + psnr = RangeInvariantPsnr(target_normalized[:, i].clone(), recons_img[:, i].clone()) + channels_rinvpsnr.append(psnr) + psnr = torch_nanmean(psnr).item() + self.log(f'val_psnr_l{i+1}', psnr, on_epoch=True) + + recons_loss = recons_loss_dict['loss'] + # kl_loss = self.get_kl_divergence_loss(td_data) + # net_loss = recons_loss + self.get_kl_weight() * kl_loss + self.log('val_loss', recons_loss, on_epoch=True) + + # if batch_idx == 0 and self.power_of_2(self.current_epoch): + # all_samples = [] + # for i in range(20): + # sample, _ = self(x_normalized[0:1, ...]) + # sample = self.likelihood.get_mean_lv(sample)[0] + # all_samples.append(sample[None]) + + # all_samples = torch.cat(all_samples, dim=0) + # data_mean, data_std = self.get_mean_std_for_one_batch(dset_idx, self.data_mean, self.data_std) + # all_samples = all_samples * data_std['target'] + data_mean['target'] + # all_samples = all_samples.cpu() + # img_mmse = torch.mean(all_samples, dim=0)[0] + # self.log_images_for_tensorboard(all_samples[:, 0, 0, ...], target[0, 0, ...], img_mmse[0], 'label1') + # self.log_images_for_tensorboard(all_samples[:, 0, 1, ...], target[0, 1, ...], img_mmse[1], 'label2') + + +if __name__ == '__main__': + data_mean = { + 'subdset_0': { + 'target': torch.Tensor([1.1, 3.2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([1366]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([15, 30]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([10]).reshape((1, 1, 1, 1)) + } + } + + data_std = { + 'subdset_0': { + 'target': torch.Tensor([21, 45]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([955]).reshape((1, 1, 1, 1)) + }, + 'subdset_1': { + 'target': torch.Tensor([90, 2]).reshape((1, 2, 1, 1)), + 'input': torch.Tensor([121]).reshape((1, 1, 1, 1)) + } + } + + # dset_idx = torch.Tensor([0, 0, 0, 1, 1, 0]) + + # mean, std = LadderVaeTwoDset.get_mean_std_for_one_batch(dset_idx, data_mean, data_std) + import numpy as np + import torch + + # from denoisplit.configs.microscopy_multi_channel_lvae_config import get_config + from denoisplit.configs.twodset_config import get_config + config = get_config() + model = LadderVaeTwoDsetRestrictedRecons(data_mean, data_std, config) + mc = 1 if config.data.multiscale_lowres_count is None else config.data.multiscale_lowres_count + inp = torch.rand((2, mc, config.data.image_size, config.data.image_size)) + out, td_data = model(inp) + batch = ( + torch.rand((16, mc, config.data.image_size, config.data.image_size)), + torch.rand((16, 2, config.data.image_size, config.data.image_size)), + (torch.rand((16, )) > 0.5).type(torch.long), + torch.Tensor([LossType.Elbo] * 8 + [LossType.ElboMixedReconstruction] * 8).type(torch.long), + ) + model.training_step(batch, 0) + model.validation_step(batch, 0) diff --git a/denoisplit/nets/lvae_with_critic.py b/denoisplit/nets/lvae_with_critic.py new file mode 100644 index 0000000..d80e09b --- /dev/null +++ b/denoisplit/nets/lvae_with_critic.py @@ -0,0 +1,146 @@ +""" +Model with combines VAE with critic. Critic is used to enfore a prior on the generated images. +""" +import torch +import torch.optim as optim +from torch import nn + +from denoisplit.nets.discriminator import define_D +from denoisplit.nets.lvae import LadderVAE + + +class LadderVAECritic(LadderVAE): + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super().__init__(data_mean, data_std, config, use_uncond_mode_at=use_uncond_mode_at, target_ch=target_ch) + input_hw = config.data.image_size + dense_ch_list = [128, 64] + cnn_out_ch = 32 + self.D1 = define_D(1, + config.model.critic.ndf, + config.model.critic.netD, + n_layers_D=config.model.critic.layers_D, + norm=config.model.critic.norm, + input_hw=input_hw, + dense_ch_list=dense_ch_list, + cnn_out_ch=cnn_out_ch) + self.D2 = define_D(1, + config.model.critic.ndf, + config.model.critic.netD, + n_layers_D=config.model.critic.layers_D, + norm=config.model.critic.norm, + input_hw=input_hw, + dense_ch_list=dense_ch_list, + cnn_out_ch=cnn_out_ch) + + self.critic_loss_weight = config.loss.critic_loss_weight + self.critic_loss_fn = nn.BCEWithLogitsLoss() + + def configure_optimizers(self): + params1 = list(self.first_bottom_up.parameters()) + list(self.bottom_up_layers.parameters()) + list( + self.top_down_layers.parameters()) + list(self.final_top_down.parameters()) + list( + self.likelihood.parameters()) + + optimizer1 = optim.Adamax(params1, lr=self.lr, weight_decay=0) + params2 = list(self.D1.parameters()) + list(self.D2.parameters()) + optimizer2 = optim.Adamax(params2, lr=self.lr, weight_decay=0) + + scheduler1 = optim.lr_scheduler.ReduceLROnPlateau(optimizer1, + 'min', + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + scheduler2 = optim.lr_scheduler.ReduceLROnPlateau(optimizer2, + 'min', + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + + return [optimizer1, optimizer2], [{ + 'scheduler': scheduler1, + 'monitor': 'val_loss' + }, { + 'scheduler': scheduler2, + 'monitor': 'val_loss' + }] + + def get_critic_loss_stats(self, pred_normalized: torch.Tensor, target_normalized: torch.Tensor) -> dict: + """ + This function takes as input one batch of predicted image (both labels) and target images and returns the + crossentropy loss. + Args: + pred_normalized: The predicted (normalized) images. Note that this is not the output of the forward(). + Likelihood module is also applied on top of it to produce the image. + target_normalized: This is the normalized target images. + """ + pred1, pred2 = pred_normalized.chunk(2, dim=1) + tar1, tar2 = target_normalized.chunk(2, dim=1) + loss1, avg_pred_dict1 = self.get_critic_loss(pred1, tar1, self.D1) + loss2, avg_pred_dict2 = self.get_critic_loss(pred2, tar2, self.D2) + return { + 'loss': (loss1 + loss2) / 2, + 'loss_Label1': loss1, + 'loss_Label2': loss2, + 'avg_Label1': avg_pred_dict1, + 'avg_Label2': avg_pred_dict2, + } + + def get_critic_loss(self, pred: torch.Tensor, tar: torch.Tensor, D): + """ + Given a predicted image and a target image, here we return a binary crossentropy loss. + discriminator is trained to predict 1 for target image and 0 for the predicted image. + Args: + pred: predicted image + tar: target image + D: discriminator model + """ + pred_label = D(pred) + tar_label = D(tar) + loss_0 = self.critic_loss_fn(pred_label, torch.zeros_like(pred_label)) + loss_1 = self.critic_loss_fn(tar_label, torch.ones_like(tar_label)) + loss = loss_0 + loss_1 + return loss, {'generated': torch.sigmoid(pred_label).mean(), 'actual': torch.sigmoid(tar_label).mean()} + + def training_step(self, batch: tuple, batch_idx: int, optimizer_idx: int): + x, target = batch + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + out, td_data = self.forward(x_normalized) + recons_loss_dict, pred_nimg = self.get_reconstruction_loss(out, target_normalized, return_predicted_img=True) + recons_loss = recons_loss_dict['loss'] + if optimizer_idx == 0: + kl_loss = self.get_kl_divergence_loss(td_data) + critic_dict = self.get_critic_loss_stats(pred_nimg, target_normalized) + D_loss = critic_dict['loss'] + net_loss = recons_loss + self.get_kl_weight() * kl_loss + + # Note the negative here. It will aim to maximize the discriminator loss. + net_loss += -1 * self.critic_loss_weight * D_loss + + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss, on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('D_loss', D_loss, on_epoch=True) + self.log('L1_generated_probab', critic_dict['avg_Label1']['generated'], on_epoch=True) + self.log('L1_actual_probab', critic_dict['avg_Label1']['actual'], on_epoch=True) + self.log('L2_generated_probab', critic_dict['avg_Label2']['generated'], on_epoch=True) + self.log('L2_actual_probab', critic_dict['avg_Label2']['actual'], on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': recons_loss.detach(), + 'kl_loss': kl_loss.detach(), + } + elif optimizer_idx == 1: + D_loss = self.critic_loss_weight * self.get_critic_loss_stats(pred_nimg, target_normalized)['loss'] + output = {'loss': D_loss} + + self.log('lr', self.lr, on_epoch=True) + self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + return output diff --git a/denoisplit/nets/lvae_with_stitch.py b/denoisplit/nets/lvae_with_stitch.py new file mode 100644 index 0000000..ef4484f --- /dev/null +++ b/denoisplit/nets/lvae_with_stitch.py @@ -0,0 +1,255 @@ +from denoisplit.nets.lvae import LadderVAE, compute_batch_mean, torch_nanmean +import torch.nn as nn +import torch.optim as optim +from denoisplit.core.likelihoods import GaussianLikelihoodWithStitching +import torch +import torchvision.transforms.functional as F +from denoisplit.core.psnr import RangeInvariantPsnr +import numpy as np + + +class SqueezeLayer(nn.Module): + def forward(self, x): + return torch.squeeze(x) + + +class LadderVAEwithStitching(LadderVAE): + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super().__init__(data_mean, data_std, config, use_uncond_mode_at=use_uncond_mode_at, target_ch=target_ch) + self.offset_prediction_input_z_idx = config.model.offset_prediction_input_z_idx + latent_spatial_dims = config.data.image_size + if config.model.decoder.multiscale_retain_spatial_dims is False or config.data.multiscale_lowres_count is None: + latent_spatial_dims = latent_spatial_dims // np.power(2, 1 + self.offset_prediction_input_z_idx) + in_channels = config.model.z_dims[self.offset_prediction_input_z_idx] + offset_latent_dims = config.model.offset_latent_dims + self.nbr_set_count = config.data.get('nbr_set_count', None) + self.regularize_offset = config.model.get('regularize_offset', False) + self._offset_reg_w = None + if self.regularize_offset: + self._offset_reg_w = config.model.offset_regularization_w + + if config.model.get('offset_prediction_scalar_prediction', False): + output_ch = 1 + else: + output_ch = 2 + + self.offset_predictor = nn.Sequential( + nn.Conv2d(in_channels, offset_latent_dims, 1), + self.get_nonlin()(), + nn.AvgPool2d(latent_spatial_dims), + SqueezeLayer(), + nn.Linear(offset_latent_dims, output_ch, + bias=output_ch != 1), # If we predict just one value, then bias is not needed + ) + + def create_likelihood_module(self): + self.likelihood = GaussianLikelihoodWithStitching(self.decoder_n_filters, + self.target_ch, + predict_logvar=self.predict_logvar, + logvar_lowerbound=self.logvar_lowerbound) + + def lowres_inputbranch_parameters(self): + if self.lowres_first_bottom_ups is not None: + return list(self.lowres_first_bottom_ups.parameters()) + return [] + + def configure_optimizers(self): + params1 = list(self.first_bottom_up.parameters()) + list(self.bottom_up_layers.parameters()) + list( + self.top_down_layers.parameters()) + list(self.final_top_down.parameters()) + list( + self.likelihood.parameters()) + self.lowres_inputbranch_parameters() + + optimizer1 = optim.Adamax(params1, lr=self.lr, weight_decay=0) + params2 = self.offset_predictor.parameters() + optimizer2 = optim.Adamax(params2, lr=self.lr, weight_decay=0) + + scheduler1 = optim.lr_scheduler.ReduceLROnPlateau(optimizer1, + self.lr_scheduler_mode, + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + + scheduler2 = optim.lr_scheduler.ReduceLROnPlateau(optimizer2, + self.lr_scheduler_mode, + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + + return [optimizer1, optimizer2], [{ + 'scheduler': scheduler1, + 'monitor': self.lr_scheduler_monitor + }, { + 'scheduler': scheduler2, + 'monitor': self.lr_scheduler_monitor + }] + + def _get_reconstruction_loss_vector(self, reconstruction, input, offset, return_predicted_img=False): + """ + Args: + return_predicted_img: If set to True, the besides the loss, the reconstructed image is also returned. + """ + + # Log likelihood + ll, like_dict = self.likelihood(reconstruction, input, offset) + + recons_loss = compute_batch_mean(-1 * ll) + output = { + 'loss': recons_loss, + 'ch1_loss': compute_batch_mean(-ll[:, 0]), + 'ch2_loss': compute_batch_mean(-ll[:, 1]), + } + + if return_predicted_img: + return output, like_dict['params']['mean'] + + return output + + def get_reconstruction_loss(self, reconstruction, input, offset, return_predicted_img=False): + output = self._get_reconstruction_loss_vector(reconstruction, + input, + offset, + return_predicted_img=return_predicted_img) + loss_dict = output[0] if return_predicted_img else output + loss_dict['loss'] = torch.mean(loss_dict['loss']) + loss_dict['ch1_loss'] = torch.mean(loss_dict['ch1_loss']) + loss_dict['ch2_loss'] = torch.mean(loss_dict['ch2_loss']) + + if return_predicted_img: + assert len(output) == 2 + return loss_dict, output[1] + else: + return loss_dict + + def compute_offset(self, z_arr): + offset = self.offset_predictor(z_arr[self.offset_prediction_input_z_idx]) + # In case of a scalar prediction + if offset.shape[-1] == 1: + offset = torch.cat([offset, -1 * offset], dim=-1) + + return offset[..., None, None] + + def training_step(self, batch: tuple, batch_idx: int, optimizer_idx: int, enable_logging=True): + x, target, grid_sizes = batch + + if optimizer_idx == 0 and self.nbr_set_count is not None: + mask = np.arange(len(x)) >= 5 * self.nbr_set_count + x = x[mask] + target = target[mask] + grid_sizes = grid_sizes[mask] + + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + + out, td_data = self.forward(x_normalized) + offset = self.compute_offset(td_data['z']) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, imgs = self.get_reconstruction_loss(out, target_normalized, offset, return_predicted_img=True) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = recons_loss_dict['loss'] + + kl_loss = self.get_kl_divergence_loss(td_data) + if optimizer_idx == 0: + net_loss = recons_loss + self.get_kl_weight() * kl_loss + if enable_logging: + for i, x in enumerate(td_data['debug_qvar_max']): + self.log(f'qvar_max:{i}', x.item(), on_epoch=True) + + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + self.log('kl_loss', kl_loss, on_epoch=True) + self.log('training_loss', net_loss, on_epoch=True) + self.log('lr', self.lr, on_epoch=True) + self.log('grad_norm_bottom_up', self.grad_norm_bottom_up, on_epoch=True) + self.log('grad_norm_top_down', self.grad_norm_top_down, on_epoch=True) + + elif optimizer_idx == 1: + nbr_cons_loss = self.nbr_consistency_loss.get(imgs, grid_sizes=grid_sizes) + offset_reg_loss = 0.0 + if self.regularize_offset: + offset_reg_loss = torch.norm(offset) + offset_reg_loss = self._offset_reg_w * offset_reg_loss + self.log('offset_reg_loss', offset_reg_loss.item(), on_epoch=True) + + if nbr_cons_loss is not None: + nbr_cons_loss = self.nbr_consistency_w * nbr_cons_loss + self.log('nbr_cons_loss', nbr_cons_loss.item(), on_epoch=True) + net_loss = nbr_cons_loss + offset_reg_loss + + output = { + 'loss': net_loss, + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if net_loss is None or torch.isnan(net_loss).any(): + return None + + return output + + def validation_step(self, batch, batch_idx): + x, target = batch[:2] + self.set_params_to_same_device_as(target) + + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + out, td_data = self.forward(x_normalized) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + offset = self.compute_offset(td_data['z']) + + recons_loss_dict, recons_img = self.get_reconstruction_loss(out, + target_normalized, + offset, + return_predicted_img=True) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + self.label1_psnr.update(recons_img[:, 0], target_normalized[:, 0]) + self.label2_psnr.update(recons_img[:, 1], target_normalized[:, 1]) + + psnr_label1 = RangeInvariantPsnr(target_normalized[:, 0].clone(), recons_img[:, 0].clone()) + psnr_label2 = RangeInvariantPsnr(target_normalized[:, 1].clone(), recons_img[:, 1].clone()) + recons_loss = recons_loss_dict['loss'] + # kl_loss = self.get_kl_divergence_loss(td_data) + # net_loss = recons_loss + self.get_kl_weight() * kl_loss + self.log('val_loss', recons_loss, on_epoch=True) + val_psnr_l1 = torch_nanmean(psnr_label1).item() + val_psnr_l2 = torch_nanmean(psnr_label2).item() + self.log('val_psnr_l1', val_psnr_l1, on_epoch=True) + self.log('val_psnr_l2', val_psnr_l2, on_epoch=True) + # self.log('val_psnr', (val_psnr_l1 + val_psnr_l2) / 2, on_epoch=True) + + if batch_idx == 0 and self.power_of_2(self.current_epoch): + all_samples = [] + for i in range(20): + sample, _ = self(x_normalized[0:1, ...]) + sample = self.likelihood.get_mean_lv(sample)[0] + all_samples.append(sample[None]) + + all_samples = torch.cat(all_samples, dim=0) + all_samples = all_samples * self.data_std + self.data_mean + all_samples = all_samples.cpu() + img_mmse = torch.mean(all_samples, dim=0)[0] + self.log_images_for_tensorboard(all_samples[:, 0, 0, ...], target[0, 0, ...], img_mmse[0], 'label1') + self.log_images_for_tensorboard(all_samples[:, 0, 1, ...], target[0, 1, ...], img_mmse[1], 'label2') + + +if __name__ == '__main__': + from denoisplit.configs.lvae_with_stitch_config import get_config + import torch + config = get_config() + model = LadderVAEwithStitching(0, 1, config) + inp = torch.rand((16, 1, 64, 64)) + tar = torch.rand((16, 2, 64, 64)) + grid_sizes = torch.Tensor([32] * 5 + [40] * 5 + [24] * 5 + [41]).type(torch.int32) + + model.validation_step((inp, tar, grid_sizes), 0) + loss0 = model.training_step((inp, tar, grid_sizes), 0, 0) + loss1 = model.training_step((inp, tar, grid_sizes), 0, 1) diff --git a/denoisplit/nets/lvae_with_stitch_2stage.py b/denoisplit/nets/lvae_with_stitch_2stage.py new file mode 100644 index 0000000..2ca7115 --- /dev/null +++ b/denoisplit/nets/lvae_with_stitch_2stage.py @@ -0,0 +1,66 @@ +from denoisplit.nets.lvae_with_stitch import LadderVAEwithStitching +import torch.optim as optim +import torch +import torch.nn.functional as F +import os + + +class LadderVAEwithStitching2Stage(LadderVAEwithStitching): + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + super().__init__(data_mean, data_std, config, use_uncond_mode_at, target_ch) + assert config.training.pre_trained_ckpt_fpath and os.path.exists(config.training.pre_trained_ckpt_fpath) + + def configure_optimizers(self): + params = self.offset_predictor.parameters() + optimizer = optim.Adamax(params, lr=self.lr, weight_decay=0) + + scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, + self.lr_scheduler_mode, + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + + return {'optimizer': optimizer, 'lr_scheduler': scheduler, 'monitor': self.lr_scheduler_monitor} + + def training_step(self, batch: tuple, batch_idx: int, enable_logging=True): + x, target, grid_sizes = batch + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + + out, td_data = self.forward(x_normalized) + offset = self.compute_offset(td_data['z']) + if self.encoder_no_padding_mode and out.shape[-2:] != target_normalized.shape[-2:]: + target_normalized = F.center_crop(target_normalized, out.shape[-2:]) + + recons_loss_dict, imgs = self.get_reconstruction_loss(out, target_normalized, offset, return_predicted_img=True) + + if self.skip_nboundary_pixels_from_loss: + pad = self.skip_nboundary_pixels_from_loss + target_normalized = target_normalized[:, :, pad:-pad, pad:-pad] + + recons_loss = recons_loss_dict['loss'] + + net_loss = recons_loss + self.log('reconstruction_loss', recons_loss_dict['loss'], on_epoch=True) + + nbr_cons_loss = self.nbr_consistency_loss.get(imgs, grid_sizes=grid_sizes) + offset_reg_loss = 0.0 + if self.regularize_offset: + offset_reg_loss = torch.norm(offset) + offset_reg_loss = self._offset_reg_w * offset_reg_loss + self.log('offset_reg_loss', offset_reg_loss.item(), on_epoch=True) + + if nbr_cons_loss is not None: + nbr_cons_loss = self.nbr_consistency_w * nbr_cons_loss + self.log('nbr_cons_loss', nbr_cons_loss.item(), on_epoch=True) + net_loss += nbr_cons_loss + offset_reg_loss + + output = { + 'loss': net_loss, + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if net_loss is None or torch.isnan(net_loss).any(): + return None + + return output diff --git a/denoisplit/nets/model_utils.py b/denoisplit/nets/model_utils.py new file mode 100644 index 0000000..f83a5f5 --- /dev/null +++ b/denoisplit/nets/model_utils.py @@ -0,0 +1,133 @@ +import glob +import os +import pickle + +import pytorch_lightning as pl +import torch +import torch.nn as nn + +from denoisplit.config_utils import get_updated_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.nets.brave_net import BraveNetPL +from denoisplit.nets.denoiser_splitter import DenoiserSplitter +from denoisplit.nets.lvae import LadderVAE +from denoisplit.nets.lvae_bleedthrough import LadderVAEWithMixedRecons +from denoisplit.nets.lvae_deepencoder import LVAEWithDeepEncoder +from denoisplit.nets.lvae_denoiser import LadderVAEDenoiser +from denoisplit.nets.lvae_multidset_multi_input_branches import LadderVaeMultiDatasetMultiBranch +from denoisplit.nets.lvae_multidset_multi_optim import LadderVaeMultiDatasetMultiOptim +from denoisplit.nets.lvae_multiple_encoder_single_opt import LadderVAEMulEncoder1Optim +from denoisplit.nets.lvae_multiple_encoders import LadderVAEMultipleEncoders +from denoisplit.nets.lvae_multires_target import LadderVAEMultiTarget +from denoisplit.nets.lvae_restricted_reconstruction import LadderVAERestrictedReconstruction +from denoisplit.nets.lvae_semi_supervised import LadderVAESemiSupervised +from denoisplit.nets.lvae_twindecoder import LadderVAETwinDecoder +from denoisplit.nets.lvae_twodset import LadderVaeTwoDset +from denoisplit.nets.lvae_twodset_finetuning import LadderVaeTwoDsetFinetuning +from denoisplit.nets.lvae_twodset_restrictedrecons import LadderVaeTwoDsetRestrictedRecons +from denoisplit.nets.lvae_with_critic import LadderVAECritic +from denoisplit.nets.lvae_with_stitch import LadderVAEwithStitching +from denoisplit.nets.lvae_with_stitch_2stage import LadderVAEwithStitching2Stage +from denoisplit.nets.splitter_denoiser import SplitterDenoiser +from denoisplit.nets.unet import UNet + + +def create_model(config, data_mean, data_std, val_idx_manager=None): + if config.model.model_type == ModelType.LadderVae: + if 'num_targets' in config.model: + target_ch = config.model.num_targets + else: + target_ch = config.data.get('num_channels', 2) + + model = LadderVAE(data_mean, data_std, config, target_ch=target_ch, val_idx_manager=val_idx_manager) + elif config.model.model_type == ModelType.LadderVaeTwinDecoder: + model = LadderVAETwinDecoder(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVAECritic: + model = LadderVAECritic(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVaeSepEncoder: + model = LadderVAEMultipleEncoders(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVAEMultiTarget: + model = LadderVAEMultiTarget(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVaeSepEncoderSingleOptim: + model = LadderVAEMulEncoder1Optim(data_mean, data_std, config) + elif config.model.model_type == ModelType.UNet: + model = UNet(data_mean, data_std, config) + elif config.model.model_type == ModelType.BraveNet: + model = BraveNetPL(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVaeStitch: + model = LadderVAEwithStitching(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVaeMixedRecons: + model = LadderVAEWithMixedRecons(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVaeSemiSupervised: + model = LadderVAESemiSupervised(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVaeStitch2Stage: + model = LadderVAEwithStitching2Stage(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVaeTwoDataSet: + model = LadderVaeTwoDset(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVaeTwoDatasetMultiBranch: + model = LadderVaeMultiDatasetMultiBranch(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVaeTwoDatasetMultiOptim: + model = LadderVaeMultiDatasetMultiOptim(data_mean, data_std, config) + elif config.model.model_type == ModelType.LVaeDeepEncoderIntensityAug: + model = LVAEWithDeepEncoder(data_mean, data_std, config) + elif config.model.model_type == ModelType.Denoiser: + model = LadderVAEDenoiser(data_mean, data_std, config) + elif config.model.model_type == ModelType.DenoiserSplitter: + model = DenoiserSplitter(data_mean, data_std, config) + elif config.model.model_type == ModelType.SplitterDenoiser: + model = SplitterDenoiser(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVAERestrictedReconstruction: + model = LadderVAERestrictedReconstruction(data_mean, data_std, config, val_idx_manager=val_idx_manager) + elif config.model.model_type == ModelType.LadderVAETwoDataSetRestRecon: + model = LadderVaeTwoDsetRestrictedRecons(data_mean, data_std, config) + elif config.model.model_type == ModelType.LadderVAETwoDataSetFinetuning: + model = LadderVaeTwoDsetFinetuning(data_mean, data_std, config) + else: + raise Exception('Invalid model type:', config.model.model_type) + + if config.model.get('pretrained_weights_path', None): + ckpt_fpath = config.model.pretrained_weights_path + checkpoint = torch.load(ckpt_fpath) + skip_likelihood = config.model.get('pretrained_weights_skip_likelihood', False) + if skip_likelihood: + checkpoint['state_dict'].pop('likelihood.parameter_net.weight') + checkpoint['state_dict'].pop('likelihood.parameter_net.bias') + + _ = model.load_state_dict(checkpoint['state_dict'], strict=False) + print('Loaded model from ckpt dir', ckpt_fpath, f' at epoch:{checkpoint["epoch"]}') + + return model + + +def get_best_checkpoint(ckpt_dir): + output = [] + for filename in glob.glob(ckpt_dir + "/*_best.ckpt"): + output.append(filename) + assert len(output) == 1, '\n'.join(output) + return output[0] + + +def load_model_checkpoint(ckpt_dir: str, + data_mean: float, + data_std: float, + config=None, + model=None) -> pl.LightningModule: + """ + It loads the model from the checkpoint directory + """ + import ml_collections # Needed due to loading in pickle + if model is None: + # load config, if the config is not provided + if config is None: + with open(os.path.join(ckpt_dir, 'config.pkl'), 'rb') as f: + config = pickle.load(f) + + config = get_updated_config(config) + model = create_model(config, data_mean, data_std) + ckpt_fpath = get_best_checkpoint(ckpt_dir) + checkpoint = torch.load(ckpt_fpath) + _ = model.load_state_dict(checkpoint['state_dict']) + print('Loaded model from ckpt dir', ckpt_dir, f' at epoch:{checkpoint["epoch"]}') + return model diff --git a/denoisplit/nets/noise_model.py b/denoisplit/nets/noise_model.py new file mode 100644 index 0000000..ebc0922 --- /dev/null +++ b/denoisplit/nets/noise_model.py @@ -0,0 +1,156 @@ +import json +import os + +import numpy as np +import torch +import torch.nn as nn + +from denoisplit.core.model_type import ModelType +from denoisplit.nets.gmm_nnbased_noise_model import DeepGMMNoiseModel +from denoisplit.nets.gmm_noise_model import GaussianMixtureNoiseModel +from denoisplit.nets.hist_gmm_noise_model import HistGMMNoiseModel +from denoisplit.nets.hist_noise_model import HistNoiseModel + + +class DisentNoiseModel(nn.Module): + + def __init__(self, n1model, n2model): + super().__init__() + self.n1model = n1model + self.n2model = n2model + + def likelihood(self, obs, signal): + if obs.shape[1] == 1: + assert signal.shape[1] == 1 + assert self.n2model is None + return self.n1model.likelihood(obs, signal) + + ll1 = self.n1model.likelihood(obs[:, :1], signal[:, :1]) + ll2 = self.n2model.likelihood(obs[:, 1:], signal[:, 1:]) + return torch.cat([ll1, ll2], dim=1) + + +def last2path(fpath): + return os.path.join(*fpath.split('/')[-2:]) + + +def noise_model_config_sanity_check(noise_model_fpath, config, channel_key=None): + config_fpath = os.path.join(os.path.dirname(noise_model_fpath), 'config.json') + with open(config_fpath, 'r') as f: + noise_model_config = json.load(f) + # make sure that the amount of noise is consistent. + if 'add_gaussian_noise_std' in noise_model_config: + # data.enable_gaussian_noise = False + # config.data.synthetic_gaussian_scale = 1000 + assert 'enable_gaussian_noise' in config.data + assert config.data.enable_gaussian_noise == True, 'Gaussian noise is not enabled' + + assert 'synthetic_gaussian_scale' in config.data + assert noise_model_config[ + 'add_gaussian_noise_std'] == config.data.synthetic_gaussian_scale, f'{noise_model_config["add_gaussian_noise_std"]} != {config.data.synthetic_gaussian_scale}' + + cfg_poisson_noise_factor = config.data.get('poisson_noise_factor', -1) + nm_poisson_noise_factor = noise_model_config.get('poisson_noise_factor', -1) + assert cfg_poisson_noise_factor == nm_poisson_noise_factor, f'{nm_poisson_noise_factor} != {cfg_poisson_noise_factor}' + + if 'train_pure_noise_model' in noise_model_config and noise_model_config['train_pure_noise_model']: + print('Pure noise model is being used now.') + return + # make sure that the same file is used for noise model and data. + if channel_key is not None and channel_key in noise_model_config: + fname = noise_model_config['fname'] + if '' in fname: + fname.remove('') + assert len(fname) == 1 + fname = fname[0] + cur_data_fpath = os.path.join(config.datadir, config.data[channel_key]) + nm_data_fpath = os.path.join(noise_model_config['datadir'], fname) + if cur_data_fpath != nm_data_fpath: + print(f'Warning: {cur_data_fpath} != {nm_data_fpath}') + assert last2path(cur_data_fpath) == last2path(nm_data_fpath), f'{cur_data_fpath} != {nm_data_fpath}' + # assert cur_data_fpath == nm_data_fpath, f'{cur_data_fpath} != {nm_data_fpath}' + else: + print(f'Warning: channel_key is not found in noise model config: {channel_key}') + + +def get_noise_model(config): + if 'enable_noise_model' in config.model and config.model.enable_noise_model: + if config.model.model_type == ModelType.Denoiser: + if config.model.noise_model_type == 'hist': + if config.model.denoise_channel == 'Ch1': + print(f'Noise model Ch1: {config.model.noise_model_ch1_fpath}') + hist1 = np.load(config.model.noise_model_ch1_fpath) + nmodel1 = HistNoiseModel(hist1) + nmodel2 = None + elif config.model.denoise_channel == 'Ch2': + print(f'Noise model Ch2: {config.model.noise_model_ch2_fpath}') + hist2 = np.load(config.model.noise_model_ch2_fpath) + nmodel1 = HistNoiseModel(hist2) + nmodel2 = None + elif config.model.denoise_channel == 'input': + print(f'Noise model Ch1: {config.model.noise_model_ch1_fpath}') + hist1 = np.load(config.model.noise_model_ch1_fpath) + nmodel1 = HistNoiseModel(hist1) + nmodel2 = None + elif config.model.noise_model_type == 'gmm': + if config.model.denoise_channel == 'Ch1': + nmodel_fpath = config.model.noise_model_ch1_fpath + print(f'Noise model Ch1: {nmodel_fpath}') + nmodel1 = GaussianMixtureNoiseModel(params=np.load(nmodel_fpath)) + noise_model_config_sanity_check(nmodel_fpath, config, 'ch1_fname') + nmodel2 = None + elif config.model.denoise_channel == 'Ch2': + nmodel_fpath = config.model.noise_model_ch2_fpath + print(f'Noise model Ch2: {nmodel_fpath}') + nmodel1 = GaussianMixtureNoiseModel(params=np.load(nmodel_fpath)) + noise_model_config_sanity_check(nmodel_fpath, config, 'ch2_fname') + nmodel2 = None + elif config.model.denoise_channel == 'input': + nmodel_fpath = config.model.noise_model_ch1_fpath + print(f'Noise model input: {nmodel_fpath}') + nmodel1 = GaussianMixtureNoiseModel(params=np.load(nmodel_fpath)) + noise_model_config_sanity_check(nmodel_fpath, config) + nmodel2 = None + else: + raise ValueError(f'Invalid denoise_channel: {config.model.denoise_channel}') + elif config.model.noise_model_type == 'hist': + print(f'Noise model Ch1: {config.model.noise_model_ch1_fpath}') + print(f'Noise model Ch2: {config.model.noise_model_ch2_fpath}') + + hist1 = np.load(config.model.noise_model_ch1_fpath) + nmodel1 = HistNoiseModel(hist1) + hist2 = np.load(config.model.noise_model_ch2_fpath) + nmodel2 = HistNoiseModel(hist2) + elif config.model.noise_model_type == 'histgmm': + print(f'Noise model Ch1: {config.model.noise_model_ch1_fpath}') + print(f'Noise model Ch2: {config.model.noise_model_ch2_fpath}') + + noise_model_config_sanity_check(config.model.noise_model_ch1_fpath, config, 'ch1_fname') + noise_model_config_sanity_check(config.model.noise_model_ch2_fpath, config, 'ch2_fname') + + hist1 = np.load(config.model.noise_model_ch1_fpath) + nmodel1 = HistGMMNoiseModel(hist1) + nmodel1.fit() + + hist2 = np.load(config.model.noise_model_ch2_fpath) + nmodel2 = HistGMMNoiseModel(hist2) + nmodel2.fit() + + elif config.model.noise_model_type == 'gmm': + print(f'Noise model Ch1: {config.model.noise_model_ch1_fpath}') + print(f'Noise model Ch2: {config.model.noise_model_ch2_fpath}') + + nmodel1 = GaussianMixtureNoiseModel(params=np.load(config.model.noise_model_ch1_fpath)) + nmodel2 = GaussianMixtureNoiseModel(params=np.load(config.model.noise_model_ch2_fpath)) + noise_model_config_sanity_check(config.model.noise_model_ch1_fpath, config, 'ch1_fname') + noise_model_config_sanity_check(config.model.noise_model_ch2_fpath, config, 'ch2_fname') + # nmodel1 = DeepGMMNoiseModel(params=np.load(config.model.noise_model_ch1_fpath)) + # nmodel2 = DeepGMMNoiseModel(params=np.load(config.model.noise_model_ch2_fpath)) + + if config.model.get('noise_model_learnable', False): + nmodel1.make_learnable() + if nmodel2 is not None: + nmodel2.make_learnable() + + return DisentNoiseModel(nmodel1, nmodel2) + return None diff --git a/denoisplit/nets/seamless_stich.py b/denoisplit/nets/seamless_stich.py new file mode 100644 index 0000000..7ea23bf --- /dev/null +++ b/denoisplit/nets/seamless_stich.py @@ -0,0 +1,174 @@ +""" +Do seamless stitching +""" +import torch.nn as nn +import torch +from tqdm import tqdm +import torch.optim as optim +from denoisplit.core.seamless_stitch_base import SeamlessStitchBase + + +class Model(nn.Module): + def __init__(self, num_samples, N): + super().__init__() + self._N = N + self.params = nn.Parameter(torch.zeros(num_samples, self._N, self._N)) + self.shape = self.params.shape + + def __getitem__(self, pos): + i, j = pos + return self.params[:, i, j] + + +class SeamlessStitch(SeamlessStitchBase): + def __init__(self, grid_size, stitched_frame, learning_rate, lr_patience=10, lr_reduction_factor=0.1): + super().__init__(grid_size, stitched_frame) + self.params = Model(len(stitched_frame), self._N) + self.opt = torch.optim.SGD(self.params.parameters(), lr=learning_rate) + self.loss_metric = nn.L1Loss(reduction='sum') + + self.lr_scheduler = optim.lr_scheduler.ReduceLROnPlateau(self.opt, + 'min', + patience=lr_patience, + factor=lr_reduction_factor, + threshold_mode='abs', + min_lr=1e-12, + verbose=True) + print( + f'[{self.__class__.__name__}] Grid:{grid_size} LR:{learning_rate} LP:{lr_patience} LRF:{lr_reduction_factor}' + ) + + def get_ch0_offset(self, row_idx, col_idx): + return self.params[row_idx, col_idx].detach().cpu().numpy()[:, None, None] + + def _compute_loss_on_boundaries(self, boundary1, boundary2, boundary1_offset): + # return torch.Tensor([0.0]) + ch0_loss = self.loss_metric(boundary1[:, 0] + boundary1_offset[..., None], boundary2[:, 0]) + ch1_loss = self.loss_metric(boundary1[:, 1] - boundary1_offset[..., None], boundary2[:, 1]) + + return (ch0_loss + ch1_loss) / 2 + + def _compute_left_loss(self, row_idx, col_idx): + if col_idx == 0: + return 0.0 + p = self.params[row_idx, col_idx] + + left_p_boundary = self.get_lboundary(row_idx, col_idx) + right_p_boundary = self.get_rboundary(row_idx, col_idx - 1) + return (left_p_boundary, right_p_boundary, p) + + def _compute_right_loss(self, row_idx, col_idx): + if col_idx == self.params.shape[1] - 1: + return 0.0 + p = self.params[row_idx, col_idx] + + left_p_boundary = self.get_lboundary(row_idx, col_idx + 1) + right_p_boundary = self.get_rboundary(row_idx, col_idx) + return (right_p_boundary, left_p_boundary, p) + + def _compute_top_loss(self, row_idx, col_idx): + if row_idx == 0: + return 0.0 + p = self.params[row_idx, col_idx] + + top_p_boundary = self.get_tboundary(row_idx, col_idx) + bottom_p_boundary = self.get_bboundary(row_idx - 1, col_idx) + return (top_p_boundary, bottom_p_boundary, p) + + def _compute_bottom_loss(self, row_idx, col_idx): + if row_idx == self.params.shape[1] - 1: + return 0.0 + p = self.params[row_idx, col_idx] + + top_p_boundary = self.get_tboundary(row_idx + 1, col_idx) + bottom_p_boundary = self.get_bboundary(row_idx, col_idx) + return (bottom_p_boundary, top_p_boundary, p) + + def _compute_loss(self, + row_idx, + col_idx, + compute_left=True, + compute_right=True, + compute_top=True, + compute_bottom=True): + left_loss = self._compute_left_loss(row_idx, col_idx) if compute_left else None + right_loss = self._compute_right_loss(row_idx, col_idx) if compute_right else None + + top_loss = self._compute_top_loss(row_idx, col_idx) if compute_top else None + bottom_loss = self._compute_bottom_loss(row_idx, col_idx) if compute_bottom else None + + b1_arr = [] + b2_arr = [] + offset_arr = [] + if left_loss is not None: + b1_arr.append(left_loss[0]) + b2_arr.append(left_loss[1]) + offset_arr.append(left_loss[2]) + + if right_loss is not None: + b1_arr.append(right_loss[0]) + b2_arr.append(right_loss[1]) + offset_arr.append(right_loss[2]) + + if top_loss is not None: + b1_arr.append(top_loss[0]) + b2_arr.append(top_loss[1]) + offset_arr.append(top_loss[2]) + + if bottom_loss is not None: + b1_arr.append(bottom_loss[0]) + b2_arr.append(bottom_loss[1]) + offset_arr.append(bottom_loss[2]) + + return b1_arr, b2_arr, offset_arr + + def compute_loss(self, + batch_size=100, + compute_left=True, + compute_right=True, + compute_top=True, + compute_bottom=True): + loss = 0.0 + b1_arr = [] + b2_arr = [] + offset_arr = [] + loss = 0.0 + + normalizing_factor = self._data.shape[0] * (2 * ((self._N - 1)**2)) + for row_idx in range(self._N): + for col_idx in range(self._N): + a, b, c = self._compute_loss(row_idx, + col_idx, + compute_left=compute_left, + compute_right=compute_right, + compute_top=compute_top, + compute_bottom=compute_bottom) + b1_arr += a + b2_arr += b + offset_arr += c + if batch_size <= len(b1_arr): + loss += self._compute_loss_on_boundaries(torch.cat(b1_arr, dim=0), torch.cat(b2_arr, dim=0), + torch.cat(offset_arr, dim=0)) / normalizing_factor + b1_arr = [] + b2_arr = [] + offset_arr = [] + + if len(offset_arr): + loss += self._compute_loss_on_boundaries(torch.cat(b1_arr, dim=0), torch.cat(b2_arr, dim=0), + torch.cat(offset_arr, dim=0)) / normalizing_factor + return loss + + def fit(self, batch_size=512, steps=100): + loss_arr = [] + steps_iter = tqdm(range(steps)) + for _ in steps_iter: + self.params.zero_grad() + loss = self.compute_loss(batch_size=batch_size) + loss.backward() + self.opt.step() + + loss_arr.append(loss.item()) + steps_iter.set_description(f'Loss: {loss_arr[-1]:.3f}') + self.lr_scheduler.step(loss) + + return loss_arr diff --git a/denoisplit/nets/seamless_stich_grad1.py b/denoisplit/nets/seamless_stich_grad1.py new file mode 100644 index 0000000..a2a51c9 --- /dev/null +++ b/denoisplit/nets/seamless_stich_grad1.py @@ -0,0 +1,148 @@ +from denoisplit.nets.seamless_stich import SeamlessStitch + + +class SeamlessStitchGrad1(SeamlessStitch): + """ + here, we simply return the derivative + Top + ------------ + | + Left| + | + | + ------------ + Bottom + """ + def __init__(self, grid_size, stitched_frame, learning_rate, lr_patience=10, lr_reduction_factor=0.1): + super().__init__(grid_size, stitched_frame, learning_rate, lr_patience, lr_reduction_factor=lr_reduction_factor) + self.cache = {'lgrad': {}, 'rgrad': {}, 'tgrad': {}, 'bgrad': {}, 'lnb': {}, 'rnb': {}, 'tnb': {}, 'bnb': {}} + self.use_caching = False + + def populate_cache(self, row_idx, col_idx, cache_key, fn): + if row_idx not in self.cache[cache_key]: + self.cache[cache_key][row_idx] = {} + + if col_idx not in self.cache[cache_key][row_idx]: + self.cache[cache_key][row_idx][col_idx] = fn(row_idx, col_idx).cuda() + + # caching based gradients + def get_lgradient(self, row_idx, col_idx): + if not self.use_caching: + return super().get_lgradient(row_idx, col_idx) + cache_key = 'lgrad' + self.populate_cache(row_idx, col_idx, cache_key, super().get_lgradient) + return self.cache[cache_key][row_idx][col_idx] + + def get_rgradient(self, row_idx, col_idx): + if not self.use_caching: + return super().get_rgradient(row_idx, col_idx) + cache_key = 'rgrad' + self.populate_cache(row_idx, col_idx, cache_key, super().get_rgradient) + return self.cache[cache_key][row_idx][col_idx] + + def get_tgradient(self, row_idx, col_idx): + if not self.use_caching: + return super().get_tgradient(row_idx, col_idx) + cache_key = 'tgrad' + self.populate_cache(row_idx, col_idx, cache_key, super().get_tgradient) + return self.cache[cache_key][row_idx][col_idx] + + def get_bgradient(self, row_idx, col_idx): + if not self.use_caching: + return super().get_bgradient(row_idx, col_idx) + cache_key = 'bgrad' + self.populate_cache(row_idx, col_idx, cache_key, super().get_bgradient) + return self.cache[cache_key][row_idx][col_idx] + +# # gradient at the boundary of two patches. + + def get_lneighbor_gradient(self, row_idx, col_idx): + if not self.use_caching: + return super().get_lneighbor_gradient(row_idx, col_idx) + cache_key = 'lnb' + self.populate_cache(row_idx, col_idx, cache_key, super().get_lneighbor_gradient) + return self.cache[cache_key][row_idx][col_idx] + + def get_rneighbor_gradient(self, row_idx, col_idx): + if not self.use_caching: + return super().get_rneighbor_gradient(row_idx, col_idx) + cache_key = 'rnb' + self.populate_cache(row_idx, col_idx, cache_key, super().get_rneighbor_gradient) + return self.cache[cache_key][row_idx][col_idx] + + def get_tneighbor_gradient(self, row_idx, col_idx): + if not self.use_caching: + return super().get_tneighbor_gradient(row_idx, col_idx) + cache_key = 'tnb' + self.populate_cache(row_idx, col_idx, cache_key, super().get_tneighbor_gradient) + return self.cache[cache_key][row_idx][col_idx] + + def get_bneighbor_gradient(self, row_idx, col_idx): + if not self.use_caching: + return super().get_bneighbor_gradient(row_idx, col_idx) + cache_key = 'bnb' + self.populate_cache(row_idx, col_idx, cache_key, super().get_bneighbor_gradient) + return self.cache[cache_key][row_idx][col_idx] + + +# computing loss now. + + def _compute_left_loss(self, row_idx, col_idx): + if col_idx == 0: + return None + p = self.params[row_idx, col_idx] + nbr_p = self.params[row_idx, col_idx - 1] + + left_p_gradient = self.get_lgradient(row_idx, col_idx) + right_p_gradient = self.get_rgradient(row_idx, col_idx - 1) + avg_gradient = (left_p_gradient + right_p_gradient) / 2 + boundary_gradient = self.get_lneighbor_gradient(row_idx, col_idx) + return (boundary_gradient.squeeze(), avg_gradient.squeeze(), p - nbr_p) + + def _compute_right_loss(self, row_idx, col_idx): + if col_idx == self.params.shape[1] - 1: + return None + p = self.params[row_idx, col_idx] + nbr_p = self.params[row_idx, col_idx + 1] + + left_p_gradient = self.get_lgradient(row_idx, col_idx + 1) + right_p_gradient = self.get_rgradient(row_idx, col_idx) + avg_gradient = (left_p_gradient + right_p_gradient) / 2 + boundary_gradient = self.get_rneighbor_gradient(row_idx, col_idx) + return (boundary_gradient.squeeze(), avg_gradient.squeeze(), nbr_p - p) + + def _compute_top_loss(self, row_idx, col_idx): + if row_idx == 0: + return None + p = self.params[row_idx, col_idx] + nbr_p = self.params[row_idx - 1, col_idx] + + top_p_gradient = self.get_tgradient(row_idx, col_idx) + bottom_p_gradient = self.get_bgradient(row_idx - 1, col_idx) + avg_gradient = (top_p_gradient + bottom_p_gradient) / 2 + boundary_gradient = self.get_tneighbor_gradient(row_idx, col_idx) + return (boundary_gradient.squeeze(), avg_gradient.squeeze(), p - nbr_p) + + def _compute_bottom_loss(self, row_idx, col_idx): + if row_idx == self.params.shape[1] - 1: + return None + p = self.params[row_idx, col_idx] + nbr_p = self.params[row_idx + 1, col_idx] + + top_p_gradient = self.get_tgradient(row_idx + 1, col_idx) + bottom_p_gradient = self.get_bgradient(row_idx, col_idx) + avg_gradient = (top_p_gradient + bottom_p_gradient) / 2 + boundary_gradient = self.get_bneighbor_gradient(row_idx, col_idx) + return (boundary_gradient.squeeze(), avg_gradient.squeeze(), nbr_p - p) + +if __name__ == '__main__': + import torch + pred = torch.randn(6, 2, 1024, 1024) + grid_size = 32 + learning_rate = 10 + lr_patience = 5 + # 4347.534 + # model = SeamlessStitch(grid_size, pred, learning_rate) + stitch_model = SeamlessStitchGrad1(grid_size, pred, learning_rate, lr_patience=lr_patience) + loss_arr = stitch_model.fit(steps=10) + output = stitch_model.get_output() diff --git a/denoisplit/nets/splitter_denoiser.py b/denoisplit/nets/splitter_denoiser.py new file mode 100644 index 0000000..40f8b34 --- /dev/null +++ b/denoisplit/nets/splitter_denoiser.py @@ -0,0 +1,81 @@ +import os +from copy import deepcopy + +import torch + +import ml_collections +from denoisplit.config_utils import load_config +from denoisplit.nets.lvae import LadderVAE + + +class SplitterDenoiser(LadderVAE): + """ + It denoises the splitted output. This is the second step in the pipeline of split=>denoise. + We have 2 options for the denoise portion. + 1. Do a unsupervised denoising. + 2. Do a supervised denoising. This might even be useful to remove artefacts caused by the first model. + """ + + def __init__(self, data_mean, data_std, config, use_uncond_mode_at=[], target_ch=2): + new_config = deepcopy(ml_collections.ConfigDict(config)) + with new_config.unlocked(): + new_config.data.color_ch = 2 + + super().__init__(data_mean, data_std, new_config, use_uncond_mode_at, target_ch) + + self._splitter = self.load_splitter(config.model.pre_trained_ckpt_fpath_splitter) + + def load_data_mean_std(self, checkpoint): + # TODO: save the mean and std in the checkpoint. + data_mean = self.data_mean + data_std = self.data_std + return data_mean, data_std + + def load_splitter(self, pre_trained_ckpt_fpath): + checkpoint = torch.load(pre_trained_ckpt_fpath) + config_fpath = os.path.join(os.path.dirname(pre_trained_ckpt_fpath), 'config.pkl') + config = load_config(config_fpath) + data_mean, data_std = self.load_data_mean_std(checkpoint) + model = LadderVAE(data_mean, data_std, config) + _ = model.load_state_dict(checkpoint['state_dict'], strict=True) + print('Loaded model from ckpt dir', pre_trained_ckpt_fpath, f' at epoch:{checkpoint["epoch"]}') + + for param in model.parameters(): + param.requires_grad = False + return model + + def forward(self, x): + x = self.get_splitted_output(x) + return super().forward(x) + + def get_splitted_output(self, x): + out, _ = self._splitter(x) + return self._splitter.likelihood.distr_params(out)['mean'] + + +if __name__ == '__main__': + import numpy as np + import torch + + from denoisplit.configs.splitter_denoiser_config import get_config + + config = get_config() + data_mean = {'input': np.array([0]).reshape(1, 1, 1, 1), 'target': np.array([0, 0]).reshape(1, 2, 1, 1)} + data_std = {'input': np.array([1]).reshape(1, 1, 1, 1), 'target': np.array([1, 1]).reshape(1, 2, 1, 1)} + model = SplitterDenoiser(data_mean, data_std, config) + mc = 1 if config.data.multiscale_lowres_count is None else config.data.multiscale_lowres_count + 1 + inp = torch.rand((2, mc, config.data.image_size, config.data.image_size)) + out, td_data = model(inp) + print(out.shape) + batch = ( + torch.rand((16, mc, config.data.image_size, config.data.image_size)), + torch.rand((16, 2, config.data.image_size, config.data.image_size)), + ) + model.training_step(batch, 0) + model.validation_step(batch, 0) + + ll = torch.ones((12, 2, 32, 32)) + ll_new = model._get_weighted_likelihood(ll) + print(ll_new[:, 0].mean(), ll_new[:, 0].std()) + print(ll_new[:, 1].mean(), ll_new[:, 1].std()) + print('mar') diff --git a/denoisplit/nets/unet.py b/denoisplit/nets/unet.py new file mode 100644 index 0000000..54a0f58 --- /dev/null +++ b/denoisplit/nets/unet.py @@ -0,0 +1,295 @@ +""" +Adapted from https://github.com/milesial/Pytorch-UNet/blob/master/unet/unet_model.py +""" +from copy import deepcopy + +import numpy as np +import pytorch_lightning as pl +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +import wandb + +from denoisplit.core.metric_monitor import MetricMonitor +from denoisplit.metrics.running_psnr import RunningPSNR +from denoisplit.nets.context_transfer_module import ContextTransferModule +from denoisplit.nets.lvae_layers import BottomUpDeterministicResBlock, MergeLowRes +from denoisplit.nets.unet_parts import * + + +class UNet(pl.LightningModule): + + def __init__(self, data_mean, data_std, config): + super(UNet, self).__init__() + bilinear = True + self.bilinear = bilinear + self.lr = config.training.lr + self.n_levels = config.model.n_levels + self.lr_scheduler_patience = config.training.lr_scheduler_patience + self.lr_scheduler_monitor = config.model.get('monitor', 'val_loss') + self.lr_scheduler_mode = MetricMonitor(self.lr_scheduler_monitor).mode() + self.enable_context_transfer = config.model.get('enable_context_transfer', False) + self.ct_modules = nn.ModuleList() + init_ch = config.model.get('init_channel_count', 64) + self.multiscale_lowres_separate_branch = config.model.multiscale_lowres_separate_branch + self._img_sz = config.data.image_size + + if self.enable_context_transfer: + hw = config.data.image_size + cur_ch = init_ch + for i in range(1, self.n_levels + 1): + self.ct_modules.append( + ContextTransferModule((cur_ch, hw, hw), + initial_weight_factor=config.model.context_transfer_initial_weight_factor)) + cur_ch *= 2 + hw //= 2 + + self.inc = DoubleConv(1, init_ch) + ch = init_ch + for i in range(1, self.n_levels): + setattr(self, f'down{i}', Down(ch, 2 * ch)) + ch = 2 * ch + + factor = 2 if bilinear else 1 + setattr(self, f'down{self.n_levels}', Down(ch, 2 * ch // factor)) + ch = 2 * ch + for i in range(1, self.n_levels): + setattr(self, f'up{i}', Up(ch, (ch // 2) // factor, bilinear)) + ch = ch // 2 + + setattr(self, f'up{self.n_levels}', Up(ch, ch // 2, bilinear)) + ch = ch // 2 + self.outc = OutConv(ch, 2) + + # multiscale architecture + self.lowres_first_bottom_ups = self._multiscale_count = self.lowres_merge = self.lowres_net = None + self._init_multires(config, init_ch) + + self.normalized_input = config.data.normalized_input + self.data_mean = torch.Tensor(data_mean) if isinstance(data_mean, np.ndarray) else data_mean + self.data_std = torch.Tensor(data_std) if isinstance(data_std, np.ndarray) else data_std + self.label1_psnr = RunningPSNR() + self.label2_psnr = RunningPSNR() + print( + f'[{self.__class__.__name__}] ContextTransfer:{self.enable_context_transfer} SepBranch:{self.multiscale_lowres_separate_branch}' + ) + + def reset_for_different_output_size(self, output_size): + assert self._img_sz == output_size, f"{self._img_sz}!={output_size}. This model does not support different output size due to context transfer module" + + def _init_multires(self, config, init_n_filters): + """ + Initialize everything related to multiresolution approach. + """ + self.batchnorm = True + # self.encoder_n_filters = 34 + multiscale_retain_spatial_dims = True + res_block_type = 'bacdbacd' + res_block_skip_padding = False + # assuming no initial downscaling. otherwise it will be 2 + stride = 1 + nonlin = nn.ELU + self._multiscale_count = config.data.multiscale_lowres_count + if self._multiscale_count is None: + self._multiscale_count = 1 + + msg = "Multiscale count({}) should not exceed the number of bottom up layers ({}) by more than 1" + msg = msg.format(config.data.multiscale_lowres_count, config.model.n_levels) + assert self._multiscale_count <= 1 or config.data.multiscale_lowres_count <= 1 + config.model.n_levels, msg + + # msg = "if multiscale is enabled, then we are just working with monocrome images." + # assert self._multiscale_count == 1 or self.color_ch == 1, msg + lowres_first_bottom_up_list = [] + lowres_merge_list = [] + lowres_net_list = [] + + multiscale_lowres_size_factor = 1 + n_filters = init_n_filters + for i in range(1, self._multiscale_count): + layer_enable_multiscale = self._multiscale_count > i + 1 + multiscale_lowres_size_factor *= (1 + int(layer_enable_multiscale)) + + first_bottom_up = nn.Sequential( + nn.Conv2d(1, n_filters, 5, padding=2, stride=stride), nonlin(), + BottomUpDeterministicResBlock( + c_in=n_filters, + c_out=n_filters, + nonlin=nonlin, + batchnorm=self.batchnorm, + dropout=0, + res_block_type=res_block_type, + skip_padding=res_block_skip_padding, + )) + lowres_first_bottom_up_list.append(first_bottom_up) + lowres_merge = MergeLowRes(channels=2 * n_filters, + merge_type='residual', + nonlin=nonlin, + batchnorm=self.batchnorm, + dropout=0, + res_block_type=res_block_type, + multiscale_retain_spatial_dims=multiscale_retain_spatial_dims, + multiscale_lowres_size_factor=multiscale_lowres_size_factor) + + lowres_merge_list.append(lowres_merge) + + net = getattr(self, f'down{i}') + net = net.maxpool_conv[1] # skipping the maxpool + if self.multiscale_lowres_separate_branch: + net = deepcopy(net) + lowres_net_list.append(net) + + n_filters = 2 * n_filters + + self.lowres_net = nn.ModuleList(lowres_net_list) if len(lowres_net_list) else None + self.lowres_first_bottom_ups = nn.ModuleList(lowres_first_bottom_up_list) if len( + lowres_first_bottom_up_list) else None + + self.lowres_merge = nn.ModuleList(lowres_merge_list) if len(lowres_merge_list) else None + + def forward(self, x): + if self._multiscale_count == 1: + x1 = self.inc(x) + else: + x1 = self.inc(x[:, :1]) + + latents = [] + x_end = x1 + latents.append(x1) + for i in range(1, self.n_levels + 1): + x_end = getattr(self, f'down{i}')(x_end) + + if i < self._multiscale_count: + lowres_x = self.lowres_first_bottom_ups[i - 1](x[:, i:i + 1]) + # lowres_net = getattr(self, f'down{i}') + # lowres_net = lowres_net.maxpool_conv[1] # skipping the maxpool + lowres_flow = self.lowres_net[i - 1](lowres_x) + x_end = self.lowres_merge[i - 1](x_end, lowres_flow) + + latents.append(x_end) + + if self.enable_context_transfer: + for i in range(len(latents) - 1): + latents[i] = self.ct_modules[i](latents[i]) + + for i in range(1, self.n_levels + 1): + x_end = getattr(self, f'up{i}')(x_end, latents[-1 * (i + 1)]) + if x_end.shape[-1] > x.shape[-1]: + x_end = F.center_crop(x_end, x.shape[-2:]) + + pred = self.outc(x_end) + return pred + + def configure_optimizers(self): + optimizer = optim.Adamax(self.parameters(), lr=self.lr, weight_decay=0) + scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, + self.lr_scheduler_mode, + patience=self.lr_scheduler_patience, + factor=0.5, + min_lr=1e-12, + verbose=True) + + return {'optimizer': optimizer, 'lr_scheduler': scheduler, 'monitor': self.lr_scheduler_monitor} + + def normalize_input(self, x): + if self.normalized_input: + return x + return (x - self.data_mean.mean()) / self.data_std.mean() + + def normalize_target(self, target): + return (target - self.data_mean) / self.data_std + + def power_of_2(self, x): + assert isinstance(x, int) + if x == 1: + return True + if x == 0: + # happens with validation + return False + if x % 2 == 1: + return False + return self.power_of_2(x // 2) + + def set_params_to_same_device_as(self, correct_device_tensor): + if self.enable_context_transfer: + for i in range(len(self.ct_modules)): + self.ct_modules[i].set_params_to_same_device_as(correct_device_tensor) + + if isinstance(self.data_mean, torch.Tensor): + if self.data_mean.device != correct_device_tensor.device: + self.data_mean = self.data_mean.to(correct_device_tensor.device) + self.data_std = self.data_std.to(correct_device_tensor.device) + + def training_step(self, batch, batch_idx, enable_logging=True): + x, target = batch + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + + out = self.forward(x_normalized) + net_loss = self.get_reconstruction_loss(out, target_normalized) + + self.log('reconstruction_loss', net_loss, on_epoch=True) + + output = { + 'loss': net_loss, + 'reconstruction_loss': net_loss, + } + # https://github.com/openai/vdvae/blob/main/train.py#L26 + if torch.isnan(net_loss).any(): + return None + + return output + + def get_reconstruction_loss(self, reconstruction, input): + loss_fn = nn.MSELoss() + return loss_fn(reconstruction, input) + + def validation_step(self, batch, batch_idx): + x, target = batch + self.set_params_to_same_device_as(target) + + x_normalized = self.normalize_input(x) + target_normalized = self.normalize_target(target) + + out = self.forward(x_normalized) + recons_img = out + recons_loss = self.get_reconstruction_loss(out, target_normalized) + + self.log('val_loss', recons_loss, on_epoch=True) + self.label1_psnr.update(recons_img[:, 0], target_normalized[:, 0]) + self.label2_psnr.update(recons_img[:, 1], target_normalized[:, 1]) + + if batch_idx == 0 and self.power_of_2(self.current_epoch): + sample = self(x_normalized[0:1, ...]) + + sample = sample * self.data_std + self.data_mean + sample = sample.cpu() + self.log_images_for_tensorboard(sample[:, 0, ...], target[0, 0, ...], 'label1') + self.log_images_for_tensorboard(sample[:, 1, ...], target[0, 1, ...], 'label2') + + def log_images_for_tensorboard(self, pred, target, label): + clamped_pred = torch.clamp((pred - pred.min()) / (pred.max() - pred.min()), 0, 1) + if target is not None: + clamped_input = torch.clamp((target - target.min()) / (target.max() - target.min()), 0, 1) + img = wandb.Image(clamped_input[None].cpu().numpy()) + self.logger.experiment.log({f'target_for{label}': img}) + # self.trainer.logger.experiment.add_image(f'target_for{label}', clamped_input[None], self.current_epoch) + + img = wandb.Image(clamped_pred.cpu().numpy()) + self.logger.experiment.log({f'{label}/sample_0': img}) + + def on_validation_epoch_end(self): + psnrl1 = self.label1_psnr.get() + psnrl2 = self.label2_psnr.get() + psnr = (psnrl1 + psnrl2) / 2 + self.log('val_psnr', psnr, on_epoch=True) + self.label1_psnr.reset() + self.label2_psnr.reset() + + +if __name__ == '__main__': + from denoisplit.configs.unet_config import get_config + cnf = get_config() + model = UNet(0.0, 1.0, cnf) + # print(model)G + inp = torch.rand((12, 4, 64, 64)) + model(inp) diff --git a/denoisplit/nets/unet_parts.py b/denoisplit/nets/unet_parts.py new file mode 100644 index 0000000..98064ba --- /dev/null +++ b/denoisplit/nets/unet_parts.py @@ -0,0 +1,73 @@ +""" +Parts of the U-Net model +Taken from https://github.com/milesial/Pytorch-UNet/blob/master/unet/unet_parts.py +""" + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class DoubleConv(nn.Module): + """(convolution => [BN] => ReLU) * 2""" + + def __init__(self, in_channels, out_channels, mid_channels=None): + super().__init__() + if not mid_channels: + mid_channels = out_channels + self.double_conv = nn.Sequential(nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1, bias=False), + nn.BatchNorm2d(mid_channels), nn.ReLU(inplace=True), + nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1, bias=False), + nn.BatchNorm2d(out_channels), nn.ReLU(inplace=True)) + + def forward(self, x): + return self.double_conv(x) + + +class Down(nn.Module): + """Downscaling with maxpool then double conv""" + + def __init__(self, in_channels, out_channels): + super().__init__() + self.maxpool_conv = nn.Sequential(nn.MaxPool2d(2), DoubleConv(in_channels, out_channels)) + + def forward(self, x): + return self.maxpool_conv(x) + + +class Up(nn.Module): + """Upscaling then double conv""" + + def __init__(self, in_channels, out_channels, bilinear=True): + super().__init__() + + # if bilinear, use the normal convolutions to reduce the number of channels + if bilinear: + self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) + self.conv = DoubleConv(in_channels, out_channels, in_channels // 2) + else: + self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2) + self.conv = DoubleConv(in_channels, out_channels) + + def forward(self, x1, x2): + x1 = self.up(x1) + # input is CHW + diffY = x2.size()[2] - x1.size()[2] + diffX = x2.size()[3] - x1.size()[3] + + x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2, diffY // 2, diffY - diffY // 2]) + # if you have padding issues, see + # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a + # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd + x = torch.cat([x2, x1], dim=1) + return self.conv(x) + + +class OutConv(nn.Module): + + def __init__(self, in_channels, out_channels): + super(OutConv, self).__init__() + self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1) + + def forward(self, x): + return self.conv(x) \ No newline at end of file diff --git a/denoisplit/notebooks/Denoiser.ipynb b/denoisplit/notebooks/Denoiser.ipynb new file mode 100644 index 0000000..a7d7277 --- /dev/null +++ b/denoisplit/notebooks/Denoiser.ipynb @@ -0,0 +1,992 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "19844352", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad91cc2b", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "# os.environ[\"CUDA_DEVICE_ORDER\"]=\"PCI_BUS_ID\" # see issue #152\n", + "# os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"2\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8263ed32", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.core.tiff_reader import load_tiff\n", + "# fname = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk44/pred_disentangle_2402_D16-M23-S0-L0_31.tif'\n", + "# data = load_tiff(fname)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dcd3d0c2", + "metadata": {}, + "outputs": [], + "source": [ + "# there are two environments(debug and prod). From where you want to fetch the code and data? \n", + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27ec4422", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "96db1d21", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.core.tiff_reader import load_tiff\n", + "# import matplotlib.pyplot as plt\n", + "# # data = load_tiff('/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk44/pred_disentangle_2402_D16-M23-S0-L0_88.tif')\n", + "# # plt.imshow(data[0,...,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a9748a9", + "metadata": {}, + "outputs": [], + "source": [ + "ckpt_dir = \"/home/ashesh.ashesh/training/disentangle/2403/D7-M23-S0-L0/32\"\n", + "# 211/D3-M3-S0-L0/0\n", + "# 2210/D3-M3-S0-L0/128\n", + "# 2210/D3-M3-S0-L0/129" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27410ddc", + "metadata": {}, + "outputs": [], + "source": [ + "# !ls /home/ubuntu/ashesh/training/disentangle/2209/D3-M9-S0-L0/1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7232e05", + "metadata": {}, + "outputs": [], + "source": [ + "dtype = int(ckpt_dir.strip('/').split('/')[-2].split('-')[0][1:])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90109e80", + "metadata": {}, + "outputs": [], + "source": [ + "dtype" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b237569", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "import json\n", + "if DEBUG:\n", + " if dtype == DataType.CustomSinosoid:\n", + " data_dir = f'{DATA_ROOT}/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + "else:\n", + " if dtype in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " data_dir = f'{DATA_ROOT}/sinosoid_without_test/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + " elif dtype == DataType.Prevedel_EMBL:\n", + " data_dir = f'{DATA_ROOT}/Prevedel_EMBL/PKG_3P_dualcolor_stacks/NoAverage_NoRegistration/'\n", + " elif dtype == DataType.AllenCellMito:\n", + " data_dir = f'{DATA_ROOT}/allencell/2017_03_08_Struct_First_Pass_Seg/AICS-11/'\n", + " elif dtype == DataType.SeparateTiffData:\n", + " data_dir = f'{DATA_ROOT}/ventura_gigascience'\n", + " elif dtype == DataType.SemiSupBloodVesselsEMBL:\n", + " data_dir = f'{DATA_ROOT}/EMBL_halfsupervised/Demixing_3P'\n", + " elif dtype == DataType.Pavia2VanillaSplitting:\n", + " data_dir = f'{DATA_ROOT}/pavia2'\n", + " elif dtype == DataType.ExpansionMicroscopyMitoTub:\n", + " data_dir = f'{DATA_ROOT}/expansion_microscopy_Nick/'\n", + " elif dtype == DataType.ShroffMitoEr:\n", + " data_dir = f'{DATA_ROOT}/shrofflab/'\n", + " elif dtype == DataType.HTIba1Ki67:\n", + " data_dir = f'{DATA_ROOT}/Stefania/20230327_Ki67_and_Iba1_trainingdata/'\n", + " elif dtype == DataType.BioSR_MRC:\n", + " data_dir = f'{DATA_ROOT}/BioSR/'\n", + " \n", + "# 2720*2720: microscopy dataset.\n", + "\n", + "image_size_for_grid_centers = 32\n", + "mmse_count = 2\n", + "custom_image_size = 128\n", + "denoise_channel = None\n", + "save_output = False\n", + "save_output_dir = f'/group/jug/ashesh/data/denoiser_output/{os.path.basename(data_dir)}'\n", + "\n", + "batch_size = 8\n", + "num_workers = 1\n", + "COMPUTE_LOSS = False\n", + "use_deterministic_grid = None\n", + "threshold = None # 0.02\n", + "compute_kl_loss = False\n", + "evaluate_train = False# inspect training performance\n", + "eval_datasplit_type = DataSplitType.Test\n", + "val_repeat_factor = None\n", + "psnr_type = 'range_invariant' #'simple', 'range_invariant'\n", + "\n", + "if save_output:\n", + " assert eval_datasplit_type == DataSplitType.All\n", + " assert save_output_dir is not None\n", + " assert os.path.exists(save_output_dir), f\"{save_output_dir} does not exist\"\n", + " with open(f'{save_output_dir}/config.json', 'w') as f:\n", + " json.dump({'ckpt_dir': ckpt_dir, \n", + " 'data_dir': data_dir, \n", + " 'image_size_for_grid_centers': image_size_for_grid_centers, \n", + " 'mmse_count': mmse_count, \n", + " 'custom_image_size': custom_image_size, \n", + " 'denoise_channel': denoise_channel, \n", + " 'use_deterministic_grid': use_deterministic_grid, \n", + " 'threshold': threshold, \n", + " 'eval_datasplit_type': eval_datasplit_type, \n", + " 'val_repeat_factor': val_repeat_factor}, f)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f889dd2d", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/config_loader.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a0047fe", + "metadata": {}, + "outputs": [], + "source": [ + "# config.model.decoder" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc8a3fed", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.sampler_type import SamplerType\n", + "from denoisplit.core.loss_type import LossType\n", + "from denoisplit.data_loader.ht_iba1_ki67_rawdata_loader import SubDsetType\n", + "# from denoisplit.core.lowres_merge_type import LowresMergeType\n", + "\n", + "\n", + "with config.unlocked():\n", + " if denoise_channel is not None:\n", + " config.model.denoise_channel = denoise_channel\n", + " \n", + " config.model.skip_nboundary_pixels_from_loss = None\n", + " if config.model.model_type == ModelType.UNet and 'n_levels' not in config.model:\n", + " config.model.n_levels = 4\n", + " if config.data.sampler_type == SamplerType.NeighborSampler:\n", + " config.data.sampler_type = SamplerType.DefaultSampler\n", + " config.loss.loss_type = LossType.Elbo\n", + " config.data.grid_size = config.data.image_size\n", + " if 'ch1_fpath_list' in config.data:\n", + " config.data.ch1_fpath_list = config.data.ch1_fpath_list[:1]\n", + " config.data.mix_fpath_list = config.data.mix_fpath_list[:1]\n", + " if config.data.data_type == DataType.Pavia2VanillaSplitting:\n", + " if 'channel_2_downscale_factor' not in config.data:\n", + " config.data.channel_2_downscale_factor = 1\n", + " if config.model.model_type == ModelType.UNet and 'init_channel_count' not in config.model:\n", + " config.model.init_channel_count = 64\n", + " \n", + " if 'skip_receptive_field_loss_tokens' not in config.loss:\n", + " config.loss.skip_receptive_field_loss_tokens = []\n", + " \n", + " if dtype == DataType.HTIba1Ki67:\n", + " config.data.subdset_type = SubDsetType.Iba1Ki64\n", + " config.data.empty_patch_replacement_enabled = False\n", + " \n", + " if 'lowres_merge_type' not in config.model.encoder:\n", + " config.model.encoder.lowres_merge_type = 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e561d018", + "metadata": {}, + "outputs": [], + "source": [ + "if denoise_channel is None:\n", + " denoise_channel = config.model.denoise_channel \n", + " print(f\"denoise_channel: {denoise_channel}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "edde2155", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/disentangle_setup.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "53df96f2", + "metadata": {}, + "outputs": [], + "source": [ + "len(train_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60d5fc4a", + "metadata": {}, + "outputs": [], + "source": [ + "if config.data.multiscale_lowres_count is not None and custom_image_size is not None:\n", + " model.reset_for_different_output_size(custom_image_size)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11cf6c69", + "metadata": {}, + "outputs": [], + "source": [ + "# if config.model.model_type not in [ModelType.UNet, ModelType.BraveNet]:\n", + "# with torch.no_grad():\n", + "# inp, tar = val_dset[0][:2]\n", + "# out, td_data = model(torch.Tensor(inp[None]).cuda())\n", + "# print(td_data['z'][-1].shape)\n", + "# print(out.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d05be428", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(val_dset))\n", + "inp_tmp, tar_tmp, *_ = val_dset[idx]\n", + "ncols = max(len(inp_tmp),3)\n", + "nrows = 2\n", + "_,ax = plt.subplots(figsize=(4*ncols,4*nrows),ncols=ncols,nrows=nrows)\n", + "for i in range(len(inp_tmp)):\n", + " ax[0,i].imshow(inp_tmp[i])\n", + "\n", + "ax[1,0].imshow(tar_tmp[0]+tar_tmp[1])\n", + "ax[1,1].imshow(tar_tmp[0])\n", + "ax[1,2].imshow(tar_tmp[1])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cac092b5", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitch_predictions\n", + "from denoisplit.analysis.mmse_prediction import get_dset_predictions\n", + "# from denoisplit.analysis.stitch_prediction import get_predictions as get_dset_predictions\n", + "\n", + "pred_tiled, rec_loss, logvar, patch_psnr_tuple, pred_std_tiled = get_dset_predictions(model, val_dset,batch_size,\n", + " num_workers=num_workers,\n", + " mmse_count=mmse_count,\n", + " model_type = config.model.model_type,\n", + " )\n", + "assert patch_psnr_tuple[1] is None\n", + "print('Patch wise PSNR, as computed during training', np.round(patch_psnr_tuple[0].item(),2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "535169c1", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b693a0c", + "metadata": {}, + "outputs": [], + "source": [ + "idx_list = np.where(logvar.squeeze() < -6)[0]\n", + "if len(idx_list) > 0:\n", + " plt.imshow(val_dset[idx_list[0]][1][1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8a1573f8", + "metadata": {}, + "outputs": [], + "source": [ + "len(val_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f74f286c", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow((val_dset._data[0,...,1] + val_dset._data[0,...,0])/2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6709de9e", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "sns.histplot(logvar[::50].squeeze().reshape(-1,))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "771ac350", + "metadata": {}, + "outputs": [], + "source": [ + "print(np.quantile(rec_loss, [0,0.01,0.5, 0.9,0.99,0.999,1]).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05f2cdc7", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8673355b", + "metadata": {}, + "outputs": [], + "source": [ + "len(val_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c75b35f1", + "metadata": {}, + "outputs": [], + "source": [ + "if pred_tiled.shape[-1] != val_dset.get_img_sz():\n", + " pad = (val_dset.get_img_sz() - pred_tiled.shape[-1] )//2\n", + " pred_tiled = np.pad(pred_tiled, ((0,0),(0,0),(pad,pad),(pad,pad)))\n", + "\n", + "pred = stitch_predictions(pred_tiled,val_dset, smoothening_pixelcount=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f950003b", + "metadata": {}, + "outputs": [], + "source": [ + "if pred.shape[-1] != pred_tiled.shape[1]:\n", + " assert pred.shape[-1] == 1 + pred_tiled.shape[1]\n", + " assert pred[...,-1].std() == 0\n", + " pred = pred[...,:-1].copy()\n", + " # pred_std = pred_std[...,:-1].copy()\n", + " if logvar is not None:\n", + " logvar = logvar[...,:-1].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b09091e3", + "metadata": {}, + "outputs": [], + "source": [ + "pred.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dba3753f", + "metadata": {}, + "outputs": [], + "source": [ + "pred[np.isnan(pred)] = 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d2ad25d", + "metadata": {}, + "outputs": [], + "source": [ + "def print_ignored_pixels():\n", + " ignored_pixels = 1\n", + " while(pred[:10,-ignored_pixels:,-ignored_pixels:,].std() ==0):\n", + " ignored_pixels+=1\n", + " ignored_pixels-=1\n", + " print(f'In {pred.shape}, last {ignored_pixels} many rows and columns are all zero.')\n", + " return ignored_pixels\n", + "\n", + "actual_ignored_pixels = print_ignored_pixels()" + ] + }, + { + "cell_type": "markdown", + "id": "b8474735", + "metadata": {}, + "source": [ + "## Ignore the pixels which are present in the last few rows and columns. \n", + "1. They don't come in the batches. So, in prediction, they are simply zeros. So they are being are ignored right now. \n", + "2. For the border pixels which are on the top and the left, overlapping yields worse performance. This is becuase, there is nothing to overlap on one side. So, they are essentially zero padded. This makes the performance worse. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcb2db09", + "metadata": {}, + "outputs": [], + "source": [ + "actual_ignored_pixels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cadedfcd", + "metadata": {}, + "outputs": [], + "source": [ + "if config.data.data_type in [DataType.OptiMEM100_014,\n", + " DataType.SemiSupBloodVesselsEMBL, \n", + " DataType.Pavia2VanillaSplitting,\n", + " DataType.ExpansionMicroscopyMitoTub,\n", + " DataType.ShroffMitoEr,\n", + " DataType.HTIba1Ki67]:\n", + " ignored_last_pixels = 32 \n", + "elif config.data.data_type == DataType.BioSR_MRC:\n", + " ignored_last_pixels = 44\n", + " # assert val_dset.get_img_sz() == 64\n", + "else:\n", + " ignored_last_pixels = 0\n", + "\n", + "ignore_first_pixels = 0\n", + "\n", + "assert actual_ignored_pixels <= ignored_last_pixels, f'Set ignored_last_pixels={actual_ignored_pixels}'\n", + "print(ignored_last_pixels)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "226fed05", + "metadata": {}, + "outputs": [], + "source": [ + "if model.denoise_channel == 'Ch1':\n", + " tar = val_dset._data[...,:1]\n", + "elif model.denoise_channel == 'Ch2':\n", + " tar = val_dset._data[...,1:]\n", + "elif model.denoise_channel == 'input':\n", + " tar = np.mean(val_dset._data, axis=-1, keepdims=True)\n", + " \n", + "\n", + "def ignore_pixels(arr):\n", + " if ignore_first_pixels:\n", + " arr = arr[:,ignore_first_pixels:,ignore_first_pixels:]\n", + " if ignored_last_pixels:\n", + " arr = arr[:,:-ignored_last_pixels,:-ignored_last_pixels]\n", + " return arr\n", + "\n", + "pred = ignore_pixels(pred)\n", + "tar = ignore_pixels(tar)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d8b680f", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.metrics import structural_similarity\n", + "\n", + "def _avg_psnr(target, prediction, psnr_fn):\n", + " output = np.mean([psnr_fn(target[i:i + 1], prediction[i:i + 1]).item() for i in range(len(prediction))])\n", + " return round(output, 2)\n", + "\n", + "\n", + "def avg_range_inv_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, RangeInvariantPsnr)\n", + "\n", + "\n", + "def avg_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, PSNR)\n", + "\n", + "\n", + "def compute_masked_psnr(mask, tar1, tar2, pred1, pred2):\n", + " mask = mask.astype(bool)\n", + " mask = mask[..., 0]\n", + " tmp_tar1 = tar1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_pred1 = pred1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_tar2 = tar2[mask].reshape((len(tar2), -1, 1))\n", + " tmp_pred2 = pred2[mask].reshape((len(tar2), -1, 1))\n", + " psnr1 = avg_range_inv_psnr(tmp_tar1, tmp_pred1)\n", + " psnr2 = avg_range_inv_psnr(tmp_tar2, tmp_pred2)\n", + " return psnr1, psnr2\n", + "\n", + "def avg_ssim(target, prediction):\n", + " ssim = [structural_similarity(target[i],prediction[i], data_range=(target[i].max() - target[i].min())) for i in range(len(target))]\n", + " return np.mean(ssim),np.std(ssim)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7311e08a", + "metadata": {}, + "outputs": [], + "source": [ + "sep_mean, sep_std = model.data_mean, model.data_std\n", + "if isinstance(sep_mean, dict):\n", + " sep_mean = sep_mean['target']\n", + " sep_std = sep_std['target']\n", + "\n", + "if isinstance(sep_mean, int):\n", + " pass\n", + "else:\n", + " sep_mean = sep_mean.squeeze()[None,None,None]\n", + " sep_std = sep_std.squeeze()[None,None,None]\n", + " sep_mean = sep_mean.cpu().numpy() \n", + " sep_std = sep_std.cpu().numpy()\n", + "\n", + "tar_normalized = (tar - sep_mean)/ sep_std" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2402048", + "metadata": {}, + "outputs": [], + "source": [ + "q_vals = [0.01, 0.1,0.5,0.9,0.95, 0.99,1]\n", + "print(np.quantile(tar_normalized[...,0], q_vals).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c445e50", + "metadata": {}, + "outputs": [], + "source": [ + "print(np.quantile(tar[...,0], q_vals))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fef4512", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(6,6))\n", + "# sns.histplot(tar[:,...,0].reshape(-1,), color='g', label='Nuc')\n", + "# sns.histplot(tar[:,...,1].reshape(-1,), color='r', label='Tub')\n", + "\n", + "sns.histplot(tar[:,::10,::10,0].reshape(-1,), color='g', kde=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb572707", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.data_loader.schroff_rawdata_loader import mito_channel_fnames\n", + "# from denoisplit.core.tiff_reader import load_tiff\n", + "# import seaborn as sns\n", + "\n", + "# fpaths = [os.path.join(datapath, x) for x in mito_channel_fnames()]\n", + "# fpath = fpaths[0]\n", + "# print(fpath)\n", + "# img = load_tiff(fpaths[0])\n", + "# temp = img.copy()\n", + "# sns.histplot(temp[:,:,::10,::10].reshape(-1,))\n", + "# plt.hist(temp[:,:,::10,::10].reshape(-1,),bins=100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24708c4c", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.patches as patches\n", + "import matplotlib\n", + "from denoisplit.analysis.plot_error_utils import plot_error\n", + "\n", + "_,ax = plt.subplots(figsize=(12,8),ncols=3,nrows=2)\n", + "idx = np.random.randint(len(pred))\n", + "print(idx)\n", + "ax[0,0].imshow(tar_normalized[idx,...,0], cmap='magma')\n", + "ax[0,1].imshow(pred[idx,:,:,0], cmap='magma')\n", + "plot_error(tar_normalized[idx,...,0], \n", + " pred[idx,:,:,0], \n", + " cmap = matplotlib.cm.coolwarm, \n", + " ax = ax[0,2], max_val = None)\n", + "\n", + "cropsz = 512\n", + "h_s = np.random.randint(0, tar_normalized.shape[1] - cropsz)\n", + "h_e = h_s + cropsz\n", + "w_s = np.random.randint(0, tar_normalized.shape[2] - cropsz)\n", + "w_e = w_s + cropsz\n", + "\n", + "ax[1,0].imshow(tar_normalized[idx,h_s:h_e,w_s:w_e,0], cmap='magma')\n", + "ax[1,1].imshow(pred[idx,h_s:h_e,w_s:w_e,0], cmap='magma')\n", + "plot_error(tar_normalized[idx,h_s:h_e,w_s:w_e,0], \n", + " pred[idx,h_s:h_e,w_s:w_e,0], \n", + " cmap = matplotlib.cm.coolwarm, \n", + " ax = ax[1,2], max_val = None)\n", + "\n", + "\n", + "\n", + "clean_ax(ax[0,3:])\n", + "\n", + "# Add rectangle to the region\n", + "rect = patches.Rectangle((w_s, h_s), w_e-w_s, h_e-h_s, linewidth=1, edgecolor='r', facecolor='none')\n", + "ax[0,2].add_patch(rect)\n", + "# plt.colorbar()\n", + "pred.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "919db5ef", + "metadata": {}, + "outputs": [], + "source": [ + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "pred_unnorm = pred*sep_std + sep_mean" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba97879b", + "metadata": {}, + "outputs": [], + "source": [ + "np.sqrt(((pred[...,:1] - tar_normalized)**2).reshape(len(pred),-1).mean(axis=1)).mean()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "87cd2195", + "metadata": {}, + "outputs": [], + "source": [ + "print(sep_mean.squeeze(), sep_std.squeeze(), pred.shape )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6cae730", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0380d737", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13fc1983", + "metadata": {}, + "outputs": [], + "source": [ + "assert pred.shape == tar_normalized.shape, f\"pred.shape: {pred.shape}, tar_normalized.shape: {tar_normalized.shape}\"\n", + "rmse =np.sqrt(((pred - tar_normalized)**2).reshape(len(pred),-1).mean(axis=1))\n", + "rmse = np.round(rmse,3)\n", + "psnr = avg_psnr(tar_normalized[...,0].copy(), pred[...,0].copy()) \n", + "rinv_psnr = avg_range_inv_psnr(tar_normalized[...,0].copy(), pred[...,0].copy())\n", + "ssim_mean, ssim_std = avg_ssim(tar[...,0], pred_unnorm[...,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e87868b7", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + "print('Rec Loss',model.denoise_channel, np.round(rec_loss.mean(),3) )\n", + "print('RMSE', model.denoise_channel, np.mean(rmse).round(3))\n", + "print('PSNR',model.denoise_channel, psnr)\n", + "print('RangeInvPSNR',model.denoise_channel, rinv_psnr)\n", + "print('SSIM',model.denoise_channel, round(ssim_mean,3),'±',round(ssim_std,4))\n", + "print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3f83ed9", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.scripts.evaluate import * \n", + "highres_data = None\n", + "\n", + "if config.model.model_type == ModelType.DenoiserSplitter or config.data.data_type == DataType.SeparateTiffData:\n", + " from denoisplit.scripts.evaluate import get_highres_data_ventura\n", + " highres_data = get_highres_data_ventura(data_dir, config, eval_datasplit_type)\n", + "elif 'synthetic_gaussian_scale' in config.data or 'enable_poisson_noise' in config.data:\n", + " highres_data = get_data_without_synthetic_noise(data_dir, config, eval_datasplit_type)\n", + "\n", + "if highres_data is not None:\n", + " highres_data = ignore_pixels(highres_data).copy()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "59e53f64", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + "print('PSNR on Highres', model.denoise_channel, avg_range_inv_psnr(highres_data[...,0], pred_unnorm[...,0]))\n", + "ssim_hres_mean, ssim_hres_std = avg_ssim(highres_data[...,0], pred_unnorm[...,0])\n", + "print('SSIM on Highres', model.denoise_channel, np.round(ssim_hres_mean,3), '±', np.round(ssim_hres_std,3))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0cf9e03c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(12,8),ncols=3,nrows=2)\n", + "idx = np.random.randint(len(pred))\n", + "print(idx)\n", + "ax[0,0].imshow(tar_normalized[idx,...,0], cmap='magma')\n", + "ax[0,1].imshow(highres_data[idx,...,0], cmap='magma')\n", + "ax[0,2].imshow(pred_unnorm[idx,...,0], cmap='magma')\n", + "cropsz = 512\n", + "h_s = np.random.randint(0, tar_normalized.shape[1] - cropsz)\n", + "h_e = h_s + cropsz\n", + "w_s = np.random.randint(0, tar_normalized.shape[2] - cropsz)\n", + "w_e = w_s + cropsz\n", + "\n", + "ax[1,0].imshow(tar_normalized[idx,h_s:h_e,w_s:w_e,0], cmap='magma')\n", + "ax[1,1].imshow(highres_data[idx,h_s:h_e,w_s:w_e,0], cmap='magma')\n", + "ax[1,2].imshow(pred_unnorm[idx,h_s:h_e,w_s:w_e,0], cmap='magma')\n", + "# Add rectangle to the region\n", + "rect = patches.Rectangle((w_s, h_s), w_e-w_s, h_e-h_s, linewidth=1, edgecolor='r', facecolor='none')\n", + "ax[0,0].add_patch(rect)\n" + ] + }, + { + "cell_type": "markdown", + "id": "f19442f1", + "metadata": {}, + "source": [ + "### To save to tiff file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "236b29f6", + "metadata": {}, + "outputs": [], + "source": [ + "def get_noise_str():\n", + " noise_str = ''\n", + " if 'synthetic_gaussian_scale' in config.data:\n", + " noise_str = f'_N{config.data.synthetic_gaussian_scale}'\n", + " if 'poisson_noise_factor' in config.data and config.data.poisson_noise_factor is not None and config.data.poisson_noise_factor > 0:\n", + " noise_str += f'_P{config.data.poisson_noise_factor}'\n", + " \n", + " return noise_str\n", + "\n", + "def get_model_str():\n", + " tokens = ckpt_dir.split('/')\n", + " tokens.remove('')\n", + " return '-'.join([x.replace('-','') for x in tokens[-3:]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6422675", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import save_tiff\n", + "from denoisplit.core.data_split_type import DataSplitType\n", + "\n", + "assert pred_unnorm[...,0].std() > pred_unnorm[...,1].std()\n", + "denoised_pred = pred_unnorm[...,0].copy()\n", + "denoised_pred[denoised_pred<0] = 0\n", + "denoised_pred = denoised_pred.astype(np.uint16)\n", + "if denoise_channel == 'Ch1':\n", + " fname = config.data.ch1_fname\n", + "elif denoise_channel == 'Ch2':\n", + " fname = config.data.ch2_fname\n", + "elif denoise_channel == 'input':\n", + " fname = 'input.tif'\n", + "fname = f'{DataSplitType.name(eval_datasplit_type)}Data_{get_model_str()}{get_noise_str()}_{fname}'\n", + "output_fpath = os.path.join(save_output_dir,fname)\n", + "print(output_fpath)\n", + "save_tiff(output_fpath, denoised_pred)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7632071e", + "metadata": {}, + "outputs": [], + "source": [ + "!ls -lhrt \"$output_fpath\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5acde8f1", + "metadata": {}, + "outputs": [], + "source": [ + "d = load_tiff(output_fpath)\n", + "plt.imshow(d[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "80e6d844", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/Denoiser_Splitter.ipynb b/denoisplit/notebooks/Denoiser_Splitter.ipynb new file mode 100644 index 0000000..ce41997 --- /dev/null +++ b/denoisplit/notebooks/Denoiser_Splitter.ipynb @@ -0,0 +1,2175 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "19844352", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad91cc2b", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "# os.environ[\"CUDA_DEVICE_ORDER\"]=\"PCI_BUS_ID\" # see issue #152\n", + "# os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"2\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dcd3d0c2", + "metadata": {}, + "outputs": [], + "source": [ + "# there are two environments(debug and prod). From where you want to fetch the code and data? \n", + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27ec4422", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "db8d89b5", + "metadata": {}, + "outputs": [], + "source": [ + "# 'stats_'+'_'.join(ckpt_dir.split('/')[-4:]) + '.pkl'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a9748a9", + "metadata": {}, + "outputs": [], + "source": [ + "ckpt_dir = \"/home/ashesh.ashesh/training/disentangle/2403/D23-M3-S0-L0/28\"\n", + "# gnode01/2403/D23-M3-S0-L0/29\"\n", + "# save the results also for the following ckpt_dirs\n", + "# '/home/ashesh.ashesh/training/disentangle/2403/D23-M3-S0-L0/0', => /group/jug/ashesh/data/paper_stats/Test_PNone_G32_M10_Sk0/pred_disentangle_2403_D23-M3-S0-L0_0.tif\n", + "# '/home/ashesh.ashesh/training/disentangle/2403/D23-M3-S0-L0/15', => Written (5, 960, 960, 2) to /group/jug/ashesh/data/paper_stats/Test_PNone_G32_M10_Sk0/pred_disentangle_2403_D23-M3-S0-L0_15.tif\n", + "# '/home/ashesh.ashesh/training/disentangle/2403/D23-M3-S0-L0/22', => Written (5, 960, 960, 2) to /group/jug/ashesh/data/paper_stats/Test_PNone_G32_M10_Sk0/pred_disentangle_2403_D23-M3-S0-L0_22.tif\n", + "# '/home/ashesh.ashesh/training/disentangle/2403/D23-M3-S0-L0/0',\n", + "# '/home/ashesh.ashesh/training/disentangle/2402/D23-M3-S0-L0/59', => Written (5, 960, 960, 2) to /group/jug/ashesh/data/paper_stats/Test_PNone_G32_M10_Sk0/pred_disentangle_2402_D23-M3-S0-L0_59.tif\n", + "# '/home/ashesh.ashesh/training/disentangle/2402/D23-M3-S0-L0/60', => Written (5, 960, 960, 2) to /group/jug/ashesh/data/paper_stats/Test_PNone_G32_M10_Sk0/pred_disentangle_2402_D23-M3-S0-L0_60.tif\n", + "# '/home/ashesh.ashesh/training/disentangle/2402/D23-M3-S0-L0/67', => Written (5, 960, 960, 2) to /group/jug/ashesh/data/paper_stats/Test_PNone_G32_M10_Sk0/pred_disentangle_2402_D23-M3-S0-L0_67.tif\n", + "\n", + "assert os.path.exists(ckpt_dir)\n", + "# 211/D3-M3-S0-L0/0\n", + "# 2210/D3-M3-S0-L0/128\n", + "# 2210/D3-M3-S0-L0/129" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27410ddc", + "metadata": {}, + "outputs": [], + "source": [ + "# !ls /home/ubuntu/ashesh/training/disentangle/2209/D3-M9-S0-L0/1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c383d367", + "metadata": {}, + "outputs": [], + "source": [ + "def get_dtype(ckpt_fpath):\n", + " if os.path.isdir(ckpt_fpath):\n", + " ckpt_fpath = ckpt_fpath[:-1] if ckpt_fpath[-1] == '/' else ckpt_fpath\n", + " elif os.path.isfile(ckpt_fpath):\n", + " ckpt_fpath = os.path.dirname(ckpt_fpath)\n", + " assert ckpt_fpath[-1] != '/'\n", + " return int(ckpt_fpath.split('/')[-2].split('-')[0][1:])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7232e05", + "metadata": {}, + "outputs": [], + "source": [ + "dtype = get_dtype(ckpt_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90109e80", + "metadata": {}, + "outputs": [], + "source": [ + "dtype" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b237569", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "image_size_for_grid_centers = 64\n", + "mmse_count = 5\n", + "custom_image_size = None\n", + "data_t_list = None #[0]\n", + "\n", + "\n", + "batch_size = 8\n", + "num_workers = 4\n", + "COMPUTE_LOSS = False\n", + "use_deterministic_grid = None\n", + "threshold = None # 0.02\n", + "compute_kl_loss = False\n", + "evaluate_train = False# inspect training performance\n", + "eval_datasplit_type = DataSplitType.Test\n", + "val_repeat_factor = None\n", + "psnr_type = 'range_invariant' #'simple', 'range_invariant'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f889dd2d", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/config_loader.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a0047fe", + "metadata": {}, + "outputs": [], + "source": [ + "tokens = ckpt_dir.split('/')\n", + "idx = tokens.index('disentangle')\n", + "if config.model.model_type == 25 and tokens[idx+1] == '2312':\n", + " config.model.model_type = ModelType.LadderVAERestrictedReconstruction" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc8a3fed", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.sampler_type import SamplerType\n", + "from denoisplit.core.loss_type import LossType\n", + "from denoisplit.data_loader.ht_iba1_ki67_rawdata_loader import SubDsetType\n", + "# from denoisplit.core.lowres_merge_type import LowresMergeType\n", + "\n", + "\n", + "with config.unlocked():\n", + " config.model.skip_nboundary_pixels_from_loss = None\n", + " if config.model.model_type == ModelType.UNet and 'n_levels' not in config.model:\n", + " config.model.n_levels = 4\n", + " if config.data.sampler_type == SamplerType.NeighborSampler:\n", + " config.data.sampler_type = SamplerType.DefaultSampler\n", + " config.loss.loss_type = LossType.Elbo\n", + " config.data.grid_size = config.data.image_size\n", + " if 'ch1_fpath_list' in config.data:\n", + " config.data.ch1_fpath_list = config.data.ch1_fpath_list[:1]\n", + " config.data.mix_fpath_list = config.data.mix_fpath_list[:1]\n", + " if config.data.data_type == DataType.Pavia2VanillaSplitting:\n", + " if 'channel_2_downscale_factor' not in config.data:\n", + " config.data.channel_2_downscale_factor = 1\n", + " if config.model.model_type == ModelType.UNet and 'init_channel_count' not in config.model:\n", + " config.model.init_channel_count = 64\n", + " \n", + " if 'skip_receptive_field_loss_tokens' not in config.loss:\n", + " config.loss.skip_receptive_field_loss_tokens = []\n", + " \n", + " if dtype == DataType.HTIba1Ki67:\n", + " config.data.subdset_type = SubDsetType.Iba1Ki64\n", + " config.data.empty_patch_replacement_enabled = False\n", + " \n", + " if 'lowres_merge_type' not in config.model.encoder:\n", + " config.model.encoder.lowres_merge_type = 0\n", + " if 'validtarget_random_fraction' in config.data:\n", + " config.data.validtarget_random_fraction = None\n", + " \n", + " if config.data.data_type == DataType.TwoDset:\n", + " config.model.model_type = ModelType.LadderVae\n", + " for key in config.data.dset1:\n", + " config.data[key] = config.data.dset1[key]\n", + " if 'dump_kth_frame_prediction' in config.training:\n", + " config.training.dump_kth_frame_prediction = None\n", + "\n", + " if 'input_is_sum' not in config.data:\n", + " config.data.input_is_sum = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a03b40f4", + "metadata": {}, + "outputs": [], + "source": [ + "# config.data.channel_1 = 0 \n", + "# config.data.channel_2 = 3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ef646b2", + "metadata": {}, + "outputs": [], + "source": [ + "dtype = config.data.data_type\n", + "\n", + "if DEBUG:\n", + " if dtype == DataType.CustomSinosoid:\n", + " data_dir = f'{DATA_ROOT}/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + "else:\n", + " if dtype in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " data_dir = f'{DATA_ROOT}/sinosoid_without_test/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + " elif dtype == DataType.Prevedel_EMBL:\n", + " data_dir = f'{DATA_ROOT}/Prevedel_EMBL/PKG_3P_dualcolor_stacks/NoAverage_NoRegistration/'\n", + " elif dtype == DataType.AllenCellMito:\n", + " data_dir = f'{DATA_ROOT}/allencell/2017_03_08_Struct_First_Pass_Seg/AICS-11/'\n", + " elif dtype == DataType.SeparateTiffData:\n", + " data_dir = f'{DATA_ROOT}/ventura_gigascience'\n", + " elif dtype == DataType.SemiSupBloodVesselsEMBL:\n", + " data_dir = f'{DATA_ROOT}/EMBL_halfsupervised/Demixing_3P'\n", + " elif dtype == DataType.Pavia2VanillaSplitting:\n", + " data_dir = f'{DATA_ROOT}/pavia2'\n", + " elif dtype == DataType.ExpansionMicroscopyMitoTub:\n", + " data_dir = f'{DATA_ROOT}/expansion_microscopy_Nick/'\n", + " elif dtype == DataType.ShroffMitoEr:\n", + " data_dir = f'{DATA_ROOT}/shrofflab/'\n", + " elif dtype == DataType.HTIba1Ki67:\n", + " data_dir = f'{DATA_ROOT}/Stefania/20230327_Ki67_and_Iba1_trainingdata/'\n", + " elif dtype == DataType.BioSR_MRC:\n", + " data_dir = f'{DATA_ROOT}/BioSR/'\n", + " elif dtype == DataType.ExpMicroscopyV2:\n", + " data_dir = f'{DATA_ROOT}/expansion_microscopy_v2/'\n", + " elif dtype == DataType.TavernaSox2GolgiV2:\n", + " data_dir = f'{DATA_ROOT}/TavernaSox2Golgi/acquisition2/'\n", + " elif dtype == DataType.PredictedTiffData:\n", + " # data_dir = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk44/'\n", + " data_dir = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk32'\n", + " # data_dir = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk0'\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "edde2155", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/disentangle_setup.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1aaf1dfe", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(12,4),ncols=3)\n", + "ax[0].imshow(val_dset._data[0,...,0])\n", + "ax[1].imshow(val_dset._data[0,...,1])\n", + "ax[2].imshow(val_dset._data[0,...,2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc596262", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ccf8460a", + "metadata": {}, + "outputs": [], + "source": [ + "if image_size_for_grid_centers is not None:\n", + " assert image_size_for_grid_centers == val_dset._grid_sz" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60d5fc4a", + "metadata": {}, + "outputs": [], + "source": [ + "if config.data.multiscale_lowres_count is not None and custom_image_size is not None:\n", + " model.reset_for_different_output_size(custom_image_size)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11cf6c69", + "metadata": {}, + "outputs": [], + "source": [ + "# if config.model.model_type not in [ModelType.UNet, ModelType.BraveNet]:\n", + "# with torch.no_grad():\n", + "# inp, tar = val_dset[0][:2]\n", + "# out, td_data = model(torch.Tensor(inp[None]).cuda())\n", + "# print(td_data['z'][-1].shape)\n", + "# print(out.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d05be428", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(val_dset))\n", + "inp_tmp, tar_tmp, *_ = val_dset[idx]\n", + "ncols = len(tar_tmp)\n", + "nrows = 2\n", + "_,ax = plt.subplots(figsize=(4*ncols,4*nrows),ncols=ncols,nrows=nrows)\n", + "for i in range(min(ncols,len(inp_tmp))):\n", + " ax[0,i].imshow(inp_tmp[i])\n", + "\n", + "for channel_id in range(ncols):\n", + " ax[1,channel_id].imshow(tar_tmp[channel_id])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eece008c", + "metadata": {}, + "outputs": [], + "source": [ + "if data_t_list is not None:\n", + " val_dset.reduce_data(t_list=data_t_list)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cac092b5", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitch_predictions\n", + "from denoisplit.analysis.mmse_prediction import get_dset_predictions\n", + "# from denoisplit.analysis.stitch_prediction import get_predictions as get_dset_predictions\n", + "\n", + "pred_tiled, rec_loss, logvar_tiled, patch_psnr_tuple, pred_std_tiled = get_dset_predictions(model, \n", + " val_dset,\n", + " batch_size,\n", + " num_workers=num_workers,\n", + " mmse_count=mmse_count,\n", + " model_type = config.model.model_type)\n", + "tmp = np.round([x.item() for x in patch_psnr_tuple],2)\n", + "print('Patch wise PSNR, as computed during training', tmp,np.mean(tmp))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b693a0c", + "metadata": {}, + "outputs": [], + "source": [ + "idx_list = np.where(logvar_tiled.squeeze() < -6)[0]\n", + "if len(idx_list) > 0:\n", + " plt.imshow(val_dset[idx_list[0]][1][1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8a1573f8", + "metadata": {}, + "outputs": [], + "source": [ + "len(val_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6709de9e", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "sns.histplot(logvar_tiled[::50].squeeze().reshape(-1,))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "771ac350", + "metadata": {}, + "outputs": [], + "source": [ + "print(np.quantile(rec_loss, [0,0.01,0.5, 0.9,0.99,0.999,1]).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05f2cdc7", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8673355b", + "metadata": {}, + "outputs": [], + "source": [ + "logvar_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c75b35f1", + "metadata": {}, + "outputs": [], + "source": [ + "if pred_tiled.shape[-1] != val_dset.get_img_sz():\n", + " pad = (val_dset.get_img_sz() - pred_tiled.shape[-1] )//2\n", + " pred_tiled = np.pad(pred_tiled, ((0,0),(0,0),(pad,pad),(pad,pad)))\n", + "\n", + "pred = stitch_predictions(pred_tiled,val_dset, smoothening_pixelcount=0)\n", + "if len(np.unique(logvar_tiled)) == 1:\n", + " logvar = None\n", + "else:\n", + " logvar = stitch_predictions(logvar_tiled,val_dset, smoothening_pixelcount=0)\n", + "pred_std = stitch_predictions(pred_std_tiled,val_dset, smoothening_pixelcount=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb67522d", + "metadata": {}, + "outputs": [], + "source": [ + "if pred.shape[-1] != pred_tiled.shape[1]:\n", + " assert pred.shape[-1] == 1 + pred_tiled.shape[1]\n", + " assert pred[...,-1].std() == 0\n", + " pred = pred[...,:-1].copy()\n", + " pred_std = pred_std[...,:-1].copy()\n", + " if logvar is not None:\n", + " logvar = logvar[...,:-1].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c6c82f7", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(pred[0,...,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f950003b", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d2ad25d", + "metadata": {}, + "outputs": [], + "source": [ + "def print_ignored_pixels():\n", + " ignored_pixels = 1\n", + " while(pred[0,-ignored_pixels:,-ignored_pixels:,].std() ==0):\n", + " ignored_pixels+=1\n", + " ignored_pixels-=1\n", + " print(f'In {pred.shape}, last {ignored_pixels} many rows and columns are all zero.')\n", + " return ignored_pixels\n", + "\n", + "actual_ignored_pixels = print_ignored_pixels()" + ] + }, + { + "cell_type": "markdown", + "id": "b8474735", + "metadata": {}, + "source": [ + "## Ignore the pixels which are present in the last few rows and columns. \n", + "1. They don't come in the batches. So, in prediction, they are simply zeros. So they are being are ignored right now. \n", + "2. For the border pixels which are on the top and the left, overlapping yields worse performance. This is becuase, there is nothing to overlap on one side. So, they are essentially zero padded. This makes the performance worse. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcb2db09", + "metadata": {}, + "outputs": [], + "source": [ + "actual_ignored_pixels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cadedfcd", + "metadata": {}, + "outputs": [], + "source": [ + "if config.data.data_type in [DataType.OptiMEM100_014,\n", + " DataType.SemiSupBloodVesselsEMBL, \n", + " DataType.Pavia2VanillaSplitting,\n", + " DataType.ExpansionMicroscopyMitoTub,\n", + " DataType.ShroffMitoEr,\n", + " DataType.HTIba1Ki67]:\n", + " ignored_last_pixels = 32 \n", + "elif config.data.data_type == DataType.BioSR_MRC:\n", + " ignored_last_pixels = 44\n", + " # assert val_dset.get_img_sz() == 64\n", + " # ignored_last_pixels = 108\n", + "else:\n", + " ignored_last_pixels = 0\n", + "\n", + "ignore_first_pixels = 0\n", + "# ignored_last_pixels = 160\n", + "assert actual_ignored_pixels <= ignored_last_pixels, f'Set ignored_last_pixels={actual_ignored_pixels}'\n", + "print(ignored_last_pixels)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "226fed05", + "metadata": {}, + "outputs": [], + "source": [ + "# NOTE: This is different from the normal setup. here , we have an input channel and therefore we are ignoring it.\n", + "tar = val_dset._data[...,1:]\n", + "\n", + "def ignore_pixels(arr):\n", + " if ignore_first_pixels:\n", + " arr = arr[:,ignore_first_pixels:,ignore_first_pixels:]\n", + " if ignored_last_pixels:\n", + " arr = arr[:,:-ignored_last_pixels,:-ignored_last_pixels]\n", + " return arr\n", + "\n", + "pred = ignore_pixels(pred)\n", + "tar = ignore_pixels(tar)\n", + "if pred_std is not None:\n", + " pred_std = ignore_pixels(pred_std)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d8b680f", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.metrics import structural_similarity\n", + "\n", + "def _avg_psnr(target, prediction, psnr_fn):\n", + " output = np.mean([psnr_fn(target[i:i + 1], prediction[i:i + 1]).item() for i in range(len(prediction))])\n", + " return round(output, 2)\n", + "\n", + "\n", + "def avg_range_inv_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, RangeInvariantPsnr)\n", + "\n", + "\n", + "def avg_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, PSNR)\n", + "\n", + "\n", + "def compute_masked_psnr(mask, tar1, tar2, pred1, pred2):\n", + " mask = mask.astype(bool)\n", + " mask = mask[..., 0]\n", + " tmp_tar1 = tar1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_pred1 = pred1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_tar2 = tar2[mask].reshape((len(tar2), -1, 1))\n", + " tmp_pred2 = pred2[mask].reshape((len(tar2), -1, 1))\n", + " psnr1 = avg_range_inv_psnr(tmp_tar1, tmp_pred1)\n", + " psnr2 = avg_range_inv_psnr(tmp_tar2, tmp_pred2)\n", + " return psnr1, psnr2\n", + "\n", + "def avg_ssim(target, prediction):\n", + " ssim = [structural_similarity(target[i],prediction[i], data_range=(target[i].max() - target[i].min())) for i in range(len(target))]\n", + " return np.mean(ssim),np.std(ssim)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3991627e", + "metadata": {}, + "outputs": [], + "source": [ + "model.data_std" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c458acb8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7311e08a", + "metadata": {}, + "outputs": [], + "source": [ + "sep_mean, sep_std = model.data_mean, model.data_std\n", + "if isinstance(sep_mean, dict):\n", + " sep_mean = sep_mean['target']\n", + " sep_std = sep_std['target']\n", + "\n", + "if isinstance(sep_mean, int):\n", + " pass\n", + "else:\n", + " sep_mean = sep_mean.squeeze()[None,None,None]\n", + " sep_std = sep_std.squeeze()[None,None,None]\n", + " sep_mean = sep_mean.cpu().numpy() \n", + " sep_std = sep_std.cpu().numpy()\n", + "\n", + "tar_normalized = (tar - sep_mean)/ sep_std" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b31cd6c4", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.metrics.calibration import Calibration\n", + "\n", + "# calib = Calibration(num_bins=30, mode='pixelwise')\n", + "# # stats = calib.compute_stats(pred, logvar, tar_normalized)\n", + "# stats = calib.compute_stats(pred, pred_std, tar_normalized)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "199313d1", + "metadata": {}, + "outputs": [], + "source": [ + "# count = np.array(stats[0]['bin_count'])\n", + "# count = count / count.sum()\n", + "# count.cumsum()[:-1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f14f56d", + "metadata": {}, + "outputs": [], + "source": [ + "# import seaborn as sns\n", + "# import matplotlib.pyplot as plt\n", + "# _,ax = plt.subplots(figsize=(15,5),ncols=3,nrows=1)\n", + "# idx = -1\n", + "# highend = stats[0]['bin_matrix'][idx] > 20\n", + "# sns.heatmap(highend, cmap='hot', ax=ax[0])\n", + "# sns.heatmap(stats[1]['bin_matrix'][idx], cmap='hot', ax=ax[1])\n", + "# sns.heatmap(tar[idx,...,0]+tar[idx,...,1], cmap='hot',ax=ax[2])\n", + "# # plt.imshow(stats[0]['bin_matrix'][0], cmap='hot')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a06cb37", + "metadata": {}, + "outputs": [], + "source": [ + "# plt.plot(stats[0]['rmv'][1:-1], stats[0]['rmse'][1:-1], 'o')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb506327", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6150606a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d58e8c1", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.metrics.calibration import get_calibrated_factor_for_stdev\n", + "# calibration_factor_std = get_calibrated_factor_for_stdev(pred, np.log(pred_std**2), tar_normalized, batch_size=8, lr=0.1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "089ea14e", + "metadata": {}, + "outputs": [], + "source": [ + "# calib = Calibration(num_bins=30, mode='pixelwise')\n", + "# stats = calib.compute_stats(pred, pred_std, tar_normalized)\n", + "\n", + "# calib = Calibration(num_bins=30, mode='pixelwise')\n", + "# calib_stats = calib.compute_stats(pred, pred_std * calibration_factor_std, tar_normalized)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86b1dc22", + "metadata": {}, + "outputs": [], + "source": [ + "# plt.plot(np.log(stats[0]['rmv'][1:-16]), stats[0]['rmse'][1:-16], 'o-', color='g', label='Uncalibrated')\n", + "# plt.plot(np.log(calib_stats[0]['rmv'][1:-16]), calib_stats[0]['rmse'][1:-16], 'o-', color='r', label='Calibrated')\n", + "\n", + "# xmin = np.log(stats[0]['rmv'][1:-16]).min()\n", + "# xmax = np.log(stats[0]['rmv'][1:-16]).max()\n", + "# ymin = min(np.min(stats[0]['rmse'][1:-16]), np.min(calib_stats[0]['rmse'][1:-16]))\n", + "# ymax = max(np.max(stats[0]['rmse'][1:-16]), np.max(calib_stats[0]['rmse'][1:-16]))\n", + "# min_val = min(xmin, ymin)\n", + "# max_val = max(xmax, ymax)\n", + "# # plt.xlim([0, max_val])\n", + "# # plt.ylim([0, max_val])\n", + "# plt.legend()\n", + "# plt.xlabel('RMV')\n", + "# plt.ylabel('RMSE')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2402048", + "metadata": {}, + "outputs": [], + "source": [ + "q_vals = [0.01, 0.1,0.5,0.9,0.95, 0.99,1]\n", + "for i in range(tar_normalized.shape[-1]):\n", + " print(f'Channel {i}:', np.quantile(tar_normalized[...,i], q_vals).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fef4512", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(6,6))\n", + "# for i in range(tar.shape[-1]):\n", + "# sns.histplot(tar[:,::10,::10,i].reshape(-1,), color='g', label=f'{i}', kde=True)\n", + "\n", + "# plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb572707", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.data_loader.schroff_rawdata_loader import mito_channel_fnames\n", + "# from denoisplit.core.tiff_reader import load_tiff\n", + "# import seaborn as sns\n", + "\n", + "# fpaths = [os.path.join(datapath, x) for x in mito_channel_fnames()]\n", + "# fpath = fpaths[0]\n", + "# print(fpath)\n", + "# img = load_tiff(fpaths[0])\n", + "# temp = img.copy()\n", + "# sns.histplot(temp[:,:,::10,::10].reshape(-1,))\n", + "# plt.hist(temp[:,:,::10,::10].reshape(-1,),bins=100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24708c4c", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.patches as patches\n", + "import matplotlib\n", + "from denoisplit.analysis.plot_error_utils import plot_error\n", + "nrows = pred.shape[-1]\n", + "img_sz = 3\n", + "_,ax = plt.subplots(figsize=(4*img_sz,nrows*img_sz),ncols=4,nrows=nrows)\n", + "idx = np.random.randint(len(pred))\n", + "print(idx)\n", + "for ch_id in range(nrows):\n", + " ax[ch_id,0].imshow(tar_normalized[idx,..., ch_id], cmap='magma')\n", + " ax[ch_id,1].imshow(pred[idx,:,:,ch_id], cmap='magma')\n", + " plot_error(tar_normalized[idx,...,ch_id], \n", + " pred[idx,:,:,ch_id], \n", + " cmap = matplotlib.cm.coolwarm, \n", + " ax = ax[ch_id,2], max_val = None)\n", + "\n", + " cropsz = 256\n", + " h_s = np.random.randint(0, tar_normalized.shape[1] - cropsz)\n", + " h_e = h_s + cropsz\n", + " w_s = np.random.randint(0, tar_normalized.shape[2] - cropsz)\n", + " w_e = w_s + cropsz\n", + "\n", + " plot_error(tar_normalized[idx,h_s:h_e,w_s:w_e, ch_id], \n", + " pred[idx,h_s:h_e,w_s:w_e,ch_id], \n", + " cmap = matplotlib.cm.coolwarm, \n", + " ax = ax[ch_id,3], max_val = None)\n", + "\n", + " # Add rectangle to the region\n", + " rect = patches.Rectangle((w_s, h_s), w_e-w_s, h_e-h_s, linewidth=1, edgecolor='r', facecolor='none')\n", + " ax[ch_id,2].add_patch(rect)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4101247", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "markdown", + "id": "0a8f8b45", + "metadata": {}, + "source": [ + "### Take care of the shift which was introduced before saving the prediction to files." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "919db5ef", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "def get_offset(fname):\n", + " json_fpath = os.path.join(data_dir, fname).replace('.tif','.json')\n", + " if os.path.exists(json_fpath):\n", + " with open(json_fpath, 'r') as f:\n", + " data = json.load(f)\n", + " return float(data['offset'])\n", + " else:\n", + " return 0\n", + "\n", + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "pred_unnorm = []\n", + "for i in range(pred.shape[-1]):\n", + " if sep_std.shape[-1]==1:\n", + " temp_pred_unnorm = pred[...,i]*sep_std[...,0] + sep_mean[...,0]\n", + " else:\n", + " temp_pred_unnorm = pred[...,i]*sep_std[...,i] + sep_mean[...,i]\n", + " pred_unnorm.append(temp_pred_unnorm)\n", + "\n", + "pred_unnorm[0] = pred_unnorm[0] + get_offset(config.data.ch1_fname)\n", + "pred_unnorm[1] = pred_unnorm[1] + get_offset(config.data.ch2_fname)\n", + "pred = np.stack(pred_unnorm, axis=-1)\n", + "pred = (pred - sep_mean)/sep_std" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "698e51d1", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.scripts.evaluate import * \n", + "from denoisplit.analysis.denoiser_splitter_utils import whether_to_flip\n", + "from denoisplit.config_utils import get_configdir_from_saved_predictionfile\n", + "import ml_collections\n", + "\n", + "denoiser_configdir = get_configdir_from_saved_predictionfile(config.data.ch1_fname)\n", + "denoiser_config = load_config(denoiser_configdir)\n", + "denoiser_config = ml_collections.ConfigDict(denoiser_config)\n", + "if denoiser_config.data.data_type == DataType.BioSR_MRC:\n", + " denoiser_input_dir = '/group/jug/ashesh/data/BioSR/'\n", + "elif denoiser_config.data.data_type == DataType.OptiMEM100_014:\n", + " denoiser_input_dir = '/group/jug/ashesh/data/microscopy/OptiMEM100x014.tif'\n", + "elif denoiser_config.data.data_type == DataType.SeparateTiffData:\n", + " denoiser_input_dir = '/group/jug/ashesh/data/ventura_gigascience/'\n", + " denoiser_config.data.ch1_fname = denoiser_config.data.ch1_fname.replace('lowsnr', 'highsnr')\n", + " denoiser_config.data.ch2_fname = denoiser_config.data.ch2_fname.replace('lowsnr', 'highsnr')\n", + "with denoiser_config.unlocked():\n", + " highres_data = get_data_without_synthetic_noise(denoiser_input_dir, denoiser_config, eval_datasplit_type)\n", + "\n", + "h, w = pred.shape[1:3]\n", + "highres_data = highres_data[:, :h, :w].copy()\n", + "if 'ch1_fname' in config.data and 'ch1_fname' in denoiser_config.data and denoiser_config.data.data_type != DataType.SeparateTiffData:\n", + " if whether_to_flip(config.data.ch1_fname, config.data.ch2_fname, denoiser_config):\n", + " highres_data = np.flip(highres_data, axis=-1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b5bb044", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(highres_data[2,...,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4d4fce7", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b59eb44", + "metadata": {}, + "outputs": [], + "source": [ + "tmp_idx = 2\n", + "_,ax = plt.subplots(figsize=(10,10),ncols=2,nrows=2)\n", + "ax[0,0].imshow(highres_data[tmp_idx,...,0], cmap='magma')\n", + "ax[0,1].imshow(pred[tmp_idx,...,0], cmap='magma')\n", + "ax[1,0].imshow(highres_data[tmp_idx,...,1], cmap='magma')\n", + "ax[1,1].imshow(pred[tmp_idx,...,1], cmap='magma')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a0d4a8d", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.scripts.evaluate import compute_multiscale_ssim\n", + "if highres_data is not None:\n", + " print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + " psnr1 = avg_range_inv_psnr(highres_data[...,0], pred_unnorm[0])\n", + " psnr2 = avg_range_inv_psnr(highres_data[...,1], pred_unnorm[1])\n", + "\n", + " # ssim1_hres_mean, ssim1_hres_std = avg_ssim(highres_data[...,0], pred_unnorm[0])\n", + " # ssim2_hres_mean, ssim2_hres_std = avg_ssim(highres_data[...,1], pred_unnorm[1])\n", + " tar_tmp = (highres_data - sep_mean) /sep_std\n", + " ssim1, ssim2 = compute_multiscale_ssim(tar_tmp, pred)\n", + " print('PSNR on Highres', psnr1, psnr2)\n", + " print('SSIM on Highres', np.round(ssim1,3), np.round(ssim2,3))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3caa24e6", + "metadata": {}, + "outputs": [], + "source": [ + "Test_PNone_G32_M10_Sk0\n", + "PSNR on Highres 38.3 36.42\n", + "SSIM on Highres 0.98 0.983" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19454e00", + "metadata": {}, + "outputs": [], + "source": [ + "handler = PaperResultsHandler('/group/jug/ashesh/data/paper_stats/',\n", + " eval_datasplit_type,\n", + " custom_image_size,\n", + " image_size_for_grid_centers,\n", + " mmse_count,\n", + " ignored_last_pixels)\n", + "save_data = np.stack(pred_unnorm, axis=-1)\n", + "offset = save_data.min()\n", + "save_data -= offset\n", + "save_data = save_data.astype(np.uint32)\n", + "handler.dump_predictions(ckpt_dir, save_data, {'offset': str(offset)})\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c419163c", + "metadata": {}, + "outputs": [], + "source": [ + "break here." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "471569f2", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "_,ax = plt.subplots(figsize=(4,4))\n", + "sns.histplot(highres_data[...,1].reshape(-1,), color='g', label=f'Highres',bins=100 )\n", + "sns.histplot(pred[...,1].reshape(-1,), color='g', label=f'Lowres',bins=100 )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d75d6a1", + "metadata": {}, + "outputs": [], + "source": [ + "eps = 0.1\n", + "if config.model.model_type == ModelType.DenoiserSplitter:\n", + " ch_idx = 0\n", + " def predict(inp):\n", + " inp = model.denoise_one_channel(inp, model._denoiser_input)\n", + " out = model(inp)[0]\n", + " return model.likelihood.distr_params(out)['mean'].cpu().numpy()\n", + "\n", + " idx = np.random.randint(0, len(val_dset))\n", + " inp_tmp, tar_tmp = val_dset[idx]\n", + " h,w,t = val_dset.idx_manager.hwt_from_idx(idx)\n", + " h -= val_dset.per_side_overlap_pixelcount()\n", + " w -= val_dset.per_side_overlap_pixelcount()\n", + " print(idx)\n", + " inp_tmp = torch.Tensor(inp_tmp[None]).cuda()\n", + "\n", + " with torch.no_grad():\n", + " clean_pred1 = predict(inp_tmp)\n", + " clean_pred2 = predict(inp_tmp)\n", + " clean_pred3 = predict(inp_tmp)\n", + " pred_mmse_arr = []\n", + " for _ in range(50):\n", + " clean_pred4 = predict(inp_tmp)\n", + " pred_mmse_arr.append(clean_pred4)\n", + " pred_mmse = np.mean(pred_mmse_arr, axis=0, keepdims=False)\n", + "\n", + " _,ax = plt.subplots(ncols=6, figsize=(18,3))\n", + " ax[0].imshow(inp_tmp[0,0].cpu().numpy() ,cmap='magma')\n", + " ax[1].imshow(highres_data[t,h:h+256,w:w+256,ch_idx] , cmap='magma')\n", + " ax[2].imshow(clean_pred1[0,ch_idx], cmap='magma')\n", + " ax[3].imshow(clean_pred2[0,ch_idx], cmap='magma')\n", + " ax[4].imshow(pred_mmse[0,ch_idx], cmap='magma')\n", + " ax[5].imshow(np.std(pred_mmse_arr, axis=0, keepdims=False)[0,ch_idx]/(eps + np.abs(pred_mmse[0,ch_idx])), cmap='magma')\n", + " unnorm_temp_pred = (pred_mmse* data_std + data_mean)\n", + " minv = unnorm_temp_pred[0,ch_idx].min()\n", + " maxv = unnorm_temp_pred[0,ch_idx].max()\n", + " print(minv, maxv)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13fc1983", + "metadata": {}, + "outputs": [], + "source": [ + "rmse_arr = []\n", + "psnr_arr = []\n", + "rinv_psnr_arr = []\n", + "ssim_arr = []\n", + "for ch_id in range(pred.shape[-1]):\n", + " rmse =np.sqrt(((pred[...,ch_id] - tar_normalized[...,ch_id])**2).reshape(len(pred),-1).mean(axis=1))\n", + " rmse_arr.append(rmse)\n", + " psnr = avg_psnr(tar_normalized[...,ch_id].copy(), pred[...,ch_id].copy()) \n", + " rinv_psnr = avg_range_inv_psnr(tar_normalized[...,ch_id].copy(), pred[...,ch_id].copy())\n", + " ssim_mean, ssim_std = avg_ssim(tar[...,ch_id], pred_unnorm[ch_id])\n", + " psnr_arr.append(psnr)\n", + " rinv_psnr_arr.append(rinv_psnr)\n", + " ssim_arr.append((ssim_mean,ssim_std))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e87868b7", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + "print('Rec Loss',np.round(rec_loss.mean(),3) )\n", + "print('RMSE', '\\t'.join([str(np.mean(x).round(3)) for x in rmse_arr]))\n", + "print('PSNR', '\\t'.join([str(x) for x in psnr_arr]))\n", + "print('RangeInvPSNR','\\t'.join([str(x) for x in rinv_psnr_arr]))\n", + "print('SSIM','\\t'.join([f'{round(x,3)}±{round(y,4)}' for (x,y) in ssim_arr]))\n", + "print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2806ab6", + "metadata": {}, + "outputs": [], + "source": [ + "def show_for_one(idx):\n", + " print(f'Showing for {idx}')\n", + " with torch.no_grad():\n", + " val_dset.enable_noise()\n", + " inp, tar = val_dset[idx]\n", + " val_dset.disable_noise()\n", + " _, highres_tar = val_dset[idx]\n", + " val_dset.enable_noise()\n", + "\n", + "\n", + " inp = torch.Tensor(inp[None])\n", + " tar = torch.Tensor(tar[None])\n", + " inp = inp.cuda()\n", + " x_normalized = model.normalize_input(inp)\n", + " tar = tar.cuda()\n", + " tar_normalized = model.normalize_target(tar)\n", + "\n", + " recon_img_list = []\n", + " for _ in range(20):\n", + " if config.model.model_type == ModelType.UNet:\n", + " recon_normalized = model(x_normalized)\n", + " imgs = recon_normalized\n", + " elif config.model.model_type == ModelType.LadderVaeSemiSupervised:\n", + " out, td_data = model(x_normalized)\n", + " rec_loss, imgs = model.get_reconstruction_loss(out,\n", + " x_normalized,\n", + " tar_normalized,\n", + " return_predicted_img=True)\n", + " else:\n", + " recon_normalized, td_data = model(x_normalized)\n", + " rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, x_normalized, \n", + " tar_normalized,\n", + " return_predicted_img=True)\n", + " recon_img_list.append(imgs.cpu().numpy()[0])\n", + "\n", + " recon_img_list = np.array(recon_img_list)\n", + " print(recon_img_list.shape)\n", + " num_channels = imgs.shape[1]\n", + " img_sz = 4\n", + " # _,ax = plt.subplots(figsize=((1+num_channels)*img_sz,img_sz),ncols=num_channels+1)\n", + " # ax[0].imshow(inp[0,0].cpu().numpy(), cmap='magma')\n", + " # for i in range(num_channels):\n", + " # ax[i+1].imshow(tar[0,i].cpu().numpy(), cmap='magma')\n", + "\n", + " nrows=num_channels\n", + " img_sz = 3\n", + " ncols = 6\n", + " _,ax = plt.subplots(figsize=(img_sz * ncols,nrows*img_sz),ncols=ncols,nrows=nrows)\n", + " # add the input\n", + " ax[0,0].imshow(inp[0,0].cpu().numpy(), cmap='magma')\n", + " # sns.kdeplot(highres_tar[0].reshape(-1,), color='r', label='Ch0', ax=ax[1,0])\n", + " # sns.kdeplot(highres_tar[1].reshape(-1,), color='b', label='Ch1', ax=ax[1,0])\n", + " # ax[1,0].legend()\n", + " for i in range(1, ncols-2):\n", + " for col_idx in range(imgs.shape[1]):\n", + " ax[col_idx,i].imshow(recon_img_list[i-1][col_idx], cmap='magma')\n", + " \n", + " mmse_pred = np.mean(recon_img_list, axis=0)\n", + " for col_idx in range(imgs.shape[1]):\n", + " ax[col_idx,ncols-2].imshow(mmse_pred[col_idx], cmap='magma')\n", + " ax[col_idx,ncols-1].imshow(highres_tar[col_idx], cmap='magma')\n", + "\n", + " clean_ax(ax[col_idx,ncols-2])\n", + " clean_ax(ax[col_idx,ncols-1])\n", + "\n", + "show_for_one(np.random.randint(len(val_dset)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5610a60f", + "metadata": {}, + "outputs": [], + "source": [ + "inp, tar = val_dset[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15e66dff", + "metadata": {}, + "outputs": [], + "source": [ + "_, ax = plt.subplots()\n", + "sns.kdeplot(tar[0].reshape(-1,), color='r', label='0')\n", + "sns.kdeplot(tar[1].reshape(-1,), color='b', label='1', ax=ax)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f49239db", + "metadata": {}, + "outputs": [], + "source": [ + "break here" + ] + }, + { + "cell_type": "markdown", + "id": "824ecf7e", + "metadata": {}, + "source": [ + "## Creating tiff file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de631db9", + "metadata": {}, + "outputs": [], + "source": [ + "rdate,rconfig,rid = ckpt_dir.split(\"/\")[-3:]\n", + "fname_prefix = rdate + '-' + rconfig.replace('-','')[:-2] + '-' + rid\n", + "fname_prefix" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0465dd97", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.io import imsave\n", + "import numpy as np\n", + "pred_unnorm = np.concatenate([ch1_pred_unnorm[...,None],\n", + " ch2_pred_unnorm[...,None]],\n", + " axis=-1)\n", + "for ch_idx in [0,1]:\n", + " tif_fname = f'{fname_prefix}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}_C{ch_idx}.tif'\n", + " tif_fpath=os.path.join('paper_tifs',tif_fname)\n", + " if config.data.data_type in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " output = np.concatenate([\n", + " pred_unnorm[None,:50,...,ch_idx],tar[None,:50,...,ch_idx],\n", + " ],axis=0)\n", + " else:\n", + " output = np.concatenate([\n", + " pred_unnorm[:1,...,ch_idx],tar[:1,...,ch_idx],\n", + " ],axis=0)\n", + " imsave(tif_fpath,output,plugin='tifffile')\n", + " print(tif_fpath)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92a8d256", + "metadata": {}, + "outputs": [], + "source": [ + "! ls -lhrt paper_tifs/2211-D8M3S0-*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f7a3da19", + "metadata": {}, + "outputs": [], + "source": [ + "# !ls paper_tifs/2211-D3M3S0-0_P64_G*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7b3c066", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(val_dset))\n", + "inp, tar = val_dset[idx]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c7b56b7", + "metadata": {}, + "outputs": [], + "source": [ + "if len(inp) > 1:\n", + " _,ax = plt.subplots(figsize=(10,2.5),ncols=4)\n", + " ax[0].imshow(inp[0])\n", + " ax[1].imshow(inp[1])\n", + " ax[2].imshow(inp[2])\n", + " ax[3].imshow(inp[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f02d1078", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b9fe5ce", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(10,10))\n", + "# tmp_data =tar_unnorm[idx,:,:,1]\n", + "# q = np.quantile(tmp_data,0.95)\n", + "# tmp_data[tmp_data >q] = q\n", + "# plt.imshow(tmp_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f4d490b", + "metadata": {}, + "outputs": [], + "source": [ + "pred_unnorm.min()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d38fa69", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,20),ncols=2,nrows=2)\n", + "ax[0,0].set_title('Channel 1',size=20)\n", + "ax[0,1].set_title('Channel 2',size=20)\n", + "ax[0,0].set_ylabel('Target',size=20)\n", + "ax[1,0].set_ylabel('Predictions',size=20)\n", + "ax[0,0].imshow(tar_unnorm[idx,:,:,0])\n", + "ax[0,1].imshow(tar_unnorm[idx,:,:,1])\n", + "ax[1,0].imshow(pred_unnorm[idx,:,:,0])\n", + "ax[1,1].imshow(pred_unnorm[idx,:,:,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79d4b581", + "metadata": {}, + "outputs": [], + "source": [ + "idx = 0#np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,30),ncols=2,nrows=3)\n", + "ax[0,0].set_title('Target',size=20)\n", + "ax[0,1].set_title('Prediction',size=20)\n", + "ax[0,0].set_ylabel('Mixed Input',size=20)\n", + "ax[1,0].set_ylabel('Channel 1',size=20)\n", + "ax[2,0].set_ylabel('Channel 2',size=20)\n", + "sz = 400\n", + "ax[0,0].imshow(np.mean(tar_unnorm[idx, 1000:1000+sz,400:400+sz], axis=2))\n", + "ax[0,1].imshow(np.mean(pred_unnorm[idx,1000:1000+sz,400:400+sz], axis=2))\n", + "\n", + "ax[1,0].imshow(tar_unnorm[idx, 1000:1000+sz,400:400+sz,0],vmax=126,vmin=88)\n", + "ax[1,1].imshow(pred_unnorm[idx,1000:1000+sz,400:400+sz,0], vmax=126,vmin=88)\n", + "\n", + "ax[2,0].imshow(tar_unnorm[idx, 1000:1000+sz,400:400+sz,1],vmax=126,vmin=78)\n", + "ax[2,1].imshow(pred_unnorm[idx,1000:1000+sz,400:400+sz,1],vmax=126,vmin=78)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c6c6d82", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm[idx, 1000:1500,400:900,0].std()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2fa229c6", + "metadata": {}, + "outputs": [], + "source": [ + "pred_unnorm[idx,1000:1500,400:900,0].std()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8285b5a8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93f14602", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,30),ncols=2,nrows=3)\n", + "ax[0,0].set_title('Target',size=20)\n", + "ax[0,1].set_title('Prediction',size=20)\n", + "ax[0,0].set_ylabel('Mixed Input',size=20)\n", + "ax[1,0].set_ylabel('Channel 1',size=20)\n", + "ax[2,0].set_ylabel('Channel 2',size=20)\n", + "\n", + "ax[0,0].imshow(np.mean(tar_unnorm[idx, 1000:1500,400:900], axis=2))\n", + "ax[0,1].imshow(np.mean(pred_unnorm[idx,1000:1500,400:900], axis=2))\n", + "\n", + "ax[1,0].imshow(tar_unnorm[idx, 1000:1500,400:900,0])\n", + "ax[1,1].imshow(pred_unnorm[idx,1000:1500,400:900,0])\n", + "\n", + "ax[2,0].imshow(tar_unnorm[idx, 1000:1500,400:900,1])\n", + "ax[2,1].imshow(pred_unnorm[idx,1000:1500,400:900,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5306061", + "metadata": {}, + "outputs": [], + "source": [ + "break here" + ] + }, + { + "cell_type": "markdown", + "id": "e63fb49d", + "metadata": {}, + "source": [ + "## Comparing PSNR with high res data. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fe03625", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.data_split_type import get_datasplit_tuples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62ae1c2b", + "metadata": {}, + "outputs": [], + "source": [ + "if eval_datasplit_type == DataSplitType.Val:\n", + " N = len(pred1)/config.training.val_fraction\n", + "elif eval_datasplit_type == DataSplitType.Test:\n", + " N = len(pred1)/config.training.test_fraction\n", + "train_idx,val_idx,test_idx = get_datasplit_tuples(config.training.val_fraction,config.training.test_fraction,N,\n", + " starting_train=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67bf4a4c", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4a5c2d6", + "metadata": {}, + "outputs": [], + "source": [ + "highres_actin = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/actin-60x-noise2-highsnr.tif')[...,None]\n", + "highres_mito = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/mito-60x-noise2-highsnr.tif')[...,None]\n", + "\n", + "if eval_datasplit_type == DataSplitType.Val:\n", + " highres_data = np.concatenate([highres_actin[val_idx[0]:val_idx[1]],\n", + " highres_mito[val_idx[0]:val_idx[1]]],\n", + " axis=-1).astype(np.float32)\n", + "elif eval_datasplit_type == DataSplitType.Test:\n", + " highres_data = np.concatenate([highres_actin[test_idx[0]:test_idx[1]],\n", + " highres_mito[test_idx[0]:test_idx[1]]],\n", + " axis=-1).astype(np.float32)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d325d7b", + "metadata": {}, + "outputs": [], + "source": [ + "thresh = np.quantile(highres_data,config.data.clip_percentile)\n", + "highres_data[highres_data > thresh]=thresh\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8daa9662", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,8),ncols=2,nrows=2)\n", + "ax[0,0].imshow(tar_unnorm[5,...,0])\n", + "ax[0,1].imshow(highres_data[5,...,0])\n", + "ax[1,0].imshow(tar_unnorm[8,...,1])\n", + "ax[1,1].imshow(highres_data[8,...,1])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b53ddb0e", + "metadata": {}, + "outputs": [], + "source": [ + "print('PSNR with HighRes', avg_psnr(highres_data[...,0], pred1),avg_psnr(highres_data[...,1], pred2))\n", + "print('RangeInvPSNR with HighRes', avg_range_inv_psnr(highres_data[...,0], pred1), \n", + " avg_range_inv_psnr(highres_data[...,1], pred2))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ba9fbf7", + "metadata": {}, + "outputs": [], + "source": [ + "# RangeInvPSNR with HighRes 16.82 18.33\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd49794d", + "metadata": {}, + "outputs": [], + "source": [ + "tar_1_tmp.dtype" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8537fa04", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.psnr import fix_range, zero_mean\n", + "def fix_range_with_highresdata(pred,tar):\n", + " pred_1_tmp = torch.Tensor(pred.reshape(len(pred),-1))\n", + " tar_1_tmp = torch.Tensor(tar.reshape(len(tar),-1))\n", + " pred_1_tmp = zero_mean(pred_1_tmp)\n", + " tar_1_tmp = zero_mean(tar_1_tmp)\n", + "# import pdb;pdb.set_trace()\n", + " tar_1_tmp = tar_1_tmp / torch.std(tar_1_tmp, dim=1, keepdim=True)\n", + " \n", + " pred_1_tmp = fix_range(tar_1_tmp,pred_1_tmp)\n", + " pred_1_tmp = pred_1_tmp.reshape_as(torch.Tensor(pred))\n", + " tar_1_tmp = tar_1_tmp.reshape_as(torch.Tensor(pred))\n", + " return pred_1_tmp, tar_1_tmp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3faaee3", + "metadata": {}, + "outputs": [], + "source": [ + "pred1_tmp, tar1_tmp = fix_range_with_highresdata(pred1, highres_data[...,0])\n", + "pred2_tmp, tar2_tmp = fix_range_with_highresdata(pred2, highres_data[...,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7076ff9c", + "metadata": {}, + "outputs": [], + "source": [ + "ssim1_mean, ssim1_std = avg_ssim(tar1_tmp.numpy(), pred1_tmp.numpy())\n", + "ssim2_mean, ssim2_std = avg_ssim(tar2_tmp.numpy(), pred2_tmp.numpy())\n", + "print(ssim1_mean, ssim2_mean)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6557f6b", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "ax[0].imshow(pred_1_tmp[0])\n", + "ax[1].imshow(tar_1_tmp[0])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c40d383", + "metadata": {}, + "outputs": [], + "source": [ + "break here." + ] + }, + { + "cell_type": "markdown", + "id": "9f992749", + "metadata": {}, + "source": [ + "## Inspecting the performance on grid boundaries.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "945a258f", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitched_prediction_mask\n", + "\n", + "\n", + "skip_boundary_pixel_count = 0\n", + "for sk_c in [1,16,32,48,56]:\n", + " mask = stitched_prediction_mask(val_dset, \n", + " (val_dset._img_sz,val_dset._img_sz), \n", + " skip_boundary_pixel_count, \n", + " sk_c)\n", + " mask = ignore_pixels(mask)\n", + " psnr1, psnr2 = compute_masked_psnr(mask, tar1,tar2,pred1,pred2)\n", + " print(f'[Pad:{val_dset.per_side_overlap_pixelcount()}] SkipCentral', sk_c,\n", + " psnr1,psnr2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a265d0bb", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(mask[0,:,:,0])" + ] + }, + { + "cell_type": "markdown", + "id": "5c7c325b", + "metadata": {}, + "source": [ + "## Inspecting the performance on central regions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36c6b110", + "metadata": {}, + "outputs": [], + "source": [ + "skip_central_pixel_count = 0\n", + "\n", + "for sk_b in [1,8,16,20,24]:\n", + " mask = stitched_prediction_mask(val_dset, \n", + " (val_dset._img_sz,val_dset._img_sz), \n", + " sk_b, \n", + " skip_central_pixel_count)\n", + " mask = ignore_pixels(mask)\n", + " psnr1, psnr2 = compute_masked_psnr(mask, tar1,tar2,pred1,pred2)\n", + " print(f'[Pad:{val_dset.per_side_overlap_pixelcount()}] SkipBoundary', sk_b, psnr1,psnr2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2d87cd57", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(mask[0,:,:,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "212d5536", + "metadata": {}, + "outputs": [], + "source": [ + "# for w in range(2,202,25):\n", + "# print(f'RangeInvPSNR but skipping {w}', avg_range_inv_psnr(np.copy(tar1[:,w:-w,w:-w]), \n", + "# np.copy(pred1[:,w:-w,w:-w])),\n", + " \n", + "# avg_range_inv_psnr(np.copy(tar2[:,w:-w,w:-w]), \n", + "# np.copy(pred2[:,w:-w,w:-w]).copy()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dff40aad", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79275615", + "metadata": {}, + "outputs": [], + "source": [ + "h = 1200\n", + "w = 1200\n", + "sz = 512\n", + "x = tar_unnorm[:1,h:h+sz,w:w+sz].mean(axis=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de600304", + "metadata": {}, + "outputs": [], + "source": [ + "p_count = 32\n", + "y1 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]))\n", + "y2 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]), constant_values=237)\n", + "y3 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]), mode='linear_ramp', end_values=237)\n", + "y4 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]),mode='reflect')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae212914", + "metadata": {}, + "outputs": [], + "source": [ + "np.quantile(x, [0,0.05, 0.1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cdf5c95", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(16,4),ncols=4)\n", + "ax[0].imshow(y1[0], )\n", + "ax[1].imshow(y2[0], )\n", + "ax[2].imshow(y3[0], )\n", + "ax[3].imshow(y4[0], )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60a7a758", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(tar_unnorm[0,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(tar_unnorm[0,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29d967c9", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(tar_unnorm[-1,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(tar_unnorm[-1,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff0c91ac", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(pred_unnorm[0,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(pred_unnorm[0,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "104bbfb4", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.ticker as ticker\n", + "# import seaborn.apionly as sns\n", + "\n", + "_,ax = plt.subplots(figsize=(20,4))\n", + "sns.histplot(tar_unnorm[-1,:,:].mean(axis=2).reshape(-1,))\n", + "ax.xaxis.set_major_locator(ticker.MultipleLocator(25))\n", + "ax.xaxis.set_major_formatter(ticker.ScalarFormatter())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30034a7b", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm[-1,:,:].shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0057b73e", + "metadata": {}, + "outputs": [], + "source": [ + "# inp, tar = val_dset[11060]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01ed9ed7", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(16,4),ncols=4)\n", + "# ax[0].imshow(inp[0])\n", + "# ax[1].imshow(inp[1])\n", + "# ax[2].imshow(inp[2])\n", + "# ax[3].imshow(inp[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b65aeae", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "# ax[0].imshow(tar[0])\n", + "# ax[1].imshow(tar[1])" + ] + }, + { + "cell_type": "markdown", + "id": "950f3b3a", + "metadata": {}, + "source": [ + "## Inspecting the difference in behaviour when different sized inputs are passed. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb42adc1", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "def compute_centered_diff(big,small):\n", + " pad = (big.shape[-1] - small.shape[-1])//2\n", + "# import pdb;pdb.set_trace()\n", + " return big[:,:,pad:-pad,pad:-pad] - small\n", + " \n", + "old_img_sz = val_dset.get_img_sz()\n", + "val_dset.set_img_sz(128)\n", + "inp2, tar2 = val_dset[10000]\n", + "with torch.no_grad():\n", + " bu_values2 = model.bottomup_pass(torch.Tensor(inp2[None]).cuda())\n", + "\n", + "val_dset.set_img_sz(256)\n", + "inp3, tar3 = val_dset[10000]\n", + "with torch.no_grad():\n", + " bu_values3 = model.bottomup_pass(torch.Tensor(inp3[None]).cuda())\n", + "\n", + "diff = (bu_values2[0] - bu_values3[0][:,:,32:-32,32:-32]).cpu().numpy()\n", + "sns.histplot(diff.reshape(-1,))\n", + "\n", + "##LOOKING AT bu_values\n", + "idx=1\n", + "diff = compute_centered_diff(bu_values3[idx],bu_values2[idx]).cpu().numpy()\n", + "_,ax =plt.subplots(figsize=(10,10))\n", + "sns.heatmap(diff[0,0])\n", + "\n", + "## Looking at the difference in prediction.\n", + "with torch.no_grad():\n", + " out2,_ = model(torch.Tensor(inp2[None,]).cuda())\n", + " out3,_ = model(torch.Tensor(inp3[None,]).cuda())\n", + " img2 = get_img_from_forward_output(out3,model)\n", + " img3 = get_img_from_forward_output(out2,model)\n", + "diff = compute_centered_diff(img2,img3)\n", + "_,ax =plt.subplots(figsize=(10,10))\n", + "sns.heatmap(diff[0,1].cpu().numpy())\n", + "val_dset.set_img_sz(old_img_sz)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c561780", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "489b52dd", + "metadata": {}, + "outputs": [], + "source": [ + "img = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/actin-60x-noise2-highsnr.tif')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3d1b606", + "metadata": {}, + "outputs": [], + "source": [ + "img.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6f5fb2c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=4)\n", + "ax[0].imshow(img[0])\n", + "ax[1].imshow(img[1])\n", + "ax[2].imshow(img[2])\n", + "ax[3].imshow(img[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0eea97dc", + "metadata": {}, + "outputs": [], + "source": [ + "img2 =load_tiff('/home/ashesh.ashesh/data/microscopy/OptiMEM100x014.tif')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70d1399c", + "metadata": {}, + "outputs": [], + "source": [ + "img2.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9b01f2c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=4)\n", + "ax[0].imshow(img2[0,...,0])\n", + "ax[1].imshow(img2[1,...,0])\n", + "ax[2].imshow(img2[2,...,0])\n", + "ax[3].imshow(img2[3,...,0])" + ] + }, + { + "cell_type": "markdown", + "id": "d11536e0", + "metadata": {}, + "source": [ + "###### " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f497f314", + "metadata": {}, + "outputs": [], + "source": [ + "inp, tar = val_dset[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a37d3fe", + "metadata": {}, + "outputs": [], + "source": [ + "inp.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "551123e4", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(3,3))\n", + "plt.imshow(tar[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0b01d1d", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(inp[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf517837", + "metadata": {}, + "outputs": [], + "source": [ + "(0.436+0.810)/2" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/ECCV24/denoiser_performance.ipynb b/denoisplit/notebooks/ECCV24/denoiser_performance.ipynb new file mode 100644 index 0000000..bdaaead --- /dev/null +++ b/denoisplit/notebooks/ECCV24/denoiser_performance.ipynb @@ -0,0 +1,159 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.config_utils import get_configdir_from_saved_predictionfile\n", + "import ml_collections\n", + "import os\n", + "from denoisplit.config_utils import load_config\n", + "from denoisplit.core.data_type import DataType\n", + "from denoisplit.scripts.evaluate import * \n", + "from denoisplit.core.data_split_type import DataSplitType\n", + "from denoisplit.core.tiff_reader import load_tiff\n", + "denoised_fpath = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk44/pred_disentangle_2403_D16-M23-S0-L0_17.tif'\n", + "paper_figures_dir = '/group/jug/ashesh/data/paper_figures'\n", + "\n", + "denoised_data = load_tiff(denoised_fpath)\n", + "denoiser_configdir = get_configdir_from_saved_predictionfile(os.path.basename(denoised_fpath))\n", + "denoiser_config = load_config(denoiser_configdir)\n", + "denoiser_config = ml_collections.ConfigDict(denoiser_config)\n", + "eval_datasplit_type = DataSplitType.Test\n", + "if denoiser_config.data.data_type == DataType.BioSR_MRC:\n", + " denoiser_input_dir = '/group/jug/ashesh/data/BioSR/'\n", + "elif denoiser_config.data.data_type == DataType.OptiMEM100_014:\n", + " denoiser_input_dir = '/group/jug/ashesh/data/microscopy/OptiMEM100x014.tif'\n", + "elif denoiser_config.data.data_type == DataType.SeparateTiffData:\n", + " denoiser_input_dir = '/group/jug/ashesh/data/ventura_gigascience/'\n", + " denoiser_config.data.ch1_fname = denoiser_config.data.ch1_fname.replace('lowsnr', 'highsnr')\n", + " denoiser_config.data.ch2_fname = denoiser_config.data.ch2_fname.replace('lowsnr', 'highsnr')\n", + "with denoiser_config.unlocked():\n", + " highres_data = get_data_without_synthetic_noise(denoiser_input_dir, denoiser_config, eval_datasplit_type)\n", + "\n", + "if denoiser_config.model.denoise_channel == 'Ch1':\n", + " highres_data = highres_data[...,0]\n", + "elif denoiser_config.model.denoise_channel == 'Ch2':\n", + " highres_data = highres_data[...,1]\n", + "elif denoiser_config.model.denoise_channel == 'input':\n", + " highres_data = np.mean(highres_data, axis=-1)\n", + "else:\n", + " raise ValueError('Invalid denoise channel')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def get_noisy_data(highres_data):\n", + " poisson_noise_factor = denoiser_config.data.poisson_noise_factor\n", + " noisy_data = (np.random.poisson(highres_data / poisson_noise_factor) * poisson_noise_factor).astype(np.float32)\n", + "\n", + " if denoiser_config.data.get('enable_gaussian_noise', False):\n", + " synthetic_scale = denoiser_config.data.get('synthetic_gaussian_scale', 0.1)\n", + " shape = highres_data.shape\n", + " noisy_data += np.random.normal(0, synthetic_scale, shape)\n", + " return noisy_data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "noisy_data = get_noisy_data(highres_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "from denoisplit.analysis.plot_utils import clean_ax\n", + "nimgs = 3\n", + "imgsz = 2\n", + "factor = 1.2\n", + "_,ax = plt.subplots(figsize=(imgsz*3/factor,nimgs*imgsz),ncols=3,nrows=nimgs)\n", + "h = 256\n", + "w = int(256/factor)\n", + "for i in range(nimgs):\n", + " hs = np.random.randint(0, highres_data.shape[1]-h)\n", + " ws = np.random.randint(0, highres_data.shape[2]-w)\n", + " print(h,w)\n", + " ax[i,0].imshow(noisy_data[0,hs:hs+h,ws:ws+w],cmap='magma')\n", + " ax[i,1].imshow(denoised_data[0,hs:hs+h,ws:ws+w,0],cmap='magma')\n", + " ax[i,2].imshow(highres_data[0,hs:hs+h,ws:ws+w],cmap='magma')\n", + "\n", + "ax[0,0].set_title('Noisy')\n", + "ax[0,1].set_title('Denoised')\n", + "ax[0,2].set_title('High SNR')\n", + "clean_ax(ax)\n", + "plt.subplots_adjust(wspace=0.02, hspace=0.02)\n", + "postfix = os.path.basename(denoised_fpath).replace('pred_disentangle_', '').replace('.tif', '')\n", + "fpath = os.path.join(paper_figures_dir, f'denoising_{postfix}.png')\n", + "plt.savefig(fpath, bbox_inches='tight', dpi=200)\n", + "print(fpath)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "highres_data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "h,w" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/EvalFineTuning.ipynb b/denoisplit/notebooks/EvalFineTuning.ipynb new file mode 100644 index 0000000..25f948f --- /dev/null +++ b/denoisplit/notebooks/EvalFineTuning.ipynb @@ -0,0 +1,2380 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "19844352", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad91cc2b", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "# os.environ[\"CUDA_DEVICE_ORDER\"]=\"PCI_BUS_ID\" # see issue #152\n", + "# os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"2\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dcd3d0c2", + "metadata": {}, + "outputs": [], + "source": [ + "# there are two environments(debug and prod). From where you want to fetch the code and data? \n", + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27ec4422", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d19b5a6", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.config_utils import load_config, get_configdir_from_saved_predictionfile\n", + "\n", + "# def check_correctness_of_noise(data_config):\n", + "# cfg1 = load_config(get_configdir_from_saved_predictionfile(data_config.ch1_fname))\n", + "# cfg2 = load_config(get_configdir_from_saved_predictionfile(data_config.ch2_fname))\n", + "# cfg3 = load_config(get_configdir_from_saved_predictionfile(data_config.ch_input_fname))\n", + "# msg = f'p1:{cfg1.data.poisson_noise_factor} p2:{cfg2.data.poisson_noise_factor} p3:{cfg3.data.poisson_noise_factor}'\n", + "# assert cfg1.data.poisson_noise_factor == cfg2.data.poisson_noise_factor == cfg3.data.poisson_noise_factor, msg\n", + "# assert cfg1.data.enable_gaussian_noise == cfg2.data.enable_gaussian_noise == cfg3.data.enable_gaussian_noise\n", + "# if cfg1.data.enable_gaussian_noise:\n", + "# msg = f'g1:{cfg1.data.synthetic_gaussian_scale} g2:{cfg2.data.synthetic_gaussian_scale} g3:{cfg3.data.synthetic_gaussian_scale}'\n", + "# assert cfg1.data.synthetic_gaussian_scale == cfg2.data.synthetic_gaussian_scale == cfg3.data.synthetic_gaussian_scale, msg\n", + "\n", + "\n", + "# for idx in [44,59,46,55,49,60, 51,56, 58, 52, 54, 23, 32, 33, 34, 35, 37, 38, 40,42,39,41]:\n", + "# cfg = load_config(f'/home/ashesh.ashesh/training/disentangle/2402/D23-M3-S0-L0/{idx}/')\n", + "# try:\n", + "# check_correctness_of_noise(cfg.data) \n", + "# except:\n", + "# print(idx)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "db8d89b5", + "metadata": {}, + "outputs": [], + "source": [ + "# 'stats_'+'_'.join(ckpt_dir.split('/')[-4:]) + '.pkl'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a9748a9", + "metadata": {}, + "outputs": [], + "source": [ + "ckpt_dir = \"/home/ashesh.ashesh/training/disentangle/2403/D22-M28-S0-L7/7\"\n", + "# ckpt_dir = '/home/ashesh.ashesh/training/disentangle/2402/D16-M3-S0-L0/78'\n", + "# ckpt_dir = '/home/ubuntu/ashesh/training/disentangle/2403/D22-M28-S0-L7/13'\n", + "assert os.path.exists(ckpt_dir)\n", + "# 211/D3-M3-S0-L0/0\n", + "# 2210/D3-M3-S0-L0/128\n", + "# 2210/D3-M3-S0-L0/129" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27410ddc", + "metadata": {}, + "outputs": [], + "source": [ + "# !ls /home/ubuntu/ashesh/training/disentangle/2209/D3-M9-S0-L0/1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c383d367", + "metadata": {}, + "outputs": [], + "source": [ + "def get_dtype(ckpt_fpath):\n", + " if os.path.isdir(ckpt_fpath):\n", + " ckpt_fpath = ckpt_fpath[:-1] if ckpt_fpath[-1] == '/' else ckpt_fpath\n", + " elif os.path.isfile(ckpt_fpath):\n", + " ckpt_fpath = os.path.dirname(ckpt_fpath)\n", + " assert ckpt_fpath[-1] != '/'\n", + " return int(ckpt_fpath.split('/')[-2].split('-')[0][1:])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7232e05", + "metadata": {}, + "outputs": [], + "source": [ + "dtype = get_dtype(ckpt_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90109e80", + "metadata": {}, + "outputs": [], + "source": [ + "dtype" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b237569", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "image_size_for_grid_centers = 64\n", + "mmse_count = 30\n", + "custom_image_size = None\n", + "data_t_list = None #[0]\n", + "\n", + "\n", + "batch_size = 16\n", + "num_workers = 4\n", + "COMPUTE_LOSS = False\n", + "use_deterministic_grid = None\n", + "threshold = None # 0.02\n", + "compute_kl_loss = False\n", + "evaluate_train = False# inspect training performance\n", + "eval_datasplit_type = DataSplitType.Test\n", + "val_repeat_factor = None\n", + "psnr_type = 'range_invariant' #'simple', 'range_invariant'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f889dd2d", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/config_loader.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1abc8067", + "metadata": {}, + "outputs": [], + "source": [ + "config.data.data_type" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "341a99f6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a0047fe", + "metadata": {}, + "outputs": [], + "source": [ + "tokens = ckpt_dir.split('/')\n", + "idx = tokens.index('disentangle')\n", + "if config.model.model_type == 25 and tokens[idx+1] == '2312':\n", + " config.model.model_type = ModelType.LadderVAERestrictedReconstruction" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc8a3fed", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.sampler_type import SamplerType\n", + "from denoisplit.core.loss_type import LossType\n", + "from denoisplit.data_loader.ht_iba1_ki67_rawdata_loader import SubDsetType\n", + "# from denoisplit.core.lowres_merge_type import LowresMergeType\n", + "\n", + "\n", + "with config.unlocked():\n", + " config.model.skip_nboundary_pixels_from_loss = None\n", + " if config.model.model_type == ModelType.UNet and 'n_levels' not in config.model:\n", + " config.model.n_levels = 4\n", + " if config.data.sampler_type == SamplerType.NeighborSampler:\n", + " config.data.sampler_type = SamplerType.DefaultSampler\n", + " config.loss.loss_type = LossType.Elbo\n", + " config.data.grid_size = config.data.image_size\n", + " if 'ch1_fpath_list' in config.data:\n", + " config.data.ch1_fpath_list = config.data.ch1_fpath_list[:1]\n", + " config.data.mix_fpath_list = config.data.mix_fpath_list[:1]\n", + " if config.data.data_type == DataType.Pavia2VanillaSplitting:\n", + " if 'channel_2_downscale_factor' not in config.data:\n", + " config.data.channel_2_downscale_factor = 1\n", + " if config.model.model_type == ModelType.UNet and 'init_channel_count' not in config.model:\n", + " config.model.init_channel_count = 64\n", + " \n", + " if 'skip_receptive_field_loss_tokens' not in config.loss:\n", + " config.loss.skip_receptive_field_loss_tokens = []\n", + " \n", + " if dtype == DataType.HTIba1Ki67:\n", + " config.data.subdset_type = SubDsetType.Iba1Ki64\n", + " config.data.empty_patch_replacement_enabled = False\n", + " \n", + " if 'lowres_merge_type' not in config.model.encoder:\n", + " config.model.encoder.lowres_merge_type = 0\n", + " if 'validtarget_random_fraction' in config.data:\n", + " config.data.validtarget_random_fraction = None\n", + " \n", + " if config.data.data_type == DataType.TwoDset:\n", + " config.model.model_type = ModelType.LadderVae\n", + " for key in config.data.dset1:\n", + " config.data[key] = config.data.dset1[key]\n", + " if 'dump_kth_frame_prediction' in config.training:\n", + " config.training.dump_kth_frame_prediction = None\n", + "\n", + " if 'input_is_sum' not in config.data:\n", + " config.data.input_is_sum = False\n", + "\n", + " \n", + " config.model.noise_model_ch1_fpath = config.model.noise_model_ch1_fpath.replace('/home/ubuntu/ashesh/training_hpc/', '/home/ashesh.ashesh/training/')\n", + " config.model.noise_model_ch2_fpath = config.model.noise_model_ch2_fpath.replace('/home/ubuntu/ashesh/training_hpc/', '/home/ashesh.ashesh/training/')\n", + " if 'finetuning_noise_model_ch1_fpath' in config.model:\n", + " config.model.finetuning_noise_model_ch1_fpath = config.model.finetuning_noise_model_ch1_fpath.replace('/home/ubuntu/ashesh/training_hpc/', '/home/ashesh.ashesh/training/')\n", + " \n", + " # config.model.noise_model_ch1_fpath = config.model.noise_model_ch1_fpath.replace('/home/ashesh.ashesh/training/', '/home/ubuntu/ashesh/training_hpc/')\n", + " # config.model.noise_model_ch2_fpath = config.model.noise_model_ch2_fpath.replace('/home/ashesh.ashesh/training/', '/home/ubuntu/ashesh/training_hpc/')\n", + " # if 'finetuning_noise_model_ch1_fpath' in config.model:\n", + " # config.model.finetuning_noise_model_ch1_fpath = config.model.finetuning_noise_model_ch1_fpath.replace('/home/ashesh.ashesh/training/', '/home/ubuntu/ashesh/training_hpc/')\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57a7671b", + "metadata": {}, + "outputs": [], + "source": [ + "config.data.synthetic_gaussian_scale = 3400" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a03b40f4", + "metadata": {}, + "outputs": [], + "source": [ + "# config.data.channel_1 = 0 \n", + "# config.data.channel_2 = 3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ef646b2", + "metadata": {}, + "outputs": [], + "source": [ + "dtype = config.data.data_type\n", + "\n", + "if DEBUG:\n", + " if dtype == DataType.CustomSinosoid:\n", + " data_dir = f'{DATA_ROOT}/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + "else:\n", + " if dtype in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " data_dir = f'{DATA_ROOT}/sinosoid_without_test/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + " elif dtype == DataType.Prevedel_EMBL:\n", + " data_dir = f'{DATA_ROOT}/Prevedel_EMBL/PKG_3P_dualcolor_stacks/NoAverage_NoRegistration/'\n", + " elif dtype == DataType.AllenCellMito:\n", + " data_dir = f'{DATA_ROOT}/allencell/2017_03_08_Struct_First_Pass_Seg/AICS-11/'\n", + " elif dtype == DataType.SeparateTiffData:\n", + " data_dir = f'{DATA_ROOT}/ventura_gigascience'\n", + " elif dtype == DataType.SemiSupBloodVesselsEMBL:\n", + " data_dir = f'{DATA_ROOT}/EMBL_halfsupervised/Demixing_3P'\n", + " elif dtype == DataType.Pavia2VanillaSplitting:\n", + " data_dir = f'{DATA_ROOT}/pavia2'\n", + " elif dtype == DataType.ExpansionMicroscopyMitoTub:\n", + " data_dir = f'{DATA_ROOT}/expansion_microscopy_Nick/'\n", + " elif dtype == DataType.ShroffMitoEr:\n", + " data_dir = f'{DATA_ROOT}/shrofflab/'\n", + " elif dtype == DataType.HTIba1Ki67:\n", + " data_dir = f'{DATA_ROOT}/Stefania/20230327_Ki67_and_Iba1_trainingdata/'\n", + " elif dtype == DataType.BioSR_MRC:\n", + " data_dir = f'{DATA_ROOT}/BioSR/'\n", + " elif dtype == DataType.ExpMicroscopyV2:\n", + " data_dir = f'{DATA_ROOT}/expansion_microscopy_v2/'\n", + " elif dtype == DataType.TavernaSox2GolgiV2:\n", + " data_dir = f'{DATA_ROOT}/TavernaSox2Golgi/acquisition2/'\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "edde2155", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/disentangle_setup.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60d5fc4a", + "metadata": {}, + "outputs": [], + "source": [ + "if config.data.multiscale_lowres_count is not None and custom_image_size is not None:\n", + " model.reset_for_different_output_size(custom_image_size)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11cf6c69", + "metadata": {}, + "outputs": [], + "source": [ + "# if config.model.model_type not in [ModelType.UNet, ModelType.BraveNet]:\n", + "# with torch.no_grad():\n", + "# inp, tar = val_dset[0][:2]\n", + "# out, td_data = model(torch.Tensor(inp[None]).cuda())\n", + "# print(td_data['z'][-1].shape)\n", + "# print(out.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d05be428", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(val_dset))\n", + "inp_tmp, tar_tmp, *_ = val_dset[idx]\n", + "ncols = len(tar_tmp)\n", + "nrows = 2\n", + "_,ax = plt.subplots(figsize=(4*ncols,4*nrows),ncols=ncols,nrows=nrows)\n", + "for i in range(min(ncols,len(inp_tmp))):\n", + " ax[0,i].imshow(inp_tmp[i])\n", + "\n", + "for channel_id in range(ncols):\n", + " ax[1,channel_id].imshow(tar_tmp[channel_id])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eece008c", + "metadata": {}, + "outputs": [], + "source": [ + "if data_t_list is not None:\n", + " val_dset.reduce_data(t_list=data_t_list)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58aae760", + "metadata": {}, + "outputs": [], + "source": [ + "# break here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac7ac09e", + "metadata": {}, + "outputs": [], + "source": [ + "# # high val dset \n", + "# import ml_collections\n", + "# new_config = ml_collections.ConfigDict(config)\n", + "# if 'poisson_noise_factor' in new_config.data:\n", + "# new_config.data.poisson_noise_factor = -1\n", + "# _, highsnr_val_dset = create_dataset(new_config, data_dir, eval_datasplit_type=eval_datasplit_type,\n", + "# kwargs_dict=dloader_kwargs)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4812a8ce", + "metadata": {}, + "outputs": [], + "source": [ + "# plt.imshow(np.mean(val_dset._data[0], axis=-1) + val_dset._noise_data[0,...,0], cmap='gray')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4894b0d5", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "77918a82", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.core.tiff_reader import load_tiff\n", + "# from denoisplit.analysis.paper_plots import show_for_one, get_plotoutput_dir\n", + "# def get_hwt_start(idx):\n", + "# h,w,t = val_dset.idx_manager.hwt_from_idx(idx, grid_size=64)\n", + "# print(h,w,t)\n", + "# pad = val_dset.per_side_overlap_pixelcount()\n", + "# h = h - pad\n", + "# w = w - pad\n", + "# return h,w,t\n", + "\n", + "# def get_crop_from_fulldset_prediction(full_dset_pred, idx, patch_size=256):\n", + "# h,w,t = get_hwt_start(idx)\n", + "# return np.swapaxes(full_dset_pred[t,h:h+patch_size,w:w+patch_size].astype(np.float32)[None], 0, 3)[...,0]\n", + "\n", + "# # CCP vs Microtubules: 925, 659, 502\n", + "# hdn_usplitdata = load_tiff('/group/jug/ashesh/data/paper_stats/Test_PNone_G16_M3_Sk0/pred_disentangle_2402_D23-M3-S0-L0_67.tif')\n", + "\n", + "# # ER vs Microtubule 853, 859, 332\n", + "# # hdn_usplitdata = load_tiff('/group/jug/ashesh/data/paper_stats/Test_PNone_G16_M3_Sk0/pred_disentangle_2402_D23-M3-S0-L0_60.tif')\n", + "\n", + "# # ER vs CCP 327, 479, 637, 568\n", + "# # hdn_usplitdata = load_tiff('/group/jug/ashesh/data/paper_stats/Test_PNone_G16_M3_Sk0/pred_disentangle_2402_D23-M3-S0-L0_59.tif')\n", + "\n", + "# idx = 502 #np.random.randint(len(val_dset))\n", + "# patch_size = 256\n", + "# mmse_count = 50\n", + "# print(idx)\n", + "# show_for_one(idx, val_dset, highsnr_val_dset, model, None, mmse_count=mmse_count, patch_size=patch_size, baseline_preds=[\n", + "# get_crop_from_fulldset_prediction(hdn_usplitdata, idx).astype(np.float32),\n", + "# ], num_samples=0)\n", + "\n", + "\n", + "# plotsdir = get_plotoutput_dir(ckpt_dir, patch_size, mmse_count=mmse_count)\n", + "# model_id = ckpt_dir.strip('/').split('/')[-1]\n", + "# fname = f'patch_comparison_{idx}.png'\n", + "# fpath = os.path.join(plotsdir, fname)\n", + "# plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + "# print(f'Saved to {fpath}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee84e005", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1866e9b2", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cac092b5", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitch_predictions\n", + "from denoisplit.analysis.mmse_prediction import get_dset_predictions\n", + "# from denoisplit.analysis.stitch_prediction import get_predictions as get_dset_predictions\n", + "\n", + "pred_tiled, rec_loss, logvar_tiled, patch_psnr_tuple, pred_std_tiled = get_dset_predictions(model, val_dset,batch_size,\n", + " num_workers=num_workers,\n", + " mmse_count=mmse_count,\n", + " model_type = config.model.model_type,\n", + " )\n", + "tmp = np.round([x.item() for x in patch_psnr_tuple],2)\n", + "print('Patch wise PSNR, as computed during training', tmp,np.mean(tmp))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b693a0c", + "metadata": {}, + "outputs": [], + "source": [ + "idx_list = np.where(logvar_tiled.squeeze() < -6)[0]\n", + "if len(idx_list) > 0:\n", + " plt.imshow(val_dset[idx_list[0]][1][1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8a1573f8", + "metadata": {}, + "outputs": [], + "source": [ + "len(val_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6709de9e", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "sns.histplot(logvar_tiled[::50].squeeze().reshape(-1,))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "771ac350", + "metadata": {}, + "outputs": [], + "source": [ + "print(np.quantile(rec_loss, [0,0.01,0.5, 0.9,0.99,0.999,1]).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "61ca7f49", + "metadata": {}, + "outputs": [], + "source": [ + "val_dset._data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0101ff41", + "metadata": {}, + "outputs": [], + "source": [ + "(1004//128)**2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05f2cdc7", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8673355b", + "metadata": {}, + "outputs": [], + "source": [ + "logvar_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c75b35f1", + "metadata": {}, + "outputs": [], + "source": [ + "if pred_tiled.shape[-1] != val_dset.get_img_sz():\n", + " pad = (val_dset.get_img_sz() - pred_tiled.shape[-1] )//2\n", + " pred_tiled = np.pad(pred_tiled, ((0,0),(0,0),(pad,pad),(pad,pad)))\n", + "\n", + "pred = stitch_predictions(pred_tiled,val_dset, smoothening_pixelcount=0)\n", + "if len(np.unique(logvar_tiled)) == 1:\n", + " logvar = None\n", + "else:\n", + " logvar = stitch_predictions(logvar_tiled,val_dset, smoothening_pixelcount=0)\n", + "pred_std = stitch_predictions(pred_std_tiled,val_dset, smoothening_pixelcount=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c6c82f7", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(pred[0,...,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f950003b", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d2ad25d", + "metadata": {}, + "outputs": [], + "source": [ + "def print_ignored_pixels():\n", + " ignored_pixels = 1\n", + " while(pred[:10,-ignored_pixels:,-ignored_pixels:,].std() ==0):\n", + " ignored_pixels+=1\n", + " ignored_pixels-=1\n", + " print(f'In {pred.shape}, last {ignored_pixels} many rows and columns are all zero.')\n", + " return ignored_pixels\n", + "\n", + "actual_ignored_pixels = print_ignored_pixels()" + ] + }, + { + "cell_type": "markdown", + "id": "b8474735", + "metadata": {}, + "source": [ + "## Ignore the pixels which are present in the last few rows and columns. \n", + "1. They don't come in the batches. So, in prediction, they are simply zeros. So they are being are ignored right now. \n", + "2. For the border pixels which are on the top and the left, overlapping yields worse performance. This is becuase, there is nothing to overlap on one side. So, they are essentially zero padded. This makes the performance worse. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcb2db09", + "metadata": {}, + "outputs": [], + "source": [ + "actual_ignored_pixels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cadedfcd", + "metadata": {}, + "outputs": [], + "source": [ + "if config.data.data_type in [DataType.OptiMEM100_014,\n", + " DataType.SemiSupBloodVesselsEMBL, \n", + " DataType.Pavia2VanillaSplitting,\n", + " DataType.ExpansionMicroscopyMitoTub,\n", + " DataType.ShroffMitoEr,\n", + " DataType.HTIba1Ki67]:\n", + " ignored_last_pixels = 32 \n", + "elif config.data.data_type == DataType.BioSR_MRC:\n", + " ignored_last_pixels = 44\n", + " # assert val_dset.get_img_sz() == 64\n", + " # ignored_last_pixels = 108\n", + "else:\n", + " ignored_last_pixels = 0\n", + "\n", + "ignore_first_pixels = 0\n", + "# ignored_last_pixels = 160\n", + "assert actual_ignored_pixels <= ignored_last_pixels, f'Set ignored_last_pixels={actual_ignored_pixels}'\n", + "print(ignored_last_pixels)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "226fed05", + "metadata": {}, + "outputs": [], + "source": [ + "tar = val_dset._data\n", + "def ignore_pixels(arr):\n", + " if ignore_first_pixels:\n", + " arr = arr[:,ignore_first_pixels:,ignore_first_pixels:]\n", + " if ignored_last_pixels:\n", + " arr = arr[:,:-ignored_last_pixels,:-ignored_last_pixels]\n", + " return arr\n", + "\n", + "pred = ignore_pixels(pred)\n", + "tar = ignore_pixels(tar)\n", + "if pred_std is not None:\n", + " pred_std = ignore_pixels(pred_std)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1be10fd7", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.analysis.plot_utils import *\n", + "# def add_pixel_kde(ax,\n", + "# rect: List[float],\n", + "# data1: np.ndarray,\n", + "# data2: Union[np.ndarray, None],\n", + "# min_labelsize: int,\n", + "# color1='r',\n", + "# color2='black',\n", + "# color_xtick='white',\n", + "# label1='Target',\n", + "# label2='Predicted'):\n", + "# \"\"\"\n", + "# Adds KDE (density plot) of data1(eg: target) and data2(ex: predicted) image pixel values as an inset\n", + "# \"\"\"\n", + "# inset_ax = add_subplot_axes(ax, rect, facecolor=\"None\", min_labelsize=min_labelsize)\n", + " \n", + "# inset_ax.tick_params(axis='x', colors=color_xtick)\n", + "\n", + "# sns.kdeplot(data=data1.reshape(-1, ), ax=inset_ax, color=color1, label=label1)\n", + "# if data2 is not None:\n", + "# sns.kdeplot(data=data2.reshape(-1, ), ax=inset_ax, color=color2, label=label2)\n", + "# inset_ax.set_xlim(left=0)\n", + "# xticks = inset_ax.get_xticks()\n", + "# # inset_ax.set_xticks([xticks[0], xticks[-1]])\n", + "# inset_ax.set_xticks([])\n", + "# clean_for_xaxis_plot(inset_ax)\n", + "\n", + "\n", + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "\n", + "# inset_rect=[0.1,0.1,0.4,0.2]\n", + "# inset_min_labelsize=10\n", + "# color_ch_list=['goldenrod','cyan']\n", + "\n", + "# _,ax = plt.subplots(figsize=(15,10),ncols=3,nrows=2)\n", + "# idx = 8\n", + "# pred1_crop = ch1_pred_unnorm[idx,1116:1372,1064:1320].copy()\n", + "# pred2_crop = ch2_pred_unnorm[idx,1116:1372,1064:1320].copy()\n", + "# pred1_crop[pred1_crop<0] = 0\n", + "# pred2_crop[pred2_crop<0] = 0\n", + "\n", + "# tar1_crop = tar[idx,1116:1372,1064:1320,0]\n", + "# tar2_crop = tar[idx,1116:1372,1064:1320,1]\n", + "\n", + "# ax[0,0].imshow(tar1_crop+tar2_crop)\n", + "# ax[0,1].imshow(tar1_crop)\n", + "# ax[0,2].imshow(tar2_crop)\n", + "\n", + "# ax[1,0].imshow(pred1_crop+pred2_crop)\n", + "# ax[1,1].imshow(pred1_crop)\n", + "# ax[1,2].imshow(pred2_crop)\n", + "# clean_ax(ax)\n", + "# add_pixel_kde(ax[0,0], inset_rect, \n", + "# tar1_crop, \n", + "# tar2_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1=color_ch_list[0], color2=color_ch_list[1])\n", + "\n", + "# add_pixel_kde(ax[1,1], inset_rect, \n", + "# pred1_crop, \n", + "# tar1_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1='red', color2=color_ch_list[0])\n", + "# add_pixel_kde(ax[1,2], inset_rect, \n", + "# pred2_crop, \n", + "# tar2_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1='red', color2=color_ch_list[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d8b680f", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.metrics import structural_similarity\n", + "\n", + "def _avg_psnr(target, prediction, psnr_fn):\n", + " output = np.mean([psnr_fn(target[i:i + 1], prediction[i:i + 1]).item() for i in range(len(prediction))])\n", + " return round(output, 2)\n", + "\n", + "\n", + "def avg_range_inv_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, RangeInvariantPsnr)\n", + "\n", + "\n", + "def avg_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, PSNR)\n", + "\n", + "\n", + "def compute_masked_psnr(mask, tar1, tar2, pred1, pred2):\n", + " mask = mask.astype(bool)\n", + " mask = mask[..., 0]\n", + " tmp_tar1 = tar1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_pred1 = pred1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_tar2 = tar2[mask].reshape((len(tar2), -1, 1))\n", + " tmp_pred2 = pred2[mask].reshape((len(tar2), -1, 1))\n", + " psnr1 = avg_range_inv_psnr(tmp_tar1, tmp_pred1)\n", + " psnr2 = avg_range_inv_psnr(tmp_tar2, tmp_pred2)\n", + " return psnr1, psnr2\n", + "\n", + "def avg_ssim(target, prediction):\n", + " ssim = [structural_similarity(target[i],prediction[i], data_range=(target[i].max() - target[i].min())) for i in range(len(target))]\n", + " return np.mean(ssim),np.std(ssim)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7311e08a", + "metadata": {}, + "outputs": [], + "source": [ + "sep_mean, sep_std = model.data_mean, model.data_std\n", + "if isinstance(sep_mean, dict):\n", + " sep_mean = sep_mean['target']\n", + " sep_std = sep_std['target']\n", + "\n", + "if isinstance(sep_mean, int):\n", + " pass\n", + "else:\n", + " sep_mean = sep_mean.squeeze()[None,None,None]\n", + " sep_std = sep_std.squeeze()[None,None,None]\n", + " sep_mean = sep_mean.cpu().numpy() \n", + " sep_std = sep_std.cpu().numpy()\n", + "\n", + "tar_normalized = (tar - sep_mean)/ sep_std" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6e19c77", + "metadata": {}, + "outputs": [], + "source": [ + "pred_std.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b31cd6c4", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "199313d1", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.metrics.calibration import Calibration\n", + "# calib = Calibration(num_bins=30, mode='pixelwise')\n", + "# native_stats = calib.compute_stats(pred, pred_std, tar_normalized)\n", + "# count = np.array(native_stats[0]['bin_count'])\n", + "# count = count / count.sum()\n", + "# count.cumsum()[:-1]\n", + "# plt.plot(native_stats[0]['rmv'][1:-1], native_stats[0]['rmse'][1:-1], 'o')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d58e8c1", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.metrics.calibration import get_calibrated_factor_for_stdev\n", + "# inp, _ = val_dset[0]\n", + "# plotsdir = get_plotoutput_dir(ckpt_dir, inp.shape[1], mmse_count=mmse_count)\n", + "# model_id = ckpt_dir.strip('/').split('/')[-1]\n", + "# fname = f'calibration_stats_{model_id}.npy'\n", + "# fpath = os.path.join(plotsdir, fname)\n", + "\n", + "# if eval_datasplit_type == DataSplitType.Val:\n", + "# calib_factor0 = get_calibrated_factor_for_stdev(pred[...,0], np.log(pred_std[...,0]**2), tar_normalized[...,0], batch_size=8, lr=0.1)\n", + "# calib_factor1 = get_calibrated_factor_for_stdev(pred[...,1], np.log(pred_std[...,1]**2), tar_normalized[...,1], batch_size=8, lr=0.1)\n", + "# print(calib_factor0, calib_factor1)\n", + "# calib_factor = np.array([calib_factor0, calib_factor1]).reshape(1,1,1,2)\n", + "# np.save(fpath, calib_factor)\n", + "# print(f'Saved evaluation stats fitted on validation set to {fpath}')\n", + "\n", + "# elif eval_datasplit_type == DataSplitType.Test:\n", + "# print('Loading the calibration factor from the file', fpath)\n", + "# calib_factor = np.load(fpath)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "077f4d02", + "metadata": {}, + "outputs": [], + "source": [ + "# /group/jug/ashesh/data/paper_figures/patch_128_mmse_15/2402-D16M3S0-145/calibration_stats_145.npy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "089ea14e", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.analysis.paper_plots import plot_calibration\n", + "\n", + "# calib = Calibration(num_bins=30, mode='pixelwise')\n", + "# stats = calib.compute_stats(pred, 2* np.log(pred_std * calib_factor), tar_normalized)\n", + "# _,ax = plt.subplots(figsize=(5,5))\n", + "# plot_calibration(ax, stats)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2402048", + "metadata": {}, + "outputs": [], + "source": [ + "q_vals = [0.01, 0.1,0.5,0.9,0.95, 0.99,1]\n", + "for i in range(tar_normalized.shape[-1]):\n", + " print(f'Channel {i}:', np.quantile(tar_normalized[...,i], q_vals).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fef4512", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(6,6))\n", + "for i in range(tar.shape[-1]):\n", + " sns.histplot(tar[:,::10,::10,i].reshape(-1,), color='g', label=f'{i}', kde=True)\n", + "\n", + "plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb572707", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.data_loader.schroff_rawdata_loader import mito_channel_fnames\n", + "# from denoisplit.core.tiff_reader import load_tiff\n", + "# import seaborn as sns\n", + "\n", + "# fpaths = [os.path.join(datapath, x) for x in mito_channel_fnames()]\n", + "# fpath = fpaths[0]\n", + "# print(fpath)\n", + "# img = load_tiff(fpaths[0])\n", + "# temp = img.copy()\n", + "# sns.histplot(temp[:,:,::10,::10].reshape(-1,))\n", + "# plt.hist(temp[:,:,::10,::10].reshape(-1,),bins=100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24708c4c", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.patches as patches\n", + "import matplotlib\n", + "from denoisplit.analysis.plot_error_utils import plot_error\n", + "nrows = pred.shape[-1]\n", + "img_sz = 3\n", + "_,ax = plt.subplots(figsize=(4*img_sz,nrows*img_sz),ncols=4,nrows=nrows)\n", + "idx = np.random.randint(len(pred))\n", + "print(idx)\n", + "for ch_id in range(nrows):\n", + " ax[ch_id,0].imshow(tar_normalized[idx,..., ch_id], cmap='magma')\n", + " ax[ch_id,1].imshow(pred[idx,:,:,ch_id], cmap='magma')\n", + " plot_error(tar_normalized[idx,...,ch_id], \n", + " pred[idx,:,:,ch_id], \n", + " cmap = matplotlib.cm.coolwarm, \n", + " ax = ax[ch_id,2], max_val = None)\n", + "\n", + " cropsz = 256\n", + " h_s = np.random.randint(0, tar_normalized.shape[1] - cropsz)\n", + " h_e = h_s + cropsz\n", + " w_s = np.random.randint(0, tar_normalized.shape[2] - cropsz)\n", + " w_e = w_s + cropsz\n", + "\n", + " plot_error(tar_normalized[idx,h_s:h_e,w_s:w_e, ch_id], \n", + " pred[idx,h_s:h_e,w_s:w_e,ch_id], \n", + " cmap = matplotlib.cm.coolwarm, \n", + " ax = ax[ch_id,3], max_val = None)\n", + "\n", + " # Add rectangle to the region\n", + " rect = patches.Rectangle((w_s, h_s), w_e-w_s, h_e-h_s, linewidth=1, edgecolor='r', facecolor='none')\n", + " ax[ch_id,2].add_patch(rect)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "919db5ef", + "metadata": {}, + "outputs": [], + "source": [ + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "pred_unnorm = []\n", + "for i in range(pred.shape[-1]):\n", + " if sep_std.shape[-1]==1:\n", + " temp_pred_unnorm = pred[...,i]*sep_std[...,0] + sep_mean[...,0]\n", + " else:\n", + " temp_pred_unnorm = pred[...,i]*sep_std[...,i] + sep_mean[...,i]\n", + " pred_unnorm.append(temp_pred_unnorm)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b39f2ddb", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.scripts.evaluate import get_highsnr_data\n", + "highres_data = get_highsnr_data(config, data_dir, eval_datasplit_type)\n", + "if highres_data is not None:\n", + " highres_data = ignore_pixels(highres_data).copy()\n", + " if data_t_list is not None:\n", + " highres_data = highres_data[data_t_list].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a0d4a8d", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.scripts.evaluate import compute_multiscale_ssim\n", + "if highres_data is not None:\n", + " print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + " psnr1 = avg_range_inv_psnr(highres_data[...,0], pred_unnorm[0])\n", + " psnr2 = avg_range_inv_psnr(highres_data[...,1], pred_unnorm[1])\n", + " tar_tmp = (highres_data - sep_mean) /sep_std\n", + " # tar0_tmp = (highres_data[...,0] - sep_mean[...,0]) /sep_std[...,0]\n", + " ssim1, ssim2 = compute_multiscale_ssim(tar_tmp, pred )\n", + " # ssim1_hres_mean, ssim1_hres_std = avg_ssim(highres_data[...,0], pred_unnorm[0])\n", + " # ssim2_hres_mean, ssim2_hres_std = avg_ssim(highres_data[...,1], pred_unnorm[1])\n", + " print('PSNR on Highres', psnr1, psnr2)\n", + " print('SSIM on Highres', np.round(ssim1,3), np.round(ssim2,3))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38bfba7c", + "metadata": {}, + "outputs": [], + "source": [ + "# 1 epoch with 0.75, 0.25: 0.75 being on the side of original data\n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 28.77 28.16\n", + "SSIM on Highres 0.873 0.796\n", + "\n", + "# 1 epoch with 0.75, 0.25: 0.75 being on the side of original data\n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 28.91 28.18\n", + "SSIM on Highres 0.877 0.821\n", + "\n", + "# 1 epoch with 0.75, 0.25: 0.75 being on the side of original data\n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 28.54 28.03\n", + "SSIM on Highres 0.87 0.809\n", + "\n", + "\n", + "# 1 epoch with 0.9,0.1 \n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 28.15 27.2\n", + "SSIM on Highres 0.877 0.817\n", + "\n", + "# 5 epochs with 0.9, 0.1\n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 25.56 25.66\n", + "SSIM on Highres 0.637 0.735\n", + "\n", + "\n", + "# 1 epoch\n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 28.96 28.57\n", + "SSIM on Highres 0.874 0.838\n", + "\n", + "# 1 epoch \n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 28.4 27.93\n", + "SSIM on Highres 0.865 0.833\n", + "\n", + "# 2 epochs\n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 28.65 28.3\n", + "SSIM on Highres 0.88 0.845\n", + "\n", + "# 5 epochs\n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 28.67 28.28\n", + "SSIM on Highres 0.864 0.839\n", + "\n", + "Test_PNone_G64_M10_Sk44\n", + "PSNR on Highres 30.61 30.26\n", + "SSIM on Highres 0.925 0.901" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d75d6a1", + "metadata": {}, + "outputs": [], + "source": [ + "eps = 0.1\n", + "if config.model.model_type == ModelType.DenoiserSplitter:\n", + " ch_idx = 0\n", + " def predict(inp):\n", + " inp = model.denoise_one_channel(inp, model._denoiser_input)\n", + " out = model(inp)[0]\n", + " return model.likelihood.distr_params(out)['mean'].cpu().numpy()\n", + "\n", + " idx = np.random.randint(0, len(val_dset))\n", + " inp_tmp, tar_tmp = val_dset[idx]\n", + " h,w,t = val_dset.idx_manager.hwt_from_idx(idx)\n", + " h -= val_dset.per_side_overlap_pixelcount()\n", + " w -= val_dset.per_side_overlap_pixelcount()\n", + " print(idx)\n", + " inp_tmp = torch.Tensor(inp_tmp[None]).cuda()\n", + "\n", + " with torch.no_grad():\n", + " clean_pred1 = predict(inp_tmp)\n", + " clean_pred2 = predict(inp_tmp)\n", + " clean_pred3 = predict(inp_tmp)\n", + " pred_mmse_arr = []\n", + " for _ in range(50):\n", + " clean_pred4 = predict(inp_tmp)\n", + " pred_mmse_arr.append(clean_pred4)\n", + " pred_mmse = np.mean(pred_mmse_arr, axis=0, keepdims=False)\n", + "\n", + " _,ax = plt.subplots(ncols=6, figsize=(18,3))\n", + " ax[0].imshow(inp_tmp[0,0].cpu().numpy() ,cmap='magma')\n", + " ax[1].imshow(highres_data[t,h:h+256,w:w+256,ch_idx] , cmap='magma')\n", + " ax[2].imshow(clean_pred1[0,ch_idx], cmap='magma')\n", + " ax[3].imshow(clean_pred2[0,ch_idx], cmap='magma')\n", + " ax[4].imshow(pred_mmse[0,ch_idx], cmap='magma')\n", + " ax[5].imshow(np.std(pred_mmse_arr, axis=0, keepdims=False)[0,ch_idx]/(eps + np.abs(pred_mmse[0,ch_idx])), cmap='magma')\n", + " unnorm_temp_pred = (pred_mmse* data_std + data_mean)\n", + " minv = unnorm_temp_pred[0,ch_idx].min()\n", + " maxv = unnorm_temp_pred[0,ch_idx].max()\n", + " print(minv, maxv)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13fc1983", + "metadata": {}, + "outputs": [], + "source": [ + "rmse_arr = []\n", + "psnr_arr = []\n", + "rinv_psnr_arr = []\n", + "ssim_arr = []\n", + "for ch_id in range(pred.shape[-1]):\n", + " rmse =np.sqrt(((pred[...,ch_id] - tar_normalized[...,ch_id])**2).reshape(len(pred),-1).mean(axis=1))\n", + " rmse_arr.append(rmse)\n", + " psnr = avg_psnr(tar_normalized[...,ch_id].copy(), pred[...,ch_id].copy()) \n", + " rinv_psnr = avg_range_inv_psnr(tar_normalized[...,ch_id].copy(), pred[...,ch_id].copy())\n", + " ssim_mean, ssim_std = avg_ssim(tar[...,ch_id], pred_unnorm[ch_id])\n", + " psnr_arr.append(psnr)\n", + " rinv_psnr_arr.append(rinv_psnr)\n", + " ssim_arr.append((ssim_mean,ssim_std))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e87868b7", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + "print('Rec Loss',np.round(rec_loss.mean(),3) )\n", + "print('RMSE', '\\t'.join([str(np.mean(x).round(3)) for x in rmse_arr]))\n", + "print('PSNR', '\\t'.join([str(x) for x in psnr_arr]))\n", + "print('RangeInvPSNR','\\t'.join([str(x) for x in rinv_psnr_arr]))\n", + "print('SSIM','\\t'.join([f'{round(x,3)}±{round(y,4)}' for (x,y) in ssim_arr]))\n", + "print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73ba24ac", + "metadata": {}, + "outputs": [], + "source": [ + "if config.model.model_type == ModelType.LadderVaeSemiSupervised:\n", + " from denoisplit.analysis.plot_utils import add_pixel_kde\n", + " inset_rect=[0.1,0.1,0.4,0.2]\n", + " min_labelsize = 15\n", + "\n", + " nimgs=5\n", + " crp_sz = 400\n", + " img_sz = 8\n", + "\n", + " _,ax = plt.subplots(figsize=(4*img_sz,img_sz*nimgs),ncols=5,nrows=nimgs)\n", + " clean_ax(ax[1:,])\n", + " clean_ax(ax[:,1:])\n", + " img_idx_list = np.random.permutation(np.arange(len(tar1)))[:nimgs] #[19,23,15,18,4] # \n", + " for ax_idx in range(nimgs):\n", + " img_idx = img_idx_list[ax_idx]\n", + " overlapping_pred = pred1[img_idx] + pred2[img_idx]\n", + " overlapping_min = min(tar1[img_idx].min(),overlapping_pred.min())\n", + " overlapping_max = max(tar1[img_idx].max(),overlapping_pred.max())\n", + "\n", + " ax[ax_idx,0].imshow(tar1[img_idx])#,vmin=overlapping_min,vmax=overlapping_max)\n", + " ax[ax_idx,1].imshow(overlapping_pred)#,vmin=overlapping_min,vmax=overlapping_max)\n", + "\n", + " ch1_min = tar2[img_idx].min()#,pred1[img_idx].min())\n", + " ch1_max = tar2[img_idx].max()#,pred1[img_idx].max())\n", + " ax[ax_idx,2].imshow(tar2[img_idx])#,vmin=ch1_min,vmax=ch1_max)\n", + " ax[ax_idx,3].imshow(pred1[img_idx])#,vmin=ch1_min,vmax=ch1_max)\n", + "\n", + " ax[ax_idx,4].imshow(pred2[img_idx])\n", + " ax[ax_idx,0].set_ylabel(f'{img_idx}',fontsize=min_labelsize)\n", + "\n", + " # add_pixel_kde(ax[ax_idx,1],\n", + " # inset_rect,\n", + " # tar1 [img_idx],\n", + " # data2 =overlapping_pred,\n", + " # min_labelsize=min_labelsize)\n", + " \n", + " # add_pixel_kde(ax[ax_idx,3],\n", + " # inset_rect,\n", + " # tar2 [img_idx],\n", + " # data2 =pred1[img_idx],\n", + " # min_labelsize=min_labelsize)\n", + " \n", + "\n", + " ax[0,0].set_title('Inp')\n", + " ax[0,1].set_title('Recons')\n", + " ax[0,2].set_title('GT 1')\n", + " ax[0,3].set_title('Pred 1')\n", + " ax[0,4].set_title('Pred 2')\n", + "\n", + "#" + ] + }, + { + "cell_type": "markdown", + "id": "f19442f1", + "metadata": {}, + "source": [ + "### To save to tiff file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3a537930", + "metadata": {}, + "outputs": [], + "source": [ + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "# input_pred_unnorm = pred[...,2]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = input_pred_unnorm - ch1_pred_unnorm\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy() #ch2_pred_unnorm - ch2_pred_unnorm.min()\n", + "\n", + "# ch1_pred_unnorm = ch1_pred_unnorm.astype(np.int32)\n", + "# input_pred_unnorm = input_pred_unnorm.astype(np.int32)\n", + "# ch2_pred_unnorm = ch2_pred_unnorm.astype(np.int32)\n", + "\n", + "# data = np.concatenate([val_dset._data[:,:480,:480], ch1_pred_unnorm[...,None],\n", + "# ch2_pred_unnorm[...,None], input_pred_unnorm[...,None]],\n", + "# axis=-1)\n", + "\n", + "# import tifffile\n", + "# tifffile.imwrite(\"prediction2.tif\", \n", + "# np.swapaxes(data[:,None],1,4)[...,0].astype(np.uint16),\n", + "# imagej=True, \n", + "# # metadata={ 'axes': 'ZYXC'}, \n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6e00983", + "metadata": {}, + "outputs": [], + "source": [ + "_, ax = plt.subplots(figsize=(10,5),ncols=2)\n", + "ax[0].imshow(highsnr_val_dset._data[0,:200,:200,0])\n", + "ax[1].imshow(val_dset._data[0,:200,:200,0])\n", + "highsnr_val_dset._data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad02e8d3", + "metadata": {}, + "outputs": [], + "source": [ + "break here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b67c59da", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.analysis.paper_plots import show_for_one\n", + "# # show_for_one(np.random.randint(len(val_dset)), mmse_count=50, patch_size=256)\n", + "# # show_for_one(899, mmse_count=50, patch_size=256)\n", + "# # show_for_one(51, mmse_count=50, patch_size=256)\n", + "# # # show_for_one(352, mmse_count=50, patch_size=256)\n", + "# # show_for_one(872, mmse_count=50, patch_size=256)\n", + "# # show_for_one(552, mmse_count=50, patch_size=256)\n", + "# 656, 327, 612, 490\n", + "# 51, 899, 352, 872, 552 ER vs Microtubules (144)\n", + "# 716, 599, 173 CCP vs Microtubules (145)\n", + "# 703, 189, 423 ER vs CCP (143)\n", + "idx = 599#np.random.randint(len(val_dset))\n", + "patch_size = 256\n", + "mmse_count = 50\n", + "print(idx)\n", + "# fname = f'patch_comparison_{idx}.png'\n", + "# show_for_one(idx, val_dset, highsnr_val_dset, model, None, mmse_count=mmse_count, patch_size=patch_size, baseline_preds=[\n", + "# get_crop_from_fulldset_prediction(hdn_usplitdata, idx).astype(np.float32),\n", + "# ], num_samples=0)\n", + "\n", + "show_for_one(idx, val_dset, highsnr_val_dset, model, stats, mmse_count=mmse_count, patch_size=patch_size, num_samples=2)\n", + "\n", + "plotsdir = get_plotoutput_dir(ckpt_dir, patch_size, mmse_count=mmse_count)\n", + "model_id = ckpt_dir.strip('/').split('/')[-1]\n", + "fname = f'sampling_figure_{idx}_{model_id}.png'\n", + "fpath = os.path.join(plotsdir, fname)\n", + "plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + "print(f'Saved to {fpath}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bda56802", + "metadata": {}, + "outputs": [], + "source": [ + "hdn_usplitdata.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "43fcdb91", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e2a75811", + "metadata": {}, + "outputs": [], + "source": [ + "break here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "441abaf6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "824ecf7e", + "metadata": {}, + "source": [ + "## Creating tiff file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de631db9", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.paper_plots import get_plotoutput_dir, get_predictions\n", + "patch_size = 256\n", + "mmse_count = 50\n", + "idx_list = [51, 899, 352, 872, 552, 841] # Tub vs MT\n", + "\n", + "\n", + "plotsdir = get_plotoutput_dir(ckpt_dir, patch_size, mmse_count=mmse_count)\n", + "for idx in idx_list:\n", + " inp, tar, tar_hsnr, recon_img_list = get_predictions(idx, val_dset, model, mmse_count=mmse_count, patch_size=patch_size)\n", + " highsnr_val_dset.set_img_sz(patch_size, 64)\n", + " highsnr_val_dset.disable_noise()\n", + " _, tar_hsnr = highsnr_val_dset[idx]\n", + " plotfpath = os.path.join(plotsdir, f'{idx}.npy')\n", + " np.save(plotfpath, {'inp':inp, 'tar':tar, 'tar_hsnr':tar_hsnr, 'recon_img_list':recon_img_list})\n", + " print(f'Generated {plotfpath}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a18e9b50", + "metadata": {}, + "outputs": [], + "source": [ + "ddict = np.load('/group/jug/ashesh/data/paper_figures/patch_256_mmse_50/2402-D16M3S0-150/841.npy', allow_pickle=True)\n", + "plt.imshow(ddict[()]['inp'][0,0].cpu().numpy())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "98a0af0f", + "metadata": {}, + "outputs": [], + "source": [ + "plot_crops(ddict[()]['inp'], ddict[()]['tar'], ddict[()]['tar_hsnr'], ddict[()]['recon_img_list'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b84bc45", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0465dd97", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.io import imsave\n", + "import numpy as np\n", + "pred_unnorm = np.concatenate([ch1_pred_unnorm[...,None],\n", + " ch2_pred_unnorm[...,None]],\n", + " axis=-1)\n", + "for ch_idx in [0,1]:\n", + " tif_fname = f'{fname_prefix}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}_C{ch_idx}.tif'\n", + " tif_fpath=os.path.join('paper_tifs',tif_fname)\n", + " if config.data.data_type in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " output = np.concatenate([\n", + " pred_unnorm[None,:50,...,ch_idx],tar[None,:50,...,ch_idx],\n", + " ],axis=0)\n", + " else:\n", + " output = np.concatenate([\n", + " pred_unnorm[:1,...,ch_idx],tar[:1,...,ch_idx],\n", + " ],axis=0)\n", + " imsave(tif_fpath,output,plugin='tifffile')\n", + " print(tif_fpath)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92a8d256", + "metadata": {}, + "outputs": [], + "source": [ + "! ls -lhrt paper_tifs/2211-D8M3S0-*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f7a3da19", + "metadata": {}, + "outputs": [], + "source": [ + "# !ls paper_tifs/2211-D3M3S0-0_P64_G*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7b3c066", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(val_dset))\n", + "inp, tar = val_dset[idx]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c7b56b7", + "metadata": {}, + "outputs": [], + "source": [ + "if len(inp) > 1:\n", + " _,ax = plt.subplots(figsize=(10,2.5),ncols=4)\n", + " ax[0].imshow(inp[0])\n", + " ax[1].imshow(inp[1])\n", + " ax[2].imshow(inp[2])\n", + " ax[3].imshow(inp[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f02d1078", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b9fe5ce", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(10,10))\n", + "# tmp_data =tar_unnorm[idx,:,:,1]\n", + "# q = np.quantile(tmp_data,0.95)\n", + "# tmp_data[tmp_data >q] = q\n", + "# plt.imshow(tmp_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f4d490b", + "metadata": {}, + "outputs": [], + "source": [ + "pred_unnorm.min()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d38fa69", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,20),ncols=2,nrows=2)\n", + "ax[0,0].set_title('Channel 1',size=20)\n", + "ax[0,1].set_title('Channel 2',size=20)\n", + "ax[0,0].set_ylabel('Target',size=20)\n", + "ax[1,0].set_ylabel('Predictions',size=20)\n", + "ax[0,0].imshow(tar_unnorm[idx,:,:,0])\n", + "ax[0,1].imshow(tar_unnorm[idx,:,:,1])\n", + "ax[1,0].imshow(pred_unnorm[idx,:,:,0])\n", + "ax[1,1].imshow(pred_unnorm[idx,:,:,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79d4b581", + "metadata": {}, + "outputs": [], + "source": [ + "idx = 0#np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,30),ncols=2,nrows=3)\n", + "ax[0,0].set_title('Target',size=20)\n", + "ax[0,1].set_title('Prediction',size=20)\n", + "ax[0,0].set_ylabel('Mixed Input',size=20)\n", + "ax[1,0].set_ylabel('Channel 1',size=20)\n", + "ax[2,0].set_ylabel('Channel 2',size=20)\n", + "sz = 400\n", + "ax[0,0].imshow(np.mean(tar_unnorm[idx, 1000:1000+sz,400:400+sz], axis=2))\n", + "ax[0,1].imshow(np.mean(pred_unnorm[idx,1000:1000+sz,400:400+sz], axis=2))\n", + "\n", + "ax[1,0].imshow(tar_unnorm[idx, 1000:1000+sz,400:400+sz,0],vmax=126,vmin=88)\n", + "ax[1,1].imshow(pred_unnorm[idx,1000:1000+sz,400:400+sz,0], vmax=126,vmin=88)\n", + "\n", + "ax[2,0].imshow(tar_unnorm[idx, 1000:1000+sz,400:400+sz,1],vmax=126,vmin=78)\n", + "ax[2,1].imshow(pred_unnorm[idx,1000:1000+sz,400:400+sz,1],vmax=126,vmin=78)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c6c6d82", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm[idx, 1000:1500,400:900,0].std()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2fa229c6", + "metadata": {}, + "outputs": [], + "source": [ + "pred_unnorm[idx,1000:1500,400:900,0].std()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8285b5a8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93f14602", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,30),ncols=2,nrows=3)\n", + "ax[0,0].set_title('Target',size=20)\n", + "ax[0,1].set_title('Prediction',size=20)\n", + "ax[0,0].set_ylabel('Mixed Input',size=20)\n", + "ax[1,0].set_ylabel('Channel 1',size=20)\n", + "ax[2,0].set_ylabel('Channel 2',size=20)\n", + "\n", + "ax[0,0].imshow(np.mean(tar_unnorm[idx, 1000:1500,400:900], axis=2))\n", + "ax[0,1].imshow(np.mean(pred_unnorm[idx,1000:1500,400:900], axis=2))\n", + "\n", + "ax[1,0].imshow(tar_unnorm[idx, 1000:1500,400:900,0])\n", + "ax[1,1].imshow(pred_unnorm[idx,1000:1500,400:900,0])\n", + "\n", + "ax[2,0].imshow(tar_unnorm[idx, 1000:1500,400:900,1])\n", + "ax[2,1].imshow(pred_unnorm[idx,1000:1500,400:900,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5306061", + "metadata": {}, + "outputs": [], + "source": [ + "break here" + ] + }, + { + "cell_type": "markdown", + "id": "e63fb49d", + "metadata": {}, + "source": [ + "## Comparing PSNR with high res data. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fe03625", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.data_split_type import get_datasplit_tuples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62ae1c2b", + "metadata": {}, + "outputs": [], + "source": [ + "if eval_datasplit_type == DataSplitType.Val:\n", + " N = len(pred1)/config.training.val_fraction\n", + "elif eval_datasplit_type == DataSplitType.Test:\n", + " N = len(pred1)/config.training.test_fraction\n", + "train_idx,val_idx,test_idx = get_datasplit_tuples(config.training.val_fraction,config.training.test_fraction,N,\n", + " starting_train=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67bf4a4c", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4a5c2d6", + "metadata": {}, + "outputs": [], + "source": [ + "highres_actin = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/actin-60x-noise2-highsnr.tif')[...,None]\n", + "highres_mito = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/mito-60x-noise2-highsnr.tif')[...,None]\n", + "\n", + "if eval_datasplit_type == DataSplitType.Val:\n", + " highres_data = np.concatenate([highres_actin[val_idx[0]:val_idx[1]],\n", + " highres_mito[val_idx[0]:val_idx[1]]],\n", + " axis=-1).astype(np.float32)\n", + "elif eval_datasplit_type == DataSplitType.Test:\n", + " highres_data = np.concatenate([highres_actin[test_idx[0]:test_idx[1]],\n", + " highres_mito[test_idx[0]:test_idx[1]]],\n", + " axis=-1).astype(np.float32)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d325d7b", + "metadata": {}, + "outputs": [], + "source": [ + "thresh = np.quantile(highres_data,config.data.clip_percentile)\n", + "highres_data[highres_data > thresh]=thresh\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8daa9662", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,8),ncols=2,nrows=2)\n", + "ax[0,0].imshow(tar_unnorm[5,...,0])\n", + "ax[0,1].imshow(highres_data[5,...,0])\n", + "ax[1,0].imshow(tar_unnorm[8,...,1])\n", + "ax[1,1].imshow(highres_data[8,...,1])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b53ddb0e", + "metadata": {}, + "outputs": [], + "source": [ + "print('PSNR with HighRes', avg_psnr(highres_data[...,0], pred1),avg_psnr(highres_data[...,1], pred2))\n", + "print('RangeInvPSNR with HighRes', avg_range_inv_psnr(highres_data[...,0], pred1), \n", + " avg_range_inv_psnr(highres_data[...,1], pred2))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ba9fbf7", + "metadata": {}, + "outputs": [], + "source": [ + "# RangeInvPSNR with HighRes 16.82 18.33\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd49794d", + "metadata": {}, + "outputs": [], + "source": [ + "tar_1_tmp.dtype" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8537fa04", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.psnr import fix_range, zero_mean\n", + "def fix_range_with_highresdata(pred,tar):\n", + " pred_1_tmp = torch.Tensor(pred.reshape(len(pred),-1))\n", + " tar_1_tmp = torch.Tensor(tar.reshape(len(tar),-1))\n", + " pred_1_tmp = zero_mean(pred_1_tmp)\n", + " tar_1_tmp = zero_mean(tar_1_tmp)\n", + "# import pdb;pdb.set_trace()\n", + " tar_1_tmp = tar_1_tmp / torch.std(tar_1_tmp, dim=1, keepdim=True)\n", + " \n", + " pred_1_tmp = fix_range(tar_1_tmp,pred_1_tmp)\n", + " pred_1_tmp = pred_1_tmp.reshape_as(torch.Tensor(pred))\n", + " tar_1_tmp = tar_1_tmp.reshape_as(torch.Tensor(pred))\n", + " return pred_1_tmp, tar_1_tmp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3faaee3", + "metadata": {}, + "outputs": [], + "source": [ + "pred1_tmp, tar1_tmp = fix_range_with_highresdata(pred1, highres_data[...,0])\n", + "pred2_tmp, tar2_tmp = fix_range_with_highresdata(pred2, highres_data[...,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7076ff9c", + "metadata": {}, + "outputs": [], + "source": [ + "ssim1_mean, ssim1_std = avg_ssim(tar1_tmp.numpy(), pred1_tmp.numpy())\n", + "ssim2_mean, ssim2_std = avg_ssim(tar2_tmp.numpy(), pred2_tmp.numpy())\n", + "print(ssim1_mean, ssim2_mean)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6557f6b", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "ax[0].imshow(pred_1_tmp[0])\n", + "ax[1].imshow(tar_1_tmp[0])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c40d383", + "metadata": {}, + "outputs": [], + "source": [ + "break here." + ] + }, + { + "cell_type": "markdown", + "id": "9f992749", + "metadata": {}, + "source": [ + "## Inspecting the performance on grid boundaries.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "945a258f", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitched_prediction_mask\n", + "\n", + "\n", + "skip_boundary_pixel_count = 0\n", + "for sk_c in [1,16,32,48,56]:\n", + " mask = stitched_prediction_mask(val_dset, \n", + " (val_dset._img_sz,val_dset._img_sz), \n", + " skip_boundary_pixel_count, \n", + " sk_c)\n", + " mask = ignore_pixels(mask)\n", + " psnr1, psnr2 = compute_masked_psnr(mask, tar1,tar2,pred1,pred2)\n", + " print(f'[Pad:{val_dset.per_side_overlap_pixelcount()}] SkipCentral', sk_c,\n", + " psnr1,psnr2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a265d0bb", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(mask[0,:,:,0])" + ] + }, + { + "cell_type": "markdown", + "id": "5c7c325b", + "metadata": {}, + "source": [ + "## Inspecting the performance on central regions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36c6b110", + "metadata": {}, + "outputs": [], + "source": [ + "skip_central_pixel_count = 0\n", + "\n", + "for sk_b in [1,8,16,20,24]:\n", + " mask = stitched_prediction_mask(val_dset, \n", + " (val_dset._img_sz,val_dset._img_sz), \n", + " sk_b, \n", + " skip_central_pixel_count)\n", + " mask = ignore_pixels(mask)\n", + " psnr1, psnr2 = compute_masked_psnr(mask, tar1,tar2,pred1,pred2)\n", + " print(f'[Pad:{val_dset.per_side_overlap_pixelcount()}] SkipBoundary', sk_b, psnr1,psnr2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2d87cd57", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(mask[0,:,:,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "212d5536", + "metadata": {}, + "outputs": [], + "source": [ + "# for w in range(2,202,25):\n", + "# print(f'RangeInvPSNR but skipping {w}', avg_range_inv_psnr(np.copy(tar1[:,w:-w,w:-w]), \n", + "# np.copy(pred1[:,w:-w,w:-w])),\n", + " \n", + "# avg_range_inv_psnr(np.copy(tar2[:,w:-w,w:-w]), \n", + "# np.copy(pred2[:,w:-w,w:-w]).copy()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dff40aad", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79275615", + "metadata": {}, + "outputs": [], + "source": [ + "h = 1200\n", + "w = 1200\n", + "sz = 512\n", + "x = tar_unnorm[:1,h:h+sz,w:w+sz].mean(axis=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de600304", + "metadata": {}, + "outputs": [], + "source": [ + "p_count = 32\n", + "y1 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]))\n", + "y2 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]), constant_values=237)\n", + "y3 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]), mode='linear_ramp', end_values=237)\n", + "y4 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]),mode='reflect')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae212914", + "metadata": {}, + "outputs": [], + "source": [ + "np.quantile(x, [0,0.05, 0.1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cdf5c95", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(16,4),ncols=4)\n", + "ax[0].imshow(y1[0], )\n", + "ax[1].imshow(y2[0], )\n", + "ax[2].imshow(y3[0], )\n", + "ax[3].imshow(y4[0], )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60a7a758", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(tar_unnorm[0,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(tar_unnorm[0,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29d967c9", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(tar_unnorm[-1,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(tar_unnorm[-1,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff0c91ac", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(pred_unnorm[0,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(pred_unnorm[0,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "104bbfb4", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.ticker as ticker\n", + "# import seaborn.apionly as sns\n", + "\n", + "_,ax = plt.subplots(figsize=(20,4))\n", + "sns.histplot(tar_unnorm[-1,:,:].mean(axis=2).reshape(-1,))\n", + "ax.xaxis.set_major_locator(ticker.MultipleLocator(25))\n", + "ax.xaxis.set_major_formatter(ticker.ScalarFormatter())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30034a7b", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm[-1,:,:].shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0057b73e", + "metadata": {}, + "outputs": [], + "source": [ + "# inp, tar = val_dset[11060]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01ed9ed7", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(16,4),ncols=4)\n", + "# ax[0].imshow(inp[0])\n", + "# ax[1].imshow(inp[1])\n", + "# ax[2].imshow(inp[2])\n", + "# ax[3].imshow(inp[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b65aeae", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "# ax[0].imshow(tar[0])\n", + "# ax[1].imshow(tar[1])" + ] + }, + { + "cell_type": "markdown", + "id": "950f3b3a", + "metadata": {}, + "source": [ + "## Inspecting the difference in behaviour when different sized inputs are passed. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb42adc1", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "def compute_centered_diff(big,small):\n", + " pad = (big.shape[-1] - small.shape[-1])//2\n", + "# import pdb;pdb.set_trace()\n", + " return big[:,:,pad:-pad,pad:-pad] - small\n", + " \n", + "old_img_sz = val_dset.get_img_sz()\n", + "val_dset.set_img_sz(128)\n", + "inp2, tar2 = val_dset[10000]\n", + "with torch.no_grad():\n", + " bu_values2 = model.bottomup_pass(torch.Tensor(inp2[None]).cuda())\n", + "\n", + "val_dset.set_img_sz(256)\n", + "inp3, tar3 = val_dset[10000]\n", + "with torch.no_grad():\n", + " bu_values3 = model.bottomup_pass(torch.Tensor(inp3[None]).cuda())\n", + "\n", + "diff = (bu_values2[0] - bu_values3[0][:,:,32:-32,32:-32]).cpu().numpy()\n", + "sns.histplot(diff.reshape(-1,))\n", + "\n", + "##LOOKING AT bu_values\n", + "idx=1\n", + "diff = compute_centered_diff(bu_values3[idx],bu_values2[idx]).cpu().numpy()\n", + "_,ax =plt.subplots(figsize=(10,10))\n", + "sns.heatmap(diff[0,0])\n", + "\n", + "## Looking at the difference in prediction.\n", + "with torch.no_grad():\n", + " out2,_ = model(torch.Tensor(inp2[None,]).cuda())\n", + " out3,_ = model(torch.Tensor(inp3[None,]).cuda())\n", + " img2 = get_img_from_forward_output(out3,model)\n", + " img3 = get_img_from_forward_output(out2,model)\n", + "diff = compute_centered_diff(img2,img3)\n", + "_,ax =plt.subplots(figsize=(10,10))\n", + "sns.heatmap(diff[0,1].cpu().numpy())\n", + "val_dset.set_img_sz(old_img_sz)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c561780", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "489b52dd", + "metadata": {}, + "outputs": [], + "source": [ + "img = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/actin-60x-noise2-highsnr.tif')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3d1b606", + "metadata": {}, + "outputs": [], + "source": [ + "img.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6f5fb2c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=4)\n", + "ax[0].imshow(img[0])\n", + "ax[1].imshow(img[1])\n", + "ax[2].imshow(img[2])\n", + "ax[3].imshow(img[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0eea97dc", + "metadata": {}, + "outputs": [], + "source": [ + "img2 =load_tiff('/home/ashesh.ashesh/data/microscopy/OptiMEM100x014.tif')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70d1399c", + "metadata": {}, + "outputs": [], + "source": [ + "img2.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9b01f2c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=4)\n", + "ax[0].imshow(img2[0,...,0])\n", + "ax[1].imshow(img2[1,...,0])\n", + "ax[2].imshow(img2[2,...,0])\n", + "ax[3].imshow(img2[3,...,0])" + ] + }, + { + "cell_type": "markdown", + "id": "d11536e0", + "metadata": {}, + "source": [ + "###### " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f497f314", + "metadata": {}, + "outputs": [], + "source": [ + "inp, tar = val_dset[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a37d3fe", + "metadata": {}, + "outputs": [], + "source": [ + "inp.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "551123e4", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(3,3))\n", + "plt.imshow(tar[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0b01d1d", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(inp[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf517837", + "metadata": {}, + "outputs": [], + "source": [ + "(0.436+0.810)/2" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/EvalNoiseModel.ipynb b/denoisplit/notebooks/EvalNoiseModel.ipynb new file mode 100644 index 0000000..c4270aa --- /dev/null +++ b/denoisplit/notebooks/EvalNoiseModel.ipynb @@ -0,0 +1,332 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))\n", + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nmodel_dir = '/home/ashesh.ashesh/training/noise_model/2403/199'\n", + "# nmodel_dir = '/home/ashesh.ashesh/training/noise_model/2402/61'\n", + "\n", + "histnoisemodel_fpath = None\n", + "gmmnoisemodel_fpath = None\n", + "for fname in os.listdir(nmodel_dir):\n", + " if fname.startswith('HistNoiseModel'):\n", + " assert histnoisemodel_fpath is None\n", + " histnoisemodel_fpath = os.path.join(nmodel_dir, fname)\n", + " elif fname.startswith('GMMNoiseModel'):\n", + " assert gmmnoisemodel_fpath is None\n", + " gmmnoisemodel_fpath = os.path.join(nmodel_dir, fname)\n", + "print(gmmnoisemodel_fpath)\n", + "print(histnoisemodel_fpath)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.nets.gmm_noise_model import GaussianMixtureNoiseModel\n", + "from denoisplit.nets.hist_noise_model import HistNoiseModel\n", + "\n", + "# gmmnoisemodel_fpath = '/home/ashesh.ashesh/training/noise_model/2402/62/GMMNoiseModel_CCPs-GT_all.mrc__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz'\n", + "# histnoisemodel_fpath = os.path.join(os.path.dirname(gmmnoisemodel_fpath), 'HistNoiseModel_CCPs-GT_all.mrc__Norm0_Bins128_bootstrap.npy')\n", + "# datadir = '/group/jug/ashesh/data/ventura_gigascience/actin-60x-noise2-highsnr.tif' if 'actin' in os.path.basename(gmmnoisemodel_fpath) else '/group/jug/ashesh/data/ventura_gigascience/mito-60x-noise2-highsnr.tif'\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nmodel_params = np.load(gmmnoisemodel_fpath)\n", + "gmm_model = GaussianMixtureNoiseModel(params=nmodel_params)\n", + "histdata = np.load(histnoisemodel_fpath)\n", + "hist_model = HistNoiseModel(histdata)\n", + "bins = histdata.shape[-1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "histdata[1,25:50,0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(histdata[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.utils import plotProbabilityDistribution\n", + "signalBinIndex= 40\n", + "data_dict = plotProbabilityDistribution(signalBinIndex=signalBinIndex, \n", + " histogramNoiseModel=hist_model,\n", + " gaussianMixtureNoiseModel=gmm_model,\n", + " device='cpu')\n", + "data_dict['gmm']['x'][data_dict['gmm']['p'].argmax()]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "params = gmm_model.getGaussianParameters(signalBinIndex)\n", + "np.sqrt(np.sum((np.array(params[-6:])) * np.array(params[6:12])**2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# for i in range(histdata.shape[1]):\n", + "# assert np.std(histdata[1][i]) < 1e-7\n", + "# assert np.std(histdata[2][i]) < 1e-7" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# bin_val = (histdata[1] + histdata[2])/2\n", + "# bin_val = bin_val[:,0]\n", + "# binsize = np.mean(histdata[2] - histdata[1])\n", + "# bin_pdf = histdata[0]/binsize" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# from scipy.optimize import curve_fit\n", + "# import math\n", + "# import numpy as np\n", + "\n", + "# def gaus(x, mu,sigma):\n", + "# out = np.exp(-(x-mu)**2/(2*sigma**2)) * 1/(sigma*np.sqrt(2*math.pi))\n", + "# # print(out.shape, out.min(), out.max())\n", + "# return out\n", + "\n", + "# def sigmoid(x):\n", + "# return 1 / (1 + math.exp(-x))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# index = 90\n", + "# x = bin_val\n", + "# y = bin_pdf[index]\n", + "\n", + "# mean =bin_val[index]\n", + "# sigma = sum(y*(x-mean)**2)/len(y)\n", + "\n", + "# popt,pcov = curve_fit(gaus,\n", + "# x,\n", + "# y,\n", + "# p0=[x[index],sigma])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# pcov" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# popt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plt.plot(bin_val,bin_pdf[index],'b+:',label='data')\n", + "# plt.plot(bin_val,gaus(bin_val,*popt),'ro:',label='fit')\n", + "# plt.legend()\n", + "# plt.title('Fig. 3 - Fit for Time Constant')\n", + "# plt.xlabel('Time (s)')\n", + "# plt.ylabel('Voltage (V)')\n", + "# plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "from denoisplit.nets.hist_gmm_noise_model import HistGMMNoiseModel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nm = HistGMMNoiseModel(histdata)\n", + "nm.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "max_signal = hist_model.maxv.item()\n", + "min_signal = hist_model.minv.item()\n", + "n_bin = int(hist_model.bins.item())\n", + "\n", + "histBinSize = (max_signal - min_signal) / n_bin\n", + "querySignal_numpy = (signalBinIndex / float(n_bin) * (max_signal - min_signal) + min_signal)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nm._params = nm._params.cpu()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "signalBinIndex = 23\n", + "data_dict = plotProbabilityDistribution(signalBinIndex=signalBinIndex, \n", + " histogramNoiseModel=hist_model,\n", + " gaussianMixtureNoiseModel=nm,\n", + " device='cpu')\n", + "data_dict['gmm']['x'][data_dict['gmm']['p'].argmax()]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nm._min_valid_index" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nm._params[42]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nm._binsize" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/EvalOnMultiFileDataset.ipynb b/denoisplit/notebooks/EvalOnMultiFileDataset.ipynb new file mode 100644 index 0000000..7be2f0f --- /dev/null +++ b/denoisplit/notebooks/EvalOnMultiFileDataset.ipynb @@ -0,0 +1,2144 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "19844352", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad91cc2b", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "# os.environ[\"CUDA_DEVICE_ORDER\"]=\"PCI_BUS_ID\" # see issue #152\n", + "# os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"2\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dcd3d0c2", + "metadata": {}, + "outputs": [], + "source": [ + "# there are two environments(debug and prod). From where you want to fetch the code and data? \n", + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27ec4422", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "db8d89b5", + "metadata": {}, + "outputs": [], + "source": [ + "# 'stats_'+'_'.join(ckpt_dir.split('/')[-4:]) + '.pkl'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a9748a9", + "metadata": {}, + "outputs": [], + "source": [ + "ckpt_dir = \"/home/ashesh.ashesh/training/disentangle/2401/D21-M3-S0-L0/6\"\n", + "# 211/D3-M3-S0-L0/0\n", + "# 2210/D3-M3-S0-L0/128\n", + "# 2210/D3-M3-S0-L0/129" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27410ddc", + "metadata": {}, + "outputs": [], + "source": [ + "# !ls /home/ubuntu/ashesh/training/disentangle/2209/D3-M9-S0-L0/1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b237569", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "from denoisplit.data_loader.multifile_raw_dloader import SubDsetType\n", + "\n", + "\n", + "image_size_for_grid_centers = 64\n", + "mmse_count = 5\n", + "custom_image_size = 128\n", + "subdset_type = None # SubDsetType.OneChannel\n", + "\n", + "\n", + "batch_size = 16\n", + "num_workers = 4\n", + "COMPUTE_LOSS = False\n", + "use_deterministic_grid = None\n", + "threshold = None # 0.02\n", + "compute_kl_loss = False\n", + "evaluate_train = False# inspect training performance\n", + "eval_datasplit_type = DataSplitType.Test\n", + "val_repeat_factor = None\n", + "psnr_type = 'range_invariant' #'simple', 'range_invariant'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f889dd2d", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/config_loader.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a0047fe", + "metadata": {}, + "outputs": [], + "source": [ + "# config.model.decoder" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc8a3fed", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.sampler_type import SamplerType\n", + "from denoisplit.core.loss_type import LossType\n", + "# from denoisplit.core.lowres_merge_type import LowresMergeType\n", + "from denoisplit.data_loader.multifile_raw_dloader import SubDsetType\n", + "\n", + "with config.unlocked():\n", + " config.model.skip_nboundary_pixels_from_loss = None\n", + " if config.model.model_type == ModelType.UNet and 'n_levels' not in config.model:\n", + " config.model.n_levels = 4\n", + " if config.data.sampler_type == SamplerType.NeighborSampler:\n", + " config.data.sampler_type = SamplerType.DefaultSampler\n", + " config.loss.loss_type = LossType.Elbo\n", + " config.data.grid_size = config.data.image_size\n", + " if 'ch1_fpath_list' in config.data:\n", + " config.data.ch1_fpath_list = config.data.ch1_fpath_list[:1]\n", + " config.data.mix_fpath_list = config.data.mix_fpath_list[:1]\n", + " if config.data.data_type == DataType.Pavia2VanillaSplitting:\n", + " if 'channel_2_downscale_factor' not in config.data:\n", + " config.data.channel_2_downscale_factor = 1\n", + " if config.model.model_type == ModelType.UNet and 'init_channel_count' not in config.model:\n", + " config.model.init_channel_count = 64\n", + " \n", + " if 'skip_receptive_field_loss_tokens' not in config.loss:\n", + " config.loss.skip_receptive_field_loss_tokens = []\n", + " \n", + " if config.data.data_type == DataType.HTIba1Ki67:\n", + " config.data.subdset_type = SubDsetType.Iba1Ki64\n", + " config.data.empty_patch_replacement_enabled = False\n", + " \n", + " if 'lowres_merge_type' not in config.model.encoder:\n", + " config.model.encoder.lowres_merge_type = 0\n", + " \n", + " if config.data.data_type == DataType.TwoDset:\n", + " config.model.model_type = ModelType.LadderVae\n", + " for key in config.data.dset1:\n", + " config.data[key] = config.data.dset1[key]\n", + " if config.data.data_type == DataType.TavernaSox2GolgiV2:\n", + " config.data.channel_1 = '555-647'\n", + " config.data.channel_2 = '555-647'\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c5c2c1c8", + "metadata": {}, + "outputs": [], + "source": [ + "dtype = config.data.data_type" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "094cbe25", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6863ea5b", + "metadata": {}, + "outputs": [], + "source": [ + "if DEBUG:\n", + " if dtype == DataType.CustomSinosoid:\n", + " data_dir = f'{DATA_ROOT}/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + "else:\n", + " if dtype in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " data_dir = f'{DATA_ROOT}/sinosoid_without_test/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + " elif dtype == DataType.Prevedel_EMBL:\n", + " data_dir = f'{DATA_ROOT}/Prevedel_EMBL/PKG_3P_dualcolor_stacks/NoAverage_NoRegistration/'\n", + " elif dtype == DataType.AllenCellMito:\n", + " data_dir = f'{DATA_ROOT}/allencell/2017_03_08_Struct_First_Pass_Seg/AICS-11/'\n", + " elif dtype == DataType.SeparateTiffData:\n", + " data_dir = f'{DATA_ROOT}/ventura_gigascience'\n", + " elif dtype == DataType.SemiSupBloodVesselsEMBL:\n", + " data_dir = f'{DATA_ROOT}/EMBL_halfsupervised/Demixing_3P'\n", + " elif dtype == DataType.Pavia2VanillaSplitting:\n", + " data_dir = f'{DATA_ROOT}/pavia2'\n", + " elif dtype == DataType.ExpansionMicroscopyMitoTub:\n", + " data_dir = f'{DATA_ROOT}/expansion_microscopy_Nick/'\n", + " elif dtype == DataType.ShroffMitoEr:\n", + " data_dir = f'{DATA_ROOT}/shrofflab/'\n", + " elif dtype == DataType.HTIba1Ki67:\n", + " data_dir = f'{DATA_ROOT}/Stefania/20230327_Ki67_and_Iba1_trainingdata/'\n", + " elif dtype == DataType.BioSR_MRC:\n", + " data_dir = f'{DATA_ROOT}/BioSR/'\n", + " elif dtype == DataType.TavernaSox2Golgi:\n", + " data_dir = f'{DATA_ROOT}/TavernaSox2Golgi/'\n", + " elif dtype == DataType.ExpMicroscopyV2:\n", + " data_dir = f'{DATA_ROOT}/expansion_microscopy_v2/'\n", + " elif dtype == DataType.TavernaSox2GolgiV2:\n", + " data_dir = f'{DATA_ROOT}/TavernaSox2Golgi/acquisition2/'\n", + " \n", + "# 2720*2720: microscopy dataset.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "edde2155", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/disentangle_setup.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "53df96f2", + "metadata": {}, + "outputs": [], + "source": [ + "len(train_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60d5fc4a", + "metadata": {}, + "outputs": [], + "source": [ + "if config.data.multiscale_lowres_count is not None and custom_image_size is not None:\n", + " model.reset_for_different_output_size(custom_image_size)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11cf6c69", + "metadata": {}, + "outputs": [], + "source": [ + "# if config.model.model_type not in [ModelType.UNet, ModelType.BraveNet]:\n", + "# with torch.no_grad():\n", + "# inp, tar = val_dset[0][:2]\n", + "# out, td_data = model(torch.Tensor(inp[None]).cuda())\n", + "# print(td_data['z'][-1].shape)\n", + "# print(out.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d05be428", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(val_dset))\n", + "inp_tmp, tar_tmp, *_ = val_dset[idx]\n", + "ncols = max(len(inp_tmp),3)\n", + "nrows = 2\n", + "_,ax = plt.subplots(figsize=(4*ncols,4*nrows),ncols=ncols,nrows=nrows)\n", + "for i in range(len(inp_tmp)):\n", + " ax[0,i].imshow(inp_tmp[i])\n", + "\n", + "ax[1,0].imshow(tar_tmp[0]+tar_tmp[1])\n", + "ax[1,1].imshow(tar_tmp[0])\n", + "ax[1,2].imshow(tar_tmp[1])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cac092b5", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitch_predictions\n", + "from denoisplit.analysis.mmse_prediction import get_dset_predictions\n", + "# from denoisplit.analysis.stitch_prediction import get_predictions as get_dset_predictions\n", + "\n", + "pred_tiled, rec_loss, logvar, patch_psnr_tuple = get_dset_predictions(model, val_dset,batch_size,\n", + " num_workers=num_workers,\n", + " mmse_count=mmse_count,\n", + " model_type = config.model.model_type,\n", + " )\n", + "tmp = np.round([x.item() for x in patch_psnr_tuple],2)\n", + "print('Patch wise PSNR, as computed during training', tmp,np.mean(tmp) )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "052e0d18", + "metadata": {}, + "outputs": [], + "source": [ + "from copy import deepcopy\n", + "if config.data.data_type == DataType.TavernaSox2GolgiV2:\n", + " dset_is_input = config.data.channel_1 == config.data.channel_2 and config.data.channel_1 == '555-647'\n", + " if dset_is_input:\n", + " new_config = deepcopy(config)\n", + " new_config.data.channel_1 = 'GT_Cy5'\n", + " new_config.data.channel_2 = 'GT_TRITC'\n", + " _, val_dset_target = create_dataset(new_config, data_dir, eval_datasplit_type = eval_datasplit_type)\n", + " else:\n", + " val_dset_target = val_dset\n", + "else:\n", + " val_dset_target = val_dset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c37d71a", + "metadata": {}, + "outputs": [], + "source": [ + "np.mean(rec_loss)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee076ab0", + "metadata": {}, + "outputs": [], + "source": [ + "# Patch wise PSNR, as computed during training [ 4.71 23.01] 13.860000000000001\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "535169c1", + "metadata": {}, + "outputs": [], + "source": [ + "len(val_dset_target)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b693a0c", + "metadata": {}, + "outputs": [], + "source": [ + "idx_list = np.where(logvar.squeeze() < -6)[0]\n", + "if len(idx_list) > 0:\n", + " plt.imshow(val_dset[idx_list[0]][1][1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8a1573f8", + "metadata": {}, + "outputs": [], + "source": [ + "len(val_dset_target)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6709de9e", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "sns.histplot(logvar[::50].squeeze().reshape(-1,))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "771ac350", + "metadata": {}, + "outputs": [], + "source": [ + "print(np.quantile(rec_loss, [0,0.01,0.5, 0.9,0.99,0.999,1]).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05f2cdc7", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8673355b", + "metadata": {}, + "outputs": [], + "source": [ + "count = 0\n", + "for dset in val_dset_target.dsets:\n", + " count += dset.idx_manager.grid_count()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae3ad118", + "metadata": {}, + "outputs": [], + "source": [ + "count " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "99234fd3", + "metadata": {}, + "outputs": [], + "source": [ + "len(pred_tiled)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c75b35f1", + "metadata": {}, + "outputs": [], + "source": [ + "if pred_tiled.shape[-1] != val_dset.get_img_sz():\n", + " pad = (val_dset.get_img_sz() - pred_tiled.shape[-1] )//2\n", + " pred_tiled = np.pad(pred_tiled, ((0,0),(0,0),(pad,pad),(pad,pad)))\n", + "\n", + "pred = stitch_predictions(pred_tiled,val_dset, smoothening_pixelcount=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f950003b", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b09091e3", + "metadata": {}, + "outputs": [], + "source": [ + "pred.shape if isinstance(pred, np.ndarray) else [p.shape for p in pred]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dba3753f", + "metadata": {}, + "outputs": [], + "source": [ + "# pred[np.isnan(pred)] = 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d2ad25d", + "metadata": {}, + "outputs": [], + "source": [ + "def get_ignores_pixels(pred_frames):\n", + " ignored_pixels = 1\n", + " while(pred_frames[0,-ignored_pixels:,-ignored_pixels:,].std() ==0):\n", + " ignored_pixels+=1\n", + " ignored_pixels-=1\n", + " return ignored_pixels\n", + "\n", + "def print_ignored_pixels():\n", + " if isinstance(pred, np.ndarray):\n", + " ignored_pixels = get_ignores_pixels(pred)\n", + " elif isinstance(pred, list):\n", + " ignored_pixels = [get_ignores_pixels(p) for p in pred]\n", + "\n", + " print(f'Last {ignored_pixels} many rows and columns are all zero.')\n", + " return ignored_pixels\n", + "\n", + "actual_ignored_pixels = print_ignored_pixels()" + ] + }, + { + "cell_type": "markdown", + "id": "b8474735", + "metadata": {}, + "source": [ + "## Ignore the pixels which are present in the last few rows and columns. \n", + "1. They don't come in the batches. So, in prediction, they are simply zeros. So they are being are ignored right now. \n", + "2. For the border pixels which are on the top and the left, overlapping yields worse performance. This is becuase, there is nothing to overlap on one side. So, they are essentially zero padded. This makes the performance worse. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcb2db09", + "metadata": {}, + "outputs": [], + "source": [ + "print(actual_ignored_pixels)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cadedfcd", + "metadata": {}, + "outputs": [], + "source": [ + "if isinstance(pred, np.ndarray):\n", + " if config.data.data_type in [DataType.OptiMEM100_014,\n", + " DataType.SemiSupBloodVesselsEMBL, \n", + " DataType.Pavia2VanillaSplitting,\n", + " DataType.ExpansionMicroscopyMitoTub,\n", + " DataType.ShroffMitoEr,\n", + " DataType.HTIba1Ki67]:\n", + " ignored_last_pixels = 32 \n", + " elif config.data.data_type == DataType.BioSR_MRC:\n", + " ignored_last_pixels = 44\n", + " assert val_dset.get_img_sz() == 64\n", + " else:\n", + " ignored_last_pixels = 0\n", + "\n", + "\n", + " assert actual_ignored_pixels <= ignored_last_pixels, f'Set ignored_last_pixels={actual_ignored_pixels}'\n", + " print(ignored_last_pixels)\n", + "elif isinstance(pred, list):\n", + " ignored_last_pixels = actual_ignored_pixels\n", + "ignore_first_pixels = 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "226fed05", + "metadata": {}, + "outputs": [], + "source": [ + "tar = val_dset_target._data if isinstance(pred, np.ndarray) else [val_dset_target.dsets[i]._data for i in range(len(val_dset_target.dsets))]\n", + "\n", + "def ignore_pixels(arr):\n", + " if ignore_first_pixels:\n", + " arr = arr[:,ignore_first_pixels:,ignore_first_pixels:]\n", + " if ignored_last_pixels !=0:\n", + " if isinstance(arr, np.ndarray):\n", + " arr = arr[:,:-ignored_last_pixels,:-ignored_last_pixels]\n", + " return arr\n", + " elif isinstance(arr, list):\n", + " output_arr = []\n", + " for i,a in enumerate(arr):\n", + " if ignored_last_pixels[i] !=0:\n", + " output_arr.append(a[:,:-ignored_last_pixels[i],:-ignored_last_pixels[i]] )\n", + " else:\n", + " output_arr.append(a)\n", + " return output_arr\n", + " \n", + "pred = ignore_pixels(pred)\n", + "tar = ignore_pixels(tar)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1be10fd7", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.analysis.plot_utils import *\n", + "# def add_pixel_kde(ax,\n", + "# rect: List[float],\n", + "# data1: np.ndarray,\n", + "# data2: Union[np.ndarray, None],\n", + "# min_labelsize: int,\n", + "# color1='r',\n", + "# color2='black',\n", + "# color_xtick='white',\n", + "# label1='Target',\n", + "# label2='Predicted'):\n", + "# \"\"\"\n", + "# Adds KDE (density plot) of data1(eg: target) and data2(ex: predicted) image pixel values as an inset\n", + "# \"\"\"\n", + "# inset_ax = add_subplot_axes(ax, rect, facecolor=\"None\", min_labelsize=min_labelsize)\n", + " \n", + "# inset_ax.tick_params(axis='x', colors=color_xtick)\n", + "\n", + "# sns.kdeplot(data=data1.reshape(-1, ), ax=inset_ax, color=color1, label=label1)\n", + "# if data2 is not None:\n", + "# sns.kdeplot(data=data2.reshape(-1, ), ax=inset_ax, color=color2, label=label2)\n", + "# inset_ax.set_xlim(left=0)\n", + "# xticks = inset_ax.get_xticks()\n", + "# # inset_ax.set_xticks([xticks[0], xticks[-1]])\n", + "# inset_ax.set_xticks([])\n", + "# clean_for_xaxis_plot(inset_ax)\n", + "\n", + "\n", + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "\n", + "# inset_rect=[0.1,0.1,0.4,0.2]\n", + "# inset_min_labelsize=10\n", + "# color_ch_list=['goldenrod','cyan']\n", + "\n", + "# _,ax = plt.subplots(figsize=(15,10),ncols=3,nrows=2)\n", + "# idx = 8\n", + "# pred1_crop = ch1_pred_unnorm[idx,1116:1372,1064:1320].copy()\n", + "# pred2_crop = ch2_pred_unnorm[idx,1116:1372,1064:1320].copy()\n", + "# pred1_crop[pred1_crop<0] = 0\n", + "# pred2_crop[pred2_crop<0] = 0\n", + "\n", + "# tar1_crop = tar[idx,1116:1372,1064:1320,0]\n", + "# tar2_crop = tar[idx,1116:1372,1064:1320,1]\n", + "\n", + "# ax[0,0].imshow(tar1_crop+tar2_crop)\n", + "# ax[0,1].imshow(tar1_crop)\n", + "# ax[0,2].imshow(tar2_crop)\n", + "\n", + "# ax[1,0].imshow(pred1_crop+pred2_crop)\n", + "# ax[1,1].imshow(pred1_crop)\n", + "# ax[1,2].imshow(pred2_crop)\n", + "# clean_ax(ax)\n", + "# add_pixel_kde(ax[0,0], inset_rect, \n", + "# tar1_crop, \n", + "# tar2_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1=color_ch_list[0], color2=color_ch_list[1])\n", + "\n", + "# add_pixel_kde(ax[1,1], inset_rect, \n", + "# pred1_crop, \n", + "# tar1_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1='red', color2=color_ch_list[0])\n", + "# add_pixel_kde(ax[1,2], inset_rect, \n", + "# pred2_crop, \n", + "# tar2_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1='red', color2=color_ch_list[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d8b680f", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.metrics import structural_similarity\n", + "\n", + "def _avg_psnr(target, prediction, psnr_fn):\n", + " output = np.mean([psnr_fn(target[i:i + 1], prediction[i:i + 1]).item() for i in range(len(prediction))])\n", + " return round(output, 2)\n", + "\n", + "\n", + "def avg_range_inv_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, RangeInvariantPsnr)\n", + "\n", + "\n", + "def avg_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, PSNR)\n", + "\n", + "\n", + "def compute_masked_psnr(mask, tar1, tar2, pred1, pred2):\n", + " mask = mask.astype(bool)\n", + " mask = mask[..., 0]\n", + " tmp_tar1 = tar1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_pred1 = pred1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_tar2 = tar2[mask].reshape((len(tar2), -1, 1))\n", + " tmp_pred2 = pred2[mask].reshape((len(tar2), -1, 1))\n", + " psnr1 = avg_range_inv_psnr(tmp_tar1, tmp_pred1)\n", + " psnr2 = avg_range_inv_psnr(tmp_tar2, tmp_pred2)\n", + " return psnr1, psnr2\n", + "\n", + "def avg_ssim(target, prediction):\n", + " ssim = [structural_similarity(target[i],prediction[i], data_range=(target[i].max() - target[i].min())) for i in range(len(target))]\n", + " return np.mean(ssim),np.std(ssim)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7311e08a", + "metadata": {}, + "outputs": [], + "source": [ + "sep_mean, sep_std = model.data_mean, model.data_std\n", + "if isinstance(sep_mean, dict):\n", + " sep_mean = sep_mean['target']\n", + " sep_std = sep_std['target']\n", + " \n", + "sep_mean = sep_mean.squeeze()[None,None,None]\n", + "sep_std = sep_std.squeeze()[None,None,None]\n", + "\n", + "if isinstance(pred, np.ndarray):\n", + " tar_normalized = (tar - sep_mean.cpu().numpy())/sep_std.cpu().numpy()\n", + " tar1 =tar_normalized[...,0]\n", + " tar2 =tar_normalized[...,1]\n", + "elif isinstance(pred, list):\n", + " assert isinstance(tar, list)\n", + " assert len(pred) == len(tar)\n", + " tar_normalized = [(tar[i]-sep_mean.cpu().numpy())/sep_std.cpu().numpy() for i in range(len(tar))]\n", + " tar1 = [tar_normalized[i][...,0] for i in range(len(tar))]\n", + " tar2 = [tar_normalized[i][...,1] for i in range(len(tar))]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2402048", + "metadata": {}, + "outputs": [], + "source": [ + "if isinstance(pred, np.ndarray):\n", + " q_vals = [0.01, 0.1,0.5,0.9,0.95, 0.99,1]\n", + " print('Nuc:', np.quantile(tar_normalized[0][...,0], q_vals).round(2))\n", + " print('Tub:', np.quantile(tar_normalized[0][...,1], q_vals).round(2))\n", + " print('Nuc:', np.quantile(tar[0][...,0], q_vals))\n", + " print('Tub:', np.quantile(tar[0][...,1], q_vals))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66a3225f", + "metadata": {}, + "outputs": [], + "source": [ + "print([pred[i].shape for i in range(len(pred))])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24708c4c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(12,12),ncols=2,nrows=2)\n", + "idx = np.random.randint(len(pred))\n", + "print(idx)\n", + "if isinstance(pred, np.ndarray):\n", + " ax[0,0].imshow(pred[idx,:,:,0])\n", + " ax[0,1].imshow(pred[idx,:,:,1])\n", + " ax[1,0].imshow(tar1[idx,:,:])\n", + " ax[1,1].imshow(tar2[idx,:,:])\n", + " print(pred.shape)\n", + "else:\n", + " ax[0,0].imshow(pred[idx][0,:,:,0])\n", + " ax[0,1].imshow(pred[idx][0,:,:,1])\n", + " ax[1,0].imshow(tar1[idx][0,:,:])\n", + " ax[1,1].imshow(tar2[idx][0,:,:])\n", + " print(pred[0].shape)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "907cd0c5", + "metadata": {}, + "outputs": [], + "source": [ + "one_preds = []\n", + "k_preds = 10\n", + "one_dset = val_dset.dsets[1]\n", + "for i in range(k_preds):\n", + " one_pred_tiled, *_ = get_dset_predictions(model, one_dset,batch_size,\n", + " num_workers=num_workers,\n", + " mmse_count=1,\n", + " model_type = config.model.model_type,\n", + " )\n", + " one_pred = stitch_predictions(one_pred_tiled,one_dset, smoothening_pixelcount=0)\n", + " one_preds.append(one_pred)\n", + "\n", + "one_preds = np.concatenate(one_preds, axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b5c99d2", + "metadata": {}, + "outputs": [], + "source": [ + "one_preds_unnorm = (one_preds*sep_std.cpu().numpy() + sep_mean.cpu().numpy()).astype(np.uint16)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4546f77", + "metadata": {}, + "outputs": [], + "source": [ + "# from skimage.io import imsave\n", + "# imsave('ch1_samples.tiff', one_preds_unnorm[...,1], plugin='tifffile')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ec80e5d7", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(one_preds[1,:,:,0] - one_preds[0,:,:,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13b2e7a9", + "metadata": {}, + "outputs": [], + "source": [ + "min(tar1[idx][0].min(), pred[idx][0,...,0].min())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fbc618b3", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "83700dbc", + "metadata": {}, + "outputs": [], + "source": [ + "pred[idx].max()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5ad2ffbe", + "metadata": {}, + "outputs": [], + "source": [ + "factor = 25\n", + "vmin1 = int(25 * min(tar1[idx][0].min(), pred[idx][0,...,0].min()))\n", + "vmax1 = int(25 * max(tar1[idx][0].max(), pred[idx][0,...,0].max()))\n", + "vmin2 = int(25 * min(tar2[idx][0].min(), pred[idx][0,...,1].min()))\n", + "vmax2 = int( 25 * max(tar2[idx][0].max(), pred[idx][0,...,1].max()))\n", + "\n", + "_,ax = plt.subplots(figsize=(12,8),ncols=3, nrows=2)\n", + "ax[0,1].imshow(tar1[idx][0]*factor, vmin=vmin1, vmax=vmax1)\n", + "ax[0,2].imshow(tar2[idx][0]*factor, vmin=vmin2, vmax=vmax2)\n", + "ax[0,1].set_title('Groundtruth A')\n", + "ax[0,2].set_title('Groundtruth B')\n", + "\n", + "ax[1,0].imshow((tar1[idx][0] + tar2[idx][0])/2)\n", + "ax[1,0].set_title('Input')\n", + "ax[1,1].set_title('Prediction A')\n", + "ax[1,2].set_title('Prediction B')\n", + "\n", + "ax[1,1].imshow(pred[idx][0,...,0]*factor, vmin=vmin1, vmax=vmax1)\n", + "ax[1,2].imshow(pred[idx][0,...,1]*factor, vmin=vmin2, vmax=vmax2)\n", + "clean_ax(ax)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f16c88e5", + "metadata": {}, + "outputs": [], + "source": [ + "# pred is already normalized. no need to do it. \n", + "if isinstance(pred, np.ndarray):\n", + " pred1, pred2 = pred[...,0].astype(np.float32), pred[...,1].astype(np.float32)\n", + " pred_inp = (pred1 + pred2)/2\n", + "elif isinstance(pred, list):\n", + " pred1_arr = []\n", + " pred2_arr = []\n", + " pred_inp_arr = []\n", + " for i in range(len(pred)):\n", + " pred1, pred2 = pred[i][...,0].astype(np.float32), pred[i][...,1].astype(np.float32)\n", + " pred_inp = (pred1 + pred2)/2\n", + " pred1_arr.append(pred1)\n", + " pred2_arr.append(pred2)\n", + " pred_inp_arr.append(pred_inp)\n", + " pred1 = pred1_arr\n", + " pred2 = pred2_arr\n", + " pred_inp = pred_inp_arr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "919db5ef", + "metadata": {}, + "outputs": [], + "source": [ + "if isinstance(pred, np.ndarray):\n", + " ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + " ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "elif isinstance(pred, list):\n", + " ch1_pred_unnorm = []\n", + " ch2_pred_unnorm = []\n", + " for i in range(len(pred)):\n", + " ch1_pred_unnorm.append(pred[i][...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy())\n", + " ch2_pred_unnorm.append(pred[i][...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c18b30b", + "metadata": {}, + "outputs": [], + "source": [ + "tar[i].shape, ch1_pred_unnorm[0].shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13fc1983", + "metadata": {}, + "outputs": [], + "source": [ + "if config.model.model_type == ModelType.LadderVaeSemiSupervised:\n", + " raise NotImplementedError(\"SSIM is incorrectly implemented here.\")\n", + " pred_inp = pred[...,2].astype(np.float32)\n", + "# tar1 is the input. tar2 is the target. \n", + " rmse1 =np.sqrt(((pred1 - tar2)**2).reshape(len(pred1),-1).mean(axis=1))\n", + " rmse2 =np.sqrt(((pred_inp - tar1)**2).reshape(len(pred2),-1).mean(axis=1)) \n", + "\n", + " rmse = (rmse1 + rmse2)/2\n", + " rmse = np.round(rmse,3)\n", + "\n", + " ssim1_mean, ssim1_std = avg_ssim(tar2, pred1)\n", + " ssim2_mean, ssim2_std = avg_ssim(tar1, pred_inp)\n", + " \n", + " psnr1 = avg_psnr(tar2, pred1)\n", + " psnr2 = avg_psnr(tar1, pred_inp)\n", + " rinv_psnr1 = avg_range_inv_psnr(tar2, pred1)\n", + " rinv_psnr2 = avg_range_inv_psnr(tar1, pred_inp)\n", + " \n", + "elif isinstance(pred, np.ndarray):\n", + " rmse1 =np.sqrt(((pred1 - tar1)**2).reshape(len(pred1),-1).mean(axis=1))\n", + " rmse2 =np.sqrt(((pred2 - tar2)**2).reshape(len(pred2),-1).mean(axis=1)) \n", + "\n", + " rmse = (rmse1 + rmse2)/2\n", + " rmse = np.round(rmse,3)\n", + " psnr1 = avg_psnr(tar1, pred1) \n", + " psnr2 = avg_psnr(tar2, pred2)\n", + " rinv_psnr1 = avg_range_inv_psnr(tar1, pred1)\n", + " rinv_psnr2 = avg_range_inv_psnr(tar2, pred2)\n", + " ssim1_mean, ssim1_std = avg_ssim(tar[...,0], ch1_pred_unnorm)\n", + " ssim2_mean, ssim2_std = avg_ssim(tar[...,1], ch2_pred_unnorm)\n", + "elif isinstance(pred, list):\n", + " ssim1_mean_arr = []\n", + " ssim1_std_arr = []\n", + " ssim2_mean_arr = []\n", + " ssim2_std_arr = []\n", + " psnr1_arr = []\n", + " psnr2_arr = []\n", + " rinv_psnr1_arr = []\n", + " rinv_psnr2_arr = []\n", + " rmse_arr = []\n", + "\n", + " for i in range(len(pred)):\n", + " rmse1 =np.sqrt(((pred1[i] - tar1[i])**2).reshape(len(pred1[i]),-1).mean(axis=1))\n", + " rmse2 =np.sqrt(((pred2[i] - tar2[i])**2).reshape(len(pred2[i]),-1).mean(axis=1)) \n", + "\n", + " rmse = (rmse1 + rmse2)/2\n", + " rmse = np.round(rmse,3)\n", + " psnr1 = avg_psnr(tar1[i], pred1[i]) \n", + " psnr2 = avg_psnr(tar2[i], pred2[i])\n", + " rinv_psnr1 = avg_range_inv_psnr(tar1[i], pred1[i])\n", + " rinv_psnr2 = avg_range_inv_psnr(tar2[i], pred2[i])\n", + " ssim1_mean, ssim1_std = avg_ssim(tar[i][...,0], ch1_pred_unnorm[i])\n", + " ssim2_mean, ssim2_std = avg_ssim(tar[i][...,1], ch2_pred_unnorm[i])\n", + " ssim1_mean_arr.append(ssim1_mean)\n", + " ssim1_std_arr.append(ssim1_std)\n", + " ssim2_mean_arr.append(ssim2_mean)\n", + " ssim2_std_arr.append(ssim2_std)\n", + " psnr1_arr.append(psnr1)\n", + " psnr2_arr.append(psnr2)\n", + " rinv_psnr1_arr.append(rinv_psnr1)\n", + " rinv_psnr2_arr.append(rinv_psnr2)\n", + " rmse_arr.append(rmse)\n", + " \n", + " ssim1_mean = np.mean(ssim1_mean_arr)\n", + " ssim1_std = np.mean(ssim1_std_arr)\n", + " ssim2_mean = np.mean(ssim2_mean_arr)\n", + " ssim2_std = np.mean(ssim2_std_arr)\n", + " psnr1 = np.round(np.mean(psnr1_arr),2)\n", + " psnr2 = np.round(np.mean(psnr2_arr),2)\n", + " rinv_psnr1 = np.round(np.mean(rinv_psnr1_arr),2)\n", + " rinv_psnr2 = np.round(np.mean(rinv_psnr2_arr),2)\n", + " rmse = np.mean(rmse_arr)\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e87868b7", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + "print('Rec Loss',np.round(rec_loss.mean(),3) )\n", + "print('RMSE', np.mean(rmse1).round(3), np.mean(rmse2).round(3), np.mean(rmse).round(3))\n", + "print('PSNR', psnr1, psnr2)\n", + "print('RangeInvPSNR',rinv_psnr1, rinv_psnr2 )\n", + "print('SSIM',round(ssim1_mean,3), round(ssim2_mean,3),'±',round((ssim1_std + ssim2_std)/2,4))\n", + "print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "89184290", + "metadata": {}, + "outputs": [], + "source": [ + "# Rec Loss 2.075\n", + "# RMSE 1.317 1.108 1.043\n", + "# PSNR 13.11 10.32\n", + "# RangeInvPSNR 35.09 30.5\n", + "# SSIM 0.553 0.568 ± 0.0\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c559da4", + "metadata": {}, + "outputs": [], + "source": [ + "# Test_P64_G32_M1_Sk32\n", + "# Rec Loss -0.45\n", + "# RMSE 0.218 0.15 0.184\n", + "# PSNR 31.69 31.57\n", + "# RangeInvPSNR 31.7 31.6\n", + "# SSIM 0.757 0.658 ± 0.0033" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a1fb5107", + "metadata": {}, + "outputs": [], + "source": [ + "!ls -lhrt Act*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73ba24ac", + "metadata": {}, + "outputs": [], + "source": [ + "if config.model.model_type == ModelType.LadderVaeSemiSupervised:\n", + " from denoisplit.analysis.plot_utils import add_pixel_kde\n", + " inset_rect=[0.1,0.1,0.4,0.2]\n", + " min_labelsize = 15\n", + "\n", + " nimgs=5\n", + " crp_sz = 400\n", + " img_sz = 8\n", + "\n", + " _,ax = plt.subplots(figsize=(4*img_sz,img_sz*nimgs),ncols=5,nrows=nimgs)\n", + " clean_ax(ax[1:,])\n", + " clean_ax(ax[:,1:])\n", + " img_idx_list = np.random.permutation(np.arange(len(tar1)))[:nimgs] #[19,23,15,18,4] # \n", + " for ax_idx in range(nimgs):\n", + " img_idx = img_idx_list[ax_idx]\n", + " overlapping_pred = pred1[img_idx] + pred2[img_idx]\n", + " overlapping_min = min(tar1[img_idx].min(),overlapping_pred.min())\n", + " overlapping_max = max(tar1[img_idx].max(),overlapping_pred.max())\n", + "\n", + " ax[ax_idx,0].imshow(tar1[img_idx])#,vmin=overlapping_min,vmax=overlapping_max)\n", + " ax[ax_idx,1].imshow(overlapping_pred)#,vmin=overlapping_min,vmax=overlapping_max)\n", + "\n", + " ch1_min = tar2[img_idx].min()#,pred1[img_idx].min())\n", + " ch1_max = tar2[img_idx].max()#,pred1[img_idx].max())\n", + " ax[ax_idx,2].imshow(tar2[img_idx])#,vmin=ch1_min,vmax=ch1_max)\n", + " ax[ax_idx,3].imshow(pred1[img_idx])#,vmin=ch1_min,vmax=ch1_max)\n", + "\n", + " ax[ax_idx,4].imshow(pred2[img_idx])\n", + " ax[ax_idx,0].set_ylabel(f'{img_idx}',fontsize=min_labelsize)\n", + "\n", + " # add_pixel_kde(ax[ax_idx,1],\n", + " # inset_rect,\n", + " # tar1 [img_idx],\n", + " # data2 =overlapping_pred,\n", + " # min_labelsize=min_labelsize)\n", + " \n", + " # add_pixel_kde(ax[ax_idx,3],\n", + " # inset_rect,\n", + " # tar2 [img_idx],\n", + " # data2 =pred1[img_idx],\n", + " # min_labelsize=min_labelsize)\n", + " \n", + "\n", + " ax[0,0].set_title('Inp')\n", + " ax[0,1].set_title('Recons')\n", + " ax[0,2].set_title('GT 1')\n", + " ax[0,3].set_title('Pred 1')\n", + " ax[0,4].set_title('Pred 2')\n", + "\n", + "#" + ] + }, + { + "cell_type": "markdown", + "id": "f19442f1", + "metadata": {}, + "source": [ + "### To save to tiff file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3a537930", + "metadata": {}, + "outputs": [], + "source": [ + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "# input_pred_unnorm = pred[...,2]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = input_pred_unnorm - ch1_pred_unnorm\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy() #ch2_pred_unnorm - ch2_pred_unnorm.min()\n", + "\n", + "# ch1_pred_unnorm = ch1_pred_unnorm.astype(np.int32)\n", + "# input_pred_unnorm = input_pred_unnorm.astype(np.int32)\n", + "# ch2_pred_unnorm = ch2_pred_unnorm.astype(np.int32)\n", + "\n", + "# data = np.concatenate([val_dset._data[:,:480,:480], ch1_pred_unnorm[...,None],\n", + "# ch2_pred_unnorm[...,None], input_pred_unnorm[...,None]],\n", + "# axis=-1)\n", + "\n", + "# import tifffile\n", + "# tifffile.imwrite(\"prediction2.tif\", \n", + "# np.swapaxes(data[:,None],1,4)[...,0].astype(np.uint16),\n", + "# imagej=True, \n", + "# # metadata={ 'axes': 'ZYXC'}, \n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2806ab6", + "metadata": {}, + "outputs": [], + "source": [ + "def show_for_one(idx):\n", + " print(f'Showing for {idx}')\n", + " with torch.no_grad():\n", + " inp, tar = val_dset[idx]\n", + "\n", + " inp = torch.Tensor(inp[None])\n", + " tar = torch.Tensor(tar[None])\n", + " inp = inp.cuda()\n", + " x_normalized = model.normalize_input(inp)\n", + " tar = tar.cuda()\n", + " tar_normalized = model.normalize_target(tar)\n", + "\n", + " recon_img_list = []\n", + " for _ in range(5):\n", + " if config.model.model_type == ModelType.UNet:\n", + " recon_normalized = model(x_normalized)\n", + " imgs = recon_normalized\n", + " elif config.model.model_type == ModelType.LadderVaeSemiSupervised:\n", + " out, td_data = model(x_normalized)\n", + " rec_loss, imgs = model.get_reconstruction_loss(out,\n", + " x_normalized,\n", + " tar_normalized,\n", + " return_predicted_img=True)\n", + " else:\n", + " recon_normalized, td_data = model(x_normalized)\n", + " rec_loss, imgs = model.get_reconstruction_loss(recon_normalized, tar_normalized,\n", + " return_predicted_img=True)\n", + " recon_img_list.append(imgs.cpu().numpy()[0])\n", + "\n", + " _,ax = plt.subplots(figsize=(12,4),ncols=3)\n", + " ax[0].imshow(inp[0,0].cpu().numpy())\n", + " ax[1].imshow(tar[0,0].cpu().numpy())\n", + " if tar.shape[1] ==2:\n", + " ax[2].imshow(tar[0,1].cpu().numpy())\n", + "\n", + " _,ax = plt.subplots(figsize=(20,8),ncols=5,nrows=2)\n", + " for i in range(5):\n", + " ax[0,i].imshow(recon_img_list[i][0])\n", + " ax[1,i].imshow(recon_img_list[i][1])\n", + "\n", + "show_for_one(np.random.randint(len(val_dset)))" + ] + }, + { + "cell_type": "markdown", + "id": "824ecf7e", + "metadata": {}, + "source": [ + "## Creating tiff file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de631db9", + "metadata": {}, + "outputs": [], + "source": [ + "rdate,rconfig,rid = ckpt_dir.split(\"/\")[-3:]\n", + "fname_prefix = rdate + '-' + rconfig.replace('-','')[:-2] + '-' + rid\n", + "fname_prefix" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0465dd97", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.io import imsave\n", + "import numpy as np\n", + "pred_unnorm = np.concatenate([ch1_pred_unnorm[...,None],\n", + " ch2_pred_unnorm[...,None]],\n", + " axis=-1)\n", + "for ch_idx in [0,1]:\n", + " tif_fname = f'{fname_prefix}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}_C{ch_idx}.tif'\n", + " tif_fpath=os.path.join('paper_tifs',tif_fname)\n", + " if config.data.data_type in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " output = np.concatenate([\n", + " pred_unnorm[None,:50,...,ch_idx],tar[None,:50,...,ch_idx],\n", + " ],axis=0)\n", + " else:\n", + " output = np.concatenate([\n", + " pred_unnorm[:1,...,ch_idx],tar[:1,...,ch_idx],\n", + " ],axis=0)\n", + " imsave(tif_fpath,output,plugin='tifffile')\n", + " print(tif_fpath)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92a8d256", + "metadata": {}, + "outputs": [], + "source": [ + "! ls -lhrt paper_tifs/2211-D8M3S0-*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f7a3da19", + "metadata": {}, + "outputs": [], + "source": [ + "# !ls paper_tifs/2211-D3M3S0-0_P64_G*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7b3c066", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(val_dset))\n", + "inp, tar = val_dset[idx]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c7b56b7", + "metadata": {}, + "outputs": [], + "source": [ + "if len(inp) > 1:\n", + " _,ax = plt.subplots(figsize=(10,2.5),ncols=4)\n", + " ax[0].imshow(inp[0])\n", + " ax[1].imshow(inp[1])\n", + " ax[2].imshow(inp[2])\n", + " ax[3].imshow(inp[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f02d1078", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b9fe5ce", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(10,10))\n", + "# tmp_data =tar_unnorm[idx,:,:,1]\n", + "# q = np.quantile(tmp_data,0.95)\n", + "# tmp_data[tmp_data >q] = q\n", + "# plt.imshow(tmp_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f4d490b", + "metadata": {}, + "outputs": [], + "source": [ + "pred_unnorm.min()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d38fa69", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,20),ncols=2,nrows=2)\n", + "ax[0,0].set_title('Channel 1',size=20)\n", + "ax[0,1].set_title('Channel 2',size=20)\n", + "ax[0,0].set_ylabel('Target',size=20)\n", + "ax[1,0].set_ylabel('Predictions',size=20)\n", + "ax[0,0].imshow(tar_unnorm[idx,:,:,0])\n", + "ax[0,1].imshow(tar_unnorm[idx,:,:,1])\n", + "ax[1,0].imshow(pred_unnorm[idx,:,:,0])\n", + "ax[1,1].imshow(pred_unnorm[idx,:,:,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79d4b581", + "metadata": {}, + "outputs": [], + "source": [ + "idx = 0#np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,30),ncols=2,nrows=3)\n", + "ax[0,0].set_title('Target',size=20)\n", + "ax[0,1].set_title('Prediction',size=20)\n", + "ax[0,0].set_ylabel('Mixed Input',size=20)\n", + "ax[1,0].set_ylabel('Channel 1',size=20)\n", + "ax[2,0].set_ylabel('Channel 2',size=20)\n", + "sz = 400\n", + "ax[0,0].imshow(np.mean(tar_unnorm[idx, 1000:1000+sz,400:400+sz], axis=2))\n", + "ax[0,1].imshow(np.mean(pred_unnorm[idx,1000:1000+sz,400:400+sz], axis=2))\n", + "\n", + "ax[1,0].imshow(tar_unnorm[idx, 1000:1000+sz,400:400+sz,0],vmax=126,vmin=88)\n", + "ax[1,1].imshow(pred_unnorm[idx,1000:1000+sz,400:400+sz,0], vmax=126,vmin=88)\n", + "\n", + "ax[2,0].imshow(tar_unnorm[idx, 1000:1000+sz,400:400+sz,1],vmax=126,vmin=78)\n", + "ax[2,1].imshow(pred_unnorm[idx,1000:1000+sz,400:400+sz,1],vmax=126,vmin=78)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c6c6d82", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm[idx, 1000:1500,400:900,0].std()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2fa229c6", + "metadata": {}, + "outputs": [], + "source": [ + "pred_unnorm[idx,1000:1500,400:900,0].std()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8285b5a8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93f14602", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,30),ncols=2,nrows=3)\n", + "ax[0,0].set_title('Target',size=20)\n", + "ax[0,1].set_title('Prediction',size=20)\n", + "ax[0,0].set_ylabel('Mixed Input',size=20)\n", + "ax[1,0].set_ylabel('Channel 1',size=20)\n", + "ax[2,0].set_ylabel('Channel 2',size=20)\n", + "\n", + "ax[0,0].imshow(np.mean(tar_unnorm[idx, 1000:1500,400:900], axis=2))\n", + "ax[0,1].imshow(np.mean(pred_unnorm[idx,1000:1500,400:900], axis=2))\n", + "\n", + "ax[1,0].imshow(tar_unnorm[idx, 1000:1500,400:900,0])\n", + "ax[1,1].imshow(pred_unnorm[idx,1000:1500,400:900,0])\n", + "\n", + "ax[2,0].imshow(tar_unnorm[idx, 1000:1500,400:900,1])\n", + "ax[2,1].imshow(pred_unnorm[idx,1000:1500,400:900,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5306061", + "metadata": {}, + "outputs": [], + "source": [ + "break here" + ] + }, + { + "cell_type": "markdown", + "id": "e63fb49d", + "metadata": {}, + "source": [ + "## Comparing PSNR with high res data. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fe03625", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.data_split_type import get_datasplit_tuples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62ae1c2b", + "metadata": {}, + "outputs": [], + "source": [ + "if eval_datasplit_type == DataSplitType.Val:\n", + " N = len(pred1)/config.training.val_fraction\n", + "elif eval_datasplit_type == DataSplitType.Test:\n", + " N = len(pred1)/config.training.test_fraction\n", + "train_idx,val_idx,test_idx = get_datasplit_tuples(config.training.val_fraction,config.training.test_fraction,N,\n", + " starting_train=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67bf4a4c", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4a5c2d6", + "metadata": {}, + "outputs": [], + "source": [ + "highres_actin = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/actin-60x-noise2-highsnr.tif')[...,None]\n", + "highres_mito = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/mito-60x-noise2-highsnr.tif')[...,None]\n", + "\n", + "if eval_datasplit_type == DataSplitType.Val:\n", + " highres_data = np.concatenate([highres_actin[val_idx[0]:val_idx[1]],\n", + " highres_mito[val_idx[0]:val_idx[1]]],\n", + " axis=-1).astype(np.float32)\n", + "elif eval_datasplit_type == DataSplitType.Test:\n", + " highres_data = np.concatenate([highres_actin[test_idx[0]:test_idx[1]],\n", + " highres_mito[test_idx[0]:test_idx[1]]],\n", + " axis=-1).astype(np.float32)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d325d7b", + "metadata": {}, + "outputs": [], + "source": [ + "thresh = np.quantile(highres_data,config.data.clip_percentile)\n", + "highres_data[highres_data > thresh]=thresh\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8daa9662", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,8),ncols=2,nrows=2)\n", + "ax[0,0].imshow(tar_unnorm[5,...,0])\n", + "ax[0,1].imshow(highres_data[5,...,0])\n", + "ax[1,0].imshow(tar_unnorm[8,...,1])\n", + "ax[1,1].imshow(highres_data[8,...,1])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b53ddb0e", + "metadata": {}, + "outputs": [], + "source": [ + "print('PSNR with HighRes', avg_psnr(highres_data[...,0], pred1),avg_psnr(highres_data[...,1], pred2))\n", + "print('RangeInvPSNR with HighRes', avg_range_inv_psnr(highres_data[...,0], pred1), \n", + " avg_range_inv_psnr(highres_data[...,1], pred2))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ba9fbf7", + "metadata": {}, + "outputs": [], + "source": [ + "# RangeInvPSNR with HighRes 16.82 18.33\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd49794d", + "metadata": {}, + "outputs": [], + "source": [ + "tar_1_tmp.dtype" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8537fa04", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.psnr import fix_range, zero_mean\n", + "def fix_range_with_highresdata(pred,tar):\n", + " pred_1_tmp = torch.Tensor(pred.reshape(len(pred),-1))\n", + " tar_1_tmp = torch.Tensor(tar.reshape(len(tar),-1))\n", + " pred_1_tmp = zero_mean(pred_1_tmp)\n", + " tar_1_tmp = zero_mean(tar_1_tmp)\n", + "# import pdb;pdb.set_trace()\n", + " tar_1_tmp = tar_1_tmp / torch.std(tar_1_tmp, dim=1, keepdim=True)\n", + " \n", + " pred_1_tmp = fix_range(tar_1_tmp,pred_1_tmp)\n", + " pred_1_tmp = pred_1_tmp.reshape_as(torch.Tensor(pred))\n", + " tar_1_tmp = tar_1_tmp.reshape_as(torch.Tensor(pred))\n", + " return pred_1_tmp, tar_1_tmp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3faaee3", + "metadata": {}, + "outputs": [], + "source": [ + "pred1_tmp, tar1_tmp = fix_range_with_highresdata(pred1, highres_data[...,0])\n", + "pred2_tmp, tar2_tmp = fix_range_with_highresdata(pred2, highres_data[...,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7076ff9c", + "metadata": {}, + "outputs": [], + "source": [ + "ssim1_mean, ssim1_std = avg_ssim(tar1_tmp.numpy(), pred1_tmp.numpy())\n", + "ssim2_mean, ssim2_std = avg_ssim(tar2_tmp.numpy(), pred2_tmp.numpy())\n", + "print(ssim1_mean, ssim2_mean)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6557f6b", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "ax[0].imshow(pred_1_tmp[0])\n", + "ax[1].imshow(tar_1_tmp[0])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c40d383", + "metadata": {}, + "outputs": [], + "source": [ + "break here." + ] + }, + { + "cell_type": "markdown", + "id": "9f992749", + "metadata": {}, + "source": [ + "## Inspecting the performance on grid boundaries.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "945a258f", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitched_prediction_mask\n", + "\n", + "\n", + "skip_boundary_pixel_count = 0\n", + "for sk_c in [1,16,32,48,56]:\n", + " mask = stitched_prediction_mask(val_dset, \n", + " (val_dset._img_sz,val_dset._img_sz), \n", + " skip_boundary_pixel_count, \n", + " sk_c)\n", + " mask = ignore_pixels(mask)\n", + " psnr1, psnr2 = compute_masked_psnr(mask, tar1,tar2,pred1,pred2)\n", + " print(f'[Pad:{val_dset.per_side_overlap_pixelcount()}] SkipCentral', sk_c,\n", + " psnr1,psnr2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a265d0bb", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(mask[0,:,:,0])" + ] + }, + { + "cell_type": "markdown", + "id": "5c7c325b", + "metadata": {}, + "source": [ + "## Inspecting the performance on central regions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36c6b110", + "metadata": {}, + "outputs": [], + "source": [ + "skip_central_pixel_count = 0\n", + "\n", + "for sk_b in [1,8,16,20,24]:\n", + " mask = stitched_prediction_mask(val_dset, \n", + " (val_dset._img_sz,val_dset._img_sz), \n", + " sk_b, \n", + " skip_central_pixel_count)\n", + " mask = ignore_pixels(mask)\n", + " psnr1, psnr2 = compute_masked_psnr(mask, tar1,tar2,pred1,pred2)\n", + " print(f'[Pad:{val_dset.per_side_overlap_pixelcount()}] SkipBoundary', sk_b, psnr1,psnr2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2d87cd57", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(mask[0,:,:,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "212d5536", + "metadata": {}, + "outputs": [], + "source": [ + "# for w in range(2,202,25):\n", + "# print(f'RangeInvPSNR but skipping {w}', avg_range_inv_psnr(np.copy(tar1[:,w:-w,w:-w]), \n", + "# np.copy(pred1[:,w:-w,w:-w])),\n", + " \n", + "# avg_range_inv_psnr(np.copy(tar2[:,w:-w,w:-w]), \n", + "# np.copy(pred2[:,w:-w,w:-w]).copy()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dff40aad", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79275615", + "metadata": {}, + "outputs": [], + "source": [ + "h = 1200\n", + "w = 1200\n", + "sz = 512\n", + "x = tar_unnorm[:1,h:h+sz,w:w+sz].mean(axis=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de600304", + "metadata": {}, + "outputs": [], + "source": [ + "p_count = 32\n", + "y1 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]))\n", + "y2 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]), constant_values=237)\n", + "y3 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]), mode='linear_ramp', end_values=237)\n", + "y4 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]),mode='reflect')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae212914", + "metadata": {}, + "outputs": [], + "source": [ + "np.quantile(x, [0,0.05, 0.1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cdf5c95", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(16,4),ncols=4)\n", + "ax[0].imshow(y1[0], )\n", + "ax[1].imshow(y2[0], )\n", + "ax[2].imshow(y3[0], )\n", + "ax[3].imshow(y4[0], )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60a7a758", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(tar_unnorm[0,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(tar_unnorm[0,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29d967c9", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(tar_unnorm[-1,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(tar_unnorm[-1,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff0c91ac", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(pred_unnorm[0,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(pred_unnorm[0,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "104bbfb4", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.ticker as ticker\n", + "# import seaborn.apionly as sns\n", + "\n", + "_,ax = plt.subplots(figsize=(20,4))\n", + "sns.histplot(tar_unnorm[-1,:,:].mean(axis=2).reshape(-1,))\n", + "ax.xaxis.set_major_locator(ticker.MultipleLocator(25))\n", + "ax.xaxis.set_major_formatter(ticker.ScalarFormatter())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30034a7b", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm[-1,:,:].shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0057b73e", + "metadata": {}, + "outputs": [], + "source": [ + "# inp, tar = val_dset[11060]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01ed9ed7", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(16,4),ncols=4)\n", + "# ax[0].imshow(inp[0])\n", + "# ax[1].imshow(inp[1])\n", + "# ax[2].imshow(inp[2])\n", + "# ax[3].imshow(inp[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b65aeae", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "# ax[0].imshow(tar[0])\n", + "# ax[1].imshow(tar[1])" + ] + }, + { + "cell_type": "markdown", + "id": "950f3b3a", + "metadata": {}, + "source": [ + "## Inspecting the difference in behaviour when different sized inputs are passed. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb42adc1", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "def compute_centered_diff(big,small):\n", + " pad = (big.shape[-1] - small.shape[-1])//2\n", + "# import pdb;pdb.set_trace()\n", + " return big[:,:,pad:-pad,pad:-pad] - small\n", + " \n", + "old_img_sz = val_dset.get_img_sz()\n", + "val_dset.set_img_sz(128)\n", + "inp2, tar2 = val_dset[10000]\n", + "with torch.no_grad():\n", + " bu_values2 = model.bottomup_pass(torch.Tensor(inp2[None]).cuda())\n", + "\n", + "val_dset.set_img_sz(256)\n", + "inp3, tar3 = val_dset[10000]\n", + "with torch.no_grad():\n", + " bu_values3 = model.bottomup_pass(torch.Tensor(inp3[None]).cuda())\n", + "\n", + "diff = (bu_values2[0] - bu_values3[0][:,:,32:-32,32:-32]).cpu().numpy()\n", + "sns.histplot(diff.reshape(-1,))\n", + "\n", + "##LOOKING AT bu_values\n", + "idx=1\n", + "diff = compute_centered_diff(bu_values3[idx],bu_values2[idx]).cpu().numpy()\n", + "_,ax =plt.subplots(figsize=(10,10))\n", + "sns.heatmap(diff[0,0])\n", + "\n", + "## Looking at the difference in prediction.\n", + "with torch.no_grad():\n", + " out2,_ = model(torch.Tensor(inp2[None,]).cuda())\n", + " out3,_ = model(torch.Tensor(inp3[None,]).cuda())\n", + " img2 = get_img_from_forward_output(out3,model)\n", + " img3 = get_img_from_forward_output(out2,model)\n", + "diff = compute_centered_diff(img2,img3)\n", + "_,ax =plt.subplots(figsize=(10,10))\n", + "sns.heatmap(diff[0,1].cpu().numpy())\n", + "val_dset.set_img_sz(old_img_sz)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c561780", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "489b52dd", + "metadata": {}, + "outputs": [], + "source": [ + "img = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/actin-60x-noise2-highsnr.tif')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3d1b606", + "metadata": {}, + "outputs": [], + "source": [ + "img.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6f5fb2c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=4)\n", + "ax[0].imshow(img[0])\n", + "ax[1].imshow(img[1])\n", + "ax[2].imshow(img[2])\n", + "ax[3].imshow(img[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0eea97dc", + "metadata": {}, + "outputs": [], + "source": [ + "img2 =load_tiff('/home/ashesh.ashesh/data/microscopy/OptiMEM100x014.tif')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70d1399c", + "metadata": {}, + "outputs": [], + "source": [ + "img2.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9b01f2c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=4)\n", + "ax[0].imshow(img2[0,...,0])\n", + "ax[1].imshow(img2[1,...,0])\n", + "ax[2].imshow(img2[2,...,0])\n", + "ax[3].imshow(img2[3,...,0])" + ] + }, + { + "cell_type": "markdown", + "id": "d11536e0", + "metadata": {}, + "source": [ + "###### " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f497f314", + "metadata": {}, + "outputs": [], + "source": [ + "inp, tar = val_dset[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a37d3fe", + "metadata": {}, + "outputs": [], + "source": [ + "inp.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "551123e4", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(3,3))\n", + "plt.imshow(tar[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0b01d1d", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(inp[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf517837", + "metadata": {}, + "outputs": [], + "source": [ + "(0.436+0.810)/2" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/EvalOnWholeFrames.ipynb b/denoisplit/notebooks/EvalOnWholeFrames.ipynb new file mode 100644 index 0000000..9df12a3 --- /dev/null +++ b/denoisplit/notebooks/EvalOnWholeFrames.ipynb @@ -0,0 +1,2431 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "19844352", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad91cc2b", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "# os.environ[\"CUDA_DEVICE_ORDER\"]=\"PCI_BUS_ID\" # see issue #152\n", + "# os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"2\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dcd3d0c2", + "metadata": {}, + "outputs": [], + "source": [ + "# there are two environments(debug and prod). From where you want to fetch the code and data? \n", + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27ec4422", + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7bccf9f", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.core.tiff_reader import load_tiff\n", + "# import numpy as np\n", + "# d1 = np.load('/group/jug/Igor/ashesh_n2v_preds/actin-60x_pred.npy')\n", + "# d2 = load_tiff('/group/jug/ashesh/N2V_inputs_igor/actin-60x-noise2-lowsnr.tif')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e96af6d5", + "metadata": {}, + "outputs": [], + "source": [ + "# val = 110\n", + "# mask = np.logical_and(d1>= val, d1 0:\n", + " factor = np.sqrt(2) if dset._input_is_sum else 1.0\n", + " img_tuples = [x + noise_tuples[0] * factor for x in img_tuples]\n", + "\n", + " inp = 0\n", + " for nch in img_tuples:\n", + " inp += nch/len(img_tuples)\n", + " h_start, w_start = dset._get_deterministic_hw(idx)\n", + " return inp, h_start, w_start\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2f11b80", + "metadata": {}, + "outputs": [], + "source": [ + "index = np.random.randint(len(val_dset))\n", + "inp, tar = val_dset[index]\n", + "frame, h_start, w_start = get_full_input_frame(index, val_dset)\n", + "print(h_start, w_start)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9595e475", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(frame[0,h_start:h_start+256,w_start:w_start+256])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c401fc9", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(inp[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "77918a82", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff\n", + "from denoisplit.analysis.paper_plots import show_for_one, get_plotoutput_dir\n", + "def get_hwt_start(idx):\n", + " h,w,t = val_dset.idx_manager.hwt_from_idx(idx, grid_size=64)\n", + " print(h,w,t)\n", + " pad = val_dset.per_side_overlap_pixelcount()\n", + " h = h - pad\n", + " w = w - pad\n", + " return h,w,t\n", + "\n", + "def get_crop_from_fulldset_prediction(full_dset_pred, idx, patch_size=256):\n", + " h,w,t = get_hwt_start(idx)\n", + " return np.swapaxes(full_dset_pred[t,h:h+patch_size,w:w+patch_size].astype(np.float32)[None], 0, 3)[...,0]\n", + "\n", + "if save_comparative_plots:\n", + " assert eval_datasplit_type == DataSplitType.Test\n", + " # CCP vs Microtubules: 925, 659, 502\n", + " # hdn_usplitdata = load_tiff('/group/jug/ashesh/data/paper_stats/Test_PNone_G16_M3_Sk0/pred_disentangle_2402_D23-M3-S0-L0_67.tif')\n", + " hdn_usplitdata = load_tiff('/group/jug/ashesh/data/paper_stats/Test_PNone_G32_M5_Sk0/pred_disentangle_2403_D23-M3-S0-L0_29.tif')\n", + "\n", + " # ER vs Microtubule 853, 859, 332\n", + " # hdn_usplitdata = load_tiff('/group/jug/ashesh/data/paper_stats/Test_PNone_G16_M3_Sk0/pred_disentangle_2402_D23-M3-S0-L0_60.tif')\n", + "\n", + " # ER vs CCP 327, 479, 637, 568\n", + " # hdn_usplitdata = load_tiff('/group/jug/ashesh/data/paper_stats/Test_PNone_G16_M3_Sk0/pred_disentangle_2402_D23-M3-S0-L0_59.tif')\n", + "\n", + " # F-actin vs ER 797\n", + " # hdn_usplitdata = load_tiff('/group/jug/ashesh/data/paper_stats/Test_PNone_G32_M10_Sk0/pred_disentangle_2403_D23-M3-S0-L0_15.tif')\n", + "\n", + " idx = 10#np.random.randint(len(val_dset))\n", + " patch_size = 500\n", + " mmse_count = 50\n", + " print(idx)\n", + " show_for_one(idx, val_dset, highsnr_val_dset, model, None, mmse_count=mmse_count, patch_size=patch_size, baseline_preds=[\n", + " get_crop_from_fulldset_prediction(hdn_usplitdata, idx).astype(np.float32),\n", + " ], num_samples=0)\n", + "\n", + "\n", + " plotsdir = get_plotoutput_dir(ckpt_dir, patch_size, mmse_count=mmse_count)\n", + " model_id = ckpt_dir.strip('/').split('/')[-1]\n", + " fname = f'patch_comparison_{idx}_{model_id}.png'\n", + " fpath = os.path.join(plotsdir, fname)\n", + " plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + " print(f'Saved to {fpath}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6505588", + "metadata": {}, + "outputs": [], + "source": [ + "val_dset[0][0].shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cac092b5", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitch_predictions\n", + "from denoisplit.analysis.mmse_prediction import get_dset_predictions\n", + "# from denoisplit.analysis.stitch_prediction import get_predictions as get_dset_predictions\n", + "\n", + "pred_tiled, rec_loss, logvar_tiled, patch_psnr_tuple, pred_std_tiled = get_dset_predictions(model, val_dset,batch_size,\n", + " num_workers=num_workers,\n", + " mmse_count=mmse_count,\n", + " model_type = config.model.model_type,\n", + " )\n", + "tmp = np.round([x.item() for x in patch_psnr_tuple],2)\n", + "print('Patch wise PSNR, as computed during training', tmp,np.mean(tmp))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b693a0c", + "metadata": {}, + "outputs": [], + "source": [ + "idx_list = np.where(logvar_tiled.squeeze() < -6)[0]\n", + "if len(idx_list) > 0:\n", + " plt.imshow(val_dset[idx_list[0]][1][1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8a1573f8", + "metadata": {}, + "outputs": [], + "source": [ + "len(val_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6709de9e", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "sns.histplot(logvar_tiled[::50].squeeze().reshape(-1,))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "771ac350", + "metadata": {}, + "outputs": [], + "source": [ + "print(np.quantile(rec_loss, [0,0.01,0.5, 0.9,0.99,0.999,1]).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05f2cdc7", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8673355b", + "metadata": {}, + "outputs": [], + "source": [ + "logvar_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c75b35f1", + "metadata": {}, + "outputs": [], + "source": [ + "if pred_tiled.shape[-1] != val_dset.get_img_sz():\n", + " pad = (val_dset.get_img_sz() - pred_tiled.shape[-1] )//2\n", + " pred_tiled = np.pad(pred_tiled, ((0,0),(0,0),(pad,pad),(pad,pad)))\n", + "\n", + "pred = stitch_predictions(pred_tiled,val_dset, smoothening_pixelcount=0)\n", + "if len(np.unique(logvar_tiled)) == 1:\n", + " logvar = None\n", + "else:\n", + " logvar = stitch_predictions(logvar_tiled,val_dset, smoothening_pixelcount=0)\n", + "pred_std = stitch_predictions(pred_std_tiled,val_dset, smoothening_pixelcount=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c6c82f7", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(pred[0,...,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f950003b", + "metadata": {}, + "outputs": [], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d2ad25d", + "metadata": {}, + "outputs": [], + "source": [ + "def print_ignored_pixels():\n", + " ignored_pixels = 1\n", + " while(pred[0,-ignored_pixels:,-ignored_pixels:,].std() ==0):\n", + " ignored_pixels+=1\n", + " ignored_pixels-=1\n", + " print(f'In {pred.shape}, last {ignored_pixels} many rows and columns are all zero.')\n", + " return ignored_pixels\n", + "\n", + "actual_ignored_pixels = print_ignored_pixels()" + ] + }, + { + "cell_type": "markdown", + "id": "b8474735", + "metadata": {}, + "source": [ + "## Ignore the pixels which are present in the last few rows and columns. \n", + "1. They don't come in the batches. So, in prediction, they are simply zeros. So they are being are ignored right now. \n", + "2. For the border pixels which are on the top and the left, overlapping yields worse performance. This is becuase, there is nothing to overlap on one side. So, they are essentially zero padded. This makes the performance worse. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcb2db09", + "metadata": {}, + "outputs": [], + "source": [ + "actual_ignored_pixels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cadedfcd", + "metadata": {}, + "outputs": [], + "source": [ + "if config.data.data_type in [DataType.OptiMEM100_014,\n", + " DataType.SemiSupBloodVesselsEMBL, \n", + " DataType.Pavia2VanillaSplitting,\n", + " DataType.ExpansionMicroscopyMitoTub,\n", + " DataType.ShroffMitoEr,\n", + " DataType.HTIba1Ki67]:\n", + " ignored_last_pixels = 32 \n", + "elif config.data.data_type == DataType.BioSR_MRC:\n", + " ignored_last_pixels = 44\n", + " # assert val_dset.get_img_sz() == 64\n", + " # ignored_last_pixels = 108\n", + "else:\n", + " ignored_last_pixels = 0\n", + "\n", + "ignore_first_pixels = 0\n", + "# ignored_last_pixels = 160\n", + "assert actual_ignored_pixels <= ignored_last_pixels, f'Set ignored_last_pixels={actual_ignored_pixels}'\n", + "print(ignored_last_pixels)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "226fed05", + "metadata": {}, + "outputs": [], + "source": [ + "tar = val_dset._data\n", + "def ignore_pixels(arr):\n", + " if ignore_first_pixels:\n", + " arr = arr[:,ignore_first_pixels:,ignore_first_pixels:]\n", + " if ignored_last_pixels:\n", + " arr = arr[:,:-ignored_last_pixels,:-ignored_last_pixels]\n", + " return arr\n", + "\n", + "pred = ignore_pixels(pred)\n", + "tar = ignore_pixels(tar)\n", + "if pred_std is not None:\n", + " pred_std = ignore_pixels(pred_std)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1be10fd7", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.analysis.plot_utils import *\n", + "# def add_pixel_kde(ax,\n", + "# rect: List[float],\n", + "# data1: np.ndarray,\n", + "# data2: Union[np.ndarray, None],\n", + "# min_labelsize: int,\n", + "# color1='r',\n", + "# color2='black',\n", + "# color_xtick='white',\n", + "# label1='Target',\n", + "# label2='Predicted'):\n", + "# \"\"\"\n", + "# Adds KDE (density plot) of data1(eg: target) and data2(ex: predicted) image pixel values as an inset\n", + "# \"\"\"\n", + "# inset_ax = add_subplot_axes(ax, rect, facecolor=\"None\", min_labelsize=min_labelsize)\n", + " \n", + "# inset_ax.tick_params(axis='x', colors=color_xtick)\n", + "\n", + "# sns.kdeplot(data=data1.reshape(-1, ), ax=inset_ax, color=color1, label=label1)\n", + "# if data2 is not None:\n", + "# sns.kdeplot(data=data2.reshape(-1, ), ax=inset_ax, color=color2, label=label2)\n", + "# inset_ax.set_xlim(left=0)\n", + "# xticks = inset_ax.get_xticks()\n", + "# # inset_ax.set_xticks([xticks[0], xticks[-1]])\n", + "# inset_ax.set_xticks([])\n", + "# clean_for_xaxis_plot(inset_ax)\n", + "\n", + "\n", + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "\n", + "# inset_rect=[0.1,0.1,0.4,0.2]\n", + "# inset_min_labelsize=10\n", + "# color_ch_list=['goldenrod','cyan']\n", + "\n", + "# _,ax = plt.subplots(figsize=(15,10),ncols=3,nrows=2)\n", + "# idx = 8\n", + "# pred1_crop = ch1_pred_unnorm[idx,1116:1372,1064:1320].copy()\n", + "# pred2_crop = ch2_pred_unnorm[idx,1116:1372,1064:1320].copy()\n", + "# pred1_crop[pred1_crop<0] = 0\n", + "# pred2_crop[pred2_crop<0] = 0\n", + "\n", + "# tar1_crop = tar[idx,1116:1372,1064:1320,0]\n", + "# tar2_crop = tar[idx,1116:1372,1064:1320,1]\n", + "\n", + "# ax[0,0].imshow(tar1_crop+tar2_crop)\n", + "# ax[0,1].imshow(tar1_crop)\n", + "# ax[0,2].imshow(tar2_crop)\n", + "\n", + "# ax[1,0].imshow(pred1_crop+pred2_crop)\n", + "# ax[1,1].imshow(pred1_crop)\n", + "# ax[1,2].imshow(pred2_crop)\n", + "# clean_ax(ax)\n", + "# add_pixel_kde(ax[0,0], inset_rect, \n", + "# tar1_crop, \n", + "# tar2_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1=color_ch_list[0], color2=color_ch_list[1])\n", + "\n", + "# add_pixel_kde(ax[1,1], inset_rect, \n", + "# pred1_crop, \n", + "# tar1_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1='red', color2=color_ch_list[0])\n", + "# add_pixel_kde(ax[1,2], inset_rect, \n", + "# pred2_crop, \n", + "# tar2_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1='red', color2=color_ch_list[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d8b680f", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.metrics import structural_similarity\n", + "\n", + "def _avg_psnr(target, prediction, psnr_fn):\n", + " output = np.mean([psnr_fn(target[i:i + 1], prediction[i:i + 1]).item() for i in range(len(prediction))])\n", + " return round(output, 2)\n", + "\n", + "\n", + "def avg_range_inv_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, RangeInvariantPsnr)\n", + "\n", + "\n", + "def avg_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, PSNR)\n", + "\n", + "\n", + "def compute_masked_psnr(mask, tar1, tar2, pred1, pred2):\n", + " mask = mask.astype(bool)\n", + " mask = mask[..., 0]\n", + " tmp_tar1 = tar1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_pred1 = pred1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_tar2 = tar2[mask].reshape((len(tar2), -1, 1))\n", + " tmp_pred2 = pred2[mask].reshape((len(tar2), -1, 1))\n", + " psnr1 = avg_range_inv_psnr(tmp_tar1, tmp_pred1)\n", + " psnr2 = avg_range_inv_psnr(tmp_tar2, tmp_pred2)\n", + " return psnr1, psnr2\n", + "\n", + "def avg_ssim(target, prediction):\n", + " ssim = [structural_similarity(target[i],prediction[i], data_range=(target[i].max() - target[i].min())) for i in range(len(target))]\n", + " return np.mean(ssim),np.std(ssim)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7311e08a", + "metadata": {}, + "outputs": [], + "source": [ + "sep_mean, sep_std = model.data_mean, model.data_std\n", + "if isinstance(sep_mean, dict):\n", + " sep_mean = sep_mean['target']\n", + " sep_std = sep_std['target']\n", + "\n", + "if isinstance(sep_mean, int):\n", + " pass\n", + "else:\n", + " sep_mean = sep_mean.squeeze()[None,None,None]\n", + " sep_std = sep_std.squeeze()[None,None,None]\n", + " sep_mean = sep_mean.cpu().numpy() \n", + " sep_std = sep_std.cpu().numpy()\n", + "\n", + "tar_normalized = (tar - sep_mean)/ sep_std" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6e19c77", + "metadata": {}, + "outputs": [], + "source": [ + "pred_std.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "32f39008", + "metadata": {}, + "outputs": [], + "source": [ + "if enable_calibration:\n", + " from denoisplit.metrics.calibration import Calibration\n", + " calib = Calibration(num_bins=30, mode='pixelwise')\n", + " native_stats = calib.compute_stats(pred, pred_std, tar_normalized)\n", + " count = np.array(native_stats[0]['bin_count'])\n", + " count = count / count.sum()\n", + " count.cumsum()[:-1]\n", + " plt.plot(native_stats[0]['rmv'][1:-1], native_stats[0]['rmse'][1:-1], 'o')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d58e8c1", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.metrics.calibration import get_calibrated_factor_for_stdev\n", + "from denoisplit.analysis.paper_plots import plot_calibration\n", + "\n", + "if enable_calibration:\n", + " inp, _ = val_dset[0]\n", + " plotsdir = get_plotoutput_dir(ckpt_dir, inp.shape[1], mmse_count=mmse_count)\n", + " model_id = ckpt_dir.strip('/').split('/')[-1]\n", + " fname = f'calibration_stats_{model_id}.npy'\n", + " fpath = os.path.join(plotsdir, fname)\n", + "\n", + " if eval_datasplit_type == DataSplitType.Val:\n", + " calib_factor0 = get_calibrated_factor_for_stdev(pred[...,0], np.log(pred_std[...,0]**2), tar_normalized[...,0], batch_size=8, lr=0.1)\n", + " calib_factor1 = get_calibrated_factor_for_stdev(pred[...,1], np.log(pred_std[...,1]**2), tar_normalized[...,1], batch_size=8, lr=0.1)\n", + " print(calib_factor0, calib_factor1)\n", + " calib_factor = np.array([calib_factor0, calib_factor1]).reshape(1,1,1,2)\n", + " np.save(fpath, calib_factor)\n", + " print(f'Saved evaluation stats fitted on validation set to {fpath}')\n", + "\n", + " elif eval_datasplit_type == DataSplitType.Test:\n", + " print('Loading the calibration factor from the file', fpath)\n", + " calib_factor = np.load(fpath)\n", + "\n", + " calib = Calibration(num_bins=30, mode='pixelwise')\n", + " stats = calib.compute_stats(pred, 2* np.log(pred_std * calib_factor), tar_normalized)\n", + " _,ax = plt.subplots(figsize=(5,5))\n", + " plot_calibration(ax, stats)" + ] + }, + { + "cell_type": "markdown", + "id": "0e2794e3", + "metadata": {}, + "source": [ + "### Calibration Plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8afb0b57", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.analysis.paper_plots import get_first_index, get_last_index\n", + "# if eval_datasplit_type == DataSplitType.Test:\n", + "# np.save(f'mmse_{mmse_count}_calib_factor.npy', stats)\n", + "# calib_factors = [np.load(fpath, allow_pickle=True) for fpath in ['mmse_2_calib_factor.npy',\n", + "# 'mmse_5_calib_factor.npy', \n", + "# 'mmse_10_calib_factor.npy', \n", + "# 'mmse_15_calib_factor.npy', \n", + "# #'mmse_50_calib_factor.npy',\n", + "# 'mmse_200_calib_factor.npy']]\n", + "# labels = ['MMSE=2', 'MMSE=5', 'MMSE=10', 'MMSE=15', \n", + "# #'MMSE=50', \n", + "#'MMSE-200']\n", + "\n", + "# _,ax = plt.subplots(figsize=(5,2.5))\n", + "# for i, calibration_stats in enumerate(calib_factors):\n", + "# first_idx = get_first_index(calibration_stats[()][0]['bin_count'], 0.0001)\n", + "# last_idx = get_last_index(calibration_stats[()][0]['bin_count'], 0.9999)\n", + "# ax.plot(calibration_stats[()][0]['rmv'][first_idx:-last_idx],\n", + "# calibration_stats[()][0]['rmse'][first_idx:-last_idx],\n", + "# '-+',\n", + "# label=labels[i])\n", + "\n", + "# ax.yaxis.grid(color='gray', linestyle='dashed')\n", + "# ax.xaxis.grid(color='gray', linestyle='dashed')\n", + "# ax.plot(np.arange(0,1.5, 0.01), np.arange(0,1.5, 0.01), 'k--')\n", + "# ax.set_facecolor('xkcd:light grey')\n", + "# plt.legend(loc='lower right')\n", + "# plt.xlim(0,3)\n", + "# plt.ylim(0,1.25)\n", + "# plt.xlabel('RMV')\n", + "# plt.ylabel('RMSE')\n", + "# ax.set_axisbelow(True)\n", + "\n", + "\n", + "# plotsdir = get_plotoutput_dir(ckpt_dir, 0, mmse_count=0)\n", + "# model_id = ckpt_dir.strip('/').split('/')[-1]\n", + "# fname = f'calibration_plot_{model_id}.png'\n", + "# fpath = os.path.join(plotsdir, fname)\n", + "# # plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + "# print(f'Saved to {fpath}')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2402048", + "metadata": {}, + "outputs": [], + "source": [ + "q_vals = [0.01, 0.1,0.5,0.9,0.95, 0.99,1]\n", + "for i in range(tar_normalized.shape[-1]):\n", + " print(f'Channel {i}:', np.quantile(tar_normalized[...,i], q_vals).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fef4512", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(6,6))\n", + "for i in range(tar.shape[-1]):\n", + " sns.histplot(tar[:,::10,::10,i].reshape(-1,), color='g', label=f'{i}', kde=True)\n", + "\n", + "plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb572707", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.data_loader.schroff_rawdata_loader import mito_channel_fnames\n", + "# from denoisplit.core.tiff_reader import load_tiff\n", + "# import seaborn as sns\n", + "\n", + "# fpaths = [os.path.join(datapath, x) for x in mito_channel_fnames()]\n", + "# fpath = fpaths[0]\n", + "# print(fpath)\n", + "# img = load_tiff(fpaths[0])\n", + "# temp = img.copy()\n", + "# sns.histplot(temp[:,:,::10,::10].reshape(-1,))\n", + "# plt.hist(temp[:,:,::10,::10].reshape(-1,),bins=100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24708c4c", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.patches as patches\n", + "import matplotlib\n", + "from denoisplit.analysis.plot_error_utils import plot_error\n", + "nrows = pred.shape[-1]\n", + "img_sz = 3\n", + "_,ax = plt.subplots(figsize=(4*img_sz,nrows*img_sz),ncols=4,nrows=nrows)\n", + "idx = np.random.randint(len(pred))\n", + "print(idx)\n", + "for ch_id in range(nrows):\n", + " ax[ch_id,0].imshow(tar_normalized[idx,..., ch_id], cmap='magma')\n", + " ax[ch_id,1].imshow(pred[idx,:,:,ch_id], cmap='magma')\n", + " plot_error(tar_normalized[idx,...,ch_id], \n", + " pred[idx,:,:,ch_id], \n", + " cmap = matplotlib.cm.coolwarm, \n", + " ax = ax[ch_id,2], max_val = None)\n", + "\n", + " cropsz = 256\n", + " h_s = np.random.randint(0, tar_normalized.shape[1] - cropsz)\n", + " h_e = h_s + cropsz\n", + " w_s = np.random.randint(0, tar_normalized.shape[2] - cropsz)\n", + " w_e = w_s + cropsz\n", + "\n", + " plot_error(tar_normalized[idx,h_s:h_e,w_s:w_e, ch_id], \n", + " pred[idx,h_s:h_e,w_s:w_e,ch_id], \n", + " cmap = matplotlib.cm.coolwarm, \n", + " ax = ax[ch_id,3], max_val = None)\n", + "\n", + " # Add rectangle to the region\n", + " rect = patches.Rectangle((w_s, h_s), w_e-w_s, h_e-h_s, linewidth=1, edgecolor='r', facecolor='none')\n", + " ax[ch_id,2].add_patch(rect)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "919db5ef", + "metadata": {}, + "outputs": [], + "source": [ + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "pred_unnorm = []\n", + "for i in range(pred.shape[-1]):\n", + " if sep_std.shape[-1]==1:\n", + " temp_pred_unnorm = pred[...,i]*sep_std[...,0] + sep_mean[...,0]\n", + " else:\n", + " temp_pred_unnorm = pred[...,i]*sep_std[...,i] + sep_mean[...,i]\n", + " pred_unnorm.append(temp_pred_unnorm)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b39f2ddb", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.scripts.evaluate import get_highsnr_data\n", + "highres_data = None\n", + "highres_data = get_highsnr_data(config, data_dir, eval_datasplit_type)\n", + "if highres_data is not None:\n", + " highres_data = ignore_pixels(highres_data).copy()\n", + " if data_t_list is not None:\n", + " highres_data = highres_data[data_t_list].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a0d4a8d", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.scripts.evaluate import compute_multiscale_ssim\n", + "if highres_data is not None:\n", + " print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + " psnr1 = avg_range_inv_psnr(highres_data[...,0], pred_unnorm[0])\n", + " psnr2 = avg_range_inv_psnr(highres_data[...,1], pred_unnorm[1])\n", + " tar_tmp = (highres_data - sep_mean) /sep_std\n", + " # tar0_tmp = (highres_data[...,0] - sep_mean[...,0]) /sep_std[...,0]\n", + " ssim1, ssim2 = compute_multiscale_ssim(tar_tmp, pred )\n", + " # ssim1_hres_mean, ssim1_hres_std = avg_ssim(highres_data[...,0], pred_unnorm[0])\n", + " # ssim2_hres_mean, ssim2_hres_std = avg_ssim(highres_data[...,1], pred_unnorm[1])\n", + " print('PSNR on Highres', psnr1, psnr2)\n", + " print('SSIM on Highres', np.round(ssim1,3), np.round(ssim2,3))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d75d6a1", + "metadata": {}, + "outputs": [], + "source": [ + "eps = 0.1\n", + "if config.model.model_type == ModelType.DenoiserSplitter:\n", + " ch_idx = 0\n", + " def predict(inp):\n", + " inp = model.denoise_one_channel(inp, model._denoiser_input)\n", + " out = model(inp)[0]\n", + " return model.likelihood.distr_params(out)['mean'].cpu().numpy()\n", + "\n", + " idx = np.random.randint(0, len(val_dset))\n", + " inp_tmp, tar_tmp = val_dset[idx]\n", + " h,w,t = val_dset.idx_manager.hwt_from_idx(idx)\n", + " h -= val_dset.per_side_overlap_pixelcount()\n", + " w -= val_dset.per_side_overlap_pixelcount()\n", + " print(idx)\n", + " inp_tmp = torch.Tensor(inp_tmp[None]).cuda()\n", + "\n", + " with torch.no_grad():\n", + " clean_pred1 = predict(inp_tmp)\n", + " clean_pred2 = predict(inp_tmp)\n", + " clean_pred3 = predict(inp_tmp)\n", + " pred_mmse_arr = []\n", + " for _ in range(50):\n", + " clean_pred4 = predict(inp_tmp)\n", + " pred_mmse_arr.append(clean_pred4)\n", + " pred_mmse = np.mean(pred_mmse_arr, axis=0, keepdims=False)\n", + "\n", + " _,ax = plt.subplots(ncols=6, figsize=(18,3))\n", + " ax[0].imshow(inp_tmp[0,0].cpu().numpy() ,cmap='magma')\n", + " ax[1].imshow(highres_data[t,h:h+256,w:w+256,ch_idx] , cmap='magma')\n", + " ax[2].imshow(clean_pred1[0,ch_idx], cmap='magma')\n", + " ax[3].imshow(clean_pred2[0,ch_idx], cmap='magma')\n", + " ax[4].imshow(pred_mmse[0,ch_idx], cmap='magma')\n", + " ax[5].imshow(np.std(pred_mmse_arr, axis=0, keepdims=False)[0,ch_idx]/(eps + np.abs(pred_mmse[0,ch_idx])), cmap='magma')\n", + " unnorm_temp_pred = (pred_mmse* data_std + data_mean)\n", + " minv = unnorm_temp_pred[0,ch_idx].min()\n", + " maxv = unnorm_temp_pred[0,ch_idx].max()\n", + " print(minv, maxv)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13fc1983", + "metadata": {}, + "outputs": [], + "source": [ + "rmse_arr = []\n", + "psnr_arr = []\n", + "rinv_psnr_arr = []\n", + "ssim_arr = []\n", + "for ch_id in range(pred.shape[-1]):\n", + " rmse =np.sqrt(((pred[...,ch_id] - tar_normalized[...,ch_id])**2).reshape(len(pred),-1).mean(axis=1))\n", + " rmse_arr.append(rmse)\n", + " psnr = avg_psnr(tar_normalized[...,ch_id].copy(), pred[...,ch_id].copy()) \n", + " rinv_psnr = avg_range_inv_psnr(tar_normalized[...,ch_id].copy(), pred[...,ch_id].copy())\n", + " ssim_mean, ssim_std = avg_ssim(tar[...,ch_id], pred_unnorm[ch_id])\n", + " psnr_arr.append(psnr)\n", + " rinv_psnr_arr.append(rinv_psnr)\n", + " ssim_arr.append((ssim_mean,ssim_std))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e87868b7", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + "print('Rec Loss',np.round(rec_loss.mean(),3) )\n", + "print('RMSE', '\\t'.join([str(np.mean(x).round(3)) for x in rmse_arr]))\n", + "print('PSNR', '\\t'.join([str(x) for x in psnr_arr]))\n", + "print('RangeInvPSNR','\\t'.join([str(x) for x in rinv_psnr_arr]))\n", + "print('SSIM','\\t'.join([f'{round(x,3)}±{round(y,4)}' for (x,y) in ssim_arr]))\n", + "print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73ba24ac", + "metadata": {}, + "outputs": [], + "source": [ + "if config.model.model_type == ModelType.LadderVaeSemiSupervised:\n", + " from denoisplit.analysis.plot_utils import add_pixel_kde\n", + " inset_rect=[0.1,0.1,0.4,0.2]\n", + " min_labelsize = 15\n", + "\n", + " nimgs=5\n", + " crp_sz = 400\n", + " img_sz = 8\n", + "\n", + " _,ax = plt.subplots(figsize=(4*img_sz,img_sz*nimgs),ncols=5,nrows=nimgs)\n", + " clean_ax(ax[1:,])\n", + " clean_ax(ax[:,1:])\n", + " img_idx_list = np.random.permutation(np.arange(len(tar1)))[:nimgs] #[19,23,15,18,4] # \n", + " for ax_idx in range(nimgs):\n", + " img_idx = img_idx_list[ax_idx]\n", + " overlapping_pred = pred1[img_idx] + pred2[img_idx]\n", + " overlapping_min = min(tar1[img_idx].min(),overlapping_pred.min())\n", + " overlapping_max = max(tar1[img_idx].max(),overlapping_pred.max())\n", + "\n", + " ax[ax_idx,0].imshow(tar1[img_idx])#,vmin=overlapping_min,vmax=overlapping_max)\n", + " ax[ax_idx,1].imshow(overlapping_pred)#,vmin=overlapping_min,vmax=overlapping_max)\n", + "\n", + " ch1_min = tar2[img_idx].min()#,pred1[img_idx].min())\n", + " ch1_max = tar2[img_idx].max()#,pred1[img_idx].max())\n", + " ax[ax_idx,2].imshow(tar2[img_idx])#,vmin=ch1_min,vmax=ch1_max)\n", + " ax[ax_idx,3].imshow(pred1[img_idx])#,vmin=ch1_min,vmax=ch1_max)\n", + "\n", + " ax[ax_idx,4].imshow(pred2[img_idx])\n", + " ax[ax_idx,0].set_ylabel(f'{img_idx}',fontsize=min_labelsize)\n", + "\n", + " # add_pixel_kde(ax[ax_idx,1],\n", + " # inset_rect,\n", + " # tar1 [img_idx],\n", + " # data2 =overlapping_pred,\n", + " # min_labelsize=min_labelsize)\n", + " \n", + " # add_pixel_kde(ax[ax_idx,3],\n", + " # inset_rect,\n", + " # tar2 [img_idx],\n", + " # data2 =pred1[img_idx],\n", + " # min_labelsize=min_labelsize)\n", + " \n", + "\n", + " ax[0,0].set_title('Inp')\n", + " ax[0,1].set_title('Recons')\n", + " ax[0,2].set_title('GT 1')\n", + " ax[0,3].set_title('Pred 1')\n", + " ax[0,4].set_title('Pred 2')\n", + "\n", + "#" + ] + }, + { + "cell_type": "markdown", + "id": "f19442f1", + "metadata": {}, + "source": [ + "### To save to tiff file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3a537930", + "metadata": {}, + "outputs": [], + "source": [ + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "# input_pred_unnorm = pred[...,2]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = input_pred_unnorm - ch1_pred_unnorm\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy() #ch2_pred_unnorm - ch2_pred_unnorm.min()\n", + "\n", + "# ch1_pred_unnorm = ch1_pred_unnorm.astype(np.int32)\n", + "# input_pred_unnorm = input_pred_unnorm.astype(np.int32)\n", + "# ch2_pred_unnorm = ch2_pred_unnorm.astype(np.int32)\n", + "\n", + "# data = np.concatenate([val_dset._data[:,:480,:480], ch1_pred_unnorm[...,None],\n", + "# ch2_pred_unnorm[...,None], input_pred_unnorm[...,None]],\n", + "# axis=-1)\n", + "\n", + "# import tifffile\n", + "# tifffile.imwrite(\"prediction2.tif\", \n", + "# np.swapaxes(data[:,None],1,4)[...,0].astype(np.uint16),\n", + "# imagej=True, \n", + "# # metadata={ 'axes': 'ZYXC'}, \n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6e00983", + "metadata": {}, + "outputs": [], + "source": [ + "_, ax = plt.subplots(figsize=(10,5),ncols=2)\n", + "ax[0].imshow(highsnr_val_dset._data[0,:200,:200,0])\n", + "ax[1].imshow(val_dset._data[0,:200,:200,0])\n", + "highsnr_val_dset._data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad02e8d3", + "metadata": {}, + "outputs": [], + "source": [ + "break here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df298730", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d93db4c5", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b67c59da", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.analysis.paper_plots import show_for_one\n", + "# # show_for_one(np.random.randint(len(val_dset)), mmse_count=50, patch_size=256)\n", + "# # show_for_one(899, mmse_count=50, patch_size=256)\n", + "# # show_for_one(51, mmse_count=50, patch_size=256)\n", + "# # # show_for_one(352, mmse_count=50, patch_size=256)\n", + "# # show_for_one(872, mmse_count=50, patch_size=256)\n", + "# # show_for_one(552, mmse_count=50, patch_size=256)\n", + "# 656, 327, 612, 490\n", + "# 51, 899, 352, 872, 552 ER vs Microtubules (144)\n", + "# 716, 599, 173 CCP vs Microtubules (145)\n", + "# 703, 189, 423 ER vs CCP (143)\n", + "# 772, 694, 237. Adverse:630 F-actin vs Er \n", + "idx = 716\n", + "patch_size = 256\n", + "mmse_count = 50\n", + "print(idx)\n", + "# fname = f'patch_comparison_{idx}.png'\n", + "# show_for_one(idx, val_dset, highsnr_val_dset, model, None, mmse_count=mmse_count, patch_size=patch_size, baseline_preds=[\n", + "# get_crop_from_fulldset_prediction(hdn_usplitdata, idx).astype(np.float32),\n", + "# ], num_samples=0)\n", + "\n", + "show_for_one(idx, val_dset, highsnr_val_dset, model, stats, mmse_count=mmse_count, patch_size=patch_size, num_samples=2)\n", + "\n", + "plotsdir = get_plotoutput_dir(ckpt_dir, patch_size, mmse_count=mmse_count)\n", + "model_id = ckpt_dir.strip('/').split('/')[-1]\n", + "fname = f'sampling_figure_{idx}_{model_id}.png'\n", + "fpath = os.path.join(plotsdir, fname)\n", + "plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + "print(f'Saved to {fpath}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e2a75811", + "metadata": {}, + "outputs": [], + "source": [ + "break here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "441abaf6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "824ecf7e", + "metadata": {}, + "source": [ + "## Creating tiff file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de631db9", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.paper_plots import get_plotoutput_dir, get_predictions\n", + "patch_size = 256\n", + "mmse_count = 50\n", + "idx_list = [51, 899, 352, 872, 552, 841] # Tub vs MT\n", + "\n", + "\n", + "plotsdir = get_plotoutput_dir(ckpt_dir, patch_size, mmse_count=mmse_count)\n", + "for idx in idx_list:\n", + " inp, tar, tar_hsnr, recon_img_list = get_predictions(idx, val_dset, model, mmse_count=mmse_count, patch_size=patch_size)\n", + " highsnr_val_dset.set_img_sz(patch_size, 64)\n", + " highsnr_val_dset.disable_noise()\n", + " _, tar_hsnr = highsnr_val_dset[idx]\n", + " plotfpath = os.path.join(plotsdir, f'{idx}.npy')\n", + " np.save(plotfpath, {'inp':inp, 'tar':tar, 'tar_hsnr':tar_hsnr, 'recon_img_list':recon_img_list})\n", + " print(f'Generated {plotfpath}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a18e9b50", + "metadata": {}, + "outputs": [], + "source": [ + "ddict = np.load('/group/jug/ashesh/data/paper_figures/patch_256_mmse_50/2402-D16M3S0-150/841.npy', allow_pickle=True)\n", + "plt.imshow(ddict[()]['inp'][0,0].cpu().numpy())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "98a0af0f", + "metadata": {}, + "outputs": [], + "source": [ + "plot_crops(ddict[()]['inp'], ddict[()]['tar'], ddict[()]['tar_hsnr'], ddict[()]['recon_img_list'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b84bc45", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0465dd97", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.io import imsave\n", + "import numpy as np\n", + "pred_unnorm = np.concatenate([ch1_pred_unnorm[...,None],\n", + " ch2_pred_unnorm[...,None]],\n", + " axis=-1)\n", + "for ch_idx in [0,1]:\n", + " tif_fname = f'{fname_prefix}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}_C{ch_idx}.tif'\n", + " tif_fpath=os.path.join('paper_tifs',tif_fname)\n", + " if config.data.data_type in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " output = np.concatenate([\n", + " pred_unnorm[None,:50,...,ch_idx],tar[None,:50,...,ch_idx],\n", + " ],axis=0)\n", + " else:\n", + " output = np.concatenate([\n", + " pred_unnorm[:1,...,ch_idx],tar[:1,...,ch_idx],\n", + " ],axis=0)\n", + " imsave(tif_fpath,output,plugin='tifffile')\n", + " print(tif_fpath)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92a8d256", + "metadata": {}, + "outputs": [], + "source": [ + "! ls -lhrt paper_tifs/2211-D8M3S0-*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f7a3da19", + "metadata": {}, + "outputs": [], + "source": [ + "# !ls paper_tifs/2211-D3M3S0-0_P64_G*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7b3c066", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(val_dset))\n", + "inp, tar = val_dset[idx]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c7b56b7", + "metadata": {}, + "outputs": [], + "source": [ + "if len(inp) > 1:\n", + " _,ax = plt.subplots(figsize=(10,2.5),ncols=4)\n", + " ax[0].imshow(inp[0])\n", + " ax[1].imshow(inp[1])\n", + " ax[2].imshow(inp[2])\n", + " ax[3].imshow(inp[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f02d1078", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b9fe5ce", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(10,10))\n", + "# tmp_data =tar_unnorm[idx,:,:,1]\n", + "# q = np.quantile(tmp_data,0.95)\n", + "# tmp_data[tmp_data >q] = q\n", + "# plt.imshow(tmp_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f4d490b", + "metadata": {}, + "outputs": [], + "source": [ + "pred_unnorm.min()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d38fa69", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,20),ncols=2,nrows=2)\n", + "ax[0,0].set_title('Channel 1',size=20)\n", + "ax[0,1].set_title('Channel 2',size=20)\n", + "ax[0,0].set_ylabel('Target',size=20)\n", + "ax[1,0].set_ylabel('Predictions',size=20)\n", + "ax[0,0].imshow(tar_unnorm[idx,:,:,0])\n", + "ax[0,1].imshow(tar_unnorm[idx,:,:,1])\n", + "ax[1,0].imshow(pred_unnorm[idx,:,:,0])\n", + "ax[1,1].imshow(pred_unnorm[idx,:,:,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79d4b581", + "metadata": {}, + "outputs": [], + "source": [ + "idx = 0#np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,30),ncols=2,nrows=3)\n", + "ax[0,0].set_title('Target',size=20)\n", + "ax[0,1].set_title('Prediction',size=20)\n", + "ax[0,0].set_ylabel('Mixed Input',size=20)\n", + "ax[1,0].set_ylabel('Channel 1',size=20)\n", + "ax[2,0].set_ylabel('Channel 2',size=20)\n", + "sz = 400\n", + "ax[0,0].imshow(np.mean(tar_unnorm[idx, 1000:1000+sz,400:400+sz], axis=2))\n", + "ax[0,1].imshow(np.mean(pred_unnorm[idx,1000:1000+sz,400:400+sz], axis=2))\n", + "\n", + "ax[1,0].imshow(tar_unnorm[idx, 1000:1000+sz,400:400+sz,0],vmax=126,vmin=88)\n", + "ax[1,1].imshow(pred_unnorm[idx,1000:1000+sz,400:400+sz,0], vmax=126,vmin=88)\n", + "\n", + "ax[2,0].imshow(tar_unnorm[idx, 1000:1000+sz,400:400+sz,1],vmax=126,vmin=78)\n", + "ax[2,1].imshow(pred_unnorm[idx,1000:1000+sz,400:400+sz,1],vmax=126,vmin=78)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c6c6d82", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm[idx, 1000:1500,400:900,0].std()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2fa229c6", + "metadata": {}, + "outputs": [], + "source": [ + "pred_unnorm[idx,1000:1500,400:900,0].std()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8285b5a8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93f14602", + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(len(tar_unnorm))\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(20,30),ncols=2,nrows=3)\n", + "ax[0,0].set_title('Target',size=20)\n", + "ax[0,1].set_title('Prediction',size=20)\n", + "ax[0,0].set_ylabel('Mixed Input',size=20)\n", + "ax[1,0].set_ylabel('Channel 1',size=20)\n", + "ax[2,0].set_ylabel('Channel 2',size=20)\n", + "\n", + "ax[0,0].imshow(np.mean(tar_unnorm[idx, 1000:1500,400:900], axis=2))\n", + "ax[0,1].imshow(np.mean(pred_unnorm[idx,1000:1500,400:900], axis=2))\n", + "\n", + "ax[1,0].imshow(tar_unnorm[idx, 1000:1500,400:900,0])\n", + "ax[1,1].imshow(pred_unnorm[idx,1000:1500,400:900,0])\n", + "\n", + "ax[2,0].imshow(tar_unnorm[idx, 1000:1500,400:900,1])\n", + "ax[2,1].imshow(pred_unnorm[idx,1000:1500,400:900,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5306061", + "metadata": {}, + "outputs": [], + "source": [ + "break here" + ] + }, + { + "cell_type": "markdown", + "id": "e63fb49d", + "metadata": {}, + "source": [ + "## Comparing PSNR with high res data. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fe03625", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.data_split_type import get_datasplit_tuples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62ae1c2b", + "metadata": {}, + "outputs": [], + "source": [ + "if eval_datasplit_type == DataSplitType.Val:\n", + " N = len(pred1)/config.training.val_fraction\n", + "elif eval_datasplit_type == DataSplitType.Test:\n", + " N = len(pred1)/config.training.test_fraction\n", + "train_idx,val_idx,test_idx = get_datasplit_tuples(config.training.val_fraction,config.training.test_fraction,N,\n", + " starting_train=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67bf4a4c", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4a5c2d6", + "metadata": {}, + "outputs": [], + "source": [ + "highres_actin = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/actin-60x-noise2-highsnr.tif')[...,None]\n", + "highres_mito = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/mito-60x-noise2-highsnr.tif')[...,None]\n", + "\n", + "if eval_datasplit_type == DataSplitType.Val:\n", + " highres_data = np.concatenate([highres_actin[val_idx[0]:val_idx[1]],\n", + " highres_mito[val_idx[0]:val_idx[1]]],\n", + " axis=-1).astype(np.float32)\n", + "elif eval_datasplit_type == DataSplitType.Test:\n", + " highres_data = np.concatenate([highres_actin[test_idx[0]:test_idx[1]],\n", + " highres_mito[test_idx[0]:test_idx[1]]],\n", + " axis=-1).astype(np.float32)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d325d7b", + "metadata": {}, + "outputs": [], + "source": [ + "thresh = np.quantile(highres_data,config.data.clip_percentile)\n", + "highres_data[highres_data > thresh]=thresh\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8daa9662", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,8),ncols=2,nrows=2)\n", + "ax[0,0].imshow(tar_unnorm[5,...,0])\n", + "ax[0,1].imshow(highres_data[5,...,0])\n", + "ax[1,0].imshow(tar_unnorm[8,...,1])\n", + "ax[1,1].imshow(highres_data[8,...,1])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b53ddb0e", + "metadata": {}, + "outputs": [], + "source": [ + "print('PSNR with HighRes', avg_psnr(highres_data[...,0], pred1),avg_psnr(highres_data[...,1], pred2))\n", + "print('RangeInvPSNR with HighRes', avg_range_inv_psnr(highres_data[...,0], pred1), \n", + " avg_range_inv_psnr(highres_data[...,1], pred2))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ba9fbf7", + "metadata": {}, + "outputs": [], + "source": [ + "# RangeInvPSNR with HighRes 16.82 18.33\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd49794d", + "metadata": {}, + "outputs": [], + "source": [ + "tar_1_tmp.dtype" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8537fa04", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.psnr import fix_range, zero_mean\n", + "def fix_range_with_highresdata(pred,tar):\n", + " pred_1_tmp = torch.Tensor(pred.reshape(len(pred),-1))\n", + " tar_1_tmp = torch.Tensor(tar.reshape(len(tar),-1))\n", + " pred_1_tmp = zero_mean(pred_1_tmp)\n", + " tar_1_tmp = zero_mean(tar_1_tmp)\n", + "# import pdb;pdb.set_trace()\n", + " tar_1_tmp = tar_1_tmp / torch.std(tar_1_tmp, dim=1, keepdim=True)\n", + " \n", + " pred_1_tmp = fix_range(tar_1_tmp,pred_1_tmp)\n", + " pred_1_tmp = pred_1_tmp.reshape_as(torch.Tensor(pred))\n", + " tar_1_tmp = tar_1_tmp.reshape_as(torch.Tensor(pred))\n", + " return pred_1_tmp, tar_1_tmp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3faaee3", + "metadata": {}, + "outputs": [], + "source": [ + "pred1_tmp, tar1_tmp = fix_range_with_highresdata(pred1, highres_data[...,0])\n", + "pred2_tmp, tar2_tmp = fix_range_with_highresdata(pred2, highres_data[...,1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7076ff9c", + "metadata": {}, + "outputs": [], + "source": [ + "ssim1_mean, ssim1_std = avg_ssim(tar1_tmp.numpy(), pred1_tmp.numpy())\n", + "ssim2_mean, ssim2_std = avg_ssim(tar2_tmp.numpy(), pred2_tmp.numpy())\n", + "print(ssim1_mean, ssim2_mean)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6557f6b", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "ax[0].imshow(pred_1_tmp[0])\n", + "ax[1].imshow(tar_1_tmp[0])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c40d383", + "metadata": {}, + "outputs": [], + "source": [ + "break here." + ] + }, + { + "cell_type": "markdown", + "id": "9f992749", + "metadata": {}, + "source": [ + "## Inspecting the performance on grid boundaries.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "945a258f", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitched_prediction_mask\n", + "\n", + "\n", + "skip_boundary_pixel_count = 0\n", + "for sk_c in [1,16,32,48,56]:\n", + " mask = stitched_prediction_mask(val_dset, \n", + " (val_dset._img_sz,val_dset._img_sz), \n", + " skip_boundary_pixel_count, \n", + " sk_c)\n", + " mask = ignore_pixels(mask)\n", + " psnr1, psnr2 = compute_masked_psnr(mask, tar1,tar2,pred1,pred2)\n", + " print(f'[Pad:{val_dset.per_side_overlap_pixelcount()}] SkipCentral', sk_c,\n", + " psnr1,psnr2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a265d0bb", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(mask[0,:,:,0])" + ] + }, + { + "cell_type": "markdown", + "id": "5c7c325b", + "metadata": {}, + "source": [ + "## Inspecting the performance on central regions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36c6b110", + "metadata": {}, + "outputs": [], + "source": [ + "skip_central_pixel_count = 0\n", + "\n", + "for sk_b in [1,8,16,20,24]:\n", + " mask = stitched_prediction_mask(val_dset, \n", + " (val_dset._img_sz,val_dset._img_sz), \n", + " sk_b, \n", + " skip_central_pixel_count)\n", + " mask = ignore_pixels(mask)\n", + " psnr1, psnr2 = compute_masked_psnr(mask, tar1,tar2,pred1,pred2)\n", + " print(f'[Pad:{val_dset.per_side_overlap_pixelcount()}] SkipBoundary', sk_b, psnr1,psnr2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2d87cd57", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(mask[0,:,:,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "212d5536", + "metadata": {}, + "outputs": [], + "source": [ + "# for w in range(2,202,25):\n", + "# print(f'RangeInvPSNR but skipping {w}', avg_range_inv_psnr(np.copy(tar1[:,w:-w,w:-w]), \n", + "# np.copy(pred1[:,w:-w,w:-w])),\n", + " \n", + "# avg_range_inv_psnr(np.copy(tar2[:,w:-w,w:-w]), \n", + "# np.copy(pred2[:,w:-w,w:-w]).copy()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dff40aad", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79275615", + "metadata": {}, + "outputs": [], + "source": [ + "h = 1200\n", + "w = 1200\n", + "sz = 512\n", + "x = tar_unnorm[:1,h:h+sz,w:w+sz].mean(axis=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de600304", + "metadata": {}, + "outputs": [], + "source": [ + "p_count = 32\n", + "y1 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]))\n", + "y2 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]), constant_values=237)\n", + "y3 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]), mode='linear_ramp', end_values=237)\n", + "y4 = np.pad(x,np.array([[0, 0], [p_count, p_count], [p_count, p_count]]),mode='reflect')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae212914", + "metadata": {}, + "outputs": [], + "source": [ + "np.quantile(x, [0,0.05, 0.1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cdf5c95", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(16,4),ncols=4)\n", + "ax[0].imshow(y1[0], )\n", + "ax[1].imshow(y2[0], )\n", + "ax[2].imshow(y3[0], )\n", + "ax[3].imshow(y4[0], )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60a7a758", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(tar_unnorm[0,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(tar_unnorm[0,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29d967c9", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(tar_unnorm[-1,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(tar_unnorm[-1,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff0c91ac", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=2)\n", + "sns.histplot(pred_unnorm[0,:,:,0].reshape(-1,),ax=ax[0])\n", + "sns.histplot(pred_unnorm[0,:,:,1].reshape(-1,),ax=ax[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "104bbfb4", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.ticker as ticker\n", + "# import seaborn.apionly as sns\n", + "\n", + "_,ax = plt.subplots(figsize=(20,4))\n", + "sns.histplot(tar_unnorm[-1,:,:].mean(axis=2).reshape(-1,))\n", + "ax.xaxis.set_major_locator(ticker.MultipleLocator(25))\n", + "ax.xaxis.set_major_formatter(ticker.ScalarFormatter())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30034a7b", + "metadata": {}, + "outputs": [], + "source": [ + "tar_unnorm[-1,:,:].shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0057b73e", + "metadata": {}, + "outputs": [], + "source": [ + "# inp, tar = val_dset[11060]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01ed9ed7", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(16,4),ncols=4)\n", + "# ax[0].imshow(inp[0])\n", + "# ax[1].imshow(inp[1])\n", + "# ax[2].imshow(inp[2])\n", + "# ax[3].imshow(inp[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b65aeae", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "# ax[0].imshow(tar[0])\n", + "# ax[1].imshow(tar[1])" + ] + }, + { + "cell_type": "markdown", + "id": "950f3b3a", + "metadata": {}, + "source": [ + "## Inspecting the difference in behaviour when different sized inputs are passed. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb42adc1", + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "def compute_centered_diff(big,small):\n", + " pad = (big.shape[-1] - small.shape[-1])//2\n", + "# import pdb;pdb.set_trace()\n", + " return big[:,:,pad:-pad,pad:-pad] - small\n", + " \n", + "old_img_sz = val_dset.get_img_sz()\n", + "val_dset.set_img_sz(128)\n", + "inp2, tar2 = val_dset[10000]\n", + "with torch.no_grad():\n", + " bu_values2 = model.bottomup_pass(torch.Tensor(inp2[None]).cuda())\n", + "\n", + "val_dset.set_img_sz(256)\n", + "inp3, tar3 = val_dset[10000]\n", + "with torch.no_grad():\n", + " bu_values3 = model.bottomup_pass(torch.Tensor(inp3[None]).cuda())\n", + "\n", + "diff = (bu_values2[0] - bu_values3[0][:,:,32:-32,32:-32]).cpu().numpy()\n", + "sns.histplot(diff.reshape(-1,))\n", + "\n", + "##LOOKING AT bu_values\n", + "idx=1\n", + "diff = compute_centered_diff(bu_values3[idx],bu_values2[idx]).cpu().numpy()\n", + "_,ax =plt.subplots(figsize=(10,10))\n", + "sns.heatmap(diff[0,0])\n", + "\n", + "## Looking at the difference in prediction.\n", + "with torch.no_grad():\n", + " out2,_ = model(torch.Tensor(inp2[None,]).cuda())\n", + " out3,_ = model(torch.Tensor(inp3[None,]).cuda())\n", + " img2 = get_img_from_forward_output(out3,model)\n", + " img3 = get_img_from_forward_output(out2,model)\n", + "diff = compute_centered_diff(img2,img3)\n", + "_,ax =plt.subplots(figsize=(10,10))\n", + "sns.heatmap(diff[0,1].cpu().numpy())\n", + "val_dset.set_img_sz(old_img_sz)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c561780", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "489b52dd", + "metadata": {}, + "outputs": [], + "source": [ + "img = load_tiff('/home/ashesh.ashesh/data/ventura_gigascience/actin-60x-noise2-highsnr.tif')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3d1b606", + "metadata": {}, + "outputs": [], + "source": [ + "img.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6f5fb2c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=4)\n", + "ax[0].imshow(img[0])\n", + "ax[1].imshow(img[1])\n", + "ax[2].imshow(img[2])\n", + "ax[3].imshow(img[3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0eea97dc", + "metadata": {}, + "outputs": [], + "source": [ + "img2 =load_tiff('/home/ashesh.ashesh/data/microscopy/OptiMEM100x014.tif')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70d1399c", + "metadata": {}, + "outputs": [], + "source": [ + "img2.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9b01f2c", + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(20,5),ncols=4)\n", + "ax[0].imshow(img2[0,...,0])\n", + "ax[1].imshow(img2[1,...,0])\n", + "ax[2].imshow(img2[2,...,0])\n", + "ax[3].imshow(img2[3,...,0])" + ] + }, + { + "cell_type": "markdown", + "id": "d11536e0", + "metadata": {}, + "source": [ + "###### " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f497f314", + "metadata": {}, + "outputs": [], + "source": [ + "inp, tar = val_dset[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a37d3fe", + "metadata": {}, + "outputs": [], + "source": [ + "inp.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "551123e4", + "metadata": {}, + "outputs": [], + "source": [ + "# _,ax = plt.subplots(figsize=(3,3))\n", + "plt.imshow(tar[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0b01d1d", + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(inp[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf517837", + "metadata": {}, + "outputs": [], + "source": [ + "(0.436+0.810)/2" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/ExpansionMicroscopyV2.ipynb b/denoisplit/notebooks/ExpansionMicroscopyV2.ipynb new file mode 100644 index 0000000..74bc459 --- /dev/null +++ b/denoisplit/notebooks/ExpansionMicroscopyV2.ipynb @@ -0,0 +1,104 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from czifile import imread as imread_czi\n", + "data = imread_czi('/group/jug/ashesh/data/expansion_microscopy_v2/Experiment-447.czi')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(data[3,0,2,0,...,0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "clean_data = data[3,0,[0,2],...,0]\n", + "clean_data = np.swapaxes(clean_data[...,None], 0,4)[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "idx = np.random.randint(0, clean_data.shape[0])\n", + "print(idx)\n", + "_,ax = plt.subplots(figsize=(10,5),ncols=2)\n", + "ax[0].imshow(clean_data[idx,..., 0])\n", + "ax[1].imshow(clean_data[idx,..., 1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/InspectingBackgroundSource.ipynb b/denoisplit/notebooks/InspectingBackgroundSource.ipynb new file mode 100644 index 0000000..5c19068 --- /dev/null +++ b/denoisplit/notebooks/InspectingBackgroundSource.ipynb @@ -0,0 +1,2161 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "59ec4ad9", + "metadata": {}, + "source": [ + "# Objective\n", + "The objective is to inspect how the background prediction happens in the model. I'll try to change the background and see what weights needs to change to allow this to happen. \n", + "Idea is to look at which region in the network is responsible for it. \n", + "## How to quantify this? \n", + "1. Look at how much weights have changed. \n", + " a. The magnitude of change in weights.\n", + " b. The fractional change in weights. \n", + " c. The number of weights that have changed above a certain threshold.\n", + "\n", + "2. Restrict different layers and see how long does it take to get this effect. \n", + "3. Also inspect if this change in weights is generalizable to other images or it is specific to just this image ? \n", + "4. Inspect how the model trained with a large patch size behaves as compared to the same architecture trained with a small patch size.\n", + "5. Inspect the above with UNet and with HVAE. The motivation is to see if stochasticity has any role to play in this." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "19844352", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "ad91cc2b", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "# os.environ[\"CUDA_DEVICE_ORDER\"]=\"PCI_BUS_ID\" # see issue #152\n", + "# os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"2\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "dcd3d0c2", + "metadata": {}, + "outputs": [], + "source": [ + "# there are two environments(debug and prod). From where you want to fetch the code and data? \n", + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "27ec4422", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DATA_ROOT:\t /group/jug/ashesh/data/\n", + "CODE_ROOT:\t /home/ashesh.ashesh/\n" + ] + } + ], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "db8d89b5", + "metadata": {}, + "outputs": [], + "source": [ + "# 'stats_'+'_'.join(ckpt_dir.split('/')[-4:]) + '.pkl'" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "5a9748a9", + "metadata": {}, + "outputs": [], + "source": [ + "ckpt_dir = \"/home/ashesh.ashesh/training/disentangle/2310/D3-M3-S0-L0/6\"\n", + "# 211/D3-M3-S0-L0/0\n", + "# 2210/D3-M3-S0-L0/128\n", + "# 2210/D3-M3-S0-L0/129" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "27410ddc", + "metadata": {}, + "outputs": [], + "source": [ + "# !ls /home/ubuntu/ashesh/training/disentangle/2209/D3-M9-S0-L0/1" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d7232e05", + "metadata": {}, + "outputs": [], + "source": [ + "dtype = int(ckpt_dir.split('/')[-2].split('-')[0][1:])" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "90109e80", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dtype" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "0b237569", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "if DEBUG:\n", + " if dtype == DataType.CustomSinosoid:\n", + " data_dir = f'{DATA_ROOT}/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + "else:\n", + " if dtype in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " data_dir = f'{DATA_ROOT}/sinosoid_without_test/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + " elif dtype == DataType.Prevedel_EMBL:\n", + " data_dir = f'{DATA_ROOT}/Prevedel_EMBL/PKG_3P_dualcolor_stacks/NoAverage_NoRegistration/'\n", + " elif dtype == DataType.AllenCellMito:\n", + " data_dir = f'{DATA_ROOT}/allencell/2017_03_08_Struct_First_Pass_Seg/AICS-11/'\n", + " elif dtype == DataType.SeparateTiffData:\n", + " data_dir = f'{DATA_ROOT}/ventura_gigascience'\n", + " elif dtype == DataType.SemiSupBloodVesselsEMBL:\n", + " data_dir = f'{DATA_ROOT}/EMBL_halfsupervised/Demixing_3P'\n", + " elif dtype == DataType.Pavia2VanillaSplitting:\n", + " data_dir = f'{DATA_ROOT}/pavia2'\n", + " elif dtype == DataType.ExpansionMicroscopyMitoTub:\n", + " data_dir = f'{DATA_ROOT}/expansion_microscopy_Nick/'\n", + " elif dtype == DataType.ShroffMitoEr:\n", + " data_dir = f'{DATA_ROOT}/shrofflab/'\n", + " elif dtype == DataType.HTIba1Ki67:\n", + " data_dir = f'{DATA_ROOT}/Stefania/20230327_Ki67_and_Iba1_trainingdata/'\n", + " \n", + "# 2720*2720: microscopy dataset.\n", + "\n", + "image_size_for_grid_centers = None\n", + "mmse_count = 1\n", + "custom_image_size = None\n", + "\n", + "\n", + "\n", + "batch_size = 8\n", + "num_workers = 4\n", + "COMPUTE_LOSS = False\n", + "use_deterministic_grid = None\n", + "threshold = None # 0.02\n", + "compute_kl_loss = False\n", + "evaluate_train = False# inspect training performance\n", + "eval_datasplit_type = DataSplitType.Test\n", + "val_repeat_factor = None\n", + "psnr_type = 'range_invariant' #'simple', 'range_invariant'" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f889dd2d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "data:\n", + " background_quantile: 0.0\n", + " channel_1: 2\n", + " channel_2: 3\n", + " clip_background_noise_to_zero: false\n", + " clip_percentile: 0.995\n", + " data_type: 3\n", + " deterministic_grid: false\n", + " image_size: 64\n", + " input_is_sum: false\n", + " multiscale_lowres_count: null\n", + " normalized_input: true\n", + " padding_mode: reflect\n", + " padding_value: null\n", + " randomized_channels: false\n", + " sampler_type: 0\n", + " skip_normalization_using_mean: false\n", + " target_separate_normalization: false\n", + " train_aug_rotate: false\n", + " use_one_mu_std: true\n", + "datadir: /group/jug/ashesh/data/microscopy/\n", + "exptname: 2310/D3-M3-S0-L0/6\n", + "git:\n", + " branch: autoregressive_v6\n", + " changedFiles: []\n", + " latest_commit: ef8393ebbce841552f735d022e5f61f914b8aa41\n", + " untracked_files: []\n", + "hostname: gnode08\n", + "loss:\n", + " free_bits: 0.0\n", + " kl_annealing: false\n", + " kl_annealtime: 10\n", + " kl_min: 1.0e-07\n", + " kl_start: -1\n", + " kl_weight: 0.1\n", + " loss_type: 0\n", + "model:\n", + " analytical_kl: false\n", + " decoder:\n", + " batchnorm: true\n", + " blocks_per_layer: 1\n", + " conv2d_bias: true\n", + " dropout: 0.1\n", + " multiscale_retain_spatial_dims: true\n", + " n_filters: 64\n", + " res_block_kernel: 3\n", + " res_block_skip_padding: false\n", + " enable_noise_model: false\n", + " encoder:\n", + " batchnorm: true\n", + " blocks_per_layer: 1\n", + " dropout: 0.1\n", + " n_filters: 64\n", + " res_block_kernel: 3\n", + " res_block_skip_padding: false\n", + " gated: true\n", + " img_shape: null\n", + " learn_top_prior: true\n", + " logvar_lowerbound: -5\n", + " merge_type: residual\n", + " mode_pred: true\n", + " model_type: 3\n", + " monitor: val_psnr\n", + " multiscale_lowres_separate_branch: false\n", + " multiscale_retain_spatial_dims: true\n", + " no_initial_downscaling: true\n", + " noise_model_ch1_fpath: null\n", + " non_stochastic_version: true\n", + " nonlin: elu\n", + " predict_logvar: pixelwise\n", + " res_block_type: bacdbacd\n", + " skip_nboundary_pixels_from_loss: null\n", + " stochastic_skip: true\n", + " use_vampprior: false\n", + " var_clip_max: 20\n", + " z_dims:\n", + " - 128\n", + " - 128\n", + " - 128\n", + " - 128\n", + "training:\n", + " batch_size: 16\n", + " earlystop_patience: 200\n", + " grad_clip_norm_value: 0.5\n", + " gradient_clip_algorithm: value\n", + " lr: 0.0005\n", + " lr_scheduler_patience: 30\n", + " max_epochs: 400\n", + " num_workers: 4\n", + " pre_trained_ckpt_fpath: ''\n", + " precision: 16\n", + " test_fraction: 0.1\n", + " train_repeat_factor: null\n", + " val_fraction: 0.1\n", + " val_repeat_factor: null\n", + "workdir: /home/ashesh.ashesh/training/disentangle/2310/D3-M3-S0-L0/6\n", + "\n" + ] + } + ], + "source": [ + "%run ./nb_core/config_loader.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "2a0047fe", + "metadata": {}, + "outputs": [], + "source": [ + "# config.model.decoder" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "bc8a3fed", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.sampler_type import SamplerType\n", + "from denoisplit.core.loss_type import LossType\n", + "from denoisplit.data_loader.ht_iba1_ki67_rawdata_loader import SubDsetType\n", + "# from denoisplit.core.lowres_merge_type import LowresMergeType\n", + "\n", + "\n", + "with config.unlocked():\n", + " config.model.skip_nboundary_pixels_from_loss = None\n", + " if config.model.model_type == ModelType.UNet and 'n_levels' not in config.model:\n", + " config.model.n_levels = 4\n", + " if config.data.sampler_type == SamplerType.NeighborSampler:\n", + " config.data.sampler_type = SamplerType.DefaultSampler\n", + " config.loss.loss_type = LossType.Elbo\n", + " config.data.grid_size = config.data.image_size\n", + " if 'ch1_fpath_list' in config.data:\n", + " config.data.ch1_fpath_list = config.data.ch1_fpath_list[:1]\n", + " config.data.mix_fpath_list = config.data.mix_fpath_list[:1]\n", + " if config.data.data_type == DataType.Pavia2VanillaSplitting:\n", + " if 'channel_2_downscale_factor' not in config.data:\n", + " config.data.channel_2_downscale_factor = 1\n", + " if config.model.model_type == ModelType.UNet and 'init_channel_count' not in config.model:\n", + " config.model.init_channel_count = 64\n", + " \n", + " if 'skip_receptive_field_loss_tokens' not in config.loss:\n", + " config.loss.skip_receptive_field_loss_tokens = []\n", + " \n", + " if dtype == DataType.HTIba1Ki67:\n", + " config.data.subdset_type = SubDsetType.Iba1Ki64\n", + " config.data.empty_patch_replacement_enabled = False\n", + " \n", + " if 'lowres_merge_type' not in config.model.encoder:\n", + " config.model.encoder.lowres_merge_type = 0" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "edde2155", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "Loading /group/jug/ashesh/data//microscopy/OptiMEM100x014.tif with Channels 2,3,datasplit mode:Train\n", + "[MultiChDeterministicTiffDloader] Sz:64 Train:1 N:49 NumPatchPerN:1764 NormInp:True SingleNorm:True Rot:False RandCrop:False Q:0.995 SummedInput:False ReplaceWithRandSample:False BckQ:0.0\n", + "Loading /group/jug/ashesh/data//microscopy/OptiMEM100x014.tif with Channels 2,3,datasplit mode:Test\n", + "[MultiChDeterministicTiffDloader] Sz:64 Train:0 N:6 NumPatchPerN:1764 NormInp:True SingleNorm:True Rot:False RandCrop:False Q:0.995 SummedInput:False ReplaceWithRandSample:False BckQ:0.0\n", + "\n", + "config.pkl\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[LadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:False\n", + "Loading from epoch 74\n", + "Model has 2.992M parameters\n" + ] + } + ], + "source": [ + "%run ./nb_core/disentangle_setup.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "53df96f2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "86436" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(train_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "60d5fc4a", + "metadata": {}, + "outputs": [], + "source": [ + "if config.data.multiscale_lowres_count is not None and custom_image_size is not None:\n", + " model.reset_for_different_output_size(custom_image_size)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "11cf6c69", + "metadata": {}, + "outputs": [], + "source": [ + "# if config.model.model_type not in [ModelType.UNet, ModelType.BraveNet]:\n", + "# with torch.no_grad():\n", + "# inp, tar = val_dset[0][:2]\n", + "# out, td_data = model(torch.Tensor(inp[None]).cuda())\n", + "# print(td_data['z'][-1].shape)\n", + "# print(out.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d05be428", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA9wAAAKVCAYAAAA9cOMNAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdeXhV1b0//vcZkpN5JhMJIcwzyCACIk7E4tB6baut1qFX+5OLbUVua6Xeb4t+vfCtveXSQaiztnVqrTi0qGBVkEkBQRCQMZCEJITM8znJOfv3R2rwvVYcgpwQ6Pv1PDwPn7P3XnvttfdZOXuf81nL5TiOAxERERERERE5qdynugIiIiIiIiIiZyLdcIuIiIiIiIiEgW64RURERERERMJAN9wiIiIiIiIiYaAbbhEREREREZEw0A23iIiIiIiISBjohltEREREREQkDHTDLSIiIiIiIhIGuuEWERERERERCQPdcIuIiIiIiIiEgW64RUROwJo1a3DFFVcgOzsbLpcLL7744udus3r1akyYMAFRUVEYMGAAfv/734e/oiIip4D6SBGRDrrhFhE5AU1NTRg7dix+97vffaH1CwsLcemll2L69OnYunUrfvrTn+KHP/wh/vrXv4a5piIiPU99pIhIB5fjOM6proSIyOnM5XJh+fLluPLKKz91nZ/85Cd4+eWXsXv37s7XZs+ejQ8++AAbNmzogVqKiJwa6iNF5F+Z91RXQETkX8GGDRtQUFBAr11yySV49NFH0dbWhoiIiC638/v98Pv9nXEoFEJ1dTVSU1PhcrnCWmcROfM4joOGhgZkZ2fD7e49P3Q8kT5S/aOInEzh6h91wy0i0gPKy8uRkZFBr2VkZKC9vR2VlZXIysrqcrtFixbhnnvu6Ykqisi/kOLiYuTk5JzqanQ6kT5S/aOIhMPJ7h/DdsO9dOlS/PKXv0RZWRlGjhyJJUuWYPr06eHanYhIr2d+4/JxRs9nfRMzf/58zJs3rzOuq6tDv379UFxcjISEhPBUVETOWPX19cjNzUV8fPyproqlu32k+kcROZnC1T+G5Yb7ueeew9y5c7F06VJMmzYNDz74IGbNmoVdu3ahX79+n7ltKBRCaWkp4uPj9XMgETkhvfEnk5mZmSgvL6fXKioq4PV6kZqa+qnb+Xw++Hw+6/WEhAR9oBSRE9bbPmOdSB+p/lFEwuFk949hueFevHgxbr75Ztxyyy0AgCVLluD111/HsmXLsGjRos/ctrS0FLm5ueGoloj8i+lNP5mcMmUKXnnlFXpt5cqVmDhx4qfmb4uI/KtQHykiZ6qTfsMdCASwZcsW3HXXXfR6QUEB1q9fb61vDnjx8c+Hxv9pNjwxHU8ty/f1sba7+fy3KN5ezx+qm9sjKT4/da9VxkO7plHsjQhR/PMR3PEDQLPDT1JX1w6luKyFn6iWN9hPWEf3KaV4W0VfioNB/kYuMabFKuP6fu9S/D9vX0ax76jH2iZuciW/8AI/MW7K5qc5QZ89gH1kPa/jO6+K4ol9iq1t1r44jmJXOy8PTGqgeM6INVYZ+1oyKV51kNvdCdlPovqnc90OHUuhuK2V/4BHlvA1AwBtuQGK43bw+Y9ostuoejwf4H3nvkDxnysmUlzrj7bKaArwfr434B0uo5TLWDLgeauMK9ffSrHLzXVNTmy2tvk8U9ILuV6p66x1/qv4CoovTttN8W//ztcqALT1aaM4IorjYAW3keOx2334qOPXXntTAG9+44mw/mSysbER+/fv74wLCwuxbds2pKSkoF+/fpg/fz6OHDmCP/zhDwA6Rtv93e9+h3nz5uF73/seNmzYgEcffRTPPPNM2OooInKqqI8UEelw0m+4KysrEQwGuxz4wvypEPDpA154YnzwxnbcdLijo6zlUXFc9Ygg3yxFGDfc5voA4I7hcj0RQYpj4u2bVoT4tUhjP1433yh5gvZPnSLjeBtPo7GOccPtjeUHAQAQbRyP2UYen133jx9gHK+IuY1x0xpl39R4/LyOWWZknP0U2uPj/biMqnli+ObKPDYAiPRwuea56+qG++Prp3ObJt7G7eIyPVH2DXcwms+Fx/jpmqfNbiN3NN9wm9dRRJNxzXjta8RjvGa2iXlscfH2z6bNNjJvuD0xfL1/ET7j/Ha134hYPj7rWo2y38/uaM9nxo6xjeO1293cLxDen0xu3rwZF1xwQWf8cR7hjTfeiCeeeAJlZWUoKirqXJ6fn48VK1bgjjvuwAMPPIDs7Gz85je/wde//vWw1VFE5FRRHyki0uGkz8NdWlqKvn37Yv369ZgyZUrn6//93/+NP/7xj/joo49offMb7o+T1XMf+lnnTaTTYt88/s8Fz1H8j7oRFBc1JVM8NP6oVcZLb51NsSeXv/Fz74yztmnN5pup4UNLKA45/AE/xWd/i3i4get2WfZOil8sHkNxU6t9I5GfWk3xzo/4Z/ieRvtGyNXOdYsaWkdx30SOD75r59u3x/HNf2S1caPEXwgDAFoG+SmOPsg3i0aToW2o/Y2+28M3h4My+Nv6krpEa5vL87hd3yofTHFNQwzFIzLtB0Jbd+ZTHH2Ebx4vu8qeG/TFj8ZSHDzGN4uRtXxuXCP4G34ACBkPEGLfjqV4wk3bKX77bb5mAMDVj6+960ZsoviPb5xnbZM/7gjFhzfxL0fM8x+XU2+V0bInibdJNy6K9i6uzQC/dtHEDyn+x+5hvH5NFw92Wo+3Wai1FYUL7kZdXd0Zl8dXX1+PxMTEM/LYRCT8zuQ+5Ew+NhEJv3D1ISf9G+60tDR4PJ4uB74wv/UGPn3ACxEREREREZHT2UkfvjcyMhITJkzAqlWr6PVVq1Zh6tSpJ3t3IiIiIiIiIr1SWEYpnzdvHq6//npMnDgRU6ZMwUMPPYSioiLMnj07HLsTERERERER6XXCcsN9zTXXoKqqCvfeey/KysowatQorFixAnl5eeHYnYiIiIiIiEivE5YbbgCYM2cO5syZc8LbXzpsZ+eI1++UDrCW//zR71AcmsSDNznbOdF9d5J9s3/W5P0U1wV46qGLv2kPiPX7zTzQlD/ITVjTzGXsK023yoiK5kGk/vj8RRS3JfDAVMEkYx4tAHGZPBCZO5ZH+h4y1B4k7qPtPAiafw8PNDbn6y9SfPtebmMAGDS4jMv4TRbFRyfZA9wlpzZSHJfNA771i6+huKzZHqSgZCNPnfZRFbfzjAm7rG2OBXhKqPIjPFjd9JE8VdzafYOsMgYM5rEIiuu4Hn9dzwPvAYC7lQc8cxnnylvGde9qrHDvBzxgX8h4p64+yHWNHGQPXtZazMf/QV+uO7JarW0Kt/E6LiPpxN3CL3y1Pw9uBgDPNU/gFxp4gLPMfnz+AaCqjgeF2/xHHnguIovHdgxk8PUOAH1HHJ8Grr3Jj0JrDRERERGRnnXSc7hFRERERERERDfcIiIiIiIiImGhG24RERERERGRMAhbDveXtb68PzwxHfNzJ0T5reXxlx6kuPBvnOfdd9ZhikcnlVplbK7inObDuzM5rkixthk7oITi/a8OpNhXw7mmf/jJA1YZ06L4OcdYz7cpjo/gnO3qj1KtMvb+aSjFcVGcN1y1ys5Zd83knN1QBc9//p/Lb6Q4uoHLBICS8lyKB97BmbJHttr7HZvObd83qpbiUdHcpscS7RzuxeYc7h5u5yxfnbXNs2unUDxlPOdsH6xL4yK9nDsPADV/5Zzm0EDeb8oH9jMrM9+6Jo5zmGOmH6O4qobztQHAO5bz3lvbODfeezCG4uYsO6fZV8/nb9shPne/POd5a5t7dl1G8a1D1lK87CMew+DV4uFWGe1+rmvcAT5+550+1jahS/narB3F74HkbD6/3g32eyJneG3n/9tcAWu5iIiIiEhP0zfcIiIiIiIiImGgG24RERERERGRMNANt4iIiIiIiEgY9Noc7v8c9AZi4jtyQd9rsufh9oDzbd2Xc25tRjTPS9wSjLTKKCrnHO0bZ7xD8ZNrp1vbfFDHOcoZ51VQ3PQ2z7t9/av/YZUBripuOe9tih9eN4NiX26TVcSIKcUUj44/QvFjL15sbXNWf95mbzzn0sZEch5w/QZ7DvG2WK78zv3G3M5Jdi7x6i0jKI5Ia6H4LziL4ql59gzKEXGck5uSyG2yrTbH2sadwtts2MVzV6et58v/mts5XxkAnmqeTPHwgZyP3jzGvq6OvZVNcWQl5zRH9ueZtz1FUVYZgTTOYY5O4TZrSea8aATtfPspBTxH9ts7hlH8X0/Z86y39uXz97/7Oafbk9tM8S1D11llNOfx2AB/jOO5yn8wZoW1zX+tuYpiXwW3WV0Lz6Ee6mfPTb+/9nhOfrDZHvdBRERERKSn6RtuERERERERkTDQDbeIiIiIiIhIGOiGW0RERERERCQMem0O989f+ybcUR25rcFYe37kuANc9dY0zi2uHldOcUubkfMKIGTMbfzkB+dQ7Pg41xYALhz1EcX5MZUU/2niJIpHpPNywM57fmTN+RR7G/k5SCDazhP+YDnnRfu+zjmtThdn9v1Cnnccddwmbce4PaImVltlJD2TRHHFRN5R2gj7eI8Wca5830f5eMq+x/m2a1ePsspw5XHOttfN18RH241jA+BpMfKa0zg/ua6A85GfXj3NKqPvGr6uDg3rT/GgAp4PHgAapnIb1Bzk4y/fwXOKh7K7mDO6neueFs/HX/Mez1XelGdfq2PjOWd/877RXOZMzvsHgKN18RS3uDm/3Cnj+b+fTxxvlVG6l8cG6DfsKMX/94NLrW2mjdxH8YZGzjePqDfeExHGQAgAKguPt3OopdVaLiIiIiLS0/QNt4iIiIiIiEgY6IZbREREREREJAx0wy0iIiIiIiISBrrhFhEREREREQmDXjto2oVTtyMyrmNwrdLmRGt50bYBFDcO5QGxSrdnUnzOtN1WGZUVPPCU087PH1ytPIgYAKxZzQNPbS3k5d6CeooP/iPfKgN9eYAzXwXvJ2UqD/hWZgxCBQAtZ/GAX6vX8kBj3oAxYBgAhPi1YaN4UK3Ct/pT/K0BW6wiHr+KB5ab2JcH3tp9jAcEA4CE3XyZFV7Fxz8guY7ig2k+u4yNcRQfGcaDecFnD6wXn8/lNu3gwct8VTx4W+hcXh8Aqr/NbRbcw4OKFVZzmQDQsp+vVyeeBzSL78/XSG0ZX4cAkL6er4mWq3mAu4hzq3iDw0lWGctemEXx4Ev5Yt27ob+1TTCaByNzeTiOO8TvkSNRaVYZZ43jgeRag1z3a4a+b23z1E4ebDDWPHeNfL5H5PB7BAAOrjr+Xgv67feuiIiIiEhP0zfcIiIiIiIiImGgG24RERERERGRMNANt4iIiIiIiEgY9Noc7n+8OwbuqI68zSlnf2Qtb87mOOYA5+O2ZHJO75aVI+yd9OW874y+NRQfLUm2Nuk/vJTiiLM5P3fvln4UJx7lHFgAcNzc7KGRjRSXHuS82OgKOx/VXRpDcXMu1yPiqLUJAm6uy+79fSk+6+J9FL9ZMdQqo2AAn4uVKyZS3D6oxdrmazdspHhA9DGKf/fcFbxBFud4A0D96ADF/ftxGdVN3B4AcFY655dvqk6luI3TsTE1+7BVxtv7B1N84cXbKf6g0rgQATQaOdvuWL7OWgOc0xy/z34bVlzgp9jXzHnt7cWxFEc02zn70cf4tY9KOb8+bxK3DwA0Bfh99NWcHRT7z+O6rq/ksRQAICemluJXto2l+EidPSZDyuvRFLdd1UqxU8XH7821c/bb449f36EI+30nIiIiItLT9A23iIiIiIiISBjohltEREREREQkDHTDLSIiIiIiIhIGvTaHO6LGDY+v43nAnup0a3nQmKr5wlk8t+87JZxb2tKHc1MBwHWM5/atquW5nt3Ndu50nyjOtz64jPOcL53Lc1f/LZ3n7QYAT5mRj2rkVl81eTPFL3ww3irD1WLULZ7zhBuHch4xALiMebhdfn7esv29gRQH4+w82cLqXIoHnFtEsddtb7N85zjer3G8zkDO10WwiznEjTnSKxs5h/mP4x63Npm9+zrej9Fk7jE81/O7y8dYZfSfWULxPz7i85283p4z3DWG2yDUxDnbsW/zddfEqfQAgMhSvl79Rqp4hJ/bKJDDOe4AEMgwnqcZc1Ob+doAEB3B19HfS0dSPCKZBwcoPMp58QCQE1tLsbuRu5nmyiRrm/pz+HpNeJPnN/dm8TWzvTDHKgMxx9s95LKvQxERERGRnqZvuEVERERERETCQDfcIiIiIiIiImGgG24RERERERGRMNANt4iIiIiIiEgY9NpB04KDm+H8cxAkl8uxlrcnt1P8+kfDKXZ7eJvbx75llfHbVy6luM0Y3Cqmwn4esemdYRQ7l7ZQfEnSDorf3DXJKgNn82BdrQfjKX5l/2SKI7oYQyyyhl+8/jtvUvzo3y+2tpl2/ocUbyjqT3HbER6IDO4u2j2bB+c69mw/iv3JdmVvue4fFD+8aTrFnlq+DL2NdrsH8nlgteZGHqzs6ne/Z20TbONBwmbf8DrFf3jyEoqjZlRaZcRG8PHGfcADnjVnWJsAsXxtRhgDoMWV8vLqcfbxJn7EdQ+kcuwJcDu3dTHQXESCn+MPeFDA2thoa5ta8GseDw8+9o8Doyh2JdqDtb29ewjvt5XrFj2s1tqmsTCR4vph3EaeRj7+gbkVVhlHVxwf0C/otwc8FBERERHpafqGW0RERERERCQMdMMtIiIiIiIiEgbdvuFes2YNrrjiCmRnZ8PlcuHFF1+k5Y7jYMGCBcjOzkZ0dDTOP/987Ny582TVV0REREREROS00O0c7qamJowdOxbf/e538fWvf91afv/992Px4sV44oknMGTIENx3332YOXMm9uzZg/j4+C5K7FpGSj28sR05qB53yFped5SrHsjifOMJwwop/t2LnK8NALO/xjm9y7afR3Fzf7tefftVUVy6tw/FC/fzfsZcsdsqY8OuQfxCLB9fMJLjhA85BxgAgtM5D/wRI2c7FGXnX2/+62gu46xmivuNKqO44s2+Vhn+UZyz3hbH+bnNIzjXGgBe+PWFFPvyePn/uebPFC984hqrDBiHExnNOb7Rb3J+MgA0nsfHt+wfM7nIgVxGaF2aVUbkpdUUN4zmvGiE7NzpyCN8vkJGOvHhr/I2sYfsfOOB39pLceGfBvM+rjxKce27djJ5ayY/T4s9h4+ludW+rtoqOYc7qszIHR/BberbHmOVEeT0ekSeVUNxfJTRhgDq4/lcwOE2GnX2QYpTfU1WGfuHZXb+P9TSZi0XEREREelp3b7hnjVrFmbNmtXlMsdxsGTJEtx999246qqrAABPPvkkMjIy8PTTT+PWW2/9crUVEREREREROU2c1BzuwsJClJeXo6CgoPM1n8+HGTNmYP369V1u4/f7UV9fT/9ERERERERETncn9Ya7vLwcAJCRwT9vzcjI6FxmWrRoERITEzv/5ebmdrmeiIiIiIiIyOkkLPNwu1ycf+k4jvXax+bPn4958+Z1xvX19cjNzcWxuji42zrmPG4vs/NEnQQjqdeYh/jajHcp3hLNObAA8KcHeB7m4DAus8/7dp2PxiVQnDecHyRU1HMucUU1rw8ASdt4vm/HeOxRPzRIcXOGnY+d8BqX2zyW877dzfazlOYxnH89PJvzgHfuy6E4potTNn3gforXF/K8zE4XOc31F3Peb1sdJ/ne+5erKQ70t/Nvk5K4jEA75xY3cdUBAK6DfN14jVTp6LwGioPpdpvNSuO5y9//YCDFg4cfsbbZ18iVSTjA5dYl8fotRl48AOxYbVyvPN05vpX9EcUvH+tqQnB+ezfEc36270N7Hm6fkV7dMpHbPdjGx9Kcy9cqAET24W0aG3ju8tD6ZGubjFK+flNuLqK48EVu9z08bTcAYMJFx/Pe25oCKLFXERERERHpUSf1hjszs2PQovLycmRlZXW+XlFRYX3r/TGfzwefz9flMhEREREREZHT1Un9SXl+fj4yMzOxatWqztcCgQBWr16NqVOnnsxdiYiIiIiIiPRq3b7hbmxsxLZt27Bt2zYAHQOlbdu2DUVFRXC5XJg7dy4WLlyI5cuX48MPP8RNN92EmJgYXHvttSe77iIip9zSpUuRn5+PqKgoTJgwAe+8885nrv/UU09h7NixiImJQVZWFr773e+iqqrqM7cRETkdqX8UEQFcjuPYCcKf4e2338YFF1xgvX7jjTfiiSeegOM4uOeee/Dggw+ipqYGkydPxgMPPIBRo0Z1UZqtvr4eiYmJGPiH+fDEdOR+tjbYPzmP3cNzCJtz/wYGc15sn1TO1wWAYx/xvMveZs4/DvQx5gbuwrTR+yhOiuD9vrZvuLXNMCN3uvJhnpj62EReP2t4hVVGIMgJyceKOS82stKe2zkYbZxqI0zcy8dffZadn5u5hp/RVF/J+boXDeD5owHg9T1GG1QaJ8uoh3keAMAZyPMuR3zAufK5Mw9b2+zdxbnU35zGef1/3ng277fObrP2JG6DiEQjyflQF/NQG3Og9xlaSXHD2nSKm/vZ11l0sTHPfIoxV3sMx976LuqexrnwcR/xe6bdTuGGfxDPo+40cz1i0/k8tByKt8roN5rncz+0n9NJumrnkVN4nu2DL3POtmNskr2m0Spj73ePX1ehllaU3P5z1NXVISHBHkfhZHnuuedw/fXXY+nSpZg2bRoefPBBPPLII9i1axf69etnrb927VrMmDED//u//4srrrgCR44cwezZszF48GAsX778C+3z4z4y3McmImemnupD1D+KyOkmXH1It7/hPv/88+E4jvXviSeeANAxYNqCBQtQVlaG1tZWrF69+gvfbIuInE4WL16Mm2++GbfccguGDx+OJUuWIDc3F8uWLety/Y0bN6J///744Q9/iPz8fJx77rm49dZbsXnz5h6uuYhIeKl/FBHpcFJzuEVE/lUEAgFs2bIFBQUF9HpBQQHWr1/f5TZTp05FSUkJVqxYAcdxcPToUTz//PO47LLLPnU/fr8f9fX19E9EpDdT/ygicpxuuEVETkBlZSWCwaA1A0NGRgbKy8u73Gbq1Kl46qmncM011yAyMhKZmZlISkrCb3/720/dz6JFi5CYmNj5Lzc396Qeh4jIyab+UUTkON1wi4h8CS4XjzngOI712sd27dqFH/7wh/jZz36GLVu24LXXXkNhYSFmz579qeXPnz8fdXV1nf+Ki4tPav1FRMJF/aOIyEmeh/tkcvbEwYnqGDTtG5dvtJb/vXAKxf4+xuBWRVEUN8fzYFAAEHuEnzc0Z/FAVL7yCGsb1wgefO1oCw8ate2lERSH+toDj31UyoOkOV8xBuKq4kHFqtdlWmU4Y7ge5qBZkXX2H7RW43Ac43FL9UQevCuiyr488r6/h+KjWwdTvLJknLVNTDnvyJ/Kg4q1pfPgXpH9eSA2AEiL48G6ilNiKR4Qb49iejSXz82BRh4kz1fBx9cey+cfACKS+Lpx7eP9ukJ2O7fHcznV2/tQ7CTy8Sd8ZLdz09ncBk4FX8+R1Xy+2xLtup81mAeSixzG1+KOvw2ztsl4jQdWc77DA77VbuIB3+x3CFBUnkKxu4XPf8Y4HjQQAHZuHEDxgEuLKG5p5z3tz+JvTQAgIuH4gIUhb6CLmp1caWlp8Hg81rc1FRUV1rc6H1u0aBGmTZuGH//4xwCAMWPGIDY2FtOnT8d9992HrKwsaxufzwefzx44UkSkt1L/KCJynL7hFhE5AZGRkZgwYQJWrVpFr69atQpTp07tcpvm5ma43dztejwdD0+6OWGEiEivpf5RROQ43XCLiJygefPm4ZFHHsFjjz2G3bt344477kBRUVHnTyDnz5+PG264oXP9K664Ai+88AKWLVuGgwcPYt26dfjhD3+Is88+G9nZ2afqMERETjr1jyIiHXrtT8pFRHq7a665BlVVVbj33ntRVlaGUaNGYcWKFcjL60gbKSsrQ1HR8Z/H33TTTWhoaMDvfvc7/Od//ieSkpJw4YUX4he/+MWpOgQRkbBQ/ygi0sHl9LLf6Xw84XjuL+6DO7ojb9WJtPNTY9I5p9ffyrmn7mLOeW2Ps8twJXKeZ6iZnz94GjlPFgCCMVxORI2xzgCuV3pSo1VG+Q7OXwpFcZnuAOcFhyLsUxSTw+UGtydS3BZvH28w2qi7kfedOraC4vo1dp5V8yAjN7aNfyQRd8B+hhNVxfVvuZyn7TDrHlNmH2/12ZznDXOVLn6rkbiNr4m64Zyj7jvGxx9Tapfhuoxzw6srOS88KYXPNwC0beAc5pZRLbxCJeebeRvsPPBgNB+geU302cbLK8bbZUQM4jz/tgCfm4hdMdY27SP5eCK3cc66P4X3257CbQoArkhj3IIGzr9O32DXtWaE8Zpxfn3VvNwcBwDgPPZQSyuKf/R/UFdXh4SEBGvd09nHfeSZeGwiEn5nch9yJh+biIRfuPoQ/aRcREREREREJAx0wy0iIiIiIiISBrrhFhEREREREQmDXjtomrfVBTc68jajD9rVnDbxAMV76nh+4MbX+lIccd0xq4zynbzN8PE89+/uPTnWNp4EzmFuD3CuuDvEzzCOFPLczwDgNnKyE/vVUXz9wPcofmBlgVVGU3U0xdMv+ZDijW+NtLZxtXPOcrAvzzFduYPbIzTCyD0GEL+N93vJdRsofuUoz48OAI2DjDzfo5wX7Ik15uWOs3N8+67gupedy+tEdJEHHXspz/9ZZ5yLKQXcZu8cHGiV4f4wlV9I5vzkrATORweAhCs4F76kIYni1rc4N752RBfDKJjzexuPxiq/zvN0e1x2Gc52zj1J28c5/I1X19q73cH59C5jKIDcf3AufeE37XbPeYHfr74fcnJ80zv83gQAxxgKIf4gxw35fHzBHL52ASB+y/FrM+i3x18QEREREelp+oZbREREREREJAx0wy0iIiIiIiISBrrhFhEREREREQmDXpvDnTa6At7YjvmK66oyreWbjvajODqCc0u9rZx8Wrqvj1WGy0g/rfMb+dhxxtzPAOLX8dzFgQs5/7q1hed+Tu7LywGgvpHzoPOTea7n3665mOK+6+z83NIr+LW1742g+OwZe6xtth3h3Nn0BJ5zOZBszCn9gpG/DKBmOO/3+XcnUZwwtsbaxvdWMq9TxHnQVSONecen2W1W1pfnv44v5GdFdaPsc1XTyOfKFeT9rN7MbTZj4i6rDPcAPt6aAJ+7rXv6W9u4IozE50Z+m7mH8eKIOvu5lz+d2yjmIOckN3s4Dz7ZrjqqJnAZLcac8U11fCwAED2Sc9L9ezgP3HEbbxqvPd979XCeZzz6KR4LoXKGMU83AE8Sj41QncF1TU7leecD6+1rs/ns43ntoWY7x1tEREREpKfpG24RERERERGRMNANt4iIiIiIiEgY6IZbREREREREJAx0wy0iIiIiIiISBr120LTEqFZERHUMyHTRd1Zby5/bM55feJUHUaosaKc4dn+EVUb7hAaKqzfw4Gz9p5dY2xQOy6I44e1EimMuqaQ4zue3ymjYlULxVj8PAJc9gMto3ZJhlRG9hwemasnhgag2bxxibZP0EQ94VTqBB83yNBrPX0bag7UF43k/8ek8mJV/e5K1jX8MD4iVsYkHOEuO4Hq0TeH1AaApjvebdHk5xWkLuU0BoPhiHmgNiTzAl7dPC8V7a+2B9ere4muiuS/XI32T/cyq4gI+vvhCHgCs7Ry+7rxeexAxbE2isGE0X0cZb/D1XPPVZphiIrjcyE08AFr6G/Z74ug0riuSuYzKMbyNO4LbEABax3BdWozB6uLi7PfE8D5HKX6/KJfiuoM88J5nrDHAH4DIyOPv+WCw3VouIiIiItLT9A23iIiIiIiISBjohltEREREREQkDHTDLSIiIiIiIhIGvTaHu+oP/eCJjAIA/PHiLHsFTgtF7VCOI47xoV34zU1WEav+Noni1izO+yx/M8faJnkK51f//Ct/o/j21ddSXOkYFQUQ3cSvtbfzc4+KbZyzHZxh57xG+LiuTk0UxaFIaxPUD+T99n2D48B3qyiOeojzZgGgMZvbddJ3D1H87ptnWdt4m7kytXfXUVy1j3O43TvT7DJyOFe4upm3afiWfSm741opTlrHbRRIiKO4uYFjAPAU1HC8J4niihmcrw0Aaen1FFc1cH758B/z8e+6287RT+A0b7RVce70Mb50kbDarnvjuUZedxaf76ahdq68u473E9mXc6XTBvGxVf+9r1WG37hsvEaad0sajz8AAHvfSuL98tAI8A/hQuJi+dwCQOiN4+M4uP32chERERGRnqZvuEVERERERETCQDfcIiIiIiIiImGgG24RERERERGRMHA5jmNPtnwK1dfXIzExETnLfg53dEfOrTsiZK13ydDdFP/jdc4dbsvh/FQnYD9bcEXxHMOeUiO3tIvHETFHOA82uorrdmwirx+KsedYjk0z5ik2cpwj93J+cmu+ncOd8AHXtWEA78fdZueOu4zXnAg+9a52Xh7MtPfrK+Q86L5vc65s5RheDgB1xjzc3mrOE25P4nx0V6R9vlHPOdpJu/jktGTax+tP5Taxjj/SuPTtIhBR/dnPpAKZ9nzPqRu5rnXGlOhRlbyj7Hd4LnMAOHhlLMXBaK5rbDHXqzXNfhs7XuO1bCOn/S2+zgCg+lzjnBtjEDjGNXLWkMNWGaY9x9IpdrvtunqMHO6QkZLvMt5GIXsKcQQmHW/HUHMrDt60EHV1dUhISLBXPo193EeeiccmIuF3JvchZ/KxiUj4hasP0TfcIiIiIiIiImGgG24RERERERGRMNANt4iIiIiIiEgYdOuGe9GiRZg0aRLi4+ORnp6OK6+8Env27KF1HMfBggULkJ2djejoaJx//vnYuXPnSa20iIiIiIiISG/n/fxVjlu9ejVuu+02TJo0Ce3t7bj77rtRUFCAXbt2ITa2Y5Cn+++/H4sXL8YTTzyBIUOG4L777sPMmTOxZ88exMfHf+F9xezzwePrGBgsp8AemGn9H8dTHHlBLcW3DH6X4qVrL7LKcFo8FCeNqqL4/Ox91jYvvXYOxe0x/MwikqsBf4Q9QJTvdU7Cbzq7jVcwHoP4YnnQMQDwzaynOO1XXGbhv9mnNr6IC27MM+qWw4Nqpa8wBpED0B7D2xy8iQfRStxkbYL4tCaKPe8nU9yUy3WNLbZHL3O3836rx/MoWjGH7eONquDz25LP7eip5m26GoirLdcYfC9k1M3VxWBlV/J15NqRSrG3hdevHMsDpAFAexIfX/xermtkHe/XP4EH4gMA5wgPihaq4vNpDkwGAKlv8zp9buD3XmOAlx96epBVRs1kbrPErbxNzlWF1ja7hnLfEH2Ez53ZZpENdrs3tRw/gaFWe7BCEREREZGe1q0b7tdee43ixx9/HOnp6diyZQvOO+88OI6DJUuW4O6778ZVV10FAHjyySeRkZGBp59+GrfeeqtVpt/vh99/fGTk+vp6ax0RERERERGR082XyuGuq6sDAKSkpAAACgsLUV5ejoKCgs51fD4fZsyYgfXr13dZxqJFi5CYmNj5Lzc398tUSURERERERKRXOOEbbsdxMG/ePJx77rkYNWoUAKC8vBwAkJGRQetmZGR0LjPNnz8fdXV1nf+Ki4tPtEoiIiIiIiIivUa3flL+Sd///vexfft2rF271lrmcnGeq+M41msf8/l88PnsXOFAsgN3VEee5qG1/azlwb6cw+nak0jx45sv4eXZdk5n3AE+/KaiNIr/ms25xgAQMZDzkYMfxVHcPoiTTWO2cx4tAJz//22k+O9/n0xx9rklFFc22jm+VdW837pbOQ/cdcROSG4YEKI4a2gFxWX7+vB+L+OcbgCAkRfsquH9WHnhAFL/wufm6PR2LqOdr43GPPs5UNQxXicuo5HiiePsBzVb/jKaYjNn2zGufl+Nvd/WaH7N1cZxv79xmwLA4a8lUVxw8TaK36/gX3F4nk2xyoCXy23O4nZ1vNwe8XFGkjOA6oRIigc/wbnVB75pX5uxxXx8x/6YR/G3571O8aPJWVYZGW/wNZGyma+znaNzrG2iyzlnO6aMj7dqPLdHdCmvDwA5WdWd/29v8kOP7kRERETkVDuhb7h/8IMf4OWXX8Zbb72FnJzjH54zMzMBwPo2u6KiwvrWW0RERERERORM1q0bbsdx8P3vfx8vvPAC3nzzTeTn59Py/Px8ZGZmYtWqVZ2vBQIBrF69GlOnTj05NRYRERERERE5DXTrJ+W33XYbnn76abz00kuIj4/v/CY7MTER0dHRcLlcmDt3LhYuXIjBgwdj8ODBWLhwIWJiYnDttdeG5QBEREREREREeiOX4zh20u2nrfwpediPP/44brrpJgAd34Lfc889ePDBB1FTU4PJkyfjgQce6BxY7fPU19cjMTEReQvvgzsqCgCQt6LNWu/obZxfHLuc56FuTeG6RjTah1l7Eee9hmo4l9zbYP8AoD2ayxk/fj/FzbckUbznVs4LBwBfNZfbMoBza33FnHsb0WAVgab+nJPubuXjDcbYucV5r3Ddiy/hPNhQPOdWZ62yn8eUT+HYl8057ZFr7bnWfcac0Q2Xcf61+33eJjDanlP6iXMeo/jGjf9OcajdPlcD+x6j+NBmzh2OGlJHsbMxySqjLZ7r7m3idg7Zww/AMd4m5vlrzuFzE4qyz1X8Pm771kncZk4R5/VHVdjvzRBfRmgbw2UMSOf5wgHgpr48m8B/vXINxZG13M65FxRZZez/gNs5IoevEd8G+xpxGUMs1A/iF1K3uo3lVhEIZB3vJ0ItrSiZswB1dXVISEiwVz6NfdxHnonHJiLhdyb3IWfysYlI+IWrD+nWN9xf5N7c5XJhwYIFWLBgwYnWSUREREREROS096Xm4RYRERERERGRrumGW0RERERERCQMTnge7nBzt7ng9nTkpVYPsxNlo//GCaoNeZzD2j6S80Zd6+25rIOtfPiDhpVSXLaS50sGgIQDHO/IzOb9/h/Oi/bttp9pBI08cAR4HV81L/YVcC4yALTsTqU4ZEy77a235ymuGsltlMDp53C1cyF+nj4bABBbwmUEGnk+cG+rnXZQNZZfcx/kbYJ9OV93fC7PQw4A16/5HsV5z3A96vLteccLB/flFzxcj9SH+Zo4erZVBDx+3k/OxZyzvHcvn38AiM3gay9iFeeAJO/gMhsG2OeqcbSf4szlMRS3GlN3t/AU6h3r9OWxD6J3crsfKLLfE4te4nm3Q8bc7RGcBo5jz9vvEddA4xrYzTnb9aN4zAIAcLVwG0Qd5fi87/Pc9cvXT7LK6JvN83DbV5GIiIiISM/SN9wiIiIiIiIiYaAbbhEREREREZEw0A23iIiIiIiISBjohltEREREREQkDHrtoGlpoyvgje0YLK00tosRoXjcKUSV8yBLsTE86NQt//GmVcSv3rqU4pI1PABUTkGxtc3BsjSKfR4eVKrNGIgttsweRCzI470hooG3aTPmWW9tjLbKiKjnZyVtQ1sojtpmb9M4oJ3ilG3cZrXntVIct8kuwz+eBwRz7+PBvPxJxokB4Hi5jdrjeJC0tPV8/FvbB1lleFq53IrxHDcP4fMNAO4aHkgtcT9vc2wsLw9G2eeqLZnbbO+BLIpTN9sDntWczyfYn2/Ui8cyQ/bZPFgfAFS8yQO+lZ3P9Yio4/1mbuDlAFBsjBnnMlYxB80DgOaZDRTHbeABzxrGcTs7rfbxu6J5R/l/aKb42ORka5vqc7nctia+vle8cg7vN88+361/yej8fzDQai0XEREREelp+oZbREREREREJAx0wy0iIiIiIiISBrrhFhH5EpYuXYr8/HxERUVhwoQJeOeddz5zfb/fj7vvvht5eXnw+XwYOHAgHnvssR6qrYhIz1H/KCLSi3O461qi4XF15HAn7bSfC7RkcD6u38hhnpbJ+df/u/ViqwzHwzm7UeOrKfZ57LzYUCPn/To+Xic7o5biurRMe79GmnPQSJX2csorYl+LtcqonBagOLIwimI3LwYAuNq4HdujuSLpf/dR3JhjlxEMGmUkchs6dkovYg8bL07jPOHaYYkUZ2y0y2hJ4bo29uP9Rhw1EuMBOMZlUzOJk6cjY7mRojfGWWW0GTnpiR8a+fb2Jsh9htfxVTZSfPhHvH7zH7OtMlrO5jx3r5Gz3WfcUYpLMu28aF8Rt4mZ5+6v5msZAJwSvtbcfFnBW8ZltqUbCemAdYEf+BbXLaHQ3sQck6E90cjzH1PF+30+3Sqitc/xQoJ+eyyBcHjuuecwd+5cLF26FNOmTcODDz6IWbNmYdeuXejXr1+X21x99dU4evQoHn30UQwaNAgVFRVob7f7GhGR05n6RxGRDr32hltEpLdbvHgxbr75Ztxyyy0AgCVLluD111/HsmXLsGjRImv91157DatXr8bBgweRkpICAOjfv39PVllEpEeofxQR6aCflIuInIBAIIAtW7agoKCAXi8oKMD69eu73Obll1/GxIkTcf/996Nv374YMmQIfvSjH6GlpaXL9YGOn1jW19fTPxGR3kz9o4jIcfqGW0TkBFRWViIYDCIjI4Nez8jIQHl5eZfbHDx4EGvXrkVUVBSWL1+OyspKzJkzB9XV1Z+ap7ho0SLcc889J73+IiLhov5RROS4XnvD3Xw0Bu7ojgTSK2evtZY/vWYqxfFbOBG6fTB/eR/7nj2n9OhrdlG886kRHI8yJsQGACPv27Wd5ymuiOWk3rZhdjJ14jbOg42q5DLrB/L6jcPsPNnUDZx/a+Zjt9lp3/A28TqBJF7eksXLI7p4UOzxcm5tm4/n2E5bZ/9oouxyzh327uGc7fYUzs8qn2qXkdSfc3jT/5hE8dGz7W2iBvIB3DZ0HcUPPcPzsAe4WgCAfn/nuLkPn6vGfnaucNFXjLp4eK7yxNWcj916VY1VRvKrSRTXDeb91q7msQFSy+05xL9350sUP/mzKyiu72+3mT+FywkZad5Z6/j8V37X/uahpYnHAogtMfLvjbm+AcCp42TxiBpuI+/KNIrrRtjt7vpE1cxxEsLJ5eKdOY5jvfaxUCgEl8uFp556ComJHRfc4sWL8Y1vfAMPPPAAoqPtfmr+/PmYN29eZ1xfX4/c3NyTeAQiIuGh/lFEpBffcIuI9GZpaWnweDzWtzUVFRXWtzofy8rKQt++fTs/TALA8OHD4TgOSkpKMHjwYGsbn88Hn89nvS4i0lupfxQROU453CIiJyAyMhITJkzAqlWr6PVVq1Zh6tSpXW4zbdo0lJaWorHx+Mj1e/fuhdvtRk5OF9MCiIichtQ/iogcpxtuEZETNG/ePDzyyCN47LHHsHv3btxxxx0oKirC7NmzAXT83PGGG27oXP/aa69Famoqvvvd72LXrl1Ys2YNfvzjH+Pf//3fu/y5pIjI6Ur9o4hIB/2kXETkBF1zzTWoqqrCvffei7KyMowaNQorVqxAXl4eAKCsrAxFRUWd68fFxWHVqlX4wQ9+gIkTJyI1NRVXX3017rvvvlN1CCIiYaH+UUSkg8txHHu0pVOovr4eiYmJyHvk/8Ad0zGQUqgm0lrPncyDkTnHOIcneQcPyvEfP1pulXHf+ss/sy7e6HbrtdS/8+BONV9tpjhQw8vdcfaAZ/HGAG51o3kdVzMPGOVE8sBkAABjsLK4XUYbTau1t1mXRGFkA5/6QAK3Wdp2e8A3d7sxeNdA3m/DBdweABAbw4OmNezjesQV8Q8tGnPtSzJ6UB3FjjEqVuIzPFgdADRmGwNvtXK5yXu5XoVfs68zbwPvJ66YlycdsNuoagRfi+3GAHbmgF6+Gvt4a6dw3ZwWfjaW8j4fW/0AqwjEFfGO/Km8vCXbvr69DVxuTBmXkfwRX6tFl9s/kvEdM65f43gTD9jHG3N9KcVNf8qm2By8LaK5izYbdLwuQX8rDvy/n6Kurg4JCV0Mfnga+7iPPBOPTUTC70zuQ87kYxOR8AtXH6KflIuIiIiIiIiEgW64RURERERERMJAN9wiIiIiIiIiYdBrB00rGLwbkXEdiZtv/mWStdyT00px20ecF23mzf7q6ausMvoUcR7okFt3U7x+0zBrm5Z0fkYRv5J3VHdRC8Wzhuy0ynilbQzFLiPH9T9nvkbx/6yZZZWRsJ3zjZuz+FgiQ0ahAFL3c85u6bl8LG4jHbmhn5E4C6BqfJBibwMvj4nuIu97RTLHFzRxGbu5Db3Ndt1D7yVR3DKcz/+UH31obfPWO6Mpvn7mGopfOszLB8Qes8oo/UcuxW1GqnjlKHv+T/NcmDI2cf596RV2LnXOC/zWPHo250XXDeF9OLwYANAey+0YSOL9uoJ2O7uNIQeaJ3FOvq+a32fJH9j79dXzfhr78nVWPdLepm59X4r9U7hNzLo6HruNYw99Yj/2ZSgiIiIi0uP0DbeIiIiIiIhIGOiGW0RERERERCQMdMMtIiIiIiIiEga9Nod7fVk+PDEd+bHNw/3WcncTz3ftDOXc6elDPqJ45fucrwsAEy/lddZuGs5lRtjzX9cP5xxmtzFntruEc1zfS8qzyoDfmKfYy/v5y4+/QrHrK3aubWsfzmFtT+GcV997idY2JVdx3jPqOUc7uoKfvzRnWkUg7gBfMmauvH97krVNlDE1d1QUJwoHEs25nu12N3OUIxv4/L/RZCcGe4089j+uOo/3M6ya4vb7M6wyMIFDcz7oppF2srCnltsocQ/Xo3wKx1H77TzwmqEcm7nV3kYzp9kqAl6z3Y3z25Rn546727jctmquW5uRF27Oyw4AtQN5P3ElvM687/3V2uaeNV+jOG0jt2Eg3tivPb09WjKP7yfo/uw8ehERERGRnqBvuEVERERERETCQDfcIiIiIiIiImGgG24RERERERGRMOhWDveyZcuwbNkyHDp0CAAwcuRI/OxnP8OsWR3zRDuOg3vuuQcPPfQQampqMHnyZDzwwAMYObKLiXc/R+P+JLijOvJ0nWQ7YbNPRj3Fza9x/u07e87iDbLtfNW1742gOCKTk16dLuayzu1TQ3HhzmyK2/twTu/R0iSrjKhSbvbWLK5b1Qhe7quyioCLU8mRvYqTeCMa7Darbea85+R9vE71UC4jaZ+xEwDeOeUUH9lsHH+snX9dN9iY77ud9+Pvx9v4U+x2bzPmkE7k9HskfWhfyrUTjdz/NiNHfV0ax+OtIjD2Mp6bvezegRT7auy5yoNRXP/6gZxPPGj++xTv+fU4q4ycN7iMc/7rPYr//sIUis3rAQBqx5qJ31yPPqvtujdczhOrO3Wcw13HbxlEl9rJ41GT+YKtGhZD8SN3/5u1TcwQLqedh0LA/DnPULxo6betMj65TRdvXRERERGRHtetb7hzcnLw//7f/8PmzZuxefNmXHjhhfja176GnTt3AgDuv/9+LF68GL/73e+wadMmZGZmYubMmWhoaPickkVERERERETOLN264b7iiitw6aWXYsiQIRgyZAj++7//G3Fxcdi4cSMcx8GSJUtw991346qrrsKoUaPw5JNPorm5GU8//fSnlun3+1FfX0//RERERERERE53J5zDHQwG8eyzz6KpqQlTpkxBYWEhysvLUVBQ0LmOz+fDjBkzsH79+k8tZ9GiRUhMTOz8l5ube6JVEhEREREREek1un3DvWPHDsTFxcHn82H27NlYvnw5RowYgfLyjtzejAzOpc7IyOhc1pX58+ejrq6u819xcXF3qyQiIiIiIiLS63Rr0DQAGDp0KLZt24ba2lr89a9/xY033ojVq1d3Lne5eLQix3Gs1z7J5/PB5/NZrwdjgnCiO0aCiiqKtJY3p/Frjfk8qFYoxhhFqosqZOdXUDy5zyGKDzT2sbb5cHM+v+DjgajMQ+WlHdoSua7ueB7cKuTl0xLF1QQAtGRyyfX9+NlJ7t/tkdaav89xUz0PGmY+fik9z24070YeJA3GuFtxh+xBtBrzjXNxJI5CTyvvpz2v1Soj4hAP+FZ/TgvFqat4OQBEHOVrxFfF++n7No8tcHCe/fxpdyU/QIpK5XNTPc4erSw2s4ni9vJYilsLxlLsTrAHuKseyqOGrfwjD5LmNU6Nt6WLK62QT07LUB5ErjXNPr+u7fEUJxgZHglFfLxVo+zd1h1MpjjusNGuXYzw1prB74lmYyC9X/zaGCTNHu8Nme8e36a9LYTD9ioiIiIiIj2q299wR0ZGYtCgQZg4cSIWLVqEsWPH4te//jUyMzMBwPo2u6KiwvrWW0RERERERORM96Xn4XYcB36/H/n5+cjMzMSqVas6lwUCAaxevRpTp079srsREREREREROa106yflP/3pTzFr1izk5uaioaEBzz77LN5++2289tprcLlcmDt3LhYuXIjBgwdj8ODBWLhwIWJiYnDttdeGq/4iIiIiIiIivVK3briPHj2K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ijvuuMPZtWuX8+ijj/bqaW++6HE9/fTTjtfrdR544AGnrKys819tbe2pOoRP1d1jM/XmUXi7e2wNDQ1OTk6O841vfMPZuXOns3r1amfw4MHOLbfccqoOoUvdPa7HH3/c8Xq9ztKlS50DBw44a9eudSZOnOicffbZp+oQPlVDQ4OzdetWZ+vWrQ4AZ/Hixc7WrVs7p/M5XfsQx1H/+DH1j73Dmdo/Os6Z20eeqv5RN9wiIr3MAw884OTl5TmRkZHO+PHjndWrV3cuu/HGG50ZM2bQ+m+//bZz1llnOZGRkU7//v2dZcuW9XCNv5juHNeMGTMcANa/G2+8secr/gV095x9Um/+QOk43T+23bt3OxdffLETHR3t5OTkOPPmzXOam5t7uNafr7vH9Zvf/MYZMWKEEx0d7WRlZTnXXXedU1JS0sO1/nxvvfXWZ753Tuc+xHHUPzqO+sfe5EztHx3nzOwjT1X/6HKc0/h7fhEREREREZFeqtfmcIuIiIiIiIicznTDLSIiIiIiIhIGuuEWERERERERCQPdcIuIiIiIiIiEgW64RURERERERMJAN9wiIiIiIiIiYaAbbhEREREREZEw0A23iIiIiIiISBjohltEREREREQkDHTDLSIiIiIiIhIGuuEWERERERERCQPdcIuIiIiIiIiEgW64RURERERERMJAN9wiIiIiIiIiYaAbbhEREREREZEw0A23iIiIiIiISBjohltEREREREQkDHTDLSIiIiIiIhIGuuEWERERERERCQPdcIuIiIiIiIiEgW64RURERERERMJAN9wiIiIiIiIiYaAbbhEREREREZEw0A23iIiIiIiISBjohltEREREREQkDHTDLSIiIiIiIhIGuuEWERERERERCQPdcIuIiIiIiIiEgW64RURERERERMJAN9wiIiIiIiIiYaAbbhEREREREZEw0A23iIiIiIiISBjohltEREREREQkDHTDLSIiIiIiIhIGuuEWERERERERCYOw3XAvXboU+fn5iIqKwoQJE/DOO++Ea1ciIqcV9Y8iIl1T/ygiZxpvOAp97rnnMHfuXCxduhTTpk3Dgw8+iFmzZmHXrl3o16/fZ24bCoVQWlqK+Ph4uFyucFRPRM5wjuOgoaEB2dnZcLt71w95vkz/CKiPFJEvR/2jiEjXwtY/OmFw9tlnO7Nnz6bXhg0b5tx1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", + "text/plain": [ + "

    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "idx = np.random.randint(len(val_dset))\n", + "inp_tmp, tar_tmp, *_ = val_dset[idx]\n", + "ncols = max(len(inp_tmp),3)\n", + "nrows = 2\n", + "_,ax = plt.subplots(figsize=(4*ncols,4*nrows),ncols=ncols,nrows=nrows)\n", + "for i in range(len(inp_tmp)):\n", + " ax[0,i].imshow(inp_tmp[i])\n", + "\n", + "ax[1,0].imshow(tar_tmp[0]+tar_tmp[1])\n", + "ax[1,1].imshow(tar_tmp[0])\n", + "ax[1,2].imshow(tar_tmp[1])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "cac092b5", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 1323/1323 [00:26<00:00, 50.05it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Patch wise PSNR, as computed during training [27.29 23.84] 25.564999999999998\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "from denoisplit.analysis.stitch_prediction import stitch_predictions\n", + "from denoisplit.analysis.mmse_prediction import get_dset_predictions\n", + "# from denoisplit.analysis.stitch_prediction import get_predictions as get_dset_predictions\n", + "\n", + "pred_tiled, rec_loss, logvar, patch_psnr_tuple = get_dset_predictions(model, val_dset,batch_size,\n", + " num_workers=num_workers,\n", + " mmse_count=mmse_count,\n", + " model_type = config.model.model_type,\n", + " )\n", + "tmp = np.round([x.item() for x in patch_psnr_tuple],2)\n", + "print('Patch wise PSNR, as computed during training', tmp,np.mean(tmp) )" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "6c37d71a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-0.33665746" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.mean(rec_loss)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "ee076ab0", + "metadata": {}, + "outputs": [], + "source": [ + "# Patch wise PSNR, as computed during training [ 4.71 23.01] 13.860000000000001\n" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "535169c1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10584" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(val_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "2b693a0c", + "metadata": {}, + "outputs": [], + "source": [ + "idx_list = np.where(logvar.squeeze() < -6)[0]\n", + "if len(idx_list) > 0:\n", + " plt.imshow(val_dset[idx_list[0]][1][1])" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "8a1573f8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10584" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(val_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "6709de9e", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead\n", + " if pd.api.types.is_categorical_dtype(vector):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.\n", + " with pd.option_context('mode.use_inf_as_na', True):\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlYAAAGdCAYAAADQYj31AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAApmElEQVR4nO3df3RU9Z3/8dfkB2OIyW00JeMAGkRhxUj1BBfB7jdQSGDlx3r2u9WeaFbOwewqCMbgsovtKvLdElbZYAtF9Lu7smdLiT0Hs+seaZoULZRDAjFNVgIFWwonkB8EJJkEmkzY5PP9o+V+HQKRhA9OJnk+zplzZu59M/NJpjRP71xuPMYYIwAAAFy3qHAvAAAAYKggrAAAACwhrAAAACwhrAAAACwhrAAAACwhrAAAACwhrAAAACwhrAAAACyJCfcChpuenh41NDQoISFBHo8n3MsBAADXwBij9vZ2+f1+RUVd/bgUYfUla2ho0NixY8O9DAAAMAAnT57UmDFjrrqfsPqSJSQkSPr9G5OYmBjm1QAAgGvR1tamsWPHuj/Hr4aw+pJd+vgvMTGRsAIAIMJ80Wk8nLwOAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgSUy4FwA7uru7dezYMffx+PHjFR0dHcYVAQAw/BBWQ8SxY8eU+4MPdHOyX+fPNuj/Lp2nCRMmhHtZAAAMK4TVEHJzsl8JKbeHexkAAAxbnGMFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgyaAJq4KCAnk8HuXl5bnbjDFavXq1/H6/4uLiNGPGDB06dCjkzwWDQS1btkzJycmKj4/XwoULderUqZCZlpYW5eTkyHEcOY6jnJwctba2hszU1dVpwYIFio+PV3JyspYvX66urq6QmYMHDyojI0NxcXEaPXq01qxZI2OM1e8DAACIXIMirCorK/X2229r8uTJIdtfe+01FRYWatOmTaqsrJTP51NmZqba29vdmby8PBUXF6uoqEh79+7V+fPnNX/+fHV3d7sz2dnZqqmpUUlJiUpKSlRTU6OcnBx3f3d3t+bNm6cLFy5o7969Kioq0o4dO7RixQp3pq2tTZmZmfL7/aqsrNTGjRu1fv16FRYW3sDvDAAAiCgmzNrb283dd99tysrKTEZGhnn++eeNMcb09PQYn89n1q1b5852dnYax3HMli1bjDHGtLa2mtjYWFNUVOTO1NfXm6ioKFNSUmKMMebw4cNGkqmoqHBnysvLjSRz5MgRY4wxO3fuNFFRUaa+vt6d2b59u/F6vSYQCBhjjNm8ebNxHMd0dna6MwUFBcbv95uenp5r/noDgYCR5D6vLUePHjWPrCkyj7+1zzyypsgcPXrU6vMDADCcXevP77AfsVq6dKnmzZun2bNnh2w/fvy4mpqalJWV5W7zer3KyMjQvn37JElVVVW6ePFiyIzf71daWpo7U15eLsdxNHXqVHfmoYcekuM4ITNpaWny+/3uzJw5cxQMBlVVVeXOZGRkyOv1hsw0NDToxIkTV/36gsGg2traQm4AAGBoCmtYFRUV6Ze//KUKCgp67WtqapIkpaSkhGxPSUlx9zU1NWnEiBFKSkrqc2bUqFG9nn/UqFEhM5e/TlJSkkaMGNHnzKXHl2aupKCgwD23y3EcjR079qqzAAAgsoUtrE6ePKnnn39eP/zhD3XTTTdddc7j8YQ8Nsb02na5y2euNG9jxvzhxPW+1rNq1SoFAgH3dvLkyT7XDgAAIlfYwqqqqkrNzc1KT09XTEyMYmJitHv3bn3/+99XTEzMVY8GNTc3u/t8Pp+6urrU0tLS58zp06d7vf6ZM2dCZi5/nZaWFl28eLHPmebmZkm9j6p9ntfrVWJiYsgNAAAMTWELq1mzZungwYOqqalxb1OmTNETTzyhmpoa3XnnnfL5fCorK3P/TFdXl3bv3q3p06dLktLT0xUbGxsy09jYqNraWndm2rRpCgQCOnDggDuzf/9+BQKBkJna2lo1Nja6M6WlpfJ6vUpPT3dn9uzZE3IJhtLSUvn9fqWmptr/BgEAgIgTE64XTkhIUFpaWsi2+Ph43Xrrre72vLw8rV27VnfffbfuvvturV27ViNHjlR2drYkyXEcLV68WCtWrNCtt96qW265RS+++KLuu+8+92T4e+65R3PnzlVubq7eeustSdJf/dVfaf78+Zo4caIkKSsrS5MmTVJOTo5ef/11nTt3Ti+++KJyc3PdI0zZ2dl69dVXtWjRIr300kv69a9/rbVr1+rll1/+wo8mAQDA8BC2sLoWK1euVEdHh5YsWaKWlhZNnTpVpaWlSkhIcGc2bNigmJgYPfbYY+ro6NCsWbO0detWRUdHuzPbtm3T8uXL3X89uHDhQm3atMndHx0drQ8++EBLlizRww8/rLi4OGVnZ2v9+vXujOM4Kisr09KlSzVlyhQlJSUpPz9f+fn5X8J3AgAARAKPMVw6/MvU1tYmx3EUCASsnm/16aef6oV3q5WQcrvaT9dpw+MPaMKECdaeHwCA4exaf36H/TpWAAAAQwVhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYAlhBQAAYElYw+rNN9/U5MmTlZiYqMTERE2bNk0/+clP3P3GGK1evVp+v19xcXGaMWOGDh06FPIcwWBQy5YtU3JysuLj47Vw4UKdOnUqZKalpUU5OTlyHEeO4ygnJ0etra0hM3V1dVqwYIHi4+OVnJys5cuXq6urK2Tm4MGDysjIUFxcnEaPHq01a9bIGGP3mwIAACJWWMNqzJgxWrdunT7++GN9/PHH+sY3vqE/+7M/c+PptddeU2FhoTZt2qTKykr5fD5lZmaqvb3dfY68vDwVFxerqKhIe/fu1fnz5zV//nx1d3e7M9nZ2aqpqVFJSYlKSkpUU1OjnJwcd393d7fmzZunCxcuaO/evSoqKtKOHTu0YsUKd6atrU2ZmZny+/2qrKzUxo0btX79ehUWFn4J3ykAABARzCCTlJRk/vmf/9n09PQYn89n1q1b5+7r7Ow0juOYLVu2GGOMaW1tNbGxsaaoqMidqa+vN1FRUaakpMQYY8zhw4eNJFNRUeHOlJeXG0nmyJEjxhhjdu7caaKiokx9fb07s337duP1ek0gEDDGGLN582bjOI7p7Ox0ZwoKCozf7zc9PT3X/PUFAgEjyX1eW44ePWoeWVNkHn9rn3lkTZE5evSo1ecHAGA4u9af34PmHKvu7m4VFRXpwoULmjZtmo4fP66mpiZlZWW5M16vVxkZGdq3b58kqaqqShcvXgyZ8fv9SktLc2fKy8vlOI6mTp3qzjz00ENyHCdkJi0tTX6/352ZM2eOgsGgqqqq3JmMjAx5vd6QmYaGBp04ccL+NwQAAEScsIfVwYMHdfPNN8vr9eqZZ55RcXGxJk2apKamJklSSkpKyHxKSoq7r6mpSSNGjFBSUlKfM6NGjer1uqNGjQqZufx1kpKSNGLEiD5nLj2+NHMlwWBQbW1tITcAADA0hT2sJk6cqJqaGlVUVOjZZ5/VU089pcOHD7v7PR5PyLwxpte2y10+c6V5GzPmDyeu97WegoIC96R5x3E0duzYPtcOAAAiV9jDasSIEbrrrrs0ZcoUFRQU6Gtf+5q+973vyefzSep9NKi5udk9UuTz+dTV1aWWlpY+Z06fPt3rdc+cORMyc/nrtLS06OLFi33ONDc3S+p9VO3zVq1apUAg4N5OnjzZ9zcEAABErLCH1eWMMQoGgxo3bpx8Pp/KysrcfV1dXdq9e7emT58uSUpPT1dsbGzITGNjo2pra92ZadOmKRAI6MCBA+7M/v37FQgEQmZqa2vV2NjozpSWlsrr9So9Pd2d2bNnT8glGEpLS+X3+5WamnrVr8fr9bqXk7h0AwAAQ1NYw+qll17SL37xC504cUIHDx7Ut7/9bf385z/XE088IY/Ho7y8PK1du1bFxcWqra3VokWLNHLkSGVnZ0uSHMfR4sWLtWLFCu3atUvV1dV68skndd9992n27NmSpHvuuUdz585Vbm6uKioqVFFRodzcXM2fP18TJ06UJGVlZWnSpEnKyclRdXW1du3apRdffFG5ubluCGVnZ8vr9WrRokWqra1VcXGx1q5dq/z8/C/8aBIAAAwPMeF88dOnTysnJ0eNjY1yHEeTJ09WSUmJMjMzJUkrV65UR0eHlixZopaWFk2dOlWlpaVKSEhwn2PDhg2KiYnRY489po6ODs2aNUtbt25VdHS0O7Nt2zYtX77c/deDCxcu1KZNm9z90dHR+uCDD7RkyRI9/PDDiouLU3Z2ttavX+/OOI6jsrIyLV26VFOmTFFSUpLy8/OVn59/o79NAAAgQniM4dLhX6a2tjY5jqNAIGD1Y8FPP/1UL7xbrYSU29V+uk4bHn9AEyZMsPb8AAAMZ9f683vQnWMFAAAQqQgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwgrAAAASwYUVnfeeac+++yzXttbW1t15513XveiAAAAItGAwurEiRPq7u7utT0YDKq+vv66FwUAABCJYvoz/P7777v3f/rTn8pxHPdxd3e3du3apdTUVGuLAwAAiCT9CqtHH31UkuTxePTUU0+F7IuNjVVqaqr+6Z/+ydriAAAAIkm/wqqnp0eSNG7cOFVWVio5OfmGLAoAACAS9SusLjl+/LjtdQAAAES8AYWVJO3atUu7du1Sc3OzeyTrkn/913+97oUBAABEmgGF1auvvqo1a9ZoypQpuu222+TxeGyvCwAAIOIMKKy2bNmirVu3Kicnx/Z6AAAAItaArmPV1dWl6dOn214LAABARBtQWD399NP60Y9+ZHstAAAAEW1AHwV2dnbq7bff1s9+9jNNnjxZsbGxIfsLCwutLA4AACCSDCisPvnkE91///2SpNra2pB9nMgOAACGqwGF1UcffWR7HQAAABFvQOdYAQAAoLcBHbGaOXNmnx/5ffjhhwNeEAAAQKQaUFhdOr/qkosXL6qmpka1tbW9fjkzAADAcDGgsNqwYcMVt69evVrnz5+/rgUBAABEKqvnWD355JP8nkAAADBsWQ2r8vJy3XTTTTafEgAAIGIM6KPAP//zPw95bIxRY2OjPv74Y/393/+9lYUBAABEmgGFleM4IY+joqI0ceJErVmzRllZWVYWBgAAEGkGFFbvvPOO7XUAAABEvAGF1SVVVVX61a9+JY/Ho0mTJumBBx6wtS4AAICIM6Cwam5u1re+9S39/Oc/11e+8hUZYxQIBDRz5kwVFRXpq1/9qu11AgAADHoD+leBy5YtU1tbmw4dOqRz586ppaVFtbW1amtr0/Lly22vEQAAICIM6IhVSUmJfvazn+mee+5xt02aNEk/+MEPOHkdAAAMWwM6YtXT06PY2Nhe22NjY9XT03PdiwIAAIhEAwqrb3zjG3r++efV0NDgbquvr9cLL7ygWbNmWVscAABAJBlQWG3atEnt7e1KTU3V+PHjddddd2ncuHFqb2/Xxo0bba8RAAAgIgzoHKuxY8fql7/8pcrKynTkyBEZYzRp0iTNnj3b9voAAAAiRr+OWH344YeaNGmS2traJEmZmZlatmyZli9frgcffFD33nuvfvGLX9yQhQIAAAx2/QqrN954Q7m5uUpMTOy1z3Ec/fVf/7UKCwutLQ4AACCS9Cus/vu//1tz58696v6srCxVVVVd96IAAAAiUb/C6vTp01e8zMIlMTExOnPmzHUvCgAAIBL1K6xGjx6tgwcPXnX/J598ottuu+26FwUAABCJ+hVWjzzyiF5++WV1dnb22tfR0aFXXnlF8+fPt7Y4AACASNKvyy185zvf0XvvvacJEyboueee08SJE+XxePSrX/1KP/jBD9Td3a1vf/vbN2qtAAAAg1q/wiolJUX79u3Ts88+q1WrVskYI0nyeDyaM2eONm/erJSUlBuyUAAAgMGu31dev+OOO7Rz506dPXtW+/fvV0VFhc6ePaudO3cqNTW1X89VUFCgBx98UAkJCRo1apQeffRRHT16NGTGGKPVq1fL7/crLi5OM2bM0KFDh0JmgsGgli1bpuTkZMXHx2vhwoU6depUyExLS4tycnLkOI4cx1FOTo5aW1tDZurq6rRgwQLFx8crOTlZy5cvV1dXV8jMwYMHlZGRobi4OI0ePVpr1qxxAxMAAAxvA/qVNpKUlJSkBx98UH/8x3+spKSkAT3H7t27tXTpUlVUVKisrEz/8z//o6ysLF24cMGdee2111RYWKhNmzapsrJSPp9PmZmZam9vd2fy8vJUXFysoqIi7d27V+fPn9f8+fPV3d3tzmRnZ6umpkYlJSUqKSlRTU2NcnJy3P3d3d2aN2+eLly4oL1796qoqEg7duzQihUr3Jm2tjZlZmbK7/ersrJSGzdu1Pr167l2FwAA+D0ziDQ3NxtJZvfu3cYYY3p6eozP5zPr1q1zZzo7O43jOGbLli3GGGNaW1tNbGysKSoqcmfq6+tNVFSUKSkpMcYYc/jwYSPJVFRUuDPl5eVGkjly5IgxxpidO3eaqKgoU19f785s377deL1eEwgEjDHGbN682TiOYzo7O92ZgoIC4/f7TU9PzzV9jYFAwEhyn9OWo0ePmkfWFJnH39pnHllTZI4ePWr1+QEAGM6u9ef3gI9Y3QiBQECSdMstt0iSjh8/rqamJmVlZbkzXq9XGRkZ2rdvnySpqqpKFy9eDJnx+/1KS0tzZ8rLy+U4jqZOnerOPPTQQ3IcJ2QmLS1Nfr/fnZkzZ46CwaB70dPy8nJlZGTI6/WGzDQ0NOjEiRNX/JqCwaDa2tpCbgAAYGgaNGFljFF+fr6+/vWvKy0tTZLU1NQkSb1OiE9JSXH3NTU1acSIEb0+jrx8ZtSoUb1ec9SoUSEzl79OUlKSRowY0efMpceXZi5XUFDgntflOI7Gjh37Bd8JAAAQqQZNWD333HP65JNPtH379l77PB5PyGNjTK9tl7t85krzNmbM5/5l5JWsWrVKgUDAvZ08ebLPdQMAgMg1KMJq2bJlev/99/XRRx9pzJgx7nafzyep99Gg5uZm90iRz+dTV1eXWlpa+pw5ffp0r9c9c+ZMyMzlr9PS0qKLFy/2OdPc3Cyp91G1S7xerxITE0NuAABgaAprWBlj9Nxzz+m9997Thx9+qHHjxoXsHzdunHw+n8rKytxtXV1d2r17t6ZPny5JSk9PV2xsbMhMY2Ojamtr3Zlp06YpEAjowIED7sz+/fsVCARCZmpra9XY2OjOlJaWyuv1Kj093Z3Zs2dPyCUYSktL5ff7+32pCQAAMPSENayWLl2qH/7wh/rRj36khIQENTU1qampSR0dHZJ+//FaXl6e1q5dq+LiYtXW1mrRokUaOXKksrOzJUmO42jx4sVasWKFdu3aperqaj355JO67777NHv2bEnSPffco7lz5yo3N1cVFRWqqKhQbm6u5s+fr4kTJ0qSsrKyNGnSJOXk5Ki6ulq7du3Siy++qNzcXPcoU3Z2trxerxYtWqTa2loVFxdr7dq1ys/P/8KPJgEAwNDXryuv2/bmm29KkmbMmBGy/Z133tGiRYskSStXrlRHR4eWLFmilpYWTZ06VaWlpUpISHDnN2zYoJiYGD322GPq6OjQrFmztHXrVkVHR7sz27Zt0/Lly91/Pbhw4UJt2rTJ3R8dHa0PPvhAS5Ys0cMPP6y4uDhlZ2dr/fr17ozjOCorK9PSpUs1ZcoUJSUlKT8/X/n5+ba/NQAAIAJ5jOGy4V+mtrY2OY6jQCBg9XyrTz/9VC+8W62ElNvVfrpOGx5/QBMmTLD2/AAADGfX+vN7UJy8DgAAMBQQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJYQVgAAAJaENaz27NmjBQsWyO/3y+Px6D/+4z9C9htjtHr1avn9fsXFxWnGjBk6dOhQyEwwGNSyZcuUnJys+Ph4LVy4UKdOnQqZaWlpUU5OjhzHkeM4ysnJUWtra8hMXV2dFixYoPj4eCUnJ2v58uXq6uoKmTl48KAyMjIUFxen0aNHa82aNTLGWPt+AACAyBbWsLpw4YK+9rWvadOmTVfc/9prr6mwsFCbNm1SZWWlfD6fMjMz1d7e7s7k5eWpuLhYRUVF2rt3r86fP6/58+eru7vbncnOzlZNTY1KSkpUUlKimpoa5eTkuPu7u7s1b948XbhwQXv37lVRUZF27NihFStWuDNtbW3KzMyU3+9XZWWlNm7cqPXr16uwsPAGfGcAAEBEMoOEJFNcXOw+7unpMT6fz6xbt87d1tnZaRzHMVu2bDHGGNPa2mpiY2NNUVGRO1NfX2+ioqJMSUmJMcaYw4cPG0mmoqLCnSkvLzeSzJEjR4wxxuzcudNERUWZ+vp6d2b79u3G6/WaQCBgjDFm8+bNxnEc09nZ6c4UFBQYv99venp6rvnrDAQCRpL7vLYcPXrUPLKmyDz+1j7zyJoic/ToUavPDwDAcHatP78H7TlWx48fV1NTk7KystxtXq9XGRkZ2rdvnySpqqpKFy9eDJnx+/1KS0tzZ8rLy+U4jqZOnerOPPTQQ3IcJ2QmLS1Nfr/fnZkzZ46CwaCqqqrcmYyMDHm93pCZhoYGnThx4qpfRzAYVFtbW8gNAAAMTYM2rJqamiRJKSkpIdtTUlLcfU1NTRoxYoSSkpL6nBk1alSv5x81alTIzOWvk5SUpBEjRvQ5c+nxpZkrKSgocM/tchxHY8eO7fsLBwAAEWvQhtUlHo8n5LExpte2y10+c6V5GzPmDyeu97WeVatWKRAIuLeTJ0/2uXYAABC5Bm1Y+Xw+Sb2PBjU3N7tHinw+n7q6utTS0tLnzOnTp3s9/5kzZ0JmLn+dlpYWXbx4sc+Z5uZmSb2Pqn2e1+tVYmJiyA0AAAxNgzasxo0bJ5/Pp7KyMndbV1eXdu/erenTp0uS0tPTFRsbGzLT2Nio2tpad2batGkKBAI6cOCAO7N//34FAoGQmdraWjU2NrozpaWl8nq9Sk9Pd2f27NkTcgmG0tJS+f1+paam2v8GAACAiBPWsDp//rxqampUU1Mj6fcnrNfU1Kiurk4ej0d5eXlau3atiouLVVtbq0WLFmnkyJHKzs6WJDmOo8WLF2vFihXatWuXqqur9eSTT+q+++7T7NmzJUn33HOP5s6dq9zcXFVUVKiiokK5ubmaP3++Jk6cKEnKysrSpEmTlJOTo+rqau3atUsvvviicnNz3SNM2dnZ8nq9WrRokWpra1VcXKy1a9cqPz//Cz+aBAAAw0NMOF/8448/1syZM93H+fn5kqSnnnpKW7du1cqVK9XR0aElS5aopaVFU6dOVWlpqRISEtw/s2HDBsXExOixxx5TR0eHZs2apa1btyo6Otqd2bZtm5YvX+7+68GFCxeGXDsrOjpaH3zwgZYsWaKHH35YcXFxys7O1vr1690Zx3FUVlampUuXasqUKUpKSlJ+fr67ZgAAAI8xXDr8y9TW1ibHcRQIBKyeb/Xpp5/qhXerlZByu9pP12nD4w9owoQJ1p4fAIDh7Fp/fg/ac6wAAAAiDWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgCWEFAABgSUy4FwAgsnR3d+vYsWPufUmKjo7u931JGj9+vHsfAIYCwgoYhq4njo4fP661HxzWzV/1q/nXNYoZ+RXdMjq13/fbm0/p2/PTNG7cOKIMwJBBWAFDzLVE0/XGUeKYP1JCyu06f7ZBMfG3DPj+6uIa3TK61VqUSQQXgPAirIAIdbWAutZoup44smXkLT6rUfb54JKILABfPsIKiDCXgqqvgLqWaIp0V4uyS8HFUS0A4UBYAYPUFx2R+l1r81UDajj7fHB90VEtgguAbYQVEGYD+UgvccwfaaQnnKuODF90VIuPEQHYRlgBYfD5mBrIR3q4Pv35GFEisgBcO8IKuIGu9WgUATU4XOljRCILQH8QVoBlAzkahcHniyKL87MAXAlhBQwQR6OGj/6cEC8RWcBwRlgBV3C9F9nkaNTQxflZAPpCWA1BpqdHx48fl3R9v8ttON+/3otsYvjho0MAEmE1JF0416TVxXUD+lUh3B9eF9nEjcG1tIDhi7Aaoq7nV4Vwn2iCPQO9lha/gBqITIQVAIRBf4Krv/FFlAHhQ1gNwObNm/X666+rsbFR9957r9544w39yZ/8SbiXBWAIuJajzV8UXzciygg04NoQVv307rvvKi8vT5s3b9bDDz+st956S3/6p3+qw4cP6/bbbw/38gAMA9fzUf9Ao4yjZsC1Iaz6qbCwUIsXL9bTTz8tSXrjjTf005/+VG+++aYKCgrCvDoA6Jut8y/DfdTM1n3p/4fe5y+zQvxhoAirfujq6lJVVZX+7u/+LmR7VlaW9u3bd8U/EwwGFQwG3ceBQECS1NbWZnVt58+fV2v9b3Wx83dqP31S0SPbFO3p4f4Qvt/9u8CgWQv3h+N9Rxc7f6furqAU03nN98+fqdeKLceU+FW/Wk7+WtE3xYf1fkfgrP7+8f+l1NRUnThxQv/n3T2S5G5D5LnrrrtuyPNe+rltjOlzjrDqh7Nnz6q7u1spKSkh21NSUtTU1HTFP1NQUKBXX3211/axY8fekDUCAPrnf//4e9e0DZCk9vZ2OY5z1f2E1QB4PJ6Qx8aYXtsuWbVqlfLz893HPT09OnfunG699dar/pmBaGtr09ixY3Xy5EklJiZae15cH96XwYn3ZfDhPRmceF/+P2OM2tvb5ff7+5wjrPohOTlZ0dHRvY5ONTc39zqKdYnX65XX6w3Z9pWvfOVGLVGJiYnD/n/8gxHvy+DE+zL48J4MTrwvv9fXkapLor6EdQwZI0aMUHp6usrKykK2l5WVafr06WFaFQAAGCw4YtVP+fn5ysnJ0ZQpUzRt2jS9/fbbqqur0zPPPBPupQEAgDAjrPrp8ccf12effaY1a9aosbFRaWlp2rlzp+64446wrsvr9eqVV17p9bEjwov3ZXDifRl8eE8GJ96X/vOYL/p3gwAAALgmnGMFAABgCWEFAABgCWEFAABgCWEFAABgCWE1BKWmpsrj8YTcLv/9hgifYDCo+++/Xx6PRzU1NeFezrC3cOFC3X777brpppt02223KScnRw0NDeFe1rB24sQJLV68WOPGjVNcXJzGjx+vV155RV1dXeFe2rD23e9+V9OnT9fIkSNv6IWuIx1hNURduhzEpdt3vvOdcC8Jf7By5cov/JUI+PLMnDlTP/7xj3X06FHt2LFDx44d01/8xV+Ee1nD2pEjR9TT06O33npLhw4d0oYNG7Rlyxa99NJL4V7asNbV1aVvfvObevbZZ8O9lEGNyy0MQampqcrLy1NeXl64l4LL/OQnP1F+fr527Nihe++9V9XV1br//vvDvSx8zvvvv69HH31UwWBQsbGx4V4O/uD111/Xm2++qd/+9rfhXsqwt3XrVuXl5am1tTXcSxmUOGI1RP3jP/6jbr31Vt1///367ne/yyH0QeD06dPKzc3Vv//7v2vkyJHhXg6u4Ny5c9q2bZumT59OVA0ygUBAt9xyS7iXAXwhwmoIev7551VUVKSPPvpIzz33nN544w0tWbIk3Msa1owxWrRokZ555hlNmTIl3MvBZf72b/9W8fHxuvXWW1VXV6f//M//DPeS8DnHjh3Txo0b+dVhiAiEVYRYvXp1rxPSL799/PHHkqQXXnhBGRkZmjx5sp5++mlt2bJF//Iv/6LPPvsszF/F0HOt78vGjRvV1tamVatWhXvJw0J//r5I0t/8zd+ourpapaWlio6O1l/+5V+KsyTs6+/7IkkNDQ2aO3euvvnNb+rpp58O08qHroG8J+gb51hFiLNnz+rs2bN9zqSmpuqmm27qtb2+vl5jxoxRRUWFpk6deqOWOCxd6/vyrW99S//1X/8lj8fjbu/u7lZ0dLSeeOIJ/du//duNXuqwcj1/X06dOqWxY8dq3759mjZt2o1a4rDU3/eloaFBM2fO1NSpU7V161ZFRXEswLaB/F3hHKu+8UuYI0RycrKSk5MH9Gerq6slSbfddpvNJUHX/r58//vf1z/8wz+4jxsaGjRnzhy9++67xO4NcD1/Xy79t2YwGLS5JKh/70t9fb1mzpyp9PR0vfPOO0TVDXI9f1dwZYTVEFNeXq6KigrNnDlTjuOosrJSL7zwgnutHoTH5d/7m2++WZI0fvx4jRkzJhxLgqQDBw7owIED+vrXv66kpCT99re/1csvv6zx48dztCqMGhoaNGPGDN1+++1av369zpw54+7z+XxhXNnwVldXp3Pnzqmurk7d3d3udfjuuusu9//TQFgNOV6vV++++65effVVBYNB3XHHHcrNzdXKlSvDvTRg0ImLi9N7772nV155RRcuXNBtt92muXPnqqioSF6vN9zLG7ZKS0v1m9/8Rr/5zW96/YcHZ6+Ez8svvxxy2sIDDzwgSfroo480Y8aMMK1q8OEcKwAAAEv40BoAAMASwgoAAMASwgoAAMASwgoAAMASwgoAAMASwgoAAMASwgoAAMASwgoAAMASwgoAAMASwgoAAMASwgoAAMASwgoAAMCS/wcaxXR0g83mxgAAAABJRU5ErkJggg==", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "sns.histplot(logvar[::50].squeeze().reshape(-1,))" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "771ac350", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-1.35 -1.34 -0.44 0.44 2.92 7.13 8.32]\n" + ] + } + ], + "source": [ + "print(np.quantile(rec_loss, [0,0.01,0.5, 0.9,0.99,0.999,1]).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "05f2cdc7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(10584, 2, 64, 64)" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "8673355b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10584" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(val_dset)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "c75b35f1", + "metadata": {}, + "outputs": [], + "source": [ + "if pred_tiled.shape[-1] != val_dset.get_img_sz():\n", + " pad = (val_dset.get_img_sz() - pred_tiled.shape[-1] )//2\n", + " pred_tiled = np.pad(pred_tiled, ((0,0),(0,0),(pad,pad),(pad,pad)))\n", + "\n", + "pred = stitch_predictions(pred_tiled,val_dset, smoothening_pixelcount=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "f950003b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(10584, 2, 64, 64)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pred_tiled.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "b09091e3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(6, 2720, 2720, 2)" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pred.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "dba3753f", + "metadata": {}, + "outputs": [], + "source": [ + "pred[np.isnan(pred)] = 0" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "0d2ad25d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "In (6, 2720, 2720, 2), last 32 many rows and columns are all zero.\n" + ] + } + ], + "source": [ + "def print_ignored_pixels():\n", + " ignored_pixels = 1\n", + " while(pred[0,-ignored_pixels:,-ignored_pixels:,].std() ==0):\n", + " ignored_pixels+=1\n", + " ignored_pixels-=1\n", + " print(f'In {pred.shape}, last {ignored_pixels} many rows and columns are all zero.')\n", + " return ignored_pixels\n", + "\n", + "actual_ignored_pixels = print_ignored_pixels()" + ] + }, + { + "cell_type": "markdown", + "id": "b8474735", + "metadata": {}, + "source": [ + "## Ignore the pixels which are present in the last few rows and columns. \n", + "1. They don't come in the batches. So, in prediction, they are simply zeros. So they are being are ignored right now. \n", + "2. For the border pixels which are on the top and the left, overlapping yields worse performance. This is becuase, there is nothing to overlap on one side. So, they are essentially zero padded. This makes the performance worse. " + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "fcb2db09", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "32" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "actual_ignored_pixels" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "cadedfcd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "32\n" + ] + } + ], + "source": [ + "ignored_last_pixels = 32 if config.data.data_type in [DataType.OptiMEM100_014,\n", + " DataType.SemiSupBloodVesselsEMBL, \n", + " DataType.Pavia2VanillaSplitting,\n", + " DataType.ExpansionMicroscopyMitoTub,\n", + " DataType.ShroffMitoEr,\n", + " DataType.HTIba1Ki67] else 0\n", + "ignore_first_pixels = 0\n", + "\n", + "assert actual_ignored_pixels <= ignored_last_pixels, f'Set ignored_last_pixels={actual_ignored_pixels}'\n", + "print(ignored_last_pixels)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "226fed05", + "metadata": {}, + "outputs": [], + "source": [ + "tar = val_dset._data\n", + "def ignore_pixels(arr):\n", + " if ignore_first_pixels:\n", + " arr = arr[:,ignore_first_pixels:,ignore_first_pixels:]\n", + " if ignored_last_pixels:\n", + " arr = arr[:,:-ignored_last_pixels,:-ignored_last_pixels]\n", + " return arr\n", + "\n", + "pred = ignore_pixels(pred)\n", + "tar = ignore_pixels(tar)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "1be10fd7", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.analysis.plot_utils import *\n", + "# def add_pixel_kde(ax,\n", + "# rect: List[float],\n", + "# data1: np.ndarray,\n", + "# data2: Union[np.ndarray, None],\n", + "# min_labelsize: int,\n", + "# color1='r',\n", + "# color2='black',\n", + "# color_xtick='white',\n", + "# label1='Target',\n", + "# label2='Predicted'):\n", + "# \"\"\"\n", + "# Adds KDE (density plot) of data1(eg: target) and data2(ex: predicted) image pixel values as an inset\n", + "# \"\"\"\n", + "# inset_ax = add_subplot_axes(ax, rect, facecolor=\"None\", min_labelsize=min_labelsize)\n", + " \n", + "# inset_ax.tick_params(axis='x', colors=color_xtick)\n", + "\n", + "# sns.kdeplot(data=data1.reshape(-1, ), ax=inset_ax, color=color1, label=label1)\n", + "# if data2 is not None:\n", + "# sns.kdeplot(data=data2.reshape(-1, ), ax=inset_ax, color=color2, label=label2)\n", + "# inset_ax.set_xlim(left=0)\n", + "# xticks = inset_ax.get_xticks()\n", + "# # inset_ax.set_xticks([xticks[0], xticks[-1]])\n", + "# inset_ax.set_xticks([])\n", + "# clean_for_xaxis_plot(inset_ax)\n", + "\n", + "\n", + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "\n", + "# inset_rect=[0.1,0.1,0.4,0.2]\n", + "# inset_min_labelsize=10\n", + "# color_ch_list=['goldenrod','cyan']\n", + "\n", + "# _,ax = plt.subplots(figsize=(15,10),ncols=3,nrows=2)\n", + "# idx = 8\n", + "# pred1_crop = ch1_pred_unnorm[idx,1116:1372,1064:1320].copy()\n", + "# pred2_crop = ch2_pred_unnorm[idx,1116:1372,1064:1320].copy()\n", + "# pred1_crop[pred1_crop<0] = 0\n", + "# pred2_crop[pred2_crop<0] = 0\n", + "\n", + "# tar1_crop = tar[idx,1116:1372,1064:1320,0]\n", + "# tar2_crop = tar[idx,1116:1372,1064:1320,1]\n", + "\n", + "# ax[0,0].imshow(tar1_crop+tar2_crop)\n", + "# ax[0,1].imshow(tar1_crop)\n", + "# ax[0,2].imshow(tar2_crop)\n", + "\n", + "# ax[1,0].imshow(pred1_crop+pred2_crop)\n", + "# ax[1,1].imshow(pred1_crop)\n", + "# ax[1,2].imshow(pred2_crop)\n", + "# clean_ax(ax)\n", + "# add_pixel_kde(ax[0,0], inset_rect, \n", + "# tar1_crop, \n", + "# tar2_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1=color_ch_list[0], color2=color_ch_list[1])\n", + "\n", + "# add_pixel_kde(ax[1,1], inset_rect, \n", + "# pred1_crop, \n", + "# tar1_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1='red', color2=color_ch_list[0])\n", + "# add_pixel_kde(ax[1,2], inset_rect, \n", + "# pred2_crop, \n", + "# tar2_crop, \n", + "# inset_min_labelsize,\n", + "# label1='Ch1', label2='Ch2', color1='red', color2=color_ch_list[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "5d8b680f", + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.metrics import structural_similarity\n", + "\n", + "def _avg_psnr(target, prediction, psnr_fn):\n", + " output = np.mean([psnr_fn(target[i:i + 1], prediction[i:i + 1]).item() for i in range(len(prediction))])\n", + " return round(output, 2)\n", + "\n", + "\n", + "def avg_range_inv_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, RangeInvariantPsnr)\n", + "\n", + "\n", + "def avg_psnr(target, prediction):\n", + " return _avg_psnr(target, prediction, PSNR)\n", + "\n", + "\n", + "def compute_masked_psnr(mask, tar1, tar2, pred1, pred2):\n", + " mask = mask.astype(bool)\n", + " mask = mask[..., 0]\n", + " tmp_tar1 = tar1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_pred1 = pred1[mask].reshape((len(tar1), -1, 1))\n", + " tmp_tar2 = tar2[mask].reshape((len(tar2), -1, 1))\n", + " tmp_pred2 = pred2[mask].reshape((len(tar2), -1, 1))\n", + " psnr1 = avg_range_inv_psnr(tmp_tar1, tmp_pred1)\n", + " psnr2 = avg_range_inv_psnr(tmp_tar2, tmp_pred2)\n", + " return psnr1, psnr2\n", + "\n", + "def avg_ssim(target, prediction):\n", + " ssim = [structural_similarity(target[i],prediction[i], data_range=(target[i].max() - target[i].min())) for i in range(len(target))]\n", + " return np.mean(ssim),np.std(ssim)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "7311e08a", + "metadata": {}, + "outputs": [], + "source": [ + "sep_mean, sep_std = model.data_mean, model.data_std\n", + "if isinstance(sep_mean, dict):\n", + " sep_mean = sep_mean['target']\n", + " sep_std = sep_std['target']\n", + " \n", + "sep_mean = sep_mean.squeeze()[None,None,None]\n", + "sep_std = sep_std.squeeze()[None,None,None]\n", + "\n", + "tar_normalized = (tar - sep_mean.cpu().numpy())/sep_std.cpu().numpy()\n", + "tar1 =tar_normalized[...,0]\n", + "tar2 =tar_normalized[...,1]" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "b2402048", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nuc: [-0.71 -0.4 0.93 2.24 2.68 3.68 3.83]\n", + "Tub: [-1.13 -1.03 -0.65 -0.07 0.12 0.5 2. ]\n" + ] + } + ], + "source": [ + "q_vals = [0.01, 0.1,0.5,0.9,0.95, 0.99,1]\n", + "print('Nuc:', np.quantile(tar_normalized[...,0], q_vals).round(2))\n", + "print('Tub:', np.quantile(tar_normalized[...,1], q_vals).round(2))" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "6c445e50", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nuc: [ 237. 311. 624. 932. 1036. 1271. 1308.]\n", + "Tub: [138. 162. 252. 388. 433. 521. 875.]\n" + ] + } + ], + "source": [ + "print('Nuc:', np.quantile(tar[...,0], q_vals))\n", + "print('Tub:', np.quantile(tar[...,1], q_vals))" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "7fef4512", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead\n", + " if pd.api.types.is_categorical_dtype(vector):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.\n", + " with pd.option_context('mode.use_inf_as_na', True):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead\n", + " if pd.api.types.is_categorical_dtype(vector):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.\n", + " with pd.option_context('mode.use_inf_as_na', True):\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "_,ax = plt.subplots(figsize=(6,6))\n", + "# sns.histplot(tar[:,...,0].reshape(-1,), color='g', label='Nuc')\n", + "# sns.histplot(tar[:,...,1].reshape(-1,), color='r', label='Tub')\n", + "\n", + "sns.histplot(tar[:,::10,::10,0].reshape(-1,), color='g', label='Nuc', kde=True)\n", + "sns.histplot(tar[:,::10,::10,1].reshape(-1,), color='r', label='Tub', kde=True)\n", + "ax.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "cb572707", + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.data_loader.schroff_rawdata_loader import mito_channel_fnames\n", + "# from denoisplit.core.tiff_reader import load_tiff\n", + "# import seaborn as sns\n", + "\n", + "# fpaths = [os.path.join(datapath, x) for x in mito_channel_fnames()]\n", + "# fpath = fpaths[0]\n", + "# print(fpath)\n", + "# img = load_tiff(fpaths[0])\n", + "# temp = img.copy()\n", + "# sns.histplot(temp[:,:,::10,::10].reshape(-1,))\n", + "# plt.hist(temp[:,:,::10,::10].reshape(-1,),bins=100)" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "24708c4c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n" + ] + }, + { + "data": { + "text/plain": [ + "(6, 2688, 2688, 2)" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "_,ax = plt.subplots(figsize=(12,12),ncols=2,nrows=2)\n", + "idx = np.random.randint(len(pred))\n", + "print(idx)\n", + "ax[0,0].imshow(pred[idx,:,:,0])\n", + "ax[0,1].imshow(pred[idx,:,:,1])\n", + "ax[1,0].imshow(tar1[idx,:,:])\n", + "ax[1,1].imshow(tar2[idx,:,:])\n", + "\n", + "pred.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "f16c88e5", + "metadata": {}, + "outputs": [], + "source": [ + "# pred is already normalized. no need to do it. \n", + "pred1, pred2 = pred[...,0].astype(np.float32), pred[...,1].astype(np.float32)\n", + "pred_inp = (pred1 + pred2)/2" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "919db5ef", + "metadata": {}, + "outputs": [], + "source": [ + "# ch1_pred_unnorm = pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "# ch2_pred_unnorm = pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()\n", + "ch1_pred_unnorm = 2 * pred[...,0]*sep_std[...,0].cpu().numpy() + sep_mean[...,0].cpu().numpy()\n", + "ch2_pred_unnorm = 2 * pred[...,1]*sep_std[...,1].cpu().numpy() + sep_mean[...,1].cpu().numpy()" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "6a885569", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[[[404.2586, 404.2586]]]], device='cuda:0')" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sep_mean" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "13fc1983", + "metadata": {}, + "outputs": [], + "source": [ + "if config.model.model_type == ModelType.LadderVaeSemiSupervised:\n", + " raise NotImplementedError(\"SSIM is incorrectly implemented here.\")\n", + " pred_inp = pred[...,2].astype(np.float32)\n", + "# tar1 is the input. tar2 is the target. \n", + " rmse1 =np.sqrt(((pred1 - tar2)**2).reshape(len(pred1),-1).mean(axis=1))\n", + " rmse2 =np.sqrt(((pred_inp - tar1)**2).reshape(len(pred2),-1).mean(axis=1)) \n", + "\n", + " rmse = (rmse1 + rmse2)/2\n", + " rmse = np.round(rmse,3)\n", + "\n", + " ssim1_mean, ssim1_std = avg_ssim(tar2, pred1)\n", + " ssim2_mean, ssim2_std = avg_ssim(tar1, pred_inp)\n", + " \n", + " psnr1 = avg_psnr(tar2, pred1)\n", + " psnr2 = avg_psnr(tar1, pred_inp)\n", + " rinv_psnr1 = avg_range_inv_psnr(tar2, pred1)\n", + " rinv_psnr2 = avg_range_inv_psnr(tar1, pred_inp)\n", + " \n", + "else:\n", + " rmse1 =np.sqrt(((pred1 - tar1)**2).reshape(len(pred1),-1).mean(axis=1))\n", + " rmse2 =np.sqrt(((pred2 - tar2)**2).reshape(len(pred2),-1).mean(axis=1)) \n", + "\n", + " rmse = (rmse1 + rmse2)/2\n", + " rmse = np.round(rmse,3)\n", + " psnr1 = avg_psnr(tar1, pred1) \n", + " psnr2 = avg_psnr(tar2, pred2)\n", + " rinv_psnr1 = avg_range_inv_psnr(tar1, pred1)\n", + " rinv_psnr2 = avg_range_inv_psnr(tar2, pred2)\n", + " ssim1_mean, ssim1_std = avg_ssim(tar[...,0], ch1_pred_unnorm)\n", + " ssim2_mean, ssim2_std = avg_ssim(tar[...,1], ch2_pred_unnorm)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "19d3e1cf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "100.0" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tar.min()" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "e0a1c705", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "153.0" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tar[...,0].min()" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "3c1d7581", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-1.0661422" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tar1.min()" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "e87868b7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test_PNone_GNone_M1_Sk32\n", + "Rec Loss -0.337\n", + "RMSE 0.212 0.211 0.211\n", + "PSNR 27.25 22.99\n", + "RangeInvPSNR 27.34 23.07\n", + "SSIM 0.728 0.228 ± 0.0045\n", + "\n" + ] + } + ], + "source": [ + "print(f'{DataSplitType.name(eval_datasplit_type)}_P{custom_image_size}_G{image_size_for_grid_centers}_M{mmse_count}_Sk{ignored_last_pixels}')\n", + "print('Rec Loss',np.round(rec_loss.mean(),3) )\n", + "print('RMSE', np.mean(rmse1).round(3), np.mean(rmse2).round(3), np.mean(rmse).round(3))\n", + "print('PSNR', psnr1, psnr2)\n", + "print('RangeInvPSNR',rinv_psnr1, rinv_psnr2 )\n", + "print('SSIM',round(ssim1_mean,3), round(ssim2_mean,3),'±',round((ssim1_std + ssim2_std)/2,4))\n", + "print()" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "6563e641", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(6, 2688, 2688, 2)" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tar.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65357dd7", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "d2a42a24", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'/home/ashesh.ashesh/training/disentangle/2310/D3-M3-S0-L0/6/BaselineVAECL_best.ckpt'" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ckpt_fpath" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "0bc4c021", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torch.optim as optim\n", + "\n", + "\n", + "def reload(model):\n", + " checkpoint = torch.load(ckpt_fpath)\n", + " _ = model.load_state_dict(checkpoint['state_dict'])\n", + "\n", + "def train(cur_model, background_increment_factor=0.0, ch0_offset=0, val_idx=0, step_count=100, lr=1e-3,\n", + " original_model=None,inner_pad=0, use_predicted_tar=True):\n", + " if use_predicted_tar:\n", + " raw_inp, _ = val_dset[val_idx]\n", + " out, _ = cur_model(torch.Tensor(raw_inp[None]).cuda())\n", + " raw_tar = get_img_from_forward_output(out, cur_model, unnormalized=True).detach().cpu().numpy()[0]\n", + " else:\n", + " raw_inp, raw_tar = val_dset[val_idx]\n", + " \n", + " raw_tar = raw_tar * (1+background_increment_factor)\n", + " raw_tar = np.concatenate([raw_tar[:1] + ch0_offset, raw_tar[1:] - ch0_offset], axis=0)\n", + "\n", + " cur_model.train()\n", + " cur_model.mode_pred = False\n", + " inp = torch.Tensor(raw_inp[None]).cuda()\n", + " tar = torch.Tensor(raw_tar[None]).cuda()\n", + " tar = model.normalize_target(tar)\n", + " optimizer = optim.Adamax(cur_model.parameters(), lr=lr, weight_decay=0)\n", + " losses = []\n", + " rec_losses = []\n", + " reg_losses = []\n", + " for _ in tqdm(range(step_count)):\n", + " loss, loss_dict = one_step(cur_model, inp, tar, optimizer, original_model, inner_pad)\n", + " losses.append(loss)\n", + " rec_losses.append(loss_dict['rec_loss'])\n", + " reg_losses.append(loss_dict['reg_loss'])\n", + " return {'loss':losses, 'rec_loss':rec_losses, 'reg_loss':reg_losses}, (raw_inp, raw_tar)\n", + "\n", + "def weight_regularization_loss(cur_model, original_model):\n", + " original_model_dict = {k:v.detach() for k,v in original_model.named_parameters()}\n", + " loss = 0\n", + " for name, param in cur_model.named_parameters():\n", + " loss += torch.mean(torch.abs(original_model_dict[name] - param))\n", + " return loss/len(original_model_dict)\n", + "\n", + "def one_step(cur_model, inp, tar, optimizer, original_model, inner_pad):\n", + " out = cur_model(inp)[0]\n", + " # ll = cur_model.likelihood(out, tar)[0]\n", + " pred = get_img_from_forward_output(out, cur_model, unnormalized=False)\n", + " rec_loss = (pred - tar)**2\n", + " if inner_pad > 0:\n", + " rec_loss = rec_loss[...,inner_pad:-inner_pad, inner_pad:-inner_pad]\n", + "\n", + " rec_loss = rec_loss.mean()\n", + " reg_loss = 100 * weight_regularization_loss(cur_model, original_model) \n", + " loss = rec_loss + reg_loss * 0\n", + " optimizer.zero_grad()\n", + " loss.backward()\n", + " optimizer.step()\n", + " return loss.item(), {'rec_loss': rec_loss.item(), 'reg_loss': reg_loss.item()}\n", + "\n", + "# pred, td_data = model(inpt)\n", + "# pred = get_img_from_forward_output(pred, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "e6fd44d1", + "metadata": {}, + "outputs": [], + "source": [ + "val_idx = 0\n", + "inp, tar = val_dset[val_idx]" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "2bf3c833", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[637.95 705. 733. 788. 889. 992.05]\n", + "[208. 234. 246. 272. 315. 352.05]\n" + ] + } + ], + "source": [ + "print(np.quantile(tar[0], [0.01,0.1, 0.2, 0.5, 0.9, 0.99]))\n", + "print(np.quantile(tar[1], [0.01,0.1, 0.2, 0.5, 0.9, 0.99]))" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "1572eac3", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 20/20 [00:01<00:00, 12.53it/s]\n" + ] + } + ], + "source": [ + "from copy import deepcopy\n", + "def get_cur_model():\n", + " skip_updates_to = ['top_down_layers.0', 'likelihood', 'final_top_down']\n", + " reload(model)\n", + " cur_model = deepcopy(model)\n", + " for name, param in cur_model.named_parameters():\n", + " if any([name.startswith(x) for x in skip_updates_to]):\n", + " param.requires_grad = False\n", + " # print(name, 'frozen')\n", + " return cur_model\n", + "\n", + "cur_model = get_cur_model()\n", + "val_idx = 0\n", + "\n", + "loss_dict, inptar = train(cur_model, background_increment_factor = 0, ch0_offset=100, step_count=20, lr=1e-4,\n", + " original_model=model,val_idx=val_idx, inner_pad=inp.shape[-1]//4)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "41a32c93", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'pred now')" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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+fEf/3Gcc9x9992P6xy+8Y1v5BWveAUveclL+JEf+RFu3rzJa1/7Wna73UfxRPfyiShPh32S5Vu/9Vv58i//cn7mZ36G973vfXzXd30X3/iN33jOln3Hd3wHb3zjG/mv/+v/mq/4iq/g3e9+N9///d/P29/+dn7rt36LK1eu8KIXvQhV5a1vfSvf8A3fAJy3N1n+/b//99y4ceMT397oXj6u8nf/7t9VQP/oj/7oT/xejFH7vtd//a//tQL6O7/zO+V33/It36KA/sRP/MQTOufnfd7n6d13362np6fls2EY9C/8hb+g999/v8YYVVX1J3/yJxXQb/7mb77tGPl3+bqvXbumbdvqS1/60nPfe+c736mAfuEXfuETura97OVWeSr2yGte8xoF9A1veMO5z1/5ylfqbDYre+T/+D/+j8f93s/93M8poG984xtVVXW1WmnTNPpDP/RDqqr6/ve/XwH97u/+bp3P57rdblVV9du+7dv0vvvue0LXuJc/nZLX5t/8m3/z3Oc//dM/rYD+1E/9VPns2c9+tnrv9V3vete5777iFa/Qg4MDfc973nPu87/39/6eAvr7v//7qqr6D//hP1RA/8W/+Bfnvvdt3/ZtCuhP/uRP/onX+l/+l/+ltm2r733ve899/mVf9mW6WCz0xo0bqqr6tre9TQH9T//T//S2Y+Tfve1tb1NV1RCC3nPPPfq5n/u55773nve8R+u61mc/+9l/4jXt5U+HPJ32SfanXvnKV577/A1veIMC+sEPflBVVf/gD/7gcb/3a7/2awro3/7bf7t8dv/99+vLX/5yVVXd7Xa6XC71u7/7uxUo9/O6171O67rWs7OzP/H6nu6yh6LdQfIf/+N/5K/8lb/CPffcg/eeuq75wi/8QgD+4A/+4Lbvv+QlL/mQx1ytVvzar/0af/kv/2UODg7K5957vumbvon3v//9vOtd7/qwj/urv/qr7HY7vv7rv/7c55/3eZ+3hwbs5WMmH4s9MpWv+qqvOvfv5z3veWy321Liz5m0l73sZee+91/8F/8Fy+WSt771rQAsFgue//zn85a3vAWAN7/5zVy4cIHv+q7vous6/t2/+3eAZdU+4bNne3lS5L/6r/6rc//++q//eqqq4m1ve9u5z5/3vOfdVjH/V//qX/HFX/zF3HfffQzDUH6+7Mu+DLCqPsDb3vY2Dg8Pb9sHf+Wv/JUndI2/8iu/wgtf+EKe9axnnfv8ZS97Gev1mne+853nPn8i+/Nd73oXDz300G225s/8mT/D53/+5z+h69rLnx55OuyTLI9nbwDe8573lPPA7fbmcz7nc/i0T/u0Ym8AXvjCFxZ78453vIP1es2rXvUqrly5Uqo2b3nLW3j+85/Pcrn8sK7z6Sb7wOYOkbOzM77gC76AX/u1X+OHf/iHefvb385v/MZv8KY3vQmw0udUFosFR0dHH/K4169fR1Ufl83svvvuAwznP5UnwnyW/+YZz3jGbb97vM/2spePVj5We2Qqly9fPvfvtm3PHfvq1atUVXUbkYaIcM8995zbSy960Yv41V/9VVarFW95y1v4ki/5Ei5fvsxnfdZn8Za3vIU/+qM/4o/+6I/2gc1enpDcc8895/5dVRWXL19+Qvr74Ycf5hd+4Reo6/rcz5//838egMceewyw9f14+vvWc/9xcvXq1b2t2ctTKk+HfZLlidibP+5a77vvvtvszXvf+17+8A//kLe85S18xmd8BnfffTdf8iVfwlve8hY2mw3veMc7/lTYm32PzR0iv/Irv8KDDz7I29/+9pKBBv5YylsReULHvXjxIs45PvjBD972u9ykduXKlQ/72HlDPvzww7f97qGHHtpXbfbypMvHao98OHL58mWGYeDRRx89F9yoKg899BB/6S/9pfLZC1/4Qr7/+7+ff/Nv/g1vfetbec1rXlM+/+Vf/mUeeOCB8u+97OVDyUMPPcQzn/nM8u9hGLh69eptztHjrfsrV67wvOc9j9e97nWPe+wceFy+fJlf//Vff9xzPxG5fPnyx93W7GUvU3k67JMnKvmaP/jBD3L//fef+92DDz54bj9lO/KWt7yFN7/5zbz4xS8un3/f930f/+bf/Bt2u92fisBmX7H5OMutEXmWvMny77P8o3/0jz6q8y2XSz73cz+XN73pTefOGWPkp37qp7j//vs/okb/z/3cz6VtW37u537u3Oe/+qu/Wsqoe9nLRyIf7z3y4Ug2Hj/1Uz917vN//s//OavV6lyQ8jmf8zkcHR3xP//P/zMPPfRQMTQvetGL+O3f/m1+/ud/nuc+97nFWO5lL3+S/PRP//S5f//8z/88wzA8IQbKr/iKr+D3fu/3+ORP/mQ++7M/+7afvAa/+Iu/mNPTU/7lv/yX5/7+Z37mZ57QNb7whS8sCYip/G//2//GYrH4iGicP+VTPoV77rmHn//5nz/3+Xvf+17e8Y53fNjH28sntjwd9skTlS/5ki8Bbrc3v/Ebv8Ef/MEfnLM39957L8997nP55//8n/Obv/mbxd68+MUv5tFHH+V/+p/+J46Ojs4l3z5RZV+x+TjLf/Kf/CcA/P2///f5lm/5Fuq65lM+5VN4wQtewMWLF/n2b/92XvOa11DXNT/90z/N7/zO73zU53z961/Pi1/8Yr74i7+Y/+6/++9omoYf+7Ef4/d+7/f42Z/92Y8os33p0iVe9apX8frXv56LFy/ytV/7tbz//e/nta99Lffeey/O7WPmvXxk8lTskScqL37xi/nP/rP/jO/+7u/m5OSEz//8zy+saJ/xGZ/BN33TN5Xveu/5wi/8Qn7hF36BBx54gE/+5E8G4PM///Np25a3vvWtfOd3fufH7dr38vSWN73pTVRVxYtf/OLC9vTpn/7pt/WePJ780A/9EG9+85t5wQtewHd+53fyKZ/yKWy3W9797nfzS7/0S/z4j/84999/P9/8zd/Mj/zIj/DN3/zNvO51r+PP/bk/xy/90i/xf/6f/+cTusbXvOY1pU/hB37gB7h06RI//dM/zS/+4i/yhje8gePj4w/7vp1zvPa1r+UVr3gFf/kv/2Ve/vKXc+PGjb2t2cvjytNhnzxR+ZRP+RT+2l/7a/zoj/4ozjm+7Mu+rLCiPetZz+Jv/s2/ee77L3zhC/nRH/1R5vN56T974IEHeOCBB/jlX/5lvuqrvoqq+lPg9j/V7AV/GuXVr3613nfffeqcO8f+8o53vEOf//zn62Kx0Lvuuku/9Vu/VX/rt37rNpaNb/mWb9HlcvlhnfPf/tt/q1/yJV+iy+VS5/O5ft7nfZ7+wi/8wrnvZKaO3/iN37jt729lRVM1Vqof/uEf1vvvv1+bptHnPe95+q/+1b/ST//0T9ev/dqv/bCuby97mcrHe49kRp1HH3303OePt+43m41+93d/tz772c/Wuq713nvv1e/4ju/Q69ev33bcv//3/74C+m3f9m3nPn/xi1+sgP7Lf/kvn/A17uVPp+S1+Zu/+Zv6lV/5lXpwcKCHh4f6Dd/wDfrwww+f++6zn/1s/fIv//LHPc6jjz6q3/md36kPPPCA1nWtly5d0s/6rM/S7/3e7z3HkvT+979fX/KSl5TzvOQlL9F3vOMdT4jtSVX1d3/3d/Urv/Ir9fj4WJum0U//9E+/7e8y89n//r//77f9/a2saFne+MY36p/9s39Wm6bR5zznOfoTP/ET+tVf/dX6GZ/xGR/ymvbyiS9Pp33yx/laj7f2Qwj6d/7O39HnPOc5Wte1XrlyRb/xG79R3/e+99123H/xL/6FAvriF7/43OeZre0f/IN/8Cde1yeKiKrqxzeU2ssnsvzRH/0Rn/qpn8prXvMa/vbf/ttP9eXsZS972cvTWn7wB3+Q1772tTz66KO39aj8aZYbN27wnOc8h6/5mq/hjW9841N9OXt5imW/T/aS5U9BTWovHyv5nd/5HX72Z3+WF7zgBRwdHfGud72LN7zhDRwdHfFX/+pffaovby972cte9vIJIA899BCve93r+OIv/mIuX77Me97zHn7kR36E09NT/tv/9r99qi9vL3vZyx0k+8BmLx+xLJdL/v2///f8k3/yT7hx4wbHx8d80Rd9Ea973ev2NJx72cte9rKXJ0XatuXd7343r3zlK7l27VohIvjxH//xQsW7l73sZS8AeyjaXvayl73sZS972cte9rKXp73s6UT2spe97GUve9nLXvayl7087eVjFtj82I/9GA888ACz2YzP+qzP4t/+23/7sTrVXvbytJX9PtnLXj607PfJXvbyoWW/T/ayl49RYPNzP/dz/I2/8Tf43u/9Xn77t3+bL/iCL+DLvuzLeO973/uxON1e9vK0lP0+2ctePrTs98le9vKhZb9P9rIXk49Jj83nfu7n8pmf+Zn8w3/4D8tnn/Zpn8bXfM3X8PrXv/5P/NsYIw8++CCHh4cf0eDIvezlYy2qyunpKffdd99HNRzuo9knsN8re7mzZb9P9rKXDy37fbKXvXxo+XD2yZPOitZ1Hb/5m7/J93zP95z7/Eu/9Et5xzvecdv3d7sdu92u/PsDH/gAz33uc5/sy9rLXp50ed/73sf999//Ef3th7tPYL9X9vL0lP0+2ctePrTs98le9vKh5Ynskyc9sHnssccIIdxG9/uMZzyDhx566Lbvv/71r+e1r33tbZ//pS9+Nd0zD1g90zIHzU2oNoo6iI0QHfSHMBwq6hQEVMANgtuBBEEC9qMgg/23WivtTUWCol7A2d+FRlAP3aHQXbAiVnNDqM+UWAv9AUQPzSn291FRERAI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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "out, _ = cur_model(torch.Tensor(inp[None]).cuda())\n", + "pred_now = get_img_from_forward_output(out, cur_model, unnormalized=True).detach().cpu().numpy()[0]\n", + "out, _ = model(torch.Tensor(inp[None]).cuda())\n", + "pred_orig = get_img_from_forward_output(out, model, unnormalized=True).detach().cpu().numpy()[0]\n", + "\n", + "\n", + "tar_now = inptar[1]\n", + "vmin0 = min(tar_now[0].min(), tar[0].min())\n", + "vmax0 = max(tar_now[0].max(), tar[0].max())\n", + "vmin1 = min(tar_now[1].min(), tar[1].min())\n", + "vmax1 = min(tar_now[1].max(), tar[1].max())\n", + "\n", + "_,ax = plt.subplots(ncols=4,nrows=2, figsize=(10,5))\n", + "ax[0,0].imshow(tar[0], vmin=vmin0, vmax=vmax0)\n", + "ax[0,1].imshow(tar_now[0], vmin=vmin0, vmax=vmax0)\n", + "ax[0,2].imshow(pred_orig[0], vmin=vmin0, vmax=vmax0)\n", + "ax[0,3].imshow(pred_now[0], vmin=vmin0, vmax=vmax0)\n", + "\n", + "ax[1,0].imshow(tar[1], vmin=vmin1, vmax=vmax1)\n", + "ax[1,1].imshow(tar_now[1], vmin=vmin1, vmax=vmax1)\n", + "ax[1,2].imshow(pred_orig[1], vmin=vmin1, vmax=vmax1)\n", + "ax[1,3].imshow(pred_now[1], vmin=vmin1, vmax=vmax1)\n", + "ax[0,0].set_title('tar orig')\n", + "ax[0,1].set_title('tar now')\n", + "ax[0,2].set_title('pred orig')\n", + "ax[0,3].set_title('pred now')" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "7f775bbd", + "metadata": {}, + "outputs": [], + "source": [ + "def get_param_dict(model):\n", + " param_dict = {}\n", + " for k, v in model.named_parameters():\n", + " param_dict[k] = v\n", + " return param_dict\n", + "\n", + "def get_sortedfirstk(dic, reverse=True, k=10):\n", + " return sorted([(k,v) for k,v in dic.items()], key=lambda x: x[1], reverse=reverse)[:k]\n", + "\n", + "def compare_two_models(m1, m2):\n", + " m1_dict = get_param_dict(m1)\n", + " m2_dict = get_param_dict(m2)\n", + " maxpos_diff_dict = {}\n", + " maxneg_diff_dict = {}\n", + " avg_diff_dict = {}\n", + "\n", + " for k in m1_dict.keys():\n", + " assert k in m2_dict.keys()\n", + " diff = m1_dict[k].data - m2_dict[k].data\n", + " maxpos_diff_dict[k] = diff.max().item()\n", + " maxneg_diff_dict[k] = diff.min().item()\n", + " avg_diff_dict[k] = diff.abs().mean().item()\n", + " return maxpos_diff_dict, maxneg_diff_dict, avg_diff_dict\n" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "6b6ade73", + "metadata": {}, + "outputs": [], + "source": [ + "maxpos_diff_dict, maxneg_diff_dict, avg_diff_dict = compare_two_models(model, cur_model)" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "c3d11310", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "top_down_layers.1.deterministic_block.0.pre_conv.weight \t 0.001\n", + "top_down_layers.1.merge.layer.0.weight \t 0.001\n", + "top_down_layers.2.skip_connection_merger.layer.0.weight \t 0.001\n", + "top_down_layers.1.deterministic_block.0.res.block.8.conv.weight \t 0.001\n", + "top_down_layers.1.stochastic.conv_out.weight \t 0.001\n", + "top_down_layers.1.stochastic.conv_in_q.weight \t 0.001\n", + "top_down_layers.1.deterministic_block.0.res.block.2.weight \t 0.001\n", + "top_down_layers.1.skip_connection_merger.layer.0.weight \t 0.001\n", + "top_down_layers.1.merge.layer.1.block.2.weight \t 0.001\n", + "top_down_layers.1.deterministic_block.0.pre_conv.bias \t 0.001\n", + "\n", + "\n", + "top_down_layers.1.skip_connection_merger.layer.0.weight \t -0.001\n", + "top_down_layers.1.deterministic_block.0.pre_conv.weight \t -0.001\n", + "top_down_layers.1.merge.layer.0.weight \t -0.001\n", + "top_down_layers.1.stochastic.conv_in_q.weight \t -0.001\n", + "top_down_layers.2.deterministic_block.0.pre_conv.weight \t -0.001\n", + "top_down_layers.3.deterministic_block.0.res.block.8.conv.weight \t -0.001\n", + "top_down_layers.1.deterministic_block.0.res.block.8.conv.weight \t -0.001\n", + "top_down_layers.1.deterministic_block.0.res.block.2.weight \t -0.001\n", + "top_down_layers.1.stochastic.conv_out.weight \t -0.001\n", + "top_down_layers.3.stochastic.conv_out.weight \t -0.001\n" + ] + } + ], + "source": [ + "def pretty_print(arr):\n", + " for k,v in arr:\n", + " print(k,f'\\t {v:.3f}')\n", + "\n", + "# pretty_print(sorted([(k,v) for k,v in maxpos_diff_dict.items()], key=lambda x: x[1], reverse=True)[:10])\n", + "pretty_print(get_sortedfirstk(maxpos_diff_dict, reverse=True, k=10))\n", + "print('')\n", + "print('')\n", + "pretty_print(get_sortedfirstk(maxneg_diff_dict, reverse=False, k=10))\n", + "# pretty_print(sorted([(k,v) for k,v in maxneg_diff_dict.items()], key=lambda x: x[1], reverse=True)[-10:])\n", + "\n", + "# plt.bar(range(len(maxpos_diff_dict)), list(maxpos_diff_dict.values()), align='center')\n", + "# plt.xticks(range(len(maxpos_diff_dict)), list(maxpos_diff_dict.keys()))" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "3d35ec8a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "_,ax = plt.subplots(1,3, figsize=(9,3))\n", + "ax[0].plot(loss_dict['loss'])\n", + "ax[1].plot(np.log(loss_dict['rec_loss']))\n", + "ax[2].plot(loss_dict['reg_loss'])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "1bce857e", + "metadata": {}, + "source": [ + "## doing it for the whole validation dset. " + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "0246ab84", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 20/20 [00:01<00:00, 12.06it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.98it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.06it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 10.61it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.72it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.85it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.76it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.26it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.59it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.12it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.02it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.94it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.98it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.96it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.87it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.86it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.83it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.99it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.98it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.91it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.00it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.83it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.00it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.04it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.83it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.68it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.91it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.80it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.70it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.65it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.61it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.79it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.63it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.02it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.97it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.66it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.64it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.88it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.81it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.86it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.75it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.86it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.77it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.86it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.87it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.78it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.61it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.92it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.94it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.79it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.84it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.74it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.07it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.95it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.99it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.06it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.80it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.74it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.71it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.79it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.90it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.87it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.68it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.69it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.80it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.04it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.08it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.99it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.90it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.69it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.75it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.73it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.80it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.99it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.83it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.70it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.93it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.89it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.89it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.72it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.84it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.77it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.98it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.96it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.98it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.92it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.88it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.95it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.87it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.95it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.99it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.02it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.98it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.96it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.93it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 11.79it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.01it/s]\n", + "100%|██████████| 20/20 [00:01<00:00, 12.04it/s]\n", + " 75%|███████▌ | 15/20 [00:01<00:00, 11.86it/s]\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[66], line 16\u001b[0m\n\u001b[1;32m 14\u001b[0m reload(model)\n\u001b[1;32m 15\u001b[0m cur_model \u001b[39m=\u001b[39m deepcopy(model)\n\u001b[0;32m---> 16\u001b[0m loss_dict, inptar \u001b[39m=\u001b[39m train(cur_model, background_increment_factor \u001b[39m=\u001b[39;49m \u001b[39m0\u001b[39;49m, ch0_offset\u001b[39m=\u001b[39;49m\u001b[39m100\u001b[39;49m, step_count\u001b[39m=\u001b[39;49m\u001b[39m20\u001b[39;49m, lr\u001b[39m=\u001b[39;49m\u001b[39m1e-4\u001b[39;49m,\n\u001b[1;32m 17\u001b[0m original_model\u001b[39m=\u001b[39;49mmodel,val_idx\u001b[39m=\u001b[39;49mval_idx, inner_pad\u001b[39m=\u001b[39;49minp\u001b[39m.\u001b[39;49mshape[\u001b[39m-\u001b[39;49m\u001b[39m1\u001b[39;49m]\u001b[39m/\u001b[39;49m\u001b[39m/\u001b[39;49m\u001b[39m4\u001b[39;49m)\n\u001b[1;32m 18\u001b[0m dset_loss_dict[\u001b[39m'\u001b[39m\u001b[39mloss\u001b[39m\u001b[39m'\u001b[39m] \u001b[39m+\u001b[39m\u001b[39m=\u001b[39m loss_dict[\u001b[39m'\u001b[39m\u001b[39mloss\u001b[39m\u001b[39m'\u001b[39m]\n\u001b[1;32m 19\u001b[0m dset_loss_dict[\u001b[39m'\u001b[39m\u001b[39mrec_loss\u001b[39m\u001b[39m'\u001b[39m] \u001b[39m+\u001b[39m\u001b[39m=\u001b[39m loss_dict[\u001b[39m'\u001b[39m\u001b[39mrec_loss\u001b[39m\u001b[39m'\u001b[39m]\n", + "Cell \u001b[0;32mIn[55], line 31\u001b[0m, in \u001b[0;36mtrain\u001b[0;34m(cur_model, background_increment_factor, ch0_offset, val_idx, step_count, lr, original_model, inner_pad, use_predicted_tar)\u001b[0m\n\u001b[1;32m 29\u001b[0m reg_losses \u001b[39m=\u001b[39m []\n\u001b[1;32m 30\u001b[0m \u001b[39mfor\u001b[39;00m _ \u001b[39min\u001b[39;00m tqdm(\u001b[39mrange\u001b[39m(step_count)):\n\u001b[0;32m---> 31\u001b[0m loss, loss_dict \u001b[39m=\u001b[39m one_step(cur_model, inp, tar, optimizer, original_model, inner_pad)\n\u001b[1;32m 32\u001b[0m losses\u001b[39m.\u001b[39mappend(loss)\n\u001b[1;32m 33\u001b[0m rec_losses\u001b[39m.\u001b[39mappend(loss_dict[\u001b[39m'\u001b[39m\u001b[39mrec_loss\u001b[39m\u001b[39m'\u001b[39m])\n", + "Cell \u001b[0;32mIn[55], line 53\u001b[0m, in \u001b[0;36mone_step\u001b[0;34m(cur_model, inp, tar, optimizer, original_model, inner_pad)\u001b[0m\n\u001b[1;32m 50\u001b[0m rec_loss \u001b[39m=\u001b[39m rec_loss[\u001b[39m.\u001b[39m\u001b[39m.\u001b[39m\u001b[39m.\u001b[39m,inner_pad:\u001b[39m-\u001b[39minner_pad, inner_pad:\u001b[39m-\u001b[39minner_pad]\n\u001b[1;32m 52\u001b[0m rec_loss \u001b[39m=\u001b[39m rec_loss\u001b[39m.\u001b[39mmean()\n\u001b[0;32m---> 53\u001b[0m reg_loss \u001b[39m=\u001b[39m \u001b[39m100\u001b[39m \u001b[39m*\u001b[39m weight_regularization_loss(cur_model, original_model) \n\u001b[1;32m 54\u001b[0m loss \u001b[39m=\u001b[39m rec_loss \u001b[39m+\u001b[39m reg_loss \u001b[39m*\u001b[39m \u001b[39m0\u001b[39m\n\u001b[1;32m 55\u001b[0m optimizer\u001b[39m.\u001b[39mzero_grad()\n", + "Cell \u001b[0;32mIn[55], line 41\u001b[0m, in \u001b[0;36mweight_regularization_loss\u001b[0;34m(cur_model, original_model)\u001b[0m\n\u001b[1;32m 39\u001b[0m loss \u001b[39m=\u001b[39m \u001b[39m0\u001b[39m\n\u001b[1;32m 40\u001b[0m \u001b[39mfor\u001b[39;00m name, param \u001b[39min\u001b[39;00m cur_model\u001b[39m.\u001b[39mnamed_parameters():\n\u001b[0;32m---> 41\u001b[0m loss \u001b[39m+\u001b[39m\u001b[39m=\u001b[39m torch\u001b[39m.\u001b[39mmean(torch\u001b[39m.\u001b[39mabs(original_model_dict[name] \u001b[39m-\u001b[39;49m param))\n\u001b[1;32m 42\u001b[0m \u001b[39mreturn\u001b[39;00m loss\u001b[39m/\u001b[39m\u001b[39mlen\u001b[39m(original_model_dict)\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "maxpos_val = {}\n", + "maxneg_val = {}\n", + "avg_val = {}\n", + "\n", + "maxpos_counter = {}\n", + "maxneg_counter = {}\n", + "avg_counter = {}\n", + "dset_loss_dict = {'loss':[], 'rec_loss':[], 'reg_loss':[]}\n", + "topk = 10\n", + "\n", + "\n", + "for val_idx in range(len(val_dset)):\n", + " inp, tar = val_dset[val_idx]\n", + " reload(model)\n", + " cur_model = deepcopy(model)\n", + " loss_dict, inptar = train(cur_model, background_increment_factor = 0, ch0_offset=100, step_count=20, lr=1e-4,\n", + " original_model=model,val_idx=val_idx, inner_pad=inp.shape[-1]//4)\n", + " dset_loss_dict['loss'] += loss_dict['loss']\n", + " dset_loss_dict['rec_loss'] += loss_dict['rec_loss']\n", + " dset_loss_dict['reg_loss'] += loss_dict['reg_loss']\n", + "\n", + " \n", + " maxpos_diff_dict, maxneg_diff_dict, avg_diff_dict = compare_two_models(model, cur_model)\n", + " for k,v in get_sortedfirstk(maxpos_diff_dict, k=topk, reverse=True):\n", + " maxpos_val[k] = maxpos_val.get(k,0) + v\n", + " maxpos_counter[k] = maxpos_counter.get(k,0) + 1\n", + " \n", + " for k,v in get_sortedfirstk(maxneg_diff_dict, k=topk, reverse=False):\n", + " maxneg_val[k] = maxneg_val.get(k,0) + v\n", + " maxneg_counter[k] = maxneg_counter.get(k,0) + 1\n", + " \n", + " for k,v in get_sortedfirstk(avg_diff_dict, k=topk, reverse=True):\n", + " avg_val[k] = avg_val.get(k,0) + v\n", + " avg_counter[k] = avg_counter.get(k,0) + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "77a8879e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    0
    top_down_layers.0.deterministic_block.0.pre_conv.weight0.155636
    top_down_layers.0.stochastic.conv_in_q.weight0.147696
    top_down_layers.0.stochastic.conv_out.weight0.146811
    top_down_layers.0.deterministic_block.0.pre_conv.bias0.115411
    top_down_layers.0.skip_connection_merger.layer.0.weight0.106646
    top_down_layers.0.merge.layer.0.weight0.097583
    top_down_layers.1.deterministic_block.0.pre_conv.weight0.094387
    likelihood.parameter_net.weight0.061378
    final_top_down.0.res.block.8.conv.weight0.051760
    bottom_up_layers.0.net_downsized.0.pre_conv.weight0.041778
    \n", + "
    " + ], + "text/plain": [ + " 0\n", + "top_down_layers.0.deterministic_block.0.pre_con... 0.155636\n", + "top_down_layers.0.stochastic.conv_in_q.weight 0.147696\n", + "top_down_layers.0.stochastic.conv_out.weight 0.146811\n", + "top_down_layers.0.deterministic_block.0.pre_con... 0.115411\n", + "top_down_layers.0.skip_connection_merger.layer.... 0.106646\n", + "top_down_layers.0.merge.layer.0.weight 0.097583\n", + "top_down_layers.1.deterministic_block.0.pre_con... 0.094387\n", + "likelihood.parameter_net.weight 0.061378\n", + "final_top_down.0.res.block.8.conv.weight 0.051760\n", + "bottom_up_layers.0.net_downsized.0.pre_conv.weight 0.041778" + ] + }, + "execution_count": 69, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "pd.DataFrame.from_dict(maxpos_val, orient='index').sort_values(by=0, ascending=False).head(10)" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "9069e0c2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    0
    top_down_layers.0.deterministic_block.0.pre_conv.weight97
    top_down_layers.0.stochastic.conv_out.weight96
    top_down_layers.0.stochastic.conv_in_q.weight96
    top_down_layers.0.skip_connection_merger.layer.0.weight77
    top_down_layers.1.deterministic_block.0.pre_conv.weight65
    top_down_layers.0.merge.layer.0.weight64
    likelihood.parameter_net.weight43
    final_top_down.0.res.block.8.conv.weight42
    top_down_layers.0.deterministic_block.0.pre_conv.bias41
    top_down_layers.0.deterministic_block.0.res.block.8.conv.weight29
    \n", + "
    " + ], + "text/plain": [ + " 0\n", + "top_down_layers.0.deterministic_block.0.pre_con... 97\n", + "top_down_layers.0.stochastic.conv_out.weight 96\n", + "top_down_layers.0.stochastic.conv_in_q.weight 96\n", + "top_down_layers.0.skip_connection_merger.layer.... 77\n", + "top_down_layers.1.deterministic_block.0.pre_con... 65\n", + "top_down_layers.0.merge.layer.0.weight 64\n", + "likelihood.parameter_net.weight 43\n", + "final_top_down.0.res.block.8.conv.weight 42\n", + "top_down_layers.0.deterministic_block.0.pre_con... 41\n", + "top_down_layers.0.deterministic_block.0.res.blo... 29" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.DataFrame.from_dict(maxneg_counter, orient='index').sort_values(by=0, ascending=False).head(10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13c0f073", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/WeightEvolution.ipynb b/denoisplit/notebooks/WeightEvolution.ipynb new file mode 100644 index 0000000..1212417 --- /dev/null +++ b/denoisplit/notebooks/WeightEvolution.ipynb @@ -0,0 +1,1782 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DATA_ROOT:\t /group/jug/ashesh/data/\n", + "CODE_ROOT:\t /home/ashesh.ashesh/\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "ckpt_dir = \"/home/ashesh.ashesh/training/disentangle/2310/D3-M23-S7-L0/38\"" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "dtype = int(ckpt_dir.split('/')[-2].split('-')[0][1:])\n", + "if DEBUG:\n", + " if dtype == DataType.CustomSinosoid:\n", + " data_dir = f'{DATA_ROOT}/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + "else:\n", + " if dtype in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve]:\n", + " data_dir = f'{DATA_ROOT}/sinosoid_without_test/sinosoid/'\n", + " elif dtype == DataType.OptiMEM100_014:\n", + " data_dir = f'{DATA_ROOT}/microscopy/'\n", + " elif dtype == DataType.Prevedel_EMBL:\n", + " data_dir = f'{DATA_ROOT}/Prevedel_EMBL/PKG_3P_dualcolor_stacks/NoAverage_NoRegistration/'\n", + " elif dtype == DataType.AllenCellMito:\n", + " data_dir = f'{DATA_ROOT}/allencell/2017_03_08_Struct_First_Pass_Seg/AICS-11/'\n", + " elif dtype == DataType.SeparateTiffData:\n", + " data_dir = f'{DATA_ROOT}/ventura_gigascience'\n", + " elif dtype == DataType.SemiSupBloodVesselsEMBL:\n", + " data_dir = f'{DATA_ROOT}/EMBL_halfsupervised/Demixing_3P'\n", + " elif dtype == DataType.Pavia2VanillaSplitting:\n", + " data_dir = f'{DATA_ROOT}/pavia2'\n", + " elif dtype == DataType.ExpansionMicroscopyMitoTub:\n", + " data_dir = f'{DATA_ROOT}/expansion_microscopy_Nick/'\n", + " elif dtype == DataType.ShroffMitoEr:\n", + " data_dir = f'{DATA_ROOT}/shrofflab/'\n", + " elif dtype == DataType.HTIba1Ki67:\n", + " data_dir = f'{DATA_ROOT}/Stefania/20230327_Ki67_and_Iba1_trainingdata/'\n", + " \n", + "# 2720*2720: microscopy dataset.\n", + "\n", + "image_size_for_grid_centers = None\n", + "mmse_count = 1\n", + "custom_image_size = None\n", + "\n", + "\n", + "\n", + "batch_size = 32\n", + "num_workers = 4\n", + "COMPUTE_LOSS = False\n", + "use_deterministic_grid = None\n", + "threshold = None # 0.02\n", + "compute_kl_loss = False\n", + "evaluate_train = False# inspect training performance\n", + "eval_datasplit_type = DataSplitType.Test\n", + "val_repeat_factor = None\n", + "psnr_type = 'range_invariant' #'simple', 'range_invariant'" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "data:\n", + " background_quantile: 0.0\n", + " channel_1: 2\n", + " channel_2: 3\n", + " clip_background_noise_to_zero: false\n", + " clip_percentile: 0.995\n", + " data_type: 3\n", + " deterministic_grid: true\n", + " image_size: 512\n", + " innerpad_amount: 128\n", + " input_is_sum: false\n", + " multiscale_lowres_count: null\n", + " normalized_input: true\n", + " padding_mode: reflect\n", + " padding_value: null\n", + " randomized_channels: false\n", + " sampler_type: 7\n", + " skip_normalization_using_mean: false\n", + " target_separate_normalization: false\n", + " train_aug_rotate: false\n", + " use_one_mu_std: true\n", + " val_grid_size: 256\n", + "datadir: /group/jug/ashesh/data/microscopy/\n", + "exptname: 2310/D3-M23-S7-L0/38\n", + "git:\n", + " branch: autoregressive_v6\n", + " changedFiles: []\n", + " latest_commit: 985deeb9c1a1f10c0a9a0ce1dee9641fd016e199\n", + " untracked_files: []\n", + "hostname: gnode07\n", + "loss:\n", + " free_bits: 0.0\n", + " kl_annealing: false\n", + " kl_annealtime: 10\n", + " kl_min: 1.0e-07\n", + " kl_start: -1\n", + " kl_weight: 0.1\n", + " loss_type: 0\n", + "model:\n", + " analytical_kl: false\n", + " decoder:\n", + " batchnorm: true\n", + " blocks_per_layer: 1\n", + " conv2d_bias: true\n", + " dropout: 0.1\n", + " multiscale_retain_spatial_dims: true\n", + " n_filters: 64\n", + " res_block_kernel: 3\n", + " res_block_skip_padding: false\n", + " enable_noise_model: false\n", + " encoder:\n", + " batchnorm: true\n", + " blocks_per_layer: 1\n", + " dropout: 0.1\n", + " n_filters: 64\n", + " res_block_kernel: 3\n", + " res_block_skip_padding: false\n", + " gated: true\n", + " img_shape: null\n", + " learn_top_prior: true\n", + " logvar_lowerbound: -5\n", + " merge_type: residual\n", + " mode_pred: true\n", + " model_type: 23\n", + " monitor: val_psnr\n", + " multiscale_lowres_separate_branch: false\n", + " multiscale_retain_spatial_dims: true\n", + " nbr_dropout: 0.2\n", + " nbr_share_weights: true\n", + " nbrs_enable_from: 5\n", + " no_initial_downscaling: true\n", + " noise_model_ch1_fpath: null\n", + " non_stochastic_version: false\n", + " nonlin: elu\n", + " predict_logvar: pixelwise\n", + " res_block_type: bacdbacd\n", + " rotation_with_neighbors: true\n", + " skip_nboundary_pixels_from_loss: null\n", + " stochastic_skip: true\n", + " untrained_nbr_branch: false\n", + " use_vampprior: false\n", + " var_clip_max: 20\n", + " z_dims:\n", + " - 128\n", + " - 128\n", + " - 128\n", + " - 128\n", + "training:\n", + " batch_size: 4\n", + " earlystop_patience: 200\n", + " grad_clip_norm_value: 0.5\n", + " gradient_clip_algorithm: value\n", + " lr: 0.0005\n", + " lr_scheduler_patience: 30\n", + " max_epochs: 100\n", + " num_workers: 4\n", + " pre_trained_ckpt_fpath: ''\n", + " precision: 16\n", + " save_every_n_epochs: 1\n", + " test_fraction: 0.1\n", + " train_repeat_factor: null\n", + " val_fraction: 0.1\n", + " val_repeat_factor: null\n", + "workdir: /home/ashesh.ashesh/training/disentangle/2310/D3-M23-S7-L0/38\n", + "\n" + ] + } + ], + "source": [ + "%run ./nb_core/config_loader.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.sampler_type import SamplerType\n", + "from denoisplit.core.loss_type import LossType\n", + "from denoisplit.data_loader.ht_iba1_ki67_rawdata_loader import SubDsetType\n", + "# from denoisplit.core.lowres_merge_type import LowresMergeType\n", + "\n", + "\n", + "with config.unlocked():\n", + " config.model.skip_nboundary_pixels_from_loss = None\n", + " if config.model.model_type == ModelType.UNet and 'n_levels' not in config.model:\n", + " config.model.n_levels = 4\n", + " if config.data.sampler_type == SamplerType.NeighborSampler:\n", + " config.data.sampler_type = SamplerType.DefaultSampler\n", + " config.loss.loss_type = LossType.Elbo\n", + " config.data.grid_size = config.data.image_size\n", + " if 'ch1_fpath_list' in config.data:\n", + " config.data.ch1_fpath_list = config.data.ch1_fpath_list[:1]\n", + " config.data.mix_fpath_list = config.data.mix_fpath_list[:1]\n", + " if config.data.data_type == DataType.Pavia2VanillaSplitting:\n", + " if 'channel_2_downscale_factor' not in config.data:\n", + " config.data.channel_2_downscale_factor = 1\n", + " if config.model.model_type == ModelType.UNet and 'init_channel_count' not in config.model:\n", + " config.model.init_channel_count = 64\n", + " \n", + " if 'skip_receptive_field_loss_tokens' not in config.loss:\n", + " config.loss.skip_receptive_field_loss_tokens = []\n", + " \n", + " if dtype == DataType.HTIba1Ki67:\n", + " config.data.subdset_type = SubDsetType.Iba1Ki64\n", + " config.data.empty_patch_replacement_enabled = False\n", + " \n", + " if 'lowres_merge_type' not in config.model.encoder:\n", + " config.model.encoder.lowres_merge_type = 0\n", + " \n", + " if config.model.model_type == ModelType.AutoRegresiveRALadderVAE:\n", + " patch_size = custom_image_size if custom_image_size is not None else config.data.image_size\n", + " grid_size = image_size_for_grid_centers if image_size_for_grid_centers is not None else patch_size - 2*config.data.innerpad_amount\n", + " assert grid_size % 2 == 0\n", + " \n", + " config.data.innerpad_amount = (patch_size - grid_size) // 2\n", + " image_size_for_grid_centers = grid_size\n", + " # config.data.grid_size = image_size_for_grid_centers\n", + " config.data.val_grid_size = image_size_for_grid_centers" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "Loading /group/jug/ashesh/data//microscopy/OptiMEM100x014.tif with Channels 2,3,datasplit mode:Train\n", + "[MultiChDeterministicTiffDloader] Sz:512 Train:1 N:49 NumPatchPerN:25 NormInp:True SingleNorm:True Rot:False RandCrop:False Q:0.995 SummedInput:False ReplaceWithRandSample:False BckQ:0.0\n", + "Loading /group/jug/ashesh/data//microscopy/OptiMEM100x014.tif with Channels 2,3,datasplit mode:Test\n", + "[MultiChDeterministicTiffDloader] Sz:512 Train:0 N:6 NumPatchPerN:100 NormInp:True SingleNorm:True Rot:False RandCrop:False Q:0.995 SummedInput:False ReplaceWithRandSample:False BckQ:0.0\n", + "\n", + "config.pkl\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n" + ] + }, + { + "ename": "AssertionError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m/tmp/ipykernel_63681/2403964068.py:18\u001b[0m\n\u001b[1;32m 14\u001b[0m std_fr_model \u001b[39m=\u001b[39m std_fr_model[\u001b[39mNone\u001b[39;00m]\n\u001b[1;32m 16\u001b[0m model \u001b[39m=\u001b[39m create_model(config, mean_fr_model,std_fr_model)\n\u001b[0;32m---> 18\u001b[0m ckpt_fpath \u001b[39m=\u001b[39m get_best_checkpoint(ckpt_dir)\n\u001b[1;32m 19\u001b[0m checkpoint \u001b[39m=\u001b[39m torch\u001b[39m.\u001b[39mload(ckpt_fpath)\n\u001b[1;32m 21\u001b[0m _ \u001b[39m=\u001b[39m model\u001b[39m.\u001b[39mload_state_dict(checkpoint[\u001b[39m'\u001b[39m\u001b[39mstate_dict\u001b[39m\u001b[39m'\u001b[39m])\n", + "File \u001b[0;32m/tmp/ipykernel_63681/1910139666.py:5\u001b[0m, in \u001b[0;36mget_best_checkpoint\u001b[0;34m(ckpt_dir)\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[39mfor\u001b[39;00m filename \u001b[39min\u001b[39;00m glob\u001b[39m.\u001b[39mglob(ckpt_dir \u001b[39m+\u001b[39m \u001b[39m\"\u001b[39m\u001b[39m/*_best.ckpt\u001b[39m\u001b[39m\"\u001b[39m):\n\u001b[1;32m 4\u001b[0m output\u001b[39m.\u001b[39mappend(filename)\n\u001b[0;32m----> 5\u001b[0m \u001b[39massert\u001b[39;00m \u001b[39mlen\u001b[39m(output) \u001b[39m==\u001b[39m \u001b[39m1\u001b[39m, \u001b[39m'\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m'\u001b[39m\u001b[39m.\u001b[39mjoin(output)\n\u001b[1;32m 6\u001b[0m \u001b[39mreturn\u001b[39;00m output[\u001b[39m0\u001b[39m]\n", + "\u001b[0;31mAssertionError\u001b[0m: " + ] + }, + { + "ename": "AssertionError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[7], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m get_ipython()\u001b[39m.\u001b[39;49mrun_line_magic(\u001b[39m'\u001b[39;49m\u001b[39mrun\u001b[39;49m\u001b[39m'\u001b[39;49m, \u001b[39m'\u001b[39;49m\u001b[39m./nb_core/disentangle_setup.ipynb\u001b[39;49m\u001b[39m'\u001b[39;49m)\n", + "File \u001b[0;32m~/mambaforge/envs/usplit/lib/python3.9/site-packages/IPython/core/interactiveshell.py:2369\u001b[0m, in \u001b[0;36mInteractiveShell.run_line_magic\u001b[0;34m(self, magic_name, line, _stack_depth)\u001b[0m\n\u001b[1;32m 2367\u001b[0m kwargs[\u001b[39m'\u001b[39m\u001b[39mlocal_ns\u001b[39m\u001b[39m'\u001b[39m] \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mget_local_scope(stack_depth)\n\u001b[1;32m 2368\u001b[0m \u001b[39mwith\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mbuiltin_trap:\n\u001b[0;32m-> 2369\u001b[0m result \u001b[39m=\u001b[39m fn(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 2370\u001b[0m \u001b[39mreturn\u001b[39;00m result\n", + "File \u001b[0;32m~/mambaforge/envs/usplit/lib/python3.9/site-packages/IPython/core/magics/execution.py:717\u001b[0m, in \u001b[0;36mExecutionMagics.run\u001b[0;34m(self, parameter_s, runner, file_finder)\u001b[0m\n\u001b[1;32m 715\u001b[0m \u001b[39mwith\u001b[39;00m preserve_keys(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39mshell\u001b[39m.\u001b[39muser_ns, \u001b[39m'\u001b[39m\u001b[39m__file__\u001b[39m\u001b[39m'\u001b[39m):\n\u001b[1;32m 716\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mshell\u001b[39m.\u001b[39muser_ns[\u001b[39m'\u001b[39m\u001b[39m__file__\u001b[39m\u001b[39m'\u001b[39m] \u001b[39m=\u001b[39m filename\n\u001b[0;32m--> 717\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mshell\u001b[39m.\u001b[39;49msafe_execfile_ipy(filename, raise_exceptions\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m)\n\u001b[1;32m 718\u001b[0m \u001b[39mreturn\u001b[39;00m\n\u001b[1;32m 720\u001b[0m \u001b[39m# Control the response to exit() calls made by the script being run\u001b[39;00m\n", + "File \u001b[0;32m~/mambaforge/envs/usplit/lib/python3.9/site-packages/IPython/core/interactiveshell.py:2875\u001b[0m, in \u001b[0;36mInteractiveShell.safe_execfile_ipy\u001b[0;34m(self, fname, shell_futures, raise_exceptions)\u001b[0m\n\u001b[1;32m 2873\u001b[0m result \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mrun_cell(cell, silent\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m, shell_futures\u001b[39m=\u001b[39mshell_futures)\n\u001b[1;32m 2874\u001b[0m \u001b[39mif\u001b[39;00m raise_exceptions:\n\u001b[0;32m-> 2875\u001b[0m result\u001b[39m.\u001b[39;49mraise_error()\n\u001b[1;32m 2876\u001b[0m \u001b[39melif\u001b[39;00m \u001b[39mnot\u001b[39;00m result\u001b[39m.\u001b[39msuccess:\n\u001b[1;32m 2877\u001b[0m \u001b[39mbreak\u001b[39;00m\n", + "File \u001b[0;32m~/mambaforge/envs/usplit/lib/python3.9/site-packages/IPython/core/interactiveshell.py:266\u001b[0m, in \u001b[0;36mExecutionResult.raise_error\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 264\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39merror_before_exec\n\u001b[1;32m 265\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39merror_in_exec \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[0;32m--> 266\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39merror_in_exec\n", + " \u001b[0;31m[... skipping hidden 1 frame]\u001b[0m\n", + "File \u001b[0;32m/tmp/ipykernel_63681/2403964068.py:18\u001b[0m\n\u001b[1;32m 14\u001b[0m std_fr_model \u001b[39m=\u001b[39m std_fr_model[\u001b[39mNone\u001b[39;00m]\n\u001b[1;32m 16\u001b[0m model \u001b[39m=\u001b[39m create_model(config, mean_fr_model,std_fr_model)\n\u001b[0;32m---> 18\u001b[0m ckpt_fpath \u001b[39m=\u001b[39m get_best_checkpoint(ckpt_dir)\n\u001b[1;32m 19\u001b[0m checkpoint \u001b[39m=\u001b[39m torch\u001b[39m.\u001b[39mload(ckpt_fpath)\n\u001b[1;32m 21\u001b[0m _ \u001b[39m=\u001b[39m model\u001b[39m.\u001b[39mload_state_dict(checkpoint[\u001b[39m'\u001b[39m\u001b[39mstate_dict\u001b[39m\u001b[39m'\u001b[39m])\n", + "File \u001b[0;32m/tmp/ipykernel_63681/1910139666.py:5\u001b[0m, in \u001b[0;36mget_best_checkpoint\u001b[0;34m(ckpt_dir)\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[39mfor\u001b[39;00m filename \u001b[39min\u001b[39;00m glob\u001b[39m.\u001b[39mglob(ckpt_dir \u001b[39m+\u001b[39m \u001b[39m\"\u001b[39m\u001b[39m/*_best.ckpt\u001b[39m\u001b[39m\"\u001b[39m):\n\u001b[1;32m 4\u001b[0m output\u001b[39m.\u001b[39mappend(filename)\n\u001b[0;32m----> 5\u001b[0m \u001b[39massert\u001b[39;00m \u001b[39mlen\u001b[39m(output) \u001b[39m==\u001b[39m \u001b[39m1\u001b[39m, \u001b[39m'\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m'\u001b[39m\u001b[39m.\u001b[39mjoin(output)\n\u001b[1;32m 6\u001b[0m \u001b[39mreturn\u001b[39;00m output[\u001b[39m0\u001b[39m]\n", + "\u001b[0;31mAssertionError\u001b[0m: " + ] + } + ], + "source": [ + "%run ./nb_core/disentangle_setup.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def get_kth_ckpt(epoch_num):\n", + " for fnane in os.listdir(ckpt_dir):\n", + " if fnane.startswith(f'epoch={epoch_num}-'):\n", + " return os.path.join(ckpt_dir, fnane)\n", + " \n", + " raise ValueError(f'No ckpt found for epoch {epoch_num}')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def get_kth_ckpt_model(epoch_num):\n", + " ckpt_fpath = get_kth_ckpt(epoch_num)\n", + " checkpoint = torch.load(ckpt_fpath)\n", + " model = create_model(config, mean_fr_model,std_fr_model)\n", + " _ = model.load_state_dict(checkpoint['state_dict'])\n", + " model.eval()\n", + " # _= model.cuda()\n", + " # model.set_params_to_same_device_as(torch.Tensor(1).cuda())\n", + "\n", + " print('Loading from epoch', checkpoint['epoch'])\n", + " return model" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([64, 64, 3, 3])" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 75\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 76\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 77\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 78\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 79\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 80\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 81\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 82\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 83\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 84\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 85\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 86\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 87\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 88\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 89\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 90\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 91\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 92\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 93\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 94\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 95\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 96\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 97\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 98\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[TopDownLayer] normalize_latent_factor:1.0\n", + "[3, 3] [1, 1]\n", + "[GaussianLikelihood] PredLVar:pixelwise LowBLVar:-5\n", + "[AutoRegRALadderVAE] Enc [ResKSize3 SkipPadding:False] Dec [ResKSize3 SkipPadding:False] Stoc:True\n", + "[SolutionRAManager] Train P512 Sk128 D0.2\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[SolutionRAManager] Val P512 Sk128 D0.0\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[3, 3] [1, 1]\n", + "[BottomUpLayer] McEnabled:0 \n", + "[AutoRegRALadderVAE]Rotation:True NbrSharedWeights:True\n", + "Loading from epoch 99\n" + ] + } + ], + "source": [ + "weights_begin = []\n", + "weights_end = []\n", + "skip_epoch= 1\n", + "# for epoch_num in range(0,100, skip_epoch):\n", + "for epoch_num in range(75,100, skip_epoch):\n", + "\n", + " model = get_kth_ckpt_model(epoch_num)\n", + " weights_begin.append(model.bottom_up_layers[-1].net_downsized[0].pre_conv.weight.data.cpu().numpy())\n", + " # weights_end.append(model.top_down_layers[0].deterministic_block[0].pre_conv.weight.data.cpu().numpy())\n", + " weights_end.append(model.final_top_down[0].res.block[2].weight.data.cpu().numpy())\n" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 71, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "ki = 0\n", + "kj = 1\n", + "sns.heatmap(weights_begin[2][...,ki,kj] -weights_begin[0][...,ki,kj])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Looking at how the weights evolve during training" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "714d4993d8e94fe08f6e71ab0d4d6f80", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(FloatSlider(value=1.0, description='i', max=24.0, min=1.0, step=1.0), Output()), _dom_cl…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%matplotlib inline\n", + "import numpy as np\n", + "from ipywidgets import interact, interactive, fixed, interact_manual\n", + "import ipywidgets as widgets\n", + "ymax_begin = -np.inf\n", + "ymin_begin = np.inf\n", + "ymax_end = -np.inf\n", + "ymin_end = np.inf\n", + "\n", + "def get_diff(w1, w2):\n", + " return np.mean(np.abs(w1-w2), axis=(0,2,3)).reshape(-1,)\n", + "\n", + "for i in range(1,len(weights_begin)):\n", + " ymax_begin = max(ymax_begin, np.max(get_diff(weights_begin[i],weights_begin[i-1])))\n", + " ymin_begin = min(ymin_begin, np.min(get_diff(weights_begin[i],weights_begin[i-1])))\n", + " ymax_end = max(ymax_end, np.max(get_diff(weights_end[i], weights_end[i-1])))\n", + " ymin_end = min(ymin_end, np.min(get_diff(weights_end[i], weights_end[i-1])))\n", + "\n", + "ymax = max(ymax_begin, ymax_end)\n", + "ymin = min(ymin_begin, ymin_end)\n", + "\n", + "def plot_func(i):\n", + " i = int(i)\n", + " _,ax = plt.subplots(figsize=(6,3),ncols=2)\n", + " # ax[0].plot((weights_begin[i] - weights_begin[i-1]).reshape(-1))\n", + " # ax[1].plot((weights_end[i] - weights_end[i-1]).reshape(-1))\n", + " ax[0].plot(get_diff(weights_begin[i], weights_begin[i-1]))\n", + " ax[1].plot(get_diff(weights_end[i], weights_end[i-1]))\n", + " ax[0].set_ylim(ymin, ymax)\n", + " ax[1].set_ylim(ymin, ymax)\n", + "\n", + "interact(plot_func, i = widgets.FloatSlider(value=1,\n", + " min=1,\n", + " max=len(weights_begin)-1,\n", + " step=1))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Average weight evolution" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f26ef2ecb8924641b9e98367371d0a53", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(FloatSlider(value=1.0, description='i', max=24.0, min=1.0, step=1.0), Output()), _dom_cl…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 73, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def get_one_output_channel(w):\n", + " return np.mean(np.abs(w), axis=(0,2,3))\n", + "\n", + "ymax = -np.inf\n", + "ymin = np.inf\n", + "for i in range(1,len(weights_begin)):\n", + " ymax = max(ymax, get_one_output_channel(weights_begin[i]).max())\n", + " ymax = max(ymax, get_one_output_channel(weights_end[i]).max())\n", + " ymin = min(ymin, get_one_output_channel(weights_begin[i]).min())\n", + " ymin = min(ymin, get_one_output_channel(weights_end[i]).min())\n", + "\n", + "def plot_func2(i):\n", + " i = int(i)\n", + " _,ax = plt.subplots(figsize=(6,3),ncols=2)\n", + " ax[0].plot(get_one_output_channel(weights_begin[i]))\n", + " ax[1].plot(get_one_output_channel(weights_end[i]))\n", + " ax[0].set_ylim(ymin, ymax)\n", + " ax[1].set_ylim(ymin, ymax)\n", + "\n", + "interact(plot_func2, i = widgets.FloatSlider(value=1,\n", + " min=1,\n", + " max=len(weights_begin)-1,\n", + " step=1))" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val_dset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18 | packaged by conda-forge | (main, Aug 30 2023, 03:49:32) \n[GCC 12.3.0]" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/biosr_data.ipynb b/denoisplit/notebooks/biosr_data.ipynb new file mode 100644 index 0000000..0ce7c34 --- /dev/null +++ b/denoisplit/notebooks/biosr_data.ipynb @@ -0,0 +1,224 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.data_loader.raw_mrc_dloader import get_mrc_data\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ch1path = '/group/jug/ashesh/data/BioSR/F-actin/GT_all_a.mrc'\n", + "ch2path = '/group/jug/ashesh/data/BioSR/CCPs/GT_all.mrc'\n", + "ch3path ='/group/jug/ashesh/data/BioSR/ER/GT_all.mrc'\n", + "ch4path = '/group/jug/ashesh/data/BioSR/F-actin_Nonlinear/GT_all_a.mrc'\n", + "ch5path = '/group/jug/ashesh/data/BioSR/Microtubules/GT_all.mrc'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data1 = get_mrc_data(ch1path)\n", + "data2 = get_mrc_data(ch2path)\n", + "data3 = get_mrc_data(ch3path)\n", + "data4 = get_mrc_data(ch4path)\n", + "data5 = get_mrc_data(ch5path)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sample = data1[0]\n", + "sample = sample[400:600,400:600]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "sns.histplot((np.random.poisson(sample/500)*500).reshape(-1,), color='r')\n", + "sns.histplot(sample.reshape(-1), color='b')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.quantile(data1[0], 0.01)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "_,ax = plt.subplots(figsize=(10,5),ncols=2)\n", + "\n", + "ax[0].imshow(sample)\n", + "ax[1].imshow(np.random.poisson(sample/500)*500)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "_,ax = plt.subplots(figsize=(20,4),ncols=5)\n", + "ax[0].imshow(data1[0],cmap='gray')\n", + "ax[1].imshow(data2[0],cmap='gray')\n", + "ax[2].imshow(data3[0],cmap='gray')\n", + "ax[3].imshow(data4[0],cmap='gray')\n", + "ax[4].imshow(data5[0],cmap='gray')\n", + "\n", + "ax[0].set_title(os.path.basename(os.path.dirname(ch1path)))\n", + "ax[1].set_title(os.path.basename(os.path.dirname(ch2path)))\n", + "ax[2].set_title(os.path.basename(os.path.dirname(ch3path)))\n", + "ax[3].set_title(os.path.basename(os.path.dirname(ch4path)))\n", + "ax[4].set_title(os.path.basename(os.path.dirname(ch5path)))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "sns.kdeplot(data1[0].flatten(),label=os.path.basename(os.path.dirname(ch1path)))\n", + "sns.kdeplot(data2[0].flatten(),label=os.path.basename(os.path.dirname(ch2path)))\n", + "sns.kdeplot(data3[0].flatten(),label=os.path.basename(os.path.dirname(ch3path)))\n", + "sns.kdeplot(data4[0].flatten(),label=os.path.basename(os.path.dirname(ch4path)))\n", + "sns.kdeplot(data5[0].flatten(),label=os.path.basename(os.path.dirname(ch5path)))\n", + "plt.legend()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "for idx, data in enumerate([data1, data2, data3, data4, data5]):\n", + " qs = np.quantile(data.flatten(),[0, 0.01,0.5, 0.995, 1]).astype(np.int32)\n", + " label = os.path.basename(os.path.dirname(globals()[f'ch{idx+1}path']))\n", + " print(label.rjust(20),'\\t\\t', qs, data.shape)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Two versions of F-actin data.\n", + "It is not clear why they have provided these two versions. Also, we have another 2 versions with Actin non-linear. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data12 = get_mrc_data('/group/jug/ashesh/data/BioSR/F-actin/GT_all_b.mrc')\n", + "np.quantile(data12.flatten(),[0, 0.01,0.5, 0.995, 1]).astype(np.int32)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "ax[0].imshow(data1[0],cmap='gray')\n", + "ax[1].imshow(data12[0],cmap='gray')\n", + "ax[0].set_title(os.path.basename(ch1path))\n", + "ax[1].set_title(os.path.basename(('/group/jug/ashesh/data/BioSR/F-actin/GT_all_b.mrc')))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Intensity profile across slices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(np.mean(data5.reshape(len(data5),-1),axis=1), label = os.path.basename(os.path.dirname(ch1path)))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/datasets/dao_3channel_filteringdata.ipynb b/denoisplit/notebooks/datasets/dao_3channel_filteringdata.ipynb new file mode 100644 index 0000000..e1df55a --- /dev/null +++ b/denoisplit/notebooks/datasets/dao_3channel_filteringdata.ipynb @@ -0,0 +1,156 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.data_loader.raw_mrc_dloader import get_mrc_data\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "good_data_positions = sorted([21,24,34,55,56,57,65,73,81,86,96,100,107,108,109,110,111,112,113,114,\n", + " 118,125,126,135,153,157,159,160,164,165,167,169,174,175,176,177,183,185,\n", + " 190,196,198,199,200,204,209,217,219,221,242,243,244,252,255,256,257,258,259,261])\n", + "\n", + "normal_data_positions = sorted([22,23,26,29,30,32,40,41,44,45,46,47,52,53,54,58,60,62,63,64,66,70,71,72,74,75,\n", + " 78,79,90,91,92,93,94,95,97,99,104,105,122,123,124,127,130,131,133,136,138,139,\n", + " 140,141,142,143,144,147,151,152,154,155,156,158,161,162,163,166,170,171,172,173,\n", + " 178,179,182,186,189,190,191,192,193,195,197,201,202,203,205,206,207,208,210,212,\n", + " 213,215,216,218,220,222,223,224,225,226,227,230,231,232,233,234,235,236,237,238,\n", + " 239,240,241,245,246,248,249,250,251,253,254,260,262,263]\n", + " )\n", + "\n", + "datadir = '/group/jug/ashesh/data/Dao3Channel/'\n", + "outputdir = '/group/jug/ashesh/data/Dao3ChannelReduced/'\n", + "\n", + "fpath1 ='SIM1-100.tif'\n", + "fpath2 = 'SIM101-200.tif'\n", + "fpath3 = 'SIM201-263.tif'\n", + "\n", + "def get_fpath(index):\n", + " if index <=100:\n", + " return os.path.join(datadir, fpath1)\n", + " elif index <=200:\n", + " return os.path.join(datadir, fpath2)\n", + " elif index <=263:\n", + " return os.path.join(datadir, fpath3)\n", + " else:\n", + " raise ValueError(f'Index out of range {index}')\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.tiff_reader import load_tiff, save_tiff\n", + "import numpy as np\n", + "\n", + "def load_data(fpath_list):\n", + " assert len(set(fpath_list)) ==1\n", + " fpath = fpath_list[0]\n", + " return load_tiff(fpath)\n", + "\n", + "def filter_data(data, indices):\n", + " output_data = []\n", + " for i in indices:\n", + " if i > 100 and i <= 200:\n", + " i -= 100\n", + " elif i > 200 and i <= 263:\n", + " i -= 200\n", + " assert i > 0\n", + " output_data.append(data[i-1:i])\n", + " return np.concatenate(output_data, axis=0)\n", + "\n", + "def save_data(fpath, data):\n", + " save_tiff(fpath,data)\n", + "\n", + "def dump_data(fpath_list, recent_indices, outputdir):\n", + " data = load_data(fpath_list)\n", + " low,high = os.path.basename(fpath_list[0]).split('.')[0][3:].split('-')\n", + " low, high = int(low), int(high)\n", + " assert low <= min(recent_indices)\n", + " assert high >= max(recent_indices)\n", + " \n", + " data = filter_data(data, recent_indices)\n", + " print(data.shape)\n", + " fname = os.path.basename(fpath_list[-1])\n", + " fpath = os.path.join(outputdir, f'reduced_{fname}')\n", + " print('Saving to ', fpath)\n", + " save_data(fpath,data)\n", + "\n", + "# fpath_list = []\n", + "# recent_indices = []\n", + "# for i in good_data_positions:\n", + "# fpath = get_fpath(i)\n", + "# if len(fpath_list) > 0 and fpath_list[-1] != fpath:\n", + "# print(set(fpath_list), len(fpath_list))\n", + "# dump_data(fpath_list, recent_indices, outputdir)\n", + "# fpath_list = []\n", + "# recent_indices = []\n", + "\n", + "# fpath_list.append(fpath)\n", + "# recent_indices.append(i)\n", + "\n", + "\n", + "# print(set(fpath_list), len(fpath_list))\n", + "# dump_data(fpath_list, recent_indices, outputdir)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(set(fpath_list), len(fpath_list))\n", + "dump_data(fpath_list, recent_indices, datadir)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!ls -lhrt /group/jug/ashesh/data/Dao3ChannelReduced/" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/datasets/nicola_dataset.ipynb b/denoisplit/notebooks/datasets/nicola_dataset.ipynb new file mode 100644 index 0000000..ddc45df --- /dev/null +++ b/denoisplit/notebooks/datasets/nicola_dataset.ipynb @@ -0,0 +1,145 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "# os.environ[\"CUDA_DEVICE_ORDER\"]=\"PCI_BUS_ID\" # see issue #152\n", + "# os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"2\"\n", + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%run ../nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ../nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from nd2reader import ND2Reader\n", + "\n", + "fpath = '/group/jug/ashesh/data/nicola_data/uSplit_14022025_highSNR.nd2'\n", + "with ND2Reader(fpath) as fobj:\n", + " print(fobj)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "[key for key in fobj.metadata.keys()]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fobj.metadata['channels']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def load_one_file(fpath):\n", + " \"\"\"\n", + " '/group/jug/ashesh/data/pavia3_sequential/Cond_2/Main/1_002.nd2'\n", + " \"\"\"\n", + " output = []\n", + " with ND2Reader(fpath) as fobj:\n", + " for c in range(len(fobj.metadata['channels'])):\n", + " output.append([])\n", + " for v in fobj.metadata['fields_of_view']:\n", + " img = fobj.get_frame_2D(c=c, v=v)\n", + " img = img[None, ..., None]\n", + " output[c].append(img)\n", + " output[c] = np.concatenate(output[c], axis=0)\n", + " return np.concatenate([output[i], axis=-1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data = load_one_file(fpath)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fobj.metadata['channels']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/denoiser_psnr_comparison.ipynb b/denoisplit/notebooks/denoiser_psnr_comparison.ipynb new file mode 100644 index 0000000..78468fb --- /dev/null +++ b/denoisplit/notebooks/denoiser_psnr_comparison.ipynb @@ -0,0 +1,434 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Objective\n", + "Here, we inspect the denoiser performance. we use the stored prediction files to do that." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "DEBUG=False\n", + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.scripts.evaluate import * \n", + "from denoisplit.config_utils import get_configdir_from_saved_predictionfile, load_config\n", + "from denoisplit.core.data_split_type import DataSplitType\n", + "from denoisplit.core.tiff_reader import load_tiff\n", + "from denoisplit.core.data_split_type import get_datasplit_tuples\n", + "import ml_collections\n", + "\n", + "\n", + "\n", + "# data_dir = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk44/'\n", + "data_dir = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk32'\n", + "# data_dir = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk0'\n", + "denoiser_prediction_fname = \"pred_disentangle_2402_D3-M23-S0-L0_11.tif\"\n", + "channel_idx = 0\n", + "\n", + "# get the prediction. \n", + "pred = load_tiff(os.path.join(data_dir, denoiser_prediction_fname))\n", + "_, _ , test_idx = get_datasplit_tuples(0.1, 0.1, pred.shape[0], starting_test = False)\n", + "test_pred = pred[test_idx]\n", + "denoiser_configdir = get_configdir_from_saved_predictionfile(denoiser_prediction_fname)\n", + "print(denoiser_configdir)\n", + "\n", + "# get the highres data\n", + "denoiser_config = load_config(denoiser_configdir)\n", + "denoiser_config = ml_collections.ConfigDict(denoiser_config)\n", + "if denoiser_config.data.data_type == DataType.BioSR_MRC:\n", + " denoiser_input_dir = '/group/jug/ashesh/data/BioSR/'\n", + "elif denoiser_config.data.data_type == DataType.OptiMEM100_014:\n", + " denoiser_input_dir = '/group/jug/ashesh/data/microscopy/OptiMEM100x014.tif'\n", + "elif denoiser_config.data.data_type == DataType.SeparateTiffData:\n", + " denoiser_input_dir = '/group/jug/ashesh/data/ventura_gigascience/'\n", + " denoiser_config.data.ch1_fname = denoiser_config.data.ch1_fname.replace('lowsnr', 'highsnr')\n", + " denoiser_config.data.ch2_fname = denoiser_config.data.ch2_fname.replace('lowsnr', 'highsnr')\n", + "with denoiser_config.unlocked():\n", + " highres_data = get_data_without_synthetic_noise(denoiser_input_dir, denoiser_config, DataSplitType.Test)\n", + "\n", + "h, w = pred.shape[1:3]\n", + "highres_data = highres_data[:, :h, :w]\n", + "highres_data = highres_data[..., channel_idx].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(8,4),ncols=2)\n", + "ax[0].imshow(test_pred[-1])\n", + "ax[1].imshow(highres_data[-1,...])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.psnr import RangeInvariantPsnr\n", + "print(f'PSNR: {RangeInvariantPsnr(highres_data.astype(np.float32), test_pred.astype(np.float32)).mean().item():.2f}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdn_psnr_dict = {\n", + " \"2402/D16-M23-S0-L0/93\": \"39.230\",\n", + " \"2402/D16-M23-S0-L0/88\": \"43.930\",\n", + " \"2402/D16-M23-S0-L0/94\": \"37.86\",\n", + " \"2402/D16-M23-S0-L0/89\": \"42.1\",\n", + " \"2402/D16-M23-S0-L0/95\": \"36.68\",\n", + " \"2402/D16-M23-S0-L0/87\": \"40.66\",\n", + " \"2402/D16-M23-S0-L0/92\": \"33.38\",\n", + " \"2402/D16-M23-S0-L0/90\": \"29.39\",\n", + " \"2402/D16-M23-S0-L0/104\": \"38.320\",\n", + " \"2402/D16-M23-S0-L0/96\": \"36.48\",\n", + " \"2402/D16-M23-S0-L0/105\": \"36.78\",\n", + " \"2402/D16-M23-S0-L0/97\": \"34.92\",\n", + " \"2402/D16-M23-S0-L0/106\": \"35.43\",\n", + " \"2402/D16-M23-S0-L0/98\": \"33.8\",\n", + " \"2402/D16-M23-S0-L0/107\": \"31.81\",\n", + " \"2402/D16-M23-S0-L0/99\": \"30.32\",\n", + " \"2402/D16-M23-S0-L0/114\": \"44.13\",\n", + " \"2402/D16-M23-S0-L0/101\": \"37.3\",\n", + " \"2402/D16-M23-S0-L0/113\": \"42.21\",\n", + " \"2402/D16-M23-S0-L0/100\": \"36.37\",\n", + " \"2402/D16-M23-S0-L0/117\": \"40.91\",\n", + " \"2402/D16-M23-S0-L0/103\": \"35.18\",\n", + " \"2402/D16-M23-S0-L0/120\": \"29.390\",\n", + " \"2402/D16-M23-S0-L0/102\": \"32.03\",\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import os\n", + "from denoisplit.config_utils import load_config\n", + "dir = '/home/ashesh.ashesh/training/disentangle/'\n", + "class ConfigInfo:\n", + " def __init__(self, config_path) -> None:\n", + " self._config_path = config_path\n", + " self.cfg = self.get_config_from_path(config_path)\n", + "\n", + " def get_config_from_path(self, config_path):\n", + " config_fpath = os.path.join(dir, config_path)\n", + " return load_config(config_fpath)\n", + "\n", + " def get_noise_level(self):\n", + " return self.cfg.data.synthetic_gaussian_scale, self.cfg.data.poisson_noise_factor\n", + " \n", + " def get_channel(self):\n", + " if 'denoise_channel' in self.cfg and self.cfg.model.denoise_channel == 'Ch1':\n", + " return self.cfg.data.ch1_fname\n", + " elif 'denoise_channel' in self.cfg and self.cfg.model.denoise_channel == 'Ch2':\n", + " return self.cfg.data.ch2_fname\n", + " else:\n", + " return [self.cfg.data.ch1_fname, self.cfg.data.ch2_fname]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "hdn_df = pd.DataFrame([], columns=['Gaus', 'Pois', 'Ch', 'PSNR'])\n", + "for key, val in hdn_psnr_dict.items():\n", + " config = ConfigInfo(key)\n", + " hdn_df.loc[key] = [config.get_noise_level()[0], config.get_noise_level()[1], config.get_channel(), float(val)]\n", + " # print(f'{key}: {val} - {config.get_noise_level()} - {config.get_channel()}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdn_df[hdn_df.Ch=='ER/GT_all.mrc'].sort_values('Gaus')['PSNR'].plot(marker='o', linestyle='-', label='ER/GT_all.mrc')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "denoisplit_dict = {\n", + " \"2402/D16-M3-S0-L0/149\": \"[36.79, 38.93]\",\n", + " \"2402/D16-M3-S0-L0/143\": \"[35.36, 37.24]\",\n", + " \"2402/D16-M3-S0-L0/151\": \"[33.96, 36.1]\",\n", + " \"2402/D16-M3-S0-L0/153\": \"[30.47, 31.92]\",\n", + " \"2402/D16-M3-S0-L0/150\":\"[30.2, 29.77]\",\n", + " \"2402/D16-M3-S0-L0/144\":\"[29.2, 28.71]\",\n", + " \"2402/D16-M3-S0-L0/152\": \"[27.42, 26.65]\",\n", + " \"2402/D16-M3-S0-L0/155\": \"[25.19, 24.49]\",\n", + " \"2402/D16-M3-S0-L0/154\": \"[39.9, 36.36]\",\n", + " \"2402/D16-M3-S0-L0/145\": \"[38.44, 34.85]\",\n", + " \"2402/D16-M3-S0-L0/156\": \"[36.82, 33.51]\",\n", + " \"2402/D16-M3-S0-L0/157\": \"[32.24, 29.07]\"\n", + "\n", + "}\n", + "df_denoisplit = pd.DataFrame([], columns=['Gaus', 'Pois', 'Ch', 'PSNR'])\n", + "for key, val in denoisplit_dict.items():\n", + " config = ConfigInfo(key)\n", + " val = json.loads(val)\n", + " for ch_idx in [0,1]:\n", + " k = f'{key}_Ch{ch_idx}'\n", + " df_denoisplit.loc[k] = [config.get_noise_level()[0], config.get_noise_level()[1], config.get_channel()[ch_idx], val[ch_idx]]\n", + " # print(f'{key}: {val} - {config.get_noise_level()} - {config.get_channel()}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_denoisplit = df_denoisplit.set_index(['Gaus','Pois','Ch'])\n", + "df_hdn = hdn_df.set_index(['Gaus','Pois','Ch'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.merge(df_denoisplit, df_hdn, left_index=True, right_index=True, suffixes=('_denoisplit', '_hdn'))\n", + "df = df.reset_index()\n", + "df.Ch = df.Ch.map(lambda x: x.replace('GT_all.mrc','').replace('/',''))\n", + "\n", + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch=='ER'].sort_values('Gaus')[['Gaus', 'PSNR_denoisplit', 'PSNR_hdn']]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch=='ER'][df.Gaus.isin([3400, 5100, 6800, 13600])][['PSNR_denoisplit', 'PSNR_hdn']].plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch=='ER/GT_all.mrc'][df.Gaus.isin([4450, 6675,8900,17800])][['PSNR_denoisplit', 'PSNR_hdn']].plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch=='Microtubules'].sort_values('Gaus')[['Gaus', 'PSNR_denoisplit', 'PSNR_hdn']]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch=='Microtubules'][df.Gaus.isin([4450, 6675,8900,17800])][['PSNR_denoisplit', 'PSNR_hdn']].plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch=='Microtubules'][df.Gaus.isin([3150, 4725,6300,12600])][['PSNR_denoisplit', 'PSNR_hdn']].plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch=='CCPs'].sort_values('Gaus')[['Gaus', 'PSNR_denoisplit', 'PSNR_hdn']]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch=='CCPs'][df.Gaus.isin([3150, 4725,6300,12600])][['PSNR_denoisplit', 'PSNR_hdn']].plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch=='CCPs'][df.Gaus.isin([3400, 5100, 6800, 13600])][['PSNR_denoisplit', 'PSNR_hdn']].plot(linestyle='-', marker='o')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df[df.Ch == 'ER']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "params = {'mathtext.default': 'regular' } \n", + "plt.rcParams.update(params)\n", + "\n", + "_,ax = plt.subplots(figsize=(12,3),ncols=3)\n", + "# ER\n", + "df[df.Ch == 'ER'].sort_values('Gaus').plot(x='Gaus', y='PSNR_hdn', ax=ax[0], linestyle='-', marker='*', label='HDN')\n", + "df[df.Ch=='ER'][df.Gaus.isin([4450, 6675,8900,17800])].plot(x='Gaus', y='PSNR_denoisplit', ax=ax[0], linestyle='-', marker='^', label='ER vs MT')\n", + "df[df.Ch=='ER'][df.Gaus.isin([3400, 5100,6800,13600])].plot(x='Gaus', y='PSNR_denoisplit', ax=ax[0], linestyle='-', marker='^', label='CCPs vs ER')\n", + "\n", + "# Microtubules\n", + "df[df.Ch == 'Microtubules'].sort_values('Gaus').plot(x='Gaus', y='PSNR_hdn', ax=ax[1], linestyle='-', marker='*', label='HDN')\n", + "df[df.Ch=='Microtubules'][df.Gaus.isin([4450, 6675,8900,17800])].plot(x='Gaus', y='PSNR_denoisplit', ax=ax[1], linestyle='-', marker='^', label='ER vs MT')\n", + "df[df.Ch=='Microtubules'][df.Gaus.isin([3150, 4725,6300,12600])].plot(x='Gaus', y='PSNR_denoisplit', ax=ax[1], linestyle='-', marker='^', label='CCPs vs MT')\n", + "\n", + "# CCPs\n", + "df[df.Ch == 'CCPs'].sort_values('Gaus').plot(x='Gaus', y='PSNR_hdn', ax=ax[2], linestyle='-', marker='*', label='HDN')\n", + "df[df.Ch=='CCPs'][df.Gaus.isin([3150, 4725,6300,12600])].plot(x='Gaus', y='PSNR_denoisplit', ax=ax[2], linestyle='-', marker='^', label='CCPs vs MT')\n", + "df[df.Ch=='CCPs'][df.Gaus.isin([3400, 5100,6800,13600])].plot(x='Gaus', y='PSNR_denoisplit', ax=ax[2], linestyle='-', marker='^', label='CCPs vs ER')\n", + "ax[2].legend(loc='upper right')\n", + "\n", + "ax[0].set_xlabel(f'$Gaussian\\ \\sigma$')\n", + "ax[1].set_xlabel(f'$Gaussian\\ \\sigma$')\n", + "ax[2].set_xlabel(f'$Gaussian\\ \\sigma$')\n", + "ax[0].set_ylabel(f'PSNR')\n", + "\n", + "ax[0].set_ylim(24,44.7)\n", + "ax[1].set_ylim(24,44.7)\n", + "ax[2].set_ylim(24,44.7)\n", + "\n", + "# ax[0].set_xlim(3000, 18000)\n", + "# ax[1].set_xlim(3000, 18000)\n", + "# ax[2].set_xlim(3000, 18000)\n", + "\n", + "ax[1].set_yticklabels([])\n", + "ax[2].set_yticklabels([])\n", + "\n", + "ax[0].set_title('ER')\n", + "ax[1].set_title('Microtubules')\n", + "ax[2].set_title('CCPs')\n", + "\n", + "ax[0].yaxis.grid(color='gray', linestyle='dashed')\n", + "ax[0].xaxis.grid(color='gray', linestyle='dashed')\n", + "ax[0].set_facecolor('xkcd:light grey')\n", + "\n", + "ax[1].yaxis.grid(color='gray', linestyle='dashed')\n", + "ax[1].xaxis.grid(color='gray', linestyle='dashed')\n", + "ax[1].set_facecolor('xkcd:light grey')\n", + "\n", + "ax[2].yaxis.grid(color='gray', linestyle='dashed')\n", + "ax[2].xaxis.grid(color='gray', linestyle='dashed')\n", + "ax[2].set_facecolor('xkcd:light grey')\n", + "paper_figures_dir = '/group/jug/ashesh/data/paper_figures'\n", + "fpath = os.path.join(paper_figures_dir, 'hdn_denoisplit_comparison.png')\n", + "plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + "print('Saved to:', fpath)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/full_image_plots.ipynb b/denoisplit/notebooks/full_image_plots.ipynb new file mode 100644 index 0000000..4002ffc --- /dev/null +++ b/denoisplit/notebooks/full_image_plots.ipynb @@ -0,0 +1,831 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "DEBUG = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.plot_utils import clean_ax\n", + "from denoisplit.core.tiff_reader import load_tiff\n", + "from denoisplit.config_utils import load_config, get_configdir_from_saved_predictionfile\n", + "from denoisplit.core.data_split_type import DataSplitType\n", + "from denoisplit.scripts.evaluate import get_highsnr_data\n", + "import ml_collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + " # '/home/ashesh.ashesh/training/disentangle/2402/D16-M3-S0-L0/128',\n", + " # '/home/ashesh.ashesh/training/disentangle/2402/D16-M3-S0-L0/144',\n", + "# 2402/D16-M3-S0-L0/144\n", + " # '/home/ashesh.ashesh/training/disentangle/2402/D16-M3-S0-L0/145'\n", + "\n", + " # '/home/ashesh.ashesh/training/disentangle/2402/D16-M3-S0-L0/165',\n", + " # '/home/ashesh.ashesh/training/disentangle/2402/D16-M3-S0-L0/164',\n", + " # '/home/ashesh.ashesh/training/disentangle/2402/D16-M3-S0-L0/169',\n", + "\n", + "noise_levels = ['realnoise_hagen']\n", + "pred_dir = '/group/jug/ashesh/data/paper_stats/'\n", + "\n", + "usplit_fname = {5100: 'Test_P64_G32_M5_Sk44/pred_disentangle_2402_D16-M3-S0-L0_165.tif',\n", + " # 6675: 'Test_P64_G32_M5_Sk44/pred_disentangle_2402_D16-M3-S0-L0_164.tif',\n", + " # 6675: 'Test_P64_G32_M5_Sk44/pred_disentangle_colorfuljug_2403_D16-M3-S0-L0_1.tif',\n", + " # 4725: 'Test_P64_G32_M5_Sk44/pred_disentangle_2402_D16-M3-S0-L0_169.tif',\n", + " 228: 'Test_PNone_G32_M10_Sk0/pred_disentangle_2403_D23-M3-S0-L0_0.tif',\n", + " # 4575: 'turing/Test_P64_G32_M10_Sk44/pred_training_disentangle_2403_D16-M3-S0-L0_3.tif'\n", + " # 6450:'Test_P64_G32_M50_Sk44/pred_disentangle_2403_D16-M3-S0-L0_35.tif',\n", + " 'realnoise_hagen': 'Test_P64_G32_M50_Sk0/kth_1/pred_disentangle_2402_D7-M3-S0-L0_82.tif'\n", + " \n", + " }\n", + "\n", + "denoiSplitNM_fname = {\n", + " 5100: 'Test_P128_G64_M5_Sk44/pred_disentangle_2402_D16-M3-S0-L0_128.tif',\n", + " # 6675: 'Test_P128_G64_M5_Sk44/pred_disentangle_2402_D16-M3-S0-L0_144.tif', \n", + " # 6675: 'Test_P128_G64_M50_Sk44/pred_disentangle_2403_D16-M3-S0-L0_25.tif',\n", + " # 4725: 'Test_P128_G64_M5_Sk44/pred_disentangle_2402_D16-M3-S0-L0_145.tif',\n", + " # 228: 'Test_P128_G32_M10_Sk32/pred_disentangle_2402_D3-M3-S0-L0_32.tif',\n", + " # 228: 'Test_PNone_G32_M5_Sk0/pred_disentangle_2403_D23-M3-S0-L0_29.tif'\n", + " # 4575: 'Test_P128_G64_M50_Sk44/pred_disentangle_2403_D16-M3-S0-L0_83.tif' \n", + " # 6450: 'Test_P128_G64_M50_Sk44/pred_disentangle_2403_D16-M3-S0-L0_39.tif'\n", + " # 6450: 'Test_P128_G16_M50_Sk44/kth_0/pred_disentangle_2403_D16-M3-S0-L0_39.tif',\n", + " 'realnoise_hagen': 'Test_P128_G64_M50_Sk0/kth_1/pred_disentangle_2402_D7-M3-S0-L0_108.tif'\n", + " \n", + " }\n", + "hdn_usplit = {} #{4450: 'pred_disentangle_2402_D23-M3-S0-L0_34.tif'}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _noise_model_path(nmodel_dir):\n", + " histfpath = None\n", + " gmmfpath = None\n", + " for fname in os.listdir(nmodel_dir):\n", + " if fname.startswith('HistNoiseModel'):\n", + " histfpath = os.path.join(nmodel_dir,fname)\n", + " elif fname.startswith('GMMNoiseModel'):\n", + " gmmfpath = os.path.join(nmodel_dir,fname)\n", + " return {'gmm':gmmfpath, 'hist':histfpath}\n", + "\n", + "def noise_model_paths(pred_file_name):\n", + " \"\"\"\n", + " denoiSplitNM_fname[noise_levels[0]]\n", + " \"\"\"\n", + " cfg = load_config(get_configdir_from_saved_predictionfile(pred_file_name))\n", + " nmodel1_fpath_dict = None\n", + " nmodel2_fpath_dict = None\n", + " if 'noise_model_ch1_fpath' in cfg.model and cfg.model.noise_model_ch1_fpath is not None:\n", + " nmodel1_fpath_dict = _noise_model_path(os.path.dirname(cfg.model.noise_model_ch1_fpath))\n", + " if 'noise_model_ch2_fpath' in cfg.model and cfg.model.noise_model_ch2_fpath is not None:\n", + " nmodel2_fpath_dict = _noise_model_path(os.path.dirname(cfg.model.noise_model_ch2_fpath))\n", + " return nmodel1_fpath_dict, nmodel2_fpath_dict\n", + "\n", + "def _get_noise_model(nmodel_fpath_dict):\n", + " from denoisplit.nets.gmm_noise_model import GaussianMixtureNoiseModel\n", + " from denoisplit.nets.hist_noise_model import HistNoiseModel\n", + " nmodel_params = np.load(nmodel_fpath_dict['gmm'])\n", + " gmm_model1 = GaussianMixtureNoiseModel(params=nmodel_params)\n", + " \n", + " histdata = np.load(nmodel_fpath_dict['hist'])\n", + " hist_model = HistNoiseModel(histdata)\n", + " return {'gmm':gmm_model1, 'hist':hist_model}\n", + "\n", + "def get_noise_models(pred_file_name):\n", + " nmodel1_fpath_dict, nmodel2_fpath_dict = noise_model_paths(pred_file_name)\n", + " nmodel1 = _get_noise_model(nmodel1_fpath_dict)\n", + " nmodel2 = _get_noise_model(nmodel2_fpath_dict)\n", + " return nmodel1, nmodel2\n", + "\n", + "nmodel1, nmodel2 = get_noise_models(denoiSplitNM_fname[noise_levels[0]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import numpy as np\n", + "from denoisplit.analysis.plot_utils import add_subplot_axes\n", + "\n", + "def get_signal_from_index(signalBinIndex, n_bin, min_signal, max_signal, histBinSize):\n", + " querySignal_numpy = (signalBinIndex / float(n_bin) * (max_signal - min_signal) + min_signal)\n", + " querySignal_numpy += histBinSize / 2\n", + " querySignal_torch = torch.from_numpy(np.array(querySignal_numpy)).float()\n", + " return querySignal_torch\n", + "\n", + "def get_scaled_pdf(pdf, axymax, axymin, yval, factor=0.2):\n", + " scaled_pdf = pdf/pdf.max()\n", + " scaled_pdf = scaled_pdf - scaled_pdf.min()\n", + " scaled_pdf = scaled_pdf * (axymax - axymin)*factor + yval\n", + " return scaled_pdf\n", + "\n", + "\n", + "# def add_signal_value(ax, signal)\n", + "\n", + "def plot_noise_model(signal1_index, signal2_index, histogramNoiseModel, gaussianMixtureNoiseModel, device, ax, linetxt_offset = 0.1):\n", + " \"\"\"Plots probability distribution P(x|s) for a certain ground truth signal.\n", + " Predictions from both Histogram and GMM-based Noise models are displayed for comparison.\n", + " Parameters\n", + " ----------\n", + " signalBinIndex: int\n", + " index of signal bin. Values go from 0 to number of bins (`n_bin`).\n", + " histogramNoiseModel: Histogram based noise model\n", + " gaussianMixtureNoiseModel: GaussianMixtureNoiseModel\n", + " Object containing trained parameters.\n", + " device: GPU device\n", + " \"\"\"\n", + " max_signal = histogramNoiseModel.maxv.item()\n", + " min_signal = histogramNoiseModel.minv.item()\n", + " n_bin = int(histogramNoiseModel.bins.item())\n", + "\n", + " histBinSize = (max_signal - min_signal) / n_bin\n", + " signal1 = get_signal_from_index(signal1_index, n_bin, min_signal, max_signal, histBinSize).to(device)\n", + " signal2 = None\n", + " if signal2_index is not None:\n", + " signal2 = get_signal_from_index(signal2_index, n_bin, min_signal, max_signal, histBinSize).to(device)\n", + "\n", + " queryObservations_numpy = np.arange(min_signal, max_signal, histBinSize)\n", + " queryObservations_numpy += histBinSize / 2\n", + " queryObservations = torch.from_numpy(queryObservations_numpy).float().to(device)\n", + " \n", + " gmm_pdf1 = gaussianMixtureNoiseModel.likelihood(queryObservations, signal1)\n", + " gmm_pdf1 = gmm_pdf1.detach().cpu().numpy()\n", + "\n", + " gmm_pdf2 = None\n", + " if signal2 is not None:\n", + " gmm_pdf2 = gaussianMixtureNoiseModel.likelihood(queryObservations, signal2)\n", + " gmm_pdf2 = gmm_pdf2.detach().cpu().numpy()\n", + "\n", + " # plt.figure(figsize=(12, 5))\n", + "\n", + " # plt.subplot(1, 2, 1)\n", + " # plt.xlabel('Observation Bin')\n", + " # plt.ylabel('Signal Bin')\n", + " histogram = histogramNoiseModel.fullHist.cpu().numpy()\n", + " ax.imshow(histogram**0.25, cmap='gray', aspect='auto')\n", + " yval1 = signal1_index + 0.5\n", + " yval2 = signal2_index + 0.5 if signal2 is not None else None\n", + " ax.axhline(y=yval1, linewidth=1, color='green', linestyle='--', alpha=0.5, label=f'{signal1.cpu().numpy():.1f}')\n", + " if signal2 is not None:\n", + " ax.axhline(y=yval2, linewidth=1, color='green', linestyle='--', alpha=0.5, label=f'{signal2.cpu().numpy():.1f}')\n", + "\n", + " # plt.subplot(1, 2, 2)\n", + " # hist_pdf1 = histogramNoiseModel.likelihood(queryObservations, signal1).cpu().numpy()\n", + " # hist_pdf2 = histogramNoiseModel.likelihood(queryObservations, signal2).cpu().numpy() if signal2 is not None else None\n", + " ymin, ymax = ax.get_ylim()\n", + "\n", + " pdf1 = get_scaled_pdf(gmm_pdf1, ymax, ymin, yval1)\n", + " pdf2 = None\n", + " if signal2 is not None:\n", + " pdf2 = get_scaled_pdf(gmm_pdf2, ymax, ymin, yval2)\n", + "\n", + " step = histogram.shape[1]/pdf1.shape[0]\n", + " x = np.arange(0, histogram.shape[1], step=step)\n", + " ax.plot(x, pdf1, color='green')\n", + " \n", + " if signal2 is not None:\n", + " ax.plot(x, pdf2, color='green')\n", + " \n", + " ymin, ymax = ax.get_ylim()\n", + " print(ymin, ymax)\n", + " props = dict(alpha=0)\n", + " fact1 = (signal1_index - ymin)/(ymax - ymin) + linetxt_offset\n", + " ax.text(0.77, fact1, f'{signal1.cpu().numpy():.0f}', transform=ax.transAxes, fontsize=10,\n", + " verticalalignment='top', bbox=props, color='green')\n", + " if signal2 is not None:\n", + " fact2 = (signal2_index - ymin)/(ymax - ymin) + linetxt_offset\n", + " ax.text(0.02, fact2, f'{signal2.cpu().numpy():.0f}', transform=ax.transAxes, fontsize=10,\n", + " verticalalignment='top', bbox=props, color='green')\n", + "\n", + " # ax.legend(frameon=False, labelcolor='white', loc='upper right')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_, ax = plt.subplots(figsize=(6,3))\n", + "plot_noise_model(25, None, nmodel2['hist'], nmodel2['gmm'], 'cpu', ax, linetxt_offset=0.2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# from denoisplit.utils import plotProbabilityDistribution\n", + "# signalBinIndex=60\n", + "# data_dict = plotProbabilityDistribution(signalBinIndex=signalBinIndex, \n", + "# histogramNoiseModel=nmodel2['hist'],\n", + "# gaussianMixtureNoiseModel=nmodel2['gmm'],\n", + "# device='cpu')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def sanity_check_config():\n", + " data_dicts = [usplit_fname, denoiSplitNM_fname]\n", + " for ith_data, ddict in enumerate(data_dicts):\n", + " for noise,fname in ddict.items():\n", + " configdir = get_configdir_from_saved_predictionfile(fname)\n", + " config = load_config(configdir)\n", + " assert 'synthetic_gaussian_scale' in config.data\n", + " assert config.data.synthetic_gaussian_scale == noise, f'{ith_data} {fname}: noise: {noise}, config: {config.data.synthetic_gaussian_scale}'\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sanity_check_config()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Loading target" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "configdir = get_configdir_from_saved_predictionfile(denoiSplitNM_fname[noise_levels[0]])\n", + "config = ml_collections.ConfigDict(load_config(configdir))\n", + "highsnr_data = get_highsnr_data(config, config.datadir, DataSplitType.Test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Loading predictions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "usplit_data = {k: load_tiff(os.path.join(pred_dir, v)) for k,v in usplit_fname.items()}\n", + "denoiSplitNM_data = {k: load_tiff(os.path.join(pred_dir, v)) for k,v in denoiSplitNM_fname.items()}\n", + "hdn_usplit_data = {k: load_tiff(os.path.join(pred_dir, v)) for k,v in hdn_usplit.items()}\n", + "\n", + "# Undoing the offset.\n", + "for k,v in usplit_fname.items():\n", + " with open(os.path.join(pred_dir, v.replace('.tif', '.json')),'rb') as f:\n", + " offset = float(json.load(f)['offset'])\n", + " usplit_data[k] = usplit_data[k] + offset\n", + "\n", + "for k,v in denoiSplitNM_fname.items():\n", + " with open(os.path.join(pred_dir, v.replace('.tif', '.json')),'rb') as f:\n", + " offset = float(json.load(f)['offset'])\n", + " denoiSplitNM_data[k] = denoiSplitNM_data[k] + offset\n", + "\n", + "if 4575 in usplit_data:\n", + " usplit_data[4575] = usplit_data[4575][...,::-1].copy()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Cropping the target to get to the same shape as the predictions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "shape = usplit_data[noise_levels[0]].shape\n", + "highsnr_data = highsnr_data[:, :shape[1], :shape[2]].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "highsnr_data = highsnr_data[1:2].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def sanity_check_data():\n", + " # all shapes should be same\n", + " for noise_level in noise_levels:\n", + " shape = usplit_data[noise_level].shape\n", + " if noise_level in denoiSplitNM_data:\n", + " assert shape == denoiSplitNM_data[noise_level].shape\n", + " if noise_level in hdn_usplit_data:\n", + " assert shape == hdn_usplit_data[noise_level].shape\n", + " assert shape == highsnr_data.shape, f'{shape} {highsnr_data.shape}'\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# # denoiSplitNM_data[noise_levels[0]]\n", + "# highsnr_data = highsnr_data[:1].copy()\n", + "# usplit_data[noise_levels[0]] = usplit_data[noise_levels[0]][:1].copy()\n", + "# usplit_data[noise_levels[0]] = usplit_data[noise_levels[0]][...,::-1].copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sanity_check_data()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "paper_figures_dir = '/group/jug/ashesh/data/paper_figures'\n", + "def get_output_fpath(noise_level):\n", + " if 'ch1_fname' in config.data:\n", + " ch1str = config.data.ch1_fname.split('.')[0].replace('/','').replace('GT_all', '')\n", + " ch2str = config.data.ch2_fname.split('.')[0].replace('/','').replace('GT_all', '')\n", + " else:\n", + " ch1str = config.data.channel_1\n", + " ch2str = config.data.channel_2\n", + " modelid = config.workdir.strip('/').split('/')[-1]\n", + "\n", + " output_filepath =os.path.join(paper_figures_dir, f'{modelid}_{noise_level}_{ch1str}_{ch2str}.png')\n", + " output_filepath\n", + " return output_filepath" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "def get_noisy_data(noise_level):\n", + " if noise_level == 'realnoise_hagen':\n", + " actin = load_tiff('/group/jug/ashesh/data/ventura_gigascience/actin-60x-noise2-lowsnr.tif')\n", + " actin = actin[:shape[0], :shape[1], :shape[2],None].copy()\n", + " mito = load_tiff('/group/jug/ashesh/data/ventura_gigascience/mito-60x-noise2-lowsnr.tif')\n", + " mito = mito[:shape[0], :shape[1], :shape[2], None].copy()\n", + " hagen_noisy_data = np.concatenate([actin, mito], axis=-1)\n", + " return hagen_noisy_data\n", + " \n", + " return highsnr_data + np.random.normal(0, noise_level, highsnr_data.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib.gridspec import GridSpec\n", + "import matplotlib.pyplot as plt\n", + "from denoisplit.analysis.plot_utils import add_pixel_kde, clean_ax\n", + "from denoisplit.core.psnr import RangeInvariantPsnr\n", + "import seaborn as sns \n", + "\n", + "#### inset specific\n", + "inset_rect=[0.05, 0.05, 0.4, 0.2]\n", + "inset_min_labelsize=10\n", + "color_ch_list=['goldenrod', 'cyan']\n", + "color_pred='red'\n", + "# insetplot_xmax_value = 30000\n", + "# insetplot_xmin_value = -8000\n", + "# paviaatn \n", + "insetplot_xmax_value = 200\n", + "insetplot_xmin_value = 0\n", + "\n", + "plt_dsample = 1\n", + "####\n", + "data_idx = 0\n", + "img_sz = 3\n", + "ncol_imgs = 5\n", + "nrow_imgs = 2\n", + "example_spacing = 1\n", + "grid_factor = 5\n", + "nimgs = 1\n", + "noise_level = noise_levels[0]\n", + "# extra spacing for c0. It does not work. Don't know why. I think there is some integer division happening.\n", + "c0_extra = 1\n", + "\n", + "noisy_data = get_noisy_data(noise_level)\n", + "\n", + "# for subscripts and superscripts\n", + "params = {'mathtext.default': 'regular' } \n", + "plt.rcParams.update(params)\n", + "\n", + "def get_psnr_str(prediction, ch_idx):\n", + " return f'{RangeInvariantPsnr(highsnr_data[data_idx,...,ch_idx][None], prediction[data_idx,...,ch_idx][None]).item():.1f}' \n", + "\n", + "def add_psnr_str(ax_, psnr):\n", + " \"\"\"\n", + " Add psnr string to the axes\n", + " \"\"\"\n", + " textstr = f'PSNR\\n{psnr}'\n", + " props = dict(\n", + " boxstyle='round', \n", + " facecolor='gray', alpha=0.3)\n", + " # place a text box in upper left in axes coords\n", + " ax_.text(0.05, 0.95, textstr, transform=ax_.transAxes, fontsize=11,\n", + " verticalalignment='top', bbox=props, color='white')\n", + "\n", + "# extra spacing for the first and the last column.\n", + "fig_w = ncol_imgs * img_sz + 2*c0_extra/grid_factor\n", + "fig_h = int(img_sz * nrow_imgs + (example_spacing * (nimgs - 1)) / grid_factor )\n", + "fig = plt.figure(figsize=(fig_w, fig_h))\n", + "gs = GridSpec(nrows=int(grid_factor * fig_h), ncols=int(grid_factor * fig_w), hspace=0.2, wspace=0.2)\n", + "grid_img_sz = img_sz * grid_factor\n", + "\n", + "# input\n", + "ax_temp = fig.add_subplot(gs[:grid_img_sz,:grid_img_sz])\n", + "ax_temp.imshow(np.mean(noisy_data[data_idx], axis=-1), cmap='magma')\n", + "legend_ax = ax_temp\n", + "\n", + "clean_ax(ax_temp)\n", + "\n", + "# ax[0,0].set_title('Input')\n", + "ax_temp = fig.add_subplot(gs[:grid_img_sz, (c0_extra+grid_img_sz):(c0_extra + grid_img_sz * 2)])\n", + "ax_temp.imshow(noisy_data[data_idx,:,:,0], cmap='magma')\n", + "inset_ax = add_pixel_kde(ax_temp,\n", + " inset_rect,\n", + " [noisy_data[data_idx,::plt_dsample,::plt_dsample,0],\n", + " highsnr_data[data_idx,::plt_dsample,::plt_dsample,0]],\n", + " inset_min_labelsize,\n", + " label_list=['NoisyCh1','Ch1'],\n", + " plot_kwargs_list=[{'linestyle':'--'}, {}],\n", + " color_list=[color_ch_list[0],color_ch_list[0]],\n", + " plot_xmax_value=insetplot_xmax_value,\n", + " plot_xmin_value=insetplot_xmin_value)\n", + "inset_ax.set_xticks([])\n", + "inset_ax.set_yticks([])\n", + "clean_ax(ax_temp)\n", + "\n", + "ax_temp = fig.add_subplot(gs[grid_img_sz:grid_img_sz * 2, c0_extra+grid_img_sz:c0_extra + grid_img_sz * 2])\n", + "ax_temp.imshow(noisy_data[data_idx,:,:,1], cmap='magma')\n", + "inset_ax = add_pixel_kde(ax_temp,\n", + " inset_rect,\n", + " [noisy_data[data_idx,::plt_dsample,::plt_dsample,1],\n", + " highsnr_data[data_idx,::plt_dsample,::plt_dsample,1]],\n", + " inset_min_labelsize,\n", + " label_list=['NoisyCh2','Ch2'],\n", + " color_list=[color_ch_list[1],color_ch_list[1]],\n", + " plot_kwargs_list=[{'linestyle':'--'},{}],\n", + " plot_xmax_value=insetplot_xmax_value,\n", + " plot_xmin_value=insetplot_xmin_value)\n", + "inset_ax.set_xticks([])\n", + "inset_ax.set_yticks([])\n", + "clean_ax(ax_temp)\n", + "\n", + "ax_temp = fig.add_subplot(gs[:grid_img_sz, c0_extra+grid_img_sz * 2:c0_extra+grid_img_sz * 3])\n", + "ax_temp.imshow(usplit_data[noise_level][data_idx,...,0], cmap='magma')\n", + "# inset_ax = add_pixel_kde(ax_temp,\n", + "# inset_rect,\n", + "# [highsnr_data[data_idx,::plt_dsample,::plt_dsample,0],\n", + "# noisy_data[data_idx,::plt_dsample,::plt_dsample,0],\n", + "# usplit_data[noise_level][data_idx,::plt_dsample,::plt_dsample,0]],\n", + "# inset_min_labelsize,\n", + "# label_list=['Ch1','input', 'Pred1'],\n", + "# color_list=[color_ch_list[0],color_ch_list[0], color_pred],\n", + "# plot_kwargs_list=[{},{'linestyle':'--'},{}],\n", + "# plot_xmax_value=insetplot_xmax_value,\n", + "# plot_xmin_value=insetplot_xmin_value)\n", + "inset_ax = add_pixel_kde(ax_temp,\n", + " inset_rect,\n", + " [highsnr_data[data_idx,::plt_dsample,::plt_dsample,0],\n", + " usplit_data[noise_level][data_idx,::plt_dsample,::plt_dsample,0]],\n", + " inset_min_labelsize,\n", + " label_list=['Ch1', 'Pred1'],\n", + " color_list=[color_ch_list[0], color_pred],\n", + " # plot_kwargs_list=[{},{'linestyle':'--'},{}],\n", + " plot_xmax_value=insetplot_xmax_value,\n", + " plot_xmin_value=insetplot_xmin_value)\n", + "\n", + "# adding input to the inset.\n", + "# sns.kdeplot(data=,\n", + "# ax=inset_ax,\n", + "# color=color_ch_list[0],\n", + "# label='',\n", + "# clip=(insetplot_xmin_value, None),\n", + "# )\n", + "\n", + "inset_ax.set_xticks([])\n", + "inset_ax.set_yticks([])\n", + "add_psnr_str(ax_temp, get_psnr_str(usplit_data[noise_level], 0))\n", + "clean_ax(ax_temp)\n", + "\n", + "ax_temp = fig.add_subplot(gs[grid_img_sz:grid_img_sz * 2,c0_extra+grid_img_sz * 2:c0_extra+grid_img_sz * 3])\n", + "ax_temp.imshow(usplit_data[noise_level][data_idx,...,1], cmap='magma')\n", + "# inset_ax = add_pixel_kde(ax_temp,\n", + "# inset_rect,\n", + "# [highsnr_data[data_idx,::plt_dsample,::plt_dsample,1],\n", + "# noisy_data[data_idx,::plt_dsample,::plt_dsample,1],\n", + "# usplit_data[noise_level][data_idx,::plt_dsample,::plt_dsample,1]],\n", + "# inset_min_labelsize,\n", + "# label_list=['Ch2','input','Pred2'],\n", + "# color_list=[color_ch_list[1],color_ch_list[1], color_pred],\n", + "# plot_kwargs_list=[{},{'linestyle':'--'},{}],\n", + "# plot_xmax_value=insetplot_xmax_value,\n", + "# plot_xmin_value=insetplot_xmin_value)\n", + "inset_ax = add_pixel_kde(ax_temp,\n", + " inset_rect,\n", + " [highsnr_data[data_idx,::plt_dsample,::plt_dsample,1],\n", + " # noisy_data[data_idx,::plt_dsample,::plt_dsample,1],\n", + " usplit_data[noise_level][data_idx,::plt_dsample,::plt_dsample,1]],\n", + " inset_min_labelsize,\n", + " label_list=['Ch2','Pred2'],\n", + " color_list=[color_ch_list[1], color_pred],\n", + " # plot_kwargs_list=[{},{'linestyle':'--'},{}],\n", + " plot_xmax_value=insetplot_xmax_value,\n", + " plot_xmin_value=insetplot_xmin_value)\n", + "inset_ax.set_xticks([])\n", + "inset_ax.set_yticks([])\n", + "add_psnr_str(ax_temp, get_psnr_str(usplit_data[noise_level], 1))\n", + "clean_ax(ax_temp)\n", + "\n", + "ax_temp = fig.add_subplot(gs[:grid_img_sz, c0_extra+grid_img_sz * 3:c0_extra+grid_img_sz * 4])\n", + "ax_temp.imshow(denoiSplitNM_data[noise_level][data_idx,...,0], cmap='magma')\n", + "inset_ax = add_pixel_kde(ax_temp,\n", + " inset_rect,\n", + " [highsnr_data[data_idx,::plt_dsample,::plt_dsample,0],\n", + " denoiSplitNM_data[noise_level][data_idx,::plt_dsample,::plt_dsample,0]],\n", + " inset_min_labelsize,\n", + " label_list=['Ch1','Pred1'],\n", + " color_list=[color_ch_list[0],color_pred],\n", + " plot_xmax_value=insetplot_xmax_value,\n", + " plot_xmin_value=insetplot_xmin_value)\n", + "inset_ax.set_xticks([])\n", + "inset_ax.set_yticks([])\n", + "\n", + "add_psnr_str(ax_temp, get_psnr_str(denoiSplitNM_data[noise_level], 0))\n", + "clean_ax(ax_temp)\n", + "ax_temp = fig.add_subplot(gs[grid_img_sz:grid_img_sz * 2, c0_extra+grid_img_sz * 3:c0_extra+grid_img_sz * 4])\n", + "ax_temp.imshow(denoiSplitNM_data[noise_level][data_idx,...,1], cmap='magma')\n", + "inset_ax = add_pixel_kde(ax_temp,\n", + " inset_rect,\n", + " [highsnr_data[data_idx,::plt_dsample,::plt_dsample,1],\n", + " denoiSplitNM_data[noise_level][data_idx,::plt_dsample,::plt_dsample,1]],\n", + " inset_min_labelsize,\n", + " label_list=['Ch2','Pred2'],\n", + " color_list=[color_ch_list[1],color_pred],\n", + " plot_xmax_value=insetplot_xmax_value,\n", + " plot_xmin_value=insetplot_xmin_value)\n", + "inset_ax.set_xticks([])\n", + "inset_ax.set_yticks([])\n", + "\n", + "add_psnr_str(ax_temp, get_psnr_str(denoiSplitNM_data[noise_level], 1))\n", + "clean_ax(ax_temp)\n", + "\n", + "ax_temp = fig.add_subplot(gs[:grid_img_sz, 2*c0_extra+grid_img_sz * 4:2*c0_extra+grid_img_sz * 5])\n", + "ax_temp.imshow(highsnr_data[data_idx,...,0], cmap='magma')\n", + "legend_ch1_ax = ax_temp\n", + "inset_ax = add_pixel_kde(ax_temp,\n", + " inset_rect,\n", + " [highsnr_data[data_idx,::plt_dsample,::plt_dsample,0]],\n", + " inset_min_labelsize,\n", + " label_list=['Ch1'],\n", + " color_list=[color_ch_list[0]],\n", + " plot_xmax_value=insetplot_xmax_value,\n", + " plot_xmin_value=insetplot_xmin_value)\n", + "\n", + "inset_ax.set_xticks([])\n", + "inset_ax.set_yticks([])\n", + "\n", + "clean_ax(ax_temp)\n", + "\n", + "\n", + "ax_temp = fig.add_subplot(gs[grid_img_sz:grid_img_sz * 2, 2*c0_extra+grid_img_sz * 4:2*c0_extra+grid_img_sz * 5])\n", + "ax_temp.imshow(highsnr_data[data_idx,...,1], cmap='magma')\n", + "inset_ax = add_pixel_kde(ax_temp,\n", + " inset_rect,\n", + " [highsnr_data[data_idx,::plt_dsample,::plt_dsample,1]],\n", + " inset_min_labelsize,\n", + " label_list=['Ch2'],\n", + " color_list=[color_ch_list[1]],\n", + " plot_xmax_value=insetplot_xmax_value,\n", + " plot_xmin_value=insetplot_xmin_value)\n", + "legend_ch2_ax = ax_temp\n", + "\n", + "inset_ax.set_xticks([])\n", + "inset_ax.set_yticks([])\n", + "\n", + "clean_ax(ax_temp)\n", + "\n", + "# add noise models. \n", + "nmodel1, nmodel2 = get_noise_models(denoiSplitNM_fname[noise_level])\n", + "\n", + "ax_temp = fig.add_subplot(gs[grid_img_sz+1:int(grid_img_sz * 3/2) -1, 2:grid_img_sz])\n", + "# ax_temp = fig.add_subplot(gs[grid_img_sz+grid_img_sz//4:grid_img_sz//4 + int(grid_img_sz * 3/2)+1, 1:1+grid_img_sz//2])\n", + "clean_ax(ax_temp)\n", + "plot_noise_model(40, 90, nmodel1['hist'], nmodel1['gmm'], 'cpu', ax_temp, linetxt_offset=0.2)\n", + "\n", + "ax_temp = fig.add_subplot(gs[int(grid_img_sz * 3/2)+2:2*grid_img_sz -1, 2:grid_img_sz])\n", + "# ax_temp = fig.add_subplot(gs[grid_img_sz + grid_img_sz//4:grid_img_sz//4 + int(grid_img_sz * 3/2)+1, grid_img_sz//2+1:grid_img_sz])\n", + "clean_ax(ax_temp)\n", + "plot_noise_model(25,None, nmodel2['hist'], nmodel2['gmm'], 'cpu', ax_temp, linetxt_offset=0.2)\n", + "# plot_noise_model(40, 90, nmodel2['hist'], nmodel2['gmm'], 'cpu', ax_temp, linetxt_offset=0.2)\n", + "\n", + "# ax_temp = fig.add_subplot(gs[grid_img_sz:int(grid_img_sz * 3/2), :grid_img_sz])\n", + "# plot_noise_model(45, 100, nmodel1['hist'], nmodel1['gmm'], 'cpu', ax_temp)\n", + "\n", + "# manually setting legends\n", + "import matplotlib.lines as mlines\n", + "line_ch1 = mlines.Line2D([0, 1], [0, 1], color=color_ch_list[0], linestyle='-', label='$C_1$')\n", + "line_ch2 = mlines.Line2D([0, 1], [0, 1], color=color_ch_list[1], linestyle='-', label='$C_2$')\n", + "line_pred = mlines.Line2D([0, 1], [0, 1], color=color_pred, linestyle='-', label='Pred')\n", + "line_noisych1 = mlines.Line2D([0, 1], [0, 1], color=color_ch_list[0], linestyle='--', label='$C^N_1$')\n", + "line_noisych2 = mlines.Line2D([0, 1], [0, 1], color=color_ch_list[1], linestyle='--', label='$C^N_2$')\n", + "\n", + "legend_ch1 = legend_ch1_ax.legend(handles=[line_ch1, line_noisych1, line_pred], loc='upper right', frameon=False, labelcolor='white', \n", + " prop={'size': 11})\n", + "legend_ch2 = legend_ch2_ax.legend(handles=[line_ch2, line_noisych2, line_pred], loc='upper right', frameon=False, labelcolor='white',\n", + " prop={'size': 11})\n", + "# legend = legend_ax.legend(handles=[line_ch1, line_noisych1, line_ch2, line_noisych2, line_pred], loc='upper left', frameon=False, labelcolor='white', \n", + "# prop={'size': 11})\n", + "\n", + "fpath = get_output_fpath(noise_level)\n", + "plt.savefig(fpath, dpi=100, bbox_inches='tight')\n", + "print(f'Saved to {fpath}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.imshow(usplit_data[noise_levels[0]][0,:500,:500, 0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "denoisplitfpath = '/group/jug/ashesh/data/paper_stats/Test_P128_G32_M10_Sk32/pred_disentangle_2402_D3-M3-S0-L0_32.tif'\n", + "hdn_fpath = '/group/jug/ashesh/data/paper_stats/Test_PNone_G32_M5_Sk0/pred_disentangle_2403_D23-M3-S0-L0_29.tif'\n", + "hdn = load_tiff(hdn_fpath)\n", + "denoisplit = load_tiff(denoisplitfpath)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.patches as patches\n", + "\n", + "ncols=4\n", + "nrows = 2\n", + "imgsz = 3\n", + "_,ax = plt.subplots(nrows,ncols, figsize=(ncols*imgsz, nrows*imgsz))\n", + "hs = np.random.randint(0, highsnr_data.shape[1]-500)\n", + "ws = np.random.randint(0, highsnr_data.shape[2]-500)\n", + "t = np.random.randint(0, highsnr_data.shape[0])\n", + "print(hs, ws, t)\n", + "ax[0, 0].imshow(noisy_data[t].mean(axis=-1), cmap='magma')\n", + "ax[1, 0].imshow(noisy_data[t,hs:hs+500,ws:ws+500].mean(axis=-1), cmap='magma')\n", + "ax[0, 1].imshow(hdn[t,hs:hs+500,ws:ws+500, 0], cmap='magma')\n", + "ax[0, 2].imshow(denoisplit[t,hs:hs+500,ws:ws+500, 0], cmap='magma')\n", + "ax[1, 1].imshow(hdn[t,hs:hs+500,ws:ws+500, 1], cmap='magma')\n", + "ax[1, 2].imshow(denoisplit[t,hs:hs+500,ws:ws+500, 1], cmap='magma')\n", + "\n", + "ax[0,3].imshow(highsnr_data[t,hs:hs+500,ws:ws+500, 0], cmap='magma')\n", + "ax[1,3].imshow(highsnr_data[t,hs:hs+500,ws:ws+500, 1], cmap='magma')\n", + "\n", + "# ax[2].imshow(highsnr_data[0,:500,:500, 1])\n", + "rect = patches.Rectangle((ws, hs), 500,500, linewidth=1, edgecolor='r', facecolor='none')\n", + "ax[0,0].add_patch(rect)\n", + "\n", + "plt.subplots_adjust(wspace=0.03, hspace=0.03)\n", + "ax[0,0].set_title('Noisy Input')\n", + "ax[0,1].set_title('HDN+uSplit')\n", + "ax[0,2].set_title('denoiSplit')\n", + "ax[0,3].set_title('High SNR')\n", + "clean_ax(ax)\n", + "fpath = os.path.join(paper_figures_dir, 'paviaATN_hdn_vs_denoisplit_1.png')\n", + "print(fpath)\n", + "plt.savefig(fpath, dpi=100, bbox_inches='tight')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "noisy_data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/intro_figure.ipynb b/denoisplit/notebooks/intro_figure.ipynb new file mode 100644 index 0000000..7ade448 --- /dev/null +++ b/denoisplit/notebooks/intro_figure.ipynb @@ -0,0 +1,149 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "DEBUG=False\n", + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "! ls /group/jug/ashesh/data/Downloads/" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "charA = '/group/jug/ashesh/downloads/archive/notMNIST_small/A'\n", + "charB = '/group/jug/ashesh/downloads/archive/notMNIST_small/J'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fnamesA = list(os.listdir(charA))\n", + "fnamesB = list(os.listdir(charB))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "fpath = os.path.join(charA, fnamesA[0])\n", + "cmaps = ['gray_r', 'prism', 'viridis', 'plasma', 'inferno', 'magma', 'cividis']\n", + "cmap_idx = 0\n", + "img = plt.imread(fpath)\n", + "_, ax = plt.subplots(figsize=(9,3),ncols=3)\n", + "idx1 = np.random.randint(0, len(fnamesA))\n", + "idx2 = np.random.randint(0, len(fnamesB))\n", + "img1 = plt.imread(os.path.join(charA, fnamesA[idx1]))\n", + "img2 = plt.imread(os.path.join(charB, fnamesB[idx2]))\n", + "inp = img1 + img2\n", + "\n", + "ax[0].imshow(img1, cmap=cmaps[cmap_idx])\n", + "ax[1].imshow(img2, cmap=cmaps[cmap_idx])\n", + "ax[2].imshow(inp, cmap=cmaps[cmap_idx])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np \n", + "from denoisplit.analysis.plot_utils import clean_ax\n", + "\n", + "sigma = 0.2\n", + "n1 = np.random.normal(0,sigma, size=img2.shape)\n", + "n2 = np.random.normal(0,sigma, size=img2.shape)\n", + "_, ax = plt.subplots(figsize=(9,3),ncols=3)\n", + "ax[0].imshow(img1 +n1, cmap=cmaps[cmap_idx])\n", + "ax[1].imshow(img2+n2, cmap=cmaps[cmap_idx])\n", + "ax[2].imshow(inp+ n1+n2, cmap=cmaps[cmap_idx])\n", + "clean_ax(ax)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.analysis.plot_utils import clean_ax\n", + "output_datadir = '/group/jug/ashesh/data/paper_figures/cartoon/'\n", + "for i,img in enumerate([img1, img2, inp]):\n", + " plt.imshow(img, cmap=cmaps[cmap_idx])\n", + " clean_ax(plt.gca())\n", + " fpath = os.path.join(output_datadir, f'clean_{i}.png')\n", + " plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + " print(fpath)\n", + "\n", + " # plt.imsave(os.path.join(output_datadir, f'clean_{i}.png'), img, cmap=cmaps[cmap_idx])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i,img_tuple in enumerate(zip([img1, img2, inp], [n1, n2, n1+n2])):\n", + " img, noise = img_tuple\n", + " plt.imshow(img+noise, cmap=cmaps[cmap_idx])\n", + " clean_ax(plt.gca())\n", + " fpath = os.path.join(output_datadir, f'noisy_{i}.png')\n", + " plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + " print(fpath)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/nb_core/.ipynb_checkpoints/config_loader-checkpoint.ipynb b/denoisplit/notebooks/nb_core/.ipynb_checkpoints/config_loader-checkpoint.ipynb new file mode 100644 index 0000000..6c24384 --- /dev/null +++ b/denoisplit/notebooks/nb_core/.ipynb_checkpoints/config_loader-checkpoint.ipynb @@ -0,0 +1,134 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "b9e9d4a0", + "metadata": {}, + "outputs": [], + "source": [ + "def get_best_checkpoint(ckpt_dir):\n", + " output = []\n", + " for filename in glob.glob(ckpt_dir + \"/*_best.ckpt\"):\n", + " output.append(filename)\n", + " assert len(output) == 1, '\\n'.join(output)\n", + " return output[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52206b62", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.model_type import ModelType\n", + "config = load_config(ckpt_dir)\n", + "config = ml_collections.ConfigDict(config)\n", + "old_image_size = None\n", + "with config.unlocked():\n", + " try:\n", + " if config.model.model_type == ModelType.LadderVaeSepEncoder:\n", + " if 'use_random_for_missing_inp' not in config.model:\n", + " config.model.use_random_for_missing_inp =False\n", + " if 'learnable_merge_tensors' not in config.model:\n", + " config.model.learnable_merge_tensors = False\n", + " except:\n", + " pass\n", + " \n", + " if 'test_fraction' not in config.training:\n", + " config.training.test_fraction =0.0\n", + " \n", + " if 'datadir' not in config:\n", + " config.datadir = ''\n", + " if 'encoder' not in config.model:\n", + " config.model.encoder = ml_collections.ConfigDict()\n", + " assert 'decoder' not in config.model\n", + " config.model.decoder = ml_collections.ConfigDict()\n", + " \n", + " config.model.encoder.dropout = config.model.dropout\n", + " config.model.decoder.dropout = config.model.dropout\n", + " config.model.encoder.blocks_per_layer = config.model.blocks_per_layer\n", + " config.model.decoder.blocks_per_layer = config.model.blocks_per_layer\n", + " config.model.encoder.n_filters = config.model.n_filters\n", + " config.model.decoder.n_filters = config.model.n_filters\n", + " \n", + " if 'multiscale_retain_spatial_dims' not in config.model.decoder:\n", + " config.model.decoder.multiscale_retain_spatial_dims = False\n", + " \n", + " if 'res_block_kernel' not in config.model.encoder:\n", + " config.model.encoder.res_block_kernel = 3\n", + " assert 'res_block_kernel' not in config.model.decoder\n", + " config.model.decoder.res_block_kernel = 3\n", + " \n", + " if 'res_block_skip_padding' not in config.model.encoder:\n", + " config.model.encoder.res_block_skip_padding = False\n", + " assert 'res_block_skip_padding' not in config.model.decoder\n", + " config.model.decoder.res_block_skip_padding = False\n", + " \n", + " if config.data.data_type == DataType.CustomSinosoid:\n", + " if 'max_vshift_factor' not in config.data:\n", + " config.data.max_vshift_factor = config.data.max_shift_factor\n", + " config.data.max_hshift_factor = 0\n", + " if 'encourage_non_overlap_single_channel' not in config.data:\n", + " config.data.encourage_non_overlap_single_channel = False\n", + " \n", + " \n", + " \n", + " if 'skip_bottom_layers_count' in config.model:\n", + " config.model.skip_bottom_layers_count = 0\n", + " \n", + " if 'logvar_lowerbound' not in config.model:\n", + " config.model.logvar_lowerbound = None\n", + " if 'train_aug_rotate' not in config.data:\n", + " config.data.train_aug_rotate = False\n", + " if 'multiscale_lowres_separate_branch' not in config.model:\n", + " config.model.multiscale_lowres_separate_branch = False\n", + " if 'multiscale_retain_spatial_dims' not in config.model:\n", + " config.model.multiscale_retain_spatial_dims = False\n", + " config.data.train_aug_rotate=False\n", + " \n", + " if 'randomized_channels' not in config.data:\n", + " config.data.randomized_channels = False\n", + " \n", + " if 'predict_logvar' not in config.model:\n", + " config.model.predict_logvar=None\n", + " if config.data.data_type in [DataType.OptiMEM100_014, DataType.CustomSinosoid, DataType.SeparateTiffData,\n", + " DataType.CustomSinosoidThreeCurve]:\n", + " if custom_image_size is not None:\n", + " old_image_size = config.data.image_size\n", + " config.data.image_size = custom_image_size\n", + " if use_deterministic_grid is not None:\n", + " config.data.deterministic_grid = use_deterministic_grid\n", + " if threshold is not None:\n", + " config.data.threshold = threshold\n", + " if val_repeat_factor is not None:\n", + " config.training.val_repeat_factor = val_repeat_factor\n", + " config.model.mode_pred = not compute_kl_loss\n", + "\n", + "print(config)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "DivNoising", + "language": "python", + "name": "divnoising" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/nb_core/.ipynb_checkpoints/disentangle_imports-checkpoint.ipynb b/denoisplit/notebooks/nb_core/.ipynb_checkpoints/disentangle_imports-checkpoint.ipynb new file mode 100644 index 0000000..a18f9bc --- /dev/null +++ b/denoisplit/notebooks/nb_core/.ipynb_checkpoints/disentangle_imports-checkpoint.ipynb @@ -0,0 +1,79 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0457f6b5", + "metadata": {}, + "source": [ + "## Pre-requisite\n", + "You must run root_dirs.ipynb before running this " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20e84c5a", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "\n", + "import numpy as np\n", + "import torch\n", + "import pickle\n", + "import ml_collections\n", + "import glob\n", + "import torch\n", + "from torch.utils.data import DataLoader\n", + "import torch.nn as nn\n", + "\n", + "from tqdm import tqdm\n", + "import numpy as np\n", + "from denoisplit.training import create_dataset, create_model\n", + "import matplotlib.pyplot as plt\n", + "from denoisplit.core.loss_type import LossType\n", + "from denoisplit.config_utils import load_config\n", + "from denoisplit.sampler.random_sampler import RandomSampler\n", + "from denoisplit.analysis.lvae_utils import get_img_from_forward_output\n", + "from denoisplit.analysis.plot_utils import clean_ax\n", + "from denoisplit.core.data_type import DataType\n", + "from denoisplit.core.psnr import PSNR\n", + "from denoisplit.analysis.plot_utils import get_k_largest_indices,plot_imgs_from_idx\n", + "from denoisplit.analysis.critic_notebook_utils import get_mmse_dict, get_label_separated_loss\n", + "from denoisplit.core.psnr import PSNR, RangeInvariantPsnr\n", + "from denoisplit.core.data_split_type import DataSplitType\n", + "\n", + "torch.multiprocessing.set_sharing_strategy('file_system')\n", + "\n", + "\n", + "def fix_seeds():\n", + " torch.manual_seed(0)\n", + " torch.cuda.manual_seed(0)\n", + " np.random.seed(0)\n", + " random.seed(0)\n", + " torch.backends.cudnn.deterministic = True\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "DivNoising", + "language": "python", + "name": "divnoising" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/nb_core/.ipynb_checkpoints/disentangle_setup-checkpoint.ipynb b/denoisplit/notebooks/nb_core/.ipynb_checkpoints/disentangle_setup-checkpoint.ipynb new file mode 100644 index 0000000..1a75459 --- /dev/null +++ b/denoisplit/notebooks/nb_core/.ipynb_checkpoints/disentangle_setup-checkpoint.ipynb @@ -0,0 +1,213 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "85b6af96", + "metadata": {}, + "source": [ + "## Purpose\n", + "This is to be used for loading the data loader and loading the model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "341f3881", + "metadata": {}, + "outputs": [], + "source": [ + "if image_size_for_grid_centers is None:\n", + " image_size_for_grid_centers = config.data.image_size\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "546e8b40", + "metadata": {}, + "outputs": [], + "source": [ + "print('')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3fd4469", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "from denoisplit.data_loader.overlapping_dloader import get_overlapping_dset\n", + "from denoisplit.data_loader.multi_channel_determ_tiff_dloader import MultiChDeterministicTiffDloader\n", + "from denoisplit.data_loader.multiscale_mc_tiff_dloader import MultiScaleTiffDloader\n", + "from denoisplit.core.data_split_type import DataSplitType\n", + "from denoisplit.data_loader.single_channel_dloader import SingleChannelDloader\n", + "\n", + "\n", + "padding_kwargs = {\n", + " 'mode':config.data.get('padding_mode','constant'),\n", + "}\n", + "\n", + "\n", + "if padding_kwargs['mode'] == 'constant':\n", + " padding_kwargs['constant_values'] = config.data.get('padding_value',0)\n", + "\n", + "dloader_kwargs = {'overlapping_padding_kwargs':padding_kwargs}\n", + "\n", + "\n", + "if 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None:\n", + " data_class = get_overlapping_dset(MultiScaleTiffDloader)\n", + " dloader_kwargs['num_scales'] = config.data.multiscale_lowres_count\n", + " dloader_kwargs['padding_kwargs'] = padding_kwargs\n", + "elif config.data.data_type == DataType.SemiSupBloodVesselsEMBL:\n", + " data_class = get_overlapping_dset(SingleChannelDloader)\n", + "else:\n", + " data_class = get_overlapping_dset(MultiChDeterministicTiffDloader)\n", + "if config.data.data_type in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve, \n", + " DataType.AllenCellMito,DataType.SeparateTiffData,\n", + " DataType.SemiSupBloodVesselsEMBL]:\n", + " datapath = data_dir\n", + "elif config.data.data_type == DataType.OptiMEM100_014:\n", + " datapath = os.path.join(data_dir, 'OptiMEM100x014.tif')\n", + "elif config.data.data_type == DataType.Prevedel_EMBL:\n", + " datapath = os.path.join(data_dir, 'MS14__z0_8_sl4_fr10_p_10.1_lz510_z13_bin5_00001.tif')\n", + "\n", + "\n", + "normalized_input = config.data.normalized_input\n", + "use_one_mu_std = config.data.use_one_mu_std\n", + "train_aug_rotate = config.data.train_aug_rotate\n", + "enable_random_cropping = False #config.data.deterministic_grid is False\n", + "\n", + "train_dset = data_class(\n", + " config.data,\n", + " datapath,\n", + " datasplit_type=DataSplitType.Train,\n", + " val_fraction=config.training.val_fraction,\n", + " test_fraction=config.training.test_fraction,\n", + " normalized_input=normalized_input,\n", + " use_one_mu_std=use_one_mu_std,\n", + " enable_rotation_aug=train_aug_rotate,\n", + " enable_random_cropping=enable_random_cropping,\n", + " image_size_for_grid_centers=image_size_for_grid_centers,\n", + " **dloader_kwargs)\n", + "import gc\n", + "gc.collect()\n", + "max_val = train_dset.get_max_val()\n", + "\n", + "val_dset = data_class(\n", + " config.data,\n", + " datapath,\n", + " datasplit_type=eval_datasplit_type,\n", + " val_fraction=config.training.val_fraction,\n", + " test_fraction=config.training.test_fraction,\n", + " normalized_input=normalized_input,\n", + " use_one_mu_std=use_one_mu_std,\n", + " enable_rotation_aug=False, # No rotation aug on validation\n", + " enable_random_cropping=False,\n", + " # No random cropping on validation. Validation is evaluated on determistic grids\n", + " image_size_for_grid_centers=image_size_for_grid_centers,\n", + " max_val=max_val,\n", + " **dloader_kwargs\n", + " \n", + " )\n", + "\n", + "# For normalizing, we should be using the training data's mean and std.\n", + "mean_val, std_val = train_dset.compute_mean_std()\n", + "train_dset.set_mean_std(mean_val, std_val)\n", + "val_dset.set_mean_std(mean_val, std_val)\n", + "\n", + "\n", + "if evaluate_train:\n", + " val_dset = train_dset\n", + "data_mean, data_std = train_dset.get_mean_std()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "065c3e39", + "metadata": {}, + "outputs": [], + "source": [ + "print('')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fad8e48d", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "with config.unlocked():\n", + " if config.data.data_type in [DataType.OptiMEM100_014,DataType.CustomSinosoid,\n", + " DataType.SeparateTiffData,\n", + " DataType.CustomSinosoidThreeCurve] and old_image_size is not None:\n", + " config.data.image_size = old_image_size\n", + "\n", + "if config.data.target_separate_normalization is True:\n", + " model = create_model(config, *train_dset.compute_individual_mean_std())\n", + "else:\n", + " model = create_model(config, *train_dset.get_mean_std())\n", + "\n", + "\n", + "ckpt_fpath = get_best_checkpoint(ckpt_dir)\n", + "checkpoint = torch.load(ckpt_fpath)\n", + "\n", + "_ = model.load_state_dict(checkpoint['state_dict'])\n", + "model.eval()\n", + "_= model.cuda()\n", + "\n", + "model.data_mean = model.data_mean.cuda()\n", + "model.data_std = model.data_std.cuda()\n", + "print('Loading from epoch', checkpoint['epoch'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "679042e0", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "def count_parameters(model):\n", + " return sum(p.numel() for p in model.parameters() if p.requires_grad)\n", + "\n", + "print(f'Model has {count_parameters(model)/1000_000:.3f}M parameters')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "DivNoising", + "language": "python", + "name": "divnoising" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/nb_core/.ipynb_checkpoints/root_dirs-checkpoint.ipynb b/denoisplit/notebooks/nb_core/.ipynb_checkpoints/root_dirs-checkpoint.ipynb new file mode 100644 index 0000000..dd19833 --- /dev/null +++ b/denoisplit/notebooks/nb_core/.ipynb_checkpoints/root_dirs-checkpoint.ipynb @@ -0,0 +1,106 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "f47435ef", + "metadata": {}, + "outputs": [], + "source": [ + "%config Completer.use_jedi = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86651f3e", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import re\n", + "\n", + "homedir = os.path.expanduser('~')\n", + "nodename = os.uname().nodename\n", + "if nodename == 'capablerutherford-02aa4':\n", + " DATA_ROOT = '/mnt/ashesh/'\n", + " CODE_ROOT = '/home/ubuntu/ashesh/'\n", + "elif nodename in ['capableturing-34a32','colorfuljug-fa782']:\n", + " DATA_ROOT = '/home/ubuntu/ashesh/data/'\n", + " CODE_ROOT = '/home/ubuntu/ashesh/'\n", + "elif (re.match( 'lin-jug-\\d{2}',nodename) or re.match( 'gnode\\d{2}',nodename) or \n", + "re.match( 'lin-jug-m-\\d{2}',nodename) or re.match( 'lin-jug-l-\\d{2}',nodename)):\n", + " DATA_ROOT = '/group/jug/ashesh/data/'\n", + " CODE_ROOT = '/home/ashesh.ashesh/'\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efdc1d58", + "metadata": {}, + "outputs": [], + "source": [ + "nodename" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6a2d04e", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "\n", + "def setup_syspath_disentangle(DEBUG):\n", + " if DEBUG:\n", + " sys.path.remove(os.path.join(CODE_ROOT,'code/Disentangle'))\n", + " \n", + " sys.path.append(os.path.join(CODE_ROOT,'debug/code/Disentangle'))\n", + " else:\n", + " sys.path.append(os.path.join(CODE_ROOT, 'code/Disentangle'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dba66efc", + "metadata": {}, + "outputs": [], + "source": [ + "print('DATA_ROOT:\\t', DATA_ROOT)\n", + "print('CODE_ROOT:\\t', CODE_ROOT)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af97b47f", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "disentangle", + "language": "python", + "name": "disentangle" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/nb_core/__init__.py b/denoisplit/notebooks/nb_core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/denoisplit/notebooks/nb_core/config_loader.ipynb b/denoisplit/notebooks/nb_core/config_loader.ipynb new file mode 100644 index 0000000..d1ea7af --- /dev/null +++ b/denoisplit/notebooks/nb_core/config_loader.ipynb @@ -0,0 +1,138 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "b9e9d4a0", + "metadata": {}, + "outputs": [], + "source": [ + "def get_best_checkpoint(ckpt_dir):\n", + " output = []\n", + " for filename in glob.glob(ckpt_dir + \"/*_best.ckpt\"):\n", + " output.append(filename)\n", + " assert len(output) == 1, '\\n'.join(output)\n", + " return output[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52206b62", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.core.model_type import ModelType\n", + "if os.path.isdir(ckpt_dir):\n", + " config = load_config(ckpt_dir)\n", + "else:\n", + " config = load_config(os.path.dirname(ckpt_dir))\n", + "\n", + "config = ml_collections.ConfigDict(config)\n", + "old_image_size = None\n", + "with config.unlocked():\n", + " try:\n", + " if config.model.model_type == ModelType.LadderVaeSepEncoder:\n", + " if 'use_random_for_missing_inp' not in config.model:\n", + " config.model.use_random_for_missing_inp =False\n", + " if 'learnable_merge_tensors' not in config.model:\n", + " config.model.learnable_merge_tensors = False\n", + " except:\n", + " pass\n", + " \n", + " if 'test_fraction' not in config.training:\n", + " config.training.test_fraction =0.0\n", + " \n", + " if 'datadir' not in config:\n", + " config.datadir = ''\n", + " if 'encoder' not in config.model:\n", + " config.model.encoder = ml_collections.ConfigDict()\n", + " assert 'decoder' not in config.model\n", + " config.model.decoder = ml_collections.ConfigDict()\n", + " \n", + " config.model.encoder.dropout = config.model.dropout\n", + " config.model.decoder.dropout = config.model.dropout\n", + " config.model.encoder.blocks_per_layer = config.model.blocks_per_layer\n", + " config.model.decoder.blocks_per_layer = config.model.blocks_per_layer\n", + " config.model.encoder.n_filters = config.model.n_filters\n", + " config.model.decoder.n_filters = config.model.n_filters\n", + " \n", + " if 'multiscale_retain_spatial_dims' not in config.model.decoder:\n", + " config.model.decoder.multiscale_retain_spatial_dims = False\n", + " \n", + " if 'res_block_kernel' not in config.model.encoder:\n", + " config.model.encoder.res_block_kernel = 3\n", + " assert 'res_block_kernel' not in config.model.decoder\n", + " config.model.decoder.res_block_kernel = 3\n", + " \n", + " if 'res_block_skip_padding' not in config.model.encoder:\n", + " config.model.encoder.res_block_skip_padding = False\n", + " assert 'res_block_skip_padding' not in config.model.decoder\n", + " config.model.decoder.res_block_skip_padding = False\n", + " \n", + " if config.data.data_type == DataType.CustomSinosoid:\n", + " if 'max_vshift_factor' not in config.data:\n", + " config.data.max_vshift_factor = config.data.max_shift_factor\n", + " config.data.max_hshift_factor = 0\n", + " if 'encourage_non_overlap_single_channel' not in config.data:\n", + " config.data.encourage_non_overlap_single_channel = False\n", + " \n", + " \n", + " \n", + " if 'skip_bottom_layers_count' in config.model:\n", + " config.model.skip_bottom_layers_count = 0\n", + " \n", + " if 'logvar_lowerbound' not in config.model:\n", + " config.model.logvar_lowerbound = None\n", + " if 'train_aug_rotate' not in config.data:\n", + " config.data.train_aug_rotate = False\n", + " if 'multiscale_lowres_separate_branch' not in config.model:\n", + " config.model.multiscale_lowres_separate_branch = False\n", + " if 'multiscale_retain_spatial_dims' not in config.model:\n", + " config.model.multiscale_retain_spatial_dims = False\n", + " config.data.train_aug_rotate=False\n", + " \n", + " if 'randomized_channels' not in config.data:\n", + " config.data.randomized_channels = False\n", + " \n", + " if 'predict_logvar' not in config.model:\n", + " config.model.predict_logvar=None\n", + " \n", + " if 'batchnorm' in config.model and 'batchnorm' not in config.model.encoder:\n", + " assert 'batchnorm' not in config.model.decoder\n", + " config.model.decoder.batchnorm = config.model.batchnorm\n", + " config.model.encoder.batchnorm = config.model.batchnorm\n", + " if 'conv2d_bias' not in config.model.decoder:\n", + " config.model.decoder.conv2d_bias = True\n", + " \n", + "\n", + " if custom_image_size is not None:\n", + " old_image_size = config.data.image_size\n", + " config.data.image_size = custom_image_size\n", + " if image_size_for_grid_centers is not None:\n", + " old_grid_size = config.data.get('grid_size', \"grid_size not present\")\n", + " config.data.grid_size = image_size_for_grid_centers\n", + " config.data.val_grid_size = image_size_for_grid_centers\n", + "\n", + " if use_deterministic_grid is not None:\n", + " config.data.deterministic_grid = use_deterministic_grid\n", + " if threshold is not None:\n", + " config.data.threshold = threshold\n", + " if val_repeat_factor is not None:\n", + " config.training.val_repeat_factor = val_repeat_factor\n", + " config.model.mode_pred = not compute_kl_loss\n", + "\n", + "print(config)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "DivNoising", + "language": "python", + "name": "divnoising" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/nb_core/disentangle_imports.ipynb b/denoisplit/notebooks/nb_core/disentangle_imports.ipynb new file mode 100644 index 0000000..bdf0cf9 --- /dev/null +++ b/denoisplit/notebooks/nb_core/disentangle_imports.ipynb @@ -0,0 +1,90 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0457f6b5", + "metadata": {}, + "source": [ + "## Pre-requisite\n", + "You must run root_dirs.ipynb before running this " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20e84c5a", + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "\n", + "import numpy as np\n", + "import torch\n", + "import pickle\n", + "import ml_collections\n", + "import glob\n", + "import torch\n", + "from torch.utils.data import DataLoader\n", + "import torch.nn as nn\n", + "\n", + "from tqdm import tqdm\n", + "import numpy as np\n", + "from denoisplit.training import create_dataset, create_model\n", + "import matplotlib.pyplot as plt\n", + "from denoisplit.core.loss_type import LossType\n", + "from denoisplit.config_utils import load_config\n", + "from denoisplit.sampler.random_sampler import RandomSampler\n", + "from denoisplit.analysis.lvae_utils import get_img_from_forward_output\n", + "from denoisplit.analysis.plot_utils import clean_ax\n", + "from denoisplit.core.data_type import DataType\n", + "from denoisplit.core.psnr import PSNR\n", + "from denoisplit.analysis.plot_utils import get_k_largest_indices,plot_imgs_from_idx\n", + "from denoisplit.analysis.critic_notebook_utils import get_mmse_dict, get_label_separated_loss\n", + "from denoisplit.core.psnr import PSNR, RangeInvariantPsnr\n", + "from denoisplit.core.data_split_type import DataSplitType\n", + "\n", + "torch.multiprocessing.set_sharing_strategy('file_system')\n", + "\n", + "\n", + "def fix_seeds():\n", + " torch.manual_seed(0)\n", + " torch.cuda.manual_seed(0)\n", + " np.random.seed(0)\n", + " random.seed(0)\n", + " torch.backends.cudnn.deterministic = True\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "61080778", + "metadata": {}, + "outputs": [], + "source": [ + "subdset_type = None" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "DivNoising", + "language": "python", + "name": "divnoising" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13 |Anaconda, Inc.| (default, Feb 23 2021, 21:15:04) \n[GCC 7.3.0]" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/nb_core/disentangle_setup.ipynb b/denoisplit/notebooks/nb_core/disentangle_setup.ipynb new file mode 100644 index 0000000..52f35a5 --- /dev/null +++ b/denoisplit/notebooks/nb_core/disentangle_setup.ipynb @@ -0,0 +1,299 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "85b6af96", + "metadata": {}, + "source": [ + "## Purpose\n", + "This is to be used for loading the data loader and loading the model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "341f3881", + "metadata": {}, + "outputs": [], + "source": [ + "# if image_size_for_grid_centers is None:\n", + "# image_size_for_grid_centers = config.data.image_size\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "546e8b40", + "metadata": {}, + "outputs": [], + "source": [ + "print('')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3fd4469", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "# # from denoisplit.data_loader.overlapping_dloader import get_overlapping_dset\n", + "# from denoisplit.data_loader.vanilla_dloader import MultiChDloader\n", + "# from denoisplit.data_loader.lc_multich_dloader import LCMultiChDloader\n", + "# from denoisplit.core.data_split_type import DataSplitType\n", + "# from denoisplit.data_loader.single_channel.single_channel_dloader import SingleChannelDloader\n", + "# from denoisplit.data_loader.single_channel.single_channel_mc_dloader import SingleChannelMSDloader\n", + "# from denoisplit.data_loader.pavia2_3ch_dloader import Pavia2ThreeChannelDloader\n", + "from denoisplit.data_loader.patch_index_manager import GridAlignement\n", + "# from denoisplit.data_loader.ht_iba1_ki67_dloader import IBA1Ki67DataLoader\n", + "# from denoisplit.data_loader.multifile_dset import MultiFileDset\n", + "\n", + "padding_kwargs = {\n", + " 'mode':config.data.get('padding_mode','constant'),\n", + "}\n", + "\n", + "if padding_kwargs['mode'] == 'constant':\n", + " padding_kwargs['constant_values'] = config.data.get('padding_value',0)\n", + "\n", + "dloader_kwargs = {'overlapping_padding_kwargs':padding_kwargs, \n", + " 'grid_alignment': GridAlignement.Center}\n", + "# if 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None:\n", + "# dloader_kwargs['num_scales'] = config.data.multiscale_lowres_count\n", + "# dloader_kwargs['padding_kwargs'] = padding_kwargs\n", + "\n", + "\n", + "# if config.data.data_type == DataType.SemiSupBloodVesselsEMBL:\n", + "# if 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None:\n", + "# data_class = get_overlapping_dset(SingleChannelMSDloader)\n", + "# dloader_kwargs['num_scales'] = config.data.multiscale_lowres_count\n", + "# dloader_kwargs['padding_kwargs'] = padding_kwargs\n", + "# else:\n", + "# data_class = get_overlapping_dset(SingleChannelDloader)\n", + "# elif config.data.data_type == DataType.Pavia2:\n", + "# data_class = get_overlapping_dset(Pavia2ThreeChannelDloader)\n", + "\n", + "# elif config.data.data_type == DataType.HTIba1Ki67 and config.model.model_type in [ModelType.LadderVaeMultiDataSet, \n", + "# ModelType.LadderVaeMultiDatasetMultiBranch, ModelType.LadderVaeMultiDatasetMultiOptim]:\n", + "# data_class = IBA1Ki67DataLoader\n", + "\n", + "# elif config.data.data_type in [DataType.TavernaSox2Golgi, DataType.ExpMicroscopyV2]:\n", + "# if 'num_scales' in dloader_kwargs:\n", + "# del dloader_kwargs['num_scales']\n", + "# data_class = MultiFileDset\n", + "\n", + "# elif 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None:\n", + "# data_class = LCMultiChDloader\n", + "\n", + "# elif config.model.model_type==ModelType.AutoRegresiveLadderVAE:\n", + "# from denoisplit.data_loader.autoregressive_dloader import AutoRegressiveDloader\n", + "# data_class = AutoRegressiveDloader\n", + "# else:\n", + "# # data_class = get_overlapping_dset(MultiChDloader)\n", + "# data_class = MultiChDloader\n", + "\n", + "# if config.data.data_type in [DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve, \n", + "# DataType.AllenCellMito,DataType.SeparateTiffData,\n", + "# DataType.SemiSupBloodVesselsEMBL, DataType.BSD68]:\n", + "# datapath = data_dir\n", + "# elif config.data.data_type == DataType.OptiMEM100_014:\n", + "# datapath = os.path.join(data_dir, 'OptiMEM100x014.tif')\n", + "# elif config.data.data_type == DataType.Prevedel_EMBL:\n", + "# datapath = os.path.join(data_dir, 'MS14__z0_8_sl4_fr10_p_10.1_lz510_z13_bin5_00001.tif')\n", + "# # elif config.data.data_type == DataType.Convallaria:\n", + "# # datapath = os.path.join(data_dir, '20190520_tl_25um_50msec_05pc_488_130EM_Conv_withChannel.tif')\n", + "# else:\n", + "# datapath = data_dir\n", + "\n", + "# normalized_input = config.data.normalized_input\n", + "# use_one_mu_std = config.data.use_one_mu_std\n", + "# train_aug_rotate = config.data.train_aug_rotate\n", + "# enable_random_cropping = False #config.data.deterministic_grid is False\n", + "# grid_alignment = GridAlignement.Center\n", + "# print(data_class)\n", + "\n", + "# train_dset = data_class(\n", + "# config.data,\n", + "# datapath,\n", + "# datasplit_type=DataSplitType.Train,\n", + "# val_fraction=config.training.val_fraction,\n", + "# test_fraction=config.training.test_fraction,\n", + "# normalized_input=normalized_input,\n", + "# use_one_mu_std=use_one_mu_std,\n", + "# enable_rotation_aug=train_aug_rotate,\n", + "# enable_random_cropping=enable_random_cropping,\n", + "# grid_alignment=grid_alignment,\n", + "# **dloader_kwargs)\n", + "# import gc\n", + "# gc.collect()\n", + "# max_val = train_dset.get_max_val()\n", + "\n", + "# if subdset_type is not None:\n", + "# with config.unlocked():\n", + "# config.data.subdset_type = subdset_type\n", + "# assert eval_datasplit_type != DataSplitType.Train\n", + "\n", + "# val_dset = data_class(\n", + "# config.data,\n", + "# datapath,\n", + "# datasplit_type=eval_datasplit_type,\n", + "# val_fraction=config.training.val_fraction,\n", + "# test_fraction=config.training.test_fraction,\n", + "# normalized_input=normalized_input,\n", + "# use_one_mu_std=use_one_mu_std,\n", + "# enable_rotation_aug=False, # No rotation aug on validation\n", + "# enable_random_cropping=False,\n", + "# # No random cropping on validation. Validation is evaluated on determistic grids\n", + "# grid_alignment=grid_alignment,\n", + "# max_val=max_val,\n", + "# **dloader_kwargs\n", + " \n", + "# )\n", + "\n", + "# # For normalizing, we should be using the training data's mean and std.\n", + "# mean_val, std_val = train_dset.compute_mean_std()\n", + "# train_dset.set_mean_std(mean_val, std_val)\n", + "# val_dset.set_mean_std(mean_val, std_val)\n", + "\n", + "\n", + "# if evaluate_train:\n", + "# val_dset = train_dset\n", + "# data_mean, data_std = train_dset.get_mean_std()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4605f9ca", + "metadata": {}, + "outputs": [], + "source": [ + "from denoisplit.training import create_dataset\n", + "train_dset, val_dset = create_dataset(config, data_dir, eval_datasplit_type=eval_datasplit_type,\n", + " kwargs_dict=dloader_kwargs)\n", + "data_mean, data_std = train_dset.get_mean_std()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "065c3e39", + "metadata": {}, + "outputs": [], + "source": [ + "print('')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55e8eb75", + "metadata": {}, + "outputs": [], + "source": [ + "!ls /home/ashesh.ashesh/training/disentangle/2301/D3-M10-S0-L3/25" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fad8e48d", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "with config.unlocked():\n", + " if old_image_size is not None:\n", + " config.data.image_size = old_image_size\n", + "\n", + "# if config.data.target_separate_normalization is True:\n", + "# mean_fr_model, std_fr_model = train_dset.compute_individual_mean_std()\n", + "# else:\n", + "# mean_fr_model, std_fr_model = train_dset.get_mean_std()\n", + "\n", + "# if config.model.model_type == ModelType.LadderVaeSemiSupervised:\n", + "# mean_fr_model = mean_fr_model[None]\n", + "# std_fr_model = std_fr_model[None]\n", + "\n", + "###### Create the input and target mean and std for feeding to the model\n", + "mean_dict = {'input': None, 'target': None}\n", + "std_dict = {'input': None, 'target': None}\n", + "inp_fr_mean, inp_fr_std = train_dset.get_mean_std()\n", + "mean_sq = inp_fr_mean.squeeze()\n", + "std_sq = inp_fr_std.squeeze()\n", + "assert mean_sq[0] == mean_sq[1] and len(mean_sq) == config.data.get('num_channels',2)\n", + "assert std_sq[0] == std_sq[1] and len(std_sq) == config.data.get('num_channels',2)\n", + "mean_dict['input'] = np.mean(inp_fr_mean, axis=1, keepdims=True)\n", + "std_dict['input'] = np.mean(inp_fr_std, axis=1, keepdims=True)\n", + "\n", + "if config.data.target_separate_normalization is True:\n", + " target_data_mean, target_data_std = train_dset.compute_individual_mean_std()\n", + "else:\n", + " target_data_mean, target_data_std = train_dset.get_mean_std()\n", + "\n", + "mean_dict['target'] = target_data_mean\n", + "std_dict['target'] = target_data_std\n", + "###### \n", + " \n", + "model = create_model(config, mean_dict,std_dict)\n", + "if os.path.isdir(ckpt_dir):\n", + " ckpt_fpath = get_best_checkpoint(ckpt_dir)\n", + "else:\n", + " assert os.path.isfile(ckpt_dir)\n", + " ckpt_fpath = ckpt_dir\n", + "\n", + "print('Loading checkpoint from', ckpt_fpath)\n", + "checkpoint = torch.load(ckpt_fpath)\n", + "\n", + "_ = model.load_state_dict(checkpoint['state_dict'], strict=False)\n", + "model.eval()\n", + "_= model.cuda()\n", + "\n", + "model.set_params_to_same_device_as(torch.Tensor(1).cuda())\n", + "\n", + "print('Loading from epoch', checkpoint['epoch'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "679042e0", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "def count_parameters(model):\n", + " return sum(p.numel() for p in model.parameters() if p.requires_grad)\n", + "\n", + "print(f'Model has {count_parameters(model)/1000_000:.3f}M parameters')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.9.18" + }, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/nb_core/root_dirs.ipynb b/denoisplit/notebooks/nb_core/root_dirs.ipynb new file mode 100644 index 0000000..6623dc2 --- /dev/null +++ b/denoisplit/notebooks/nb_core/root_dirs.ipynb @@ -0,0 +1,109 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "f47435ef", + "metadata": {}, + "outputs": [], + "source": [ + "%config Completer.use_jedi = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86651f3e", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import re\n", + "\n", + "homedir = os.path.expanduser('~')\n", + "nodename = os.uname().nodename\n", + "if nodename == 'capablerutherford-02aa4':\n", + " DATA_ROOT = '/mnt/ashesh/'\n", + " CODE_ROOT = '/home/ubuntu/ashesh/'\n", + "elif nodename in ['capableturing-34a32','colorfuljug-fa782','rapidkepler-ca36f']:\n", + " DATA_ROOT = '/home/ubuntu/ashesh/data/'\n", + " CODE_ROOT = '/home/ubuntu/ashesh/'\n", + "elif (re.match( 'lin-jug-\\d{2}',nodename) or re.match( 'gnode\\d{2}',nodename) or \n", + "re.match( 'lin-jug-m-\\d{2}',nodename) or re.match( 'lin-jug-l-\\d{2}',nodename)):\n", + " DATA_ROOT = '/group/jug/ashesh/data/'\n", + " CODE_ROOT = '/home/ashesh.ashesh/'\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efdc1d58", + "metadata": {}, + "outputs": [], + "source": [ + "nodename" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6a2d04e", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "\n", + "def setup_syspath_disentangle(DEBUG):\n", + " if DEBUG:\n", + " sys.path.remove(os.path.join(CODE_ROOT,'code/Disentangle'))\n", + " \n", + " sys.path.append(os.path.join(CODE_ROOT,'debug/code/Disentangle'))\n", + " else:\n", + " sys.path.append(os.path.join(CODE_ROOT, 'code/Disentangle'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dba66efc", + "metadata": {}, + "outputs": [], + "source": [ + "print('DATA_ROOT:\\t', DATA_ROOT)\n", + "print('CODE_ROOT:\\t', CODE_ROOT)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af97b47f", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "interpreter": { + "hash": "4df79d9fd0f93f0a1183e8d8cc3df2ca5976e9560579a8152ed05c08c03ff51b" + }, + "kernelspec": { + "display_name": "disentangle", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/denoisplit/notebooks/perf_comparison_diff_noise_model_ways.ipynb b/denoisplit/notebooks/perf_comparison_diff_noise_model_ways.ipynb new file mode 100644 index 0000000..12ec3d9 --- /dev/null +++ b/denoisplit/notebooks/perf_comparison_diff_noise_model_ways.ipynb @@ -0,0 +1,232 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "DEBUG=False\n", + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "paper_figures_dir = '/group/jug/ashesh/data/paper_figures'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "one_sample_denoising = {\n", + " 'ERvsCCP':{\n", + " 3400:37.9,\n", + " 5100:36.3,\n", + " 6800:35.0,\n", + " 13600:31.2,\n", + "\n", + " },\n", + " 'ERvsMT':{\n", + " 4450:30.0,\n", + " 6675:29.0,\n", + " 8900:27.0,\n", + " 17800:24.8,\n", + " }\n", + "}\n", + "n2v_denoising = {\n", + " 'ERvsCCP':{\n", + " 3400:37.6,\n", + " 5100:36.0,\n", + " 6800:34.7,\n", + " 13600:31.1,\n", + "\n", + " },\n", + " 'ERvsMT':{\n", + " 4450:29.7,\n", + " 6675:29.1,\n", + " 8900:28.0,\n", + " 17800:24.9,\n", + " }\n", + "}\n", + "\n", + "pure_denoising={\n", + " 'ERvsCCP':{\n", + " 3400:38.0,\n", + " 5100:36.4,\n", + " 6800:35.0,\n", + " 13600:30.7,\n", + "\n", + " },\n", + " 'ERvsMT':{\n", + " 4450:29.7,\n", + " 6675:29.1,\n", + " 8900:28.5,\n", + " 17800:24.9,\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "df_s1 = pd.DataFrame(one_sample_denoising)\n", + "df_sinf = pd.DataFrame(pure_denoising)\n", + "df_n2v = pd.DataFrame(n2v_denoising)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_erccp = pd.concat([df_sinf['ERvsCCP'], df_s1['ERvsCCP'],df_n2v['ERvsCCP']],axis=1,\n", + " keys=['denoiSplit+S$\\infty$','denoiSplit+S1', 'denoiSplit+N2V']).dropna()\n", + "df_erccp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ax = df_erccp.plot.bar()\n", + "ax.set_ylim(28,40)\n", + "ax.yaxis.grid(color='gray', linestyle='dashed')\n", + "ax.xaxis.grid(color='gray', linestyle='dashed')\n", + "ax.set_facecolor('xkcd:light grey')\n", + "ax.set_ylabel('PSNR')\n", + "ax.set_xlabel('Gaussian $\\sigma$')\n", + "ax.set_xticklabels(ax.get_xticklabels(), rotation=45)\n", + "ax.set_title('ER vs CCP')\n", + "fpath = os.path.join(paper_figures_dir, 'different_noise_model_types_ERvsCCP.png')\n", + "plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + "print(fpath)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_ermt = pd.concat([df_sinf['ERvsMT'], df_s1['ERvsMT'],df_n2v['ERvsMT']],axis=1,\n", + " keys=['denoiSplit+S$\\infty$','denoiSplit+S1', 'denoiSplit+N2V']).dropna()\n", + "df_ermt\n", + "ax = df_ermt.plot.bar()\n", + "ax.set_ylim(22,31)\n", + "ax.yaxis.grid(color='gray', linestyle='dashed')\n", + "ax.xaxis.grid(color='gray', linestyle='dashed')\n", + "ax.set_facecolor('xkcd:light grey')\n", + "ax.set_ylabel('PSNR')\n", + "ax.set_xlabel('Gaussian $\\sigma$')\n", + "ax.set_xticklabels(ax.get_xticklabels(), rotation=45)\n", + "ax.set_title('ER vs MT')\n", + "fpath = os.path.join(paper_figures_dir, 'different_noise_model_types_ERvsMT.png')\n", + "plt.savefig(fpath, dpi=200, bbox_inches='tight')\n", + "print(fpath)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "params = {'mathtext.default': 'regular' } \n", + "plt.rcParams.update(params)\n", + "\n", + "ax = df.plot.bar()\n", + "ax.set_ylim(24, 38)\n", + "\n", + "ax.yaxis.grid(color='gray', linestyle='dashed')\n", + "ax.xaxis.grid(color='gray', linestyle='dashed')\n", + "ax.set_facecolor('xkcd:light grey')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/sampling_video.avi b/denoisplit/notebooks/sampling_video.avi new file mode 100644 index 0000000000000000000000000000000000000000..056ffa64282bf4782c70a479ab79769b5ade4db7 GIT binary patch literal 5686 zcmWIYbaT@aV_QB=E3V<-o zK1K!}2C!LBx53o|8D61&-V#8&S)hUj1}VwN@}un05Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4T0ew0-*5$7T~}`eoAf*5M}%r{$9rEL(n*l6j0XF&&}U6*e!$) z$o5GrOEb09GcwmRG%x^.container { width:100% !important; }" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DATA_ROOT:\t /group/jug/ashesh/data/\n", + "CODE_ROOT:\t /home/ashesh.ashesh/\n" + ] + } + ], + "source": [ + "import os\n", + "DEBUG=False\n", + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loaded from TwoChannel /group/jug/ashesh/data/TavernaSox2Golgi/ 306\n", + "[SingleFileDset] Sz:64 Train:1 N:1 NumPatchPerN:256 NormInp:True SingleNorm:True Rot:False RandCrop:True Q:0.995 SummedInput:False ReplaceWithRandSample:False BckQ:0.0\n", + "MultiFileDset avg height: 1555, avg width: 1555, count: 306\n", + "Loaded from TwoChannel /group/jug/ashesh/data/TavernaSox2Golgi/ 39\n", + "[SingleFileDset] Sz:64 Train:0 N:1 NumPatchPerN:256 NormInp:True SingleNorm:True Rot:False RandCrop:False Q:0.995 SummedInput:False ReplaceWithRandSample:False BckQ:0.0\n", + "MultiFileDset avg height: 1379, avg width: 1379, count: 39\n" + ] + } + ], + "source": [ + "from denoisplit.data_loader.multifile_dset import MultiFileDset, DataSplitType\n", + "from denoisplit.core.model_type import ModelType\n", + "\n", + "from denoisplit.configs.sox2golgi_config import get_config \n", + "config = get_config()\n", + "datapath = '/group/jug/ashesh/data/TavernaSox2Golgi/'\n", + "normalized_input = config.data.normalized_input\n", + "use_one_mu_std = config.data.use_one_mu_std\n", + "train_aug_rotate = config.data.train_aug_rotate\n", + "enable_random_cropping = config.data.deterministic_grid is False\n", + "lowres_supervision = config.model.model_type == ModelType.LadderVAEMultiTarget\n", + "\n", + "train_data_kwargs = {}\n", + "val_data_kwargs = {}\n", + "train_data_kwargs['enable_random_cropping'] = enable_random_cropping\n", + "val_data_kwargs['enable_random_cropping'] = False\n", + "train_data = MultiFileDset(config.data,\n", + " datapath,\n", + " datasplit_type=DataSplitType.Train,\n", + " val_fraction=config.training.val_fraction,\n", + " test_fraction=config.training.test_fraction,\n", + " normalized_input=normalized_input,\n", + " use_one_mu_std=use_one_mu_std,\n", + " enable_rotation_aug=train_aug_rotate,\n", + " **train_data_kwargs)\n", + "\n", + "mean_val, std_val = train_data.compute_mean_std()\n", + "train_data.set_mean_std(mean_val, std_val)\n", + "max_val = train_data.get_max_val()\n", + "val_data = MultiFileDset(\n", + " config.data,\n", + " datapath,\n", + " datasplit_type=DataSplitType.Val,\n", + " val_fraction=config.training.val_fraction,\n", + " test_fraction=config.training.test_fraction,\n", + " normalized_input=normalized_input,\n", + " use_one_mu_std=use_one_mu_std,\n", + " enable_rotation_aug=False, # No rotation aug on validation\n", + " max_val=max_val,\n", + " **val_data_kwargs,\n", + " )\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "188808" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(train_data)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "_, ax = plt.subplots(figsize=(9,3),ncols=3)\n", + "inp, tar = train_data[0]\n", + "\n", + "ax[0].imshow(inp[0])\n", + "ax[1].imshow(tar[0])\n", + "ax[2].imshow(tar[1])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/taverna_sox2_golgi.ipynb b/denoisplit/notebooks/taverna_sox2_golgi.ipynb new file mode 100644 index 0000000..0d6eb37 --- /dev/null +++ b/denoisplit/notebooks/taverna_sox2_golgi.ipynb @@ -0,0 +1,538 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import display, HTML\n", + "display(HTML(\"\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "DEBUG=False" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DATA_ROOT:\t /group/jug/ashesh/data/\n", + "CODE_ROOT:\t /home/ashesh.ashesh/\n" + ] + } + ], + "source": [ + "%run ./nb_core/root_dirs.ipynb\n", + "setup_syspath_disentangle(DEBUG)\n", + "%run ./nb_core/disentangle_imports.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loaded from OneChannel /group/jug/ashesh/data/TavernaSox2Golgi/ 121\n", + "[SingleFileDset] Sz:64 Train:1 N:1 NumPatchPerN:256 NormInp:True SingleNorm:True Rot:False RandCrop:True Q:0.995 SummedInput:False ReplaceWithRandSample:False BckQ:0.0\n", + "MultiFileDset avg height: 1024, avg width: 1024, count: 121\n", + "Loaded from OneChannel /group/jug/ashesh/data/TavernaSox2Golgi/ 15\n", + "[SingleFileDset] Sz:64 Train:0 N:1 NumPatchPerN:256 NormInp:True SingleNorm:True Rot:False RandCrop:False Q:0.995 SummedInput:False ReplaceWithRandSample:False BckQ:0.0\n", + "MultiFileDset avg height: 1024, avg width: 1024, count: 15\n" + ] + } + ], + "source": [ + "from denoisplit.configs.sox2golgi_config import get_config\n", + "from denoisplit.core.model_type import ModelType\n", + "from denoisplit.core.data_split_type import DataSplitType\n", + "from denoisplit.data_loader.multifile_dset import MultiFileDset\n", + "\n", + "config = get_config()\n", + "datapath = '/group/jug/ashesh/data/TavernaSox2Golgi/'\n", + "\n", + "normalized_input = config.data.normalized_input\n", + "use_one_mu_std = config.data.use_one_mu_std\n", + "train_aug_rotate = config.data.train_aug_rotate\n", + "enable_random_cropping = config.data.deterministic_grid is False\n", + "lowres_supervision = config.model.model_type == ModelType.LadderVAEMultiTarget\n", + "\n", + "train_data_kwargs = {}\n", + "val_data_kwargs = {}\n", + "train_data_kwargs['enable_random_cropping'] = enable_random_cropping\n", + "val_data_kwargs['enable_random_cropping'] = False\n", + "padding_kwargs = None\n", + "if 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None:\n", + " padding_kwargs = {'mode': config.data.padding_mode}\n", + "if 'padding_value' in config.data and config.data.padding_value is not None:\n", + " padding_kwargs['constant_values'] = config.data.padding_value\n", + "\n", + "train_data = MultiFileDset(config.data,\n", + " datapath,\n", + " datasplit_type=DataSplitType.Train,\n", + " val_fraction=config.training.val_fraction,\n", + " test_fraction=config.training.test_fraction,\n", + " normalized_input=normalized_input,\n", + " use_one_mu_std=use_one_mu_std,\n", + " enable_rotation_aug=train_aug_rotate,\n", + " padding_kwargs=padding_kwargs,\n", + " **train_data_kwargs)\n", + "\n", + "max_val = train_data.get_max_val()\n", + "val_data = MultiFileDset(\n", + " config.data,\n", + " datapath,\n", + " datasplit_type=DataSplitType.Val,\n", + " val_fraction=config.training.val_fraction,\n", + " test_fraction=config.training.test_fraction,\n", + " normalized_input=normalized_input,\n", + " use_one_mu_std=use_one_mu_std,\n", + " enable_rotation_aug=False, # No rotation aug on validation\n", + " padding_kwargs=padding_kwargs,\n", + " max_val=max_val,\n", + " **val_data_kwargs,\n", + ")\n", + "\n", + "mean_val, std_val = train_data.compute_mean_std()\n", + "train_data.set_mean_std(mean_val, std_val)\n", + "val_data.set_mean_std(mean_val, std_val)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "inp, tar = val_data[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "_,ax = plt.subplots(figsize=(9,3),ncols=3)\n", + "ax[0].imshow(inp[0])\n", + "ax[1].imshow(tar[0])\n", + "ax[2].imshow(tar[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 64, 64)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "inp.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "inp_arr = []\n", + "for i in range(len(val_data)):\n", + " inp, tar = val_data[i]\n", + " inp_arr.append(inp)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "inpdata= np.concatenate(inp_arr,axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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aqm/ORg/frw2bdqkrVu36pprrrEup8Hl5eWpuLhYycnJvrGKigpt3bpVS5cuVXl5uUJCQgwrbDjt27fXT3/6U7+xxMREvfbaa0YV2Xj88cc1bdo03/do9+7ddezYMWVmZmrUqFHG1dlo166dpKoOSfv27X3jzfV7U6oKIsOGDdORI0f07rvvNoquiNSIwkh0dLSio6NrNffEiRMaOHCgkpOTtXr1arVo0WgaPPUmLCxMycnJ8ng8+tWvfuUb93g8+uUvf2lYWcNyHEfjx4/Xxo0b9f777yshIcG6JBO33XabPv30U7+x0aNHq1u3bpo6dWqzCSKS1L9//2qXdx88eNB3887m4ptvvqn2XRgSEtLkL+29mISEBLVr104ej0c9e/aUVHX+3ZYtWzRv3jzj6hre+SDy+eef67333lNUVJR1ST6NJozUVkFBgW655RbFx8drwYIF+ve//+372/kU3FRlZGTogQceUO/evX0dofz8fKWnp1uX1mDGjRunV155RX/5y1/UunVrX6coMjJSLVu2NK6u4bRu3braeTKtWrVSVFRUszt/ZvLkyerXr5/mzJmjYcOG6aOPPtKKFSuaRcf0/xoyZIieffZZxcfH67rrrtOePXu0aNEiPfTQQ9al1atTp07piy++8D0/cuSI9u7dqzZt2ig+Pl6TJk3SnDlz1KVLF3Xp0kVz5szR5ZdfrhEjRhhWXT8uti9iY2N1zz33aPfu3XrrrbdUUVHh+/5s06aNwsLCrMquYnsxT+BWr17tSKrx0Ry88MILTocOHZywsDCnV69eze6S1gv9269evdq6NHPN9dJex3GcN99800lKSnLcbrfTrVs3Z8WKFdYlNbjS0lJn4sSJTnx8vBMeHu506tTJmTFjhlNeXm5dWr167733avxOGDVqlOM4VZf3zpw502nXrp3jdrudn//8586nn35qW3Q9udi+OHLkyAW/P9977z3r0h2X4zhOw8QeAACA6pr+yRYAAKBRI4wAAABThBEAAGCKMAIAAEwRRgAAgCnCCAAAMEUYAQAApggjAADAFGEEAACYIowAAABThBEAAGCKMAIAAEz9P0asdGx+6jT9AAAAAElFTkSuQmCC", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "_ = plt.hist(inpdata.flatten(),bins=100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "# import seaborn as sns\n", + "# sns.histplot(inpdata.flatten(),bins=100)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-1.35542893, -1.1493119 , -0.72831666, 0.27736855, 6.13533545,\n", + " 12.25567436])" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.quantile(inpdata,[0.0, 0.01, 0.1, 0.5, 0.99,1])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "# config.data\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loaded from TwoChannel /group/jug/ashesh/data/TavernaSox2Golgi/ 8\n", + "Loaded from OneChannel /group/jug/ashesh/data/TavernaSox2Golgi/ 15\n" + ] + } + ], + "source": [ + "from denoisplit.data_loader.sox2golgi_rawdata_loader import (get_train_val_data, get_one_channel_files, get_two_channel_files, SubDsetType)\n", + "datadir = '/group/jug/ashesh/data/TavernaSox2Golgi/'\n", + "\n", + "config.data.subdset_type = SubDsetType.TwoChannel\n", + "data2ch = get_train_val_data(datadir,\n", + " config.data,\n", + " DataSplitType.Test,\n", + " val_fraction=0.1,\n", + " test_fraction=0.1)\n", + "\n", + "config.data.subdset_type = SubDsetType.OneChannel\n", + "data1ch = get_train_val_data(datadir,\n", + " config.data,\n", + " DataSplitType.Test,\n", + " val_fraction=0.1,\n", + " test_fraction=0.1)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(15, 8)" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(data1ch), len(data2ch)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "input1ch = []\n", + "input2ch = []\n", + "for idx in range(len(data1ch)):\n", + " input1ch.append(np.mean(data1ch[idx][0],axis=2, keepdims=True))\n", + "\n", + "for idx in range(len(data2ch)):\n", + " input2ch.append(np.mean(data2ch[idx][0],axis=2, keepdims=True))\n", + "\n", + "input1ch = np.concatenate(input1ch,axis=-1)\n", + "input2ch = np.concatenate(input2ch,axis=-1)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead\n", + " if pd.api.types.is_categorical_dtype(vector):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.\n", + " with pd.option_context('mode.use_inf_as_na', True):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead\n", + " if pd.api.types.is_categorical_dtype(vector):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.\n", + " with pd.option_context('mode.use_inf_as_na', True):\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlIAAAGdCAYAAADZiZ2PAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA3LElEQVR4nO3de3RU9b3//9fkNgMBhks0IRUkgBW5iHWoNFFEKg2CraB4oD39Ri6VJYdSgdQqFy+tlgWcVg5lcdPTrCDLU8BTQPm1WAlVI5gcW8LFWDBajAnGpCEREnKbXObz+4NmypAQkk2SmQnPx1qzyt7z3vvzntmcw8s9e3+2zRhjBAAAgDYL8XcDAAAAwYogBQAAYBFBCgAAwCKCFAAAgEUEKQAAAIsIUgAAABYRpAAAACwiSAEAAFgU5u8GujKPx6Mvv/xSPXv2lM1m83c7AACgFYwxOn/+vGJjYxUS0vI5J4JUB/ryyy81YMAAf7cBAAAsOH36tG644YYWawhSHahnz56SLhyIXr16+bkbAADQGuXl5RowYID33/GWEKQ6UOPPeb169SJIAQAQZFpzWQ4XmwMAAFhEkAIAALCIIAUAAGAR10gBANDFGGNUX1+vhoYGf7cSkEJDQxUWFtYuUxMRpAAA6EJqa2tVWFioqqoqf7cS0Lp3767+/fsrIiLiqvZDkAIAoIvweDzKzc1VaGioYmNjFRERwYTQlzDGqLa2VmfOnFFubq5uuummK0662RKCFAAAXURtba08Ho8GDBig7t27+7udgNWtWzeFh4crLy9PtbW1cjgclvfFxeYAAHQxV3OG5VrRXt8R3zQAAIBF/LQHAEAX5na7lZWV1aljulwu2e32Th3TXwhSAAB0YVlZWcqeM0ejIiM7ZbzsykopNVUJCQmdMp4kvfvuu5owYYLOnj2r3r17d9q4EkEKAIAub1RkpBKcTn+30aL33ntPv/rVr5SVlaXCwkLt2bNH06ZN83dbV8Q1UgAAwO8qKys1evRobdiwwd+ttAlB6hrkdruVkZHhfbndbn+3BAC4xk2ePFm//OUv9dBDDzX7vtvt1pNPPqkBAwbIbrfrpptuUkpKik9NVlaWxowZo+7duyshIUE5OTkd3jdB6hrU+Hu5Fi5U9pw5nX4RIgAAbfXII49ox44dWr9+vU6ePKktW7aoR48ePjUrVqzQiy++qMOHDyssLExz587t8L64RuoaFQy/lwMAIEmffPKJXnvtNaWlpWnixImSpMGDBzepW7lypcaPHy9JWrp0qe6//37V1NRc1YSbV8IZKQAAENCOHTum0NBQb0i6nFtvvdX75/79+0uSiouLO7Q3ghQAAAho3bp1a1VdeHi498+Nzxj0eDwd0lMjghQAAAhoo0aNksfjUXp6ur9baYJrpAAA6OKyKys7daxRFrarqKjQ3//+d+9ybm6ujh07pr59+2rQoEGaNWuW5s6dq/Xr12v06NHKy8tTcXGxZsyY0X7NW0CQAgCgC3O5XFJqaqeNN6pxzDY6fPiwJkyY4F1OTk6WJM2aNUtbt27V5s2btXz5ci1YsEClpaUaOHCgli9f3l5tW0aQAgCgC7Pb7Z36uBar7rnnHhljLvu+w+HQ2rVrtXbt2lZte9ttt7W4v/bCNVIAAAAWEaQAAAAsIkgBAABYRJACAACwiCAFAABgEUEKAADAIoIUAACARcwjdY2r9XiUk53ts87lcslut/upIwAAggdB6hqXU1Wl6pUrpagoSf98jEBqalBM3gYAuDK3262srKxOHbOz/4P83Xff1YQJE3T27Fn17t2708aVCFKQNNzhUILT6e82AAAdICsrS3PmZCsy0soT8NqusjJbqalq03+Qr1q1Srt379bHH3+sbt26KSEhQWvWrNHNN9/cgZ22D4IUAABdXGTkKDmdgftLQ3p6un784x/rm9/8purr67VixQolJibqxIkTioyM9Hd7LeJicwAA4Fd/+tOfNHv2bI0YMUKjR49Wamqq8vPzfX6SdLvdevLJJzVgwADZ7XbddNNNSklJ8dlPVlaWxowZo+7duyshIUE5OTkd3jtBCgAABJSysjJJUt++fb3rHnnkEe3YsUPr16/XyZMntWXLFvXo0cNnuxUrVujFF1/U4cOHFRYWprlz53Z4r/y0BwAAAoYxRsnJybrrrrs0cuRISdInn3yi1157TWlpaZo4caIkafDgwU22XblypcaPHy9JWrp0qe6//37V1NTI4XB0WL+ckQIAAAFj4cKF+vDDD7V9+3bvumPHjik0NNQbki7n1ltv9f65f//+kqTi4uKOafSfOCMFAAACwk9+8hPt3btX7733nm644Qbv+m7durVq+/DwcO+fbTabJMnj8bRvk5fgjBQAAPArY4wWLlyo3bt36+2331Zc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WLVqlb75zW+qZ8+euv766zVt2jTl5OT41HDMAsvmzZt16623eidjjI+P15tvvul9n+MV+FatWiWbzabFixd7111zx82ftwyi7RrnwPrv//5vc+LECbNo0SITGRlp8vLy/N1al7Nv3z6zYsUKs2vXLiPJ7Nmzx+f91atXm549e5pdu3aZ7OxsM3PmzCZzjc2fP9987WtfM2lpaebIkSNmwoQJZvTo0aa+vt5bc99995mRI0eajIwMk5GRYUaOHGm++93vet+vr683I0eONBMmTDBHjhwxaWlpJjY21ixcuLDDv4NgMmnSJJOammo++ugjc+zYMXP//febgQMHmoqKCm8Nxyyw7N271/zxj380OTk5JicnxyxfvtyEh4ebjz76yBjD8Qp0f/nLX8ygQYPMrbfeahYtWuRdf60dN4JUkLnjjjvM/PnzfdYNGzbMLF261E8dXRsuDVIej8fExMSY1atXe9fV1NQYp9NptmzZYowx5ty5cyY8PNzs2LHDW1NQUGBCQkLMn/70J2OMMSdOnDCSfCaMzczMNJLMxx9/bIy5EOhCQkJMQUGBt2b79u3GbrcH9SR2Ha24uNhI8s4RxzELDn369DG//e1vOV4B7vz58+amm24yaWlpZvz48d4gdS0eN37aCyK1tbXKyspSYmKiz/rExERlZGT4qatrU25uroqKinyOhd1u1/jx473HIisrS3V1dT41sbGxGjlypLcmMzNTTqdTY8eO9dZ861vfktPp9KkZOXKkz8MzJ02aJLfbraysrA79nMGsrKxMktS3b19JHLNA19DQoB07dqiyslLx8fEcrwD34x//WPfff78mTpzos/5aPG5+e2gx2q6kpEQNDQ1NHpwcHR3d5CHM6FiN33dzxyIvL89bExERoT59+jSpady+qKhI119/fZP9X3/99T41l47Tp08fRUREcNwvwxij5ORk3XXXXRo5cqQkjlmgys7OVnx8vGpqatSjRw/t2bNHw4cP9/5jyfEKPDt27NCRI0f017/+tcl71+L/nRGkgpDNZvNZNsY0WYfOYeVYXFrTXL2VGvzLwoUL9eGHH+rQoUNN3uOYBZabb75Zx44d07lz57Rr1y7NmjVL6enp3vc5XoHl9OnTWrRokfbv3y+Hw3HZumvpuPHTXhCJiopSaGhok6RdXFzcJJWjY8XExEhSi8ciJiZGtbW1Onv2bIs1//jHP5rs/8yZMz41l45z9uxZ1dXVcdyb8ZOf/ER79+7VO++8oxtuuMG7nmMWmCIiIjR06FCNGTNGq1at0ujRo/Wb3/yG4xWgsrKyVFxcLJfLpbCwMIWFhSk9PV3r169XWFiY9/u6lo4bQSqIREREyOVyKS0tzWd9WlqaEhIS/NTVtSkuLk4xMTE+x6K2tlbp6eneY+FyuRQeHu5TU1hYqI8++shbEx8fr7KyMv3lL3/x1nzwwQcqKyvzqfnoo49UWFjordm/f7/sdrtcLleHfs5gYozRwoULtXv3br399tuKi4vzeZ9jFhyMMXK73RyvAHXvvfcqOztbx44d877GjBmjH/7whzp27JgGDx587R23TrusHe2icfqDlJQUc+LECbN48WITGRlpPv/8c3+31uWcP3/eHD161Bw9etRIMmvXrjVHjx71TjWxevVq43Q6ze7du012drb5wQ9+0OwtvjfccIM5cOCAOXLkiPn2t7/d7C2+t956q8nMzDSZmZlm1KhRzd7ie++995ojR46YAwcOmBtuuIFbsy/xH//xH8bpdJp3333XFBYWel9VVVXeGo5ZYFm2bJl57733TG5urvnwww/N8uXLTUhIiNm/f78xhuMVLC6+a8+Ya++4EaSC0MaNG82NN95oIiIizO233+69vRvt65133jGSmrxmzZpljLlwm+9zzz1nYmJijN1uN3fffbfJzs722Ud1dbVZuHCh6du3r+nWrZv57ne/a/Lz831qSktLzQ9/+EPTs2dP07NnT/PDH/7QnD171qcmLy/P3H///aZbt26mb9++ZuHChaampqYjP37Qae5YSTKpqaneGo5ZYJk7d673/5ddd9115t577/WGKGM4XsHi0iB1rR03mzHGdN75LwAAgK6Da6QAAAAsIkgBAABYRJACAACwiCAFAABgEUEKAADAIoIUAACARQQpAAAAiwhSAAAAFhGkAAAALCJIAQAAWESQAgAAsIggBQAAYNH/DyUGRcLFdt7rAAAAAElFTkSuQmCC", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "_,ax = plt.subplots()\n", + "sns.histplot(input1ch.flatten()/2,bins=100, color='red', label='1ch', stat='density')\n", + "sns.histplot(input2ch.flatten(),bins=100, color='blue', label='2ch', stat='density')\n", + "ax.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "input 1ch [ 122 340 808 1883 3576 8184 32767]\n", + "input 2ch [ 36 522 912 1989 5595 14644 41394]\n" + ] + } + ], + "source": [ + "print('input 1ch', np.quantile(input1ch/2,[0.0, 0.01, 0.1, 0.5, 0.9, 0.99,1]).astype(np.int32))\n", + "print('input 2ch', np.quantile(input2ch,[0.0, 0.01, 0.1, 0.5, 0.9, 0.99,1]).astype(np.int32))" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [], + "source": [ + "ch1 = []\n", + "ch2 = []\n", + "for idx in range(len(data2ch)):\n", + " tmpd = data2ch[idx][0]\n", + " ch1.append(tmpd[:,:,:1])\n", + " ch2.append(tmpd[:,:,1:])\n", + "\n", + "ch1 = np.concatenate(ch1,axis=-1)\n", + "ch2 = np.concatenate(ch2,axis=-1)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead\n", + " if pd.api.types.is_categorical_dtype(vector):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.\n", + " with pd.option_context('mode.use_inf_as_na', True):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead\n", + " if pd.api.types.is_categorical_dtype(vector):\n", + "/home/ashesh.ashesh/mambaforge/envs/usplit/lib/python3.9/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.\n", + " with pd.option_context('mode.use_inf_as_na', True):\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlIAAAGdCAYAAADZiZ2PAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA8qklEQVR4nO3de1xVVf7/8feRq6AcLySXvOGlvGviRFJmjiVqFy0bGb9F2sXiW2ZmjmZmWjOmzrccakwby0H9zaR+G7Wcxko0Mw2yEUUpHTVFcQxCNMFED8JZvz/8csYjSLAFD5fX8/E4j+Gs8zl7rb2Gh7zbl7VtxhgjAAAAVFoDTw8AAACgtiJIAQAAWESQAgAAsIggBQAAYBFBCgAAwCKCFAAAgEUEKQAAAIsIUgAAABZ5e3oAdZnT6dT333+vxo0by2azeXo4AACgAowxOn36tMLDw9WgQfnHnAhS1ej7779Xq1atPD0MAABgwdGjR9WyZctyawhS1ahx48aSLvwfERQU5OHRAACAisjPz1erVq1cf8fLQ5CqRiWn84KCgghSAADUMhW5LIeLzQEAACwiSAEAAFhEkAIAALCIa6QAAHWaMUZFRUUqLi729FBQQ3h5ecnb27tKliYiSAEA6qzCwkJlZWWpoKDA00NBDRMQEKCwsDD5+vpe0XYIUgCAOsnpdCojI0NeXl4KDw+Xr68viyNDxhgVFhbq+PHjysjIUMeOHX920c3yEKQAAHVSYWGhnE6nWrVqpYCAAE8PBzVIw4YN5ePjoyNHjqiwsFD+/v6Wt8XF5gCAOu1Kjjag7qqq3wt+uwAAACzi1B4AoF5xOBxKTU29qn1GRkbKz8/vqvaJq4MgBQCoV1JTU5X+8MPqHhh4VfpLP3NGSkxUdHR0lWzv8OHDioiI0M6dO9WrV68q2WZ1uu2229SrVy8lJCR4eijVgiAFAKh3ugcGKtpu9/QwICkrK0vPPfecUlNTdeDAAY0fP75SoWvmzJn64IMPlJaWVm1jLA/XSAEAAI9xOBy65pprNG3aNPXs2dPTw6k0glQd4XA4lJycXOrlcDg8PTQAQCU5nU7NnTtXHTp0kJ+fn1q3bq1Zs2a51Rw6dEgDBgxQQECAevbsqZSUFNdnJ06c0KhRo9SyZUsFBASoe/fuWr58udv3b7vtNo0fP16TJ09Ws2bNFBoaqpkzZ7rV2Gw2vfvuu7r33nsVEBCgjh07au3atW41e/bs0dChQ9WoUSOFhIQoLi5Oubm5Fd7Xtm3b6o033tBDDz0k+2WOEn7++ee68cYbFRgYqCZNmujmm2/WkSNHtGTJEr388svatWuXbDabbDablixZUuG+qwJBqo4oOeevceNcr/SHH77qF1QCAK7c1KlTNXfuXE2fPl179uzRe++9p5CQELeaadOmadKkSUpLS9N1112nUaNGqaioSJJ07tw5RUZG6qOPPtI333yjxx9/XHFxcdq2bZvbNpYuXarAwEBt27ZNv//97/XKK68oKSnJrebll1/WyJEjtXv3bg0dOlQPPPCATp48KenCabn+/furV69e2r59uz755BP98MMPGjlyZJXNRVFRkYYPH67+/ftr9+7dSklJ0eOPPy6bzabY2Fg999xz6tq1q7KyspSVlaXY2Ngq67siuEaqDuGcPwDUfqdPn9Ybb7yh+fPna/To0ZKk9u3b65ZbbnGrmzRpku68805JF8JO165d9d1336lTp0669tprNWnSJFft008/rU8++UTvv/++oqKiXO09evTQjBkzJEkdO3bU/PnztXHjRt1xxx2umjFjxmjUqFGSpFdffVV//OMf9fXXX2vw4MFauHChevfurVdffdVV/+c//1mtWrXS/v37dd11113xfOTn5ysvL0933XWX2rdvL0nq3Lmz6/NGjRrJ29tboaGhV9yXFRyRAgCgBtm7d68cDocGDhxYbl2PHj1cP4eFhUmScnJyJEnFxcWaNWuWevTooebNm6tRo0Zav369MjMzL7uNku2UbKOsmsDAQDVu3NhVk5qaqk2bNqlRo0auV6dOnSRJBw8erMxuX1azZs00ZswYxcTE6O6779Ybb7yhrKysKtl2VSBIAQBQgzRs2LBCdT4+Pq6fS54h6HQ6JUmvv/66/vCHP2jy5Mn67LPPlJaWppiYGBUWFl52GyXbKdlGRWqcTqfuvvtupaWlub0OHDigW2+9tUL7URGJiYlKSUlRdHS0Vq5cqeuuu05fffVVlW3/ShCkAACoQTp27KiGDRtq48aNlrexZcsWDRs2TA8++KB69uypdu3a6cCBA1U4ygt69+6tb7/9Vm3btlWHDh3cXoFVvE7XDTfcoKlTpyo5OVndunXTe++9J0ny9fVVcXFxlfZVGVwjBQCod9LPnLmqfXWvRL2/v7+mTJmiyZMny9fXVzfffLOOHz+ub7/9Vo8++miFttGhQwetWrVKycnJatq0qebNm6fs7Gy3a4uqwlNPPaV33nlHo0aN0m9+8xsFBwfru+++04oVK/TOO+/Iy8urQtspWQPqp59+0vHjx5WWliZfX1916dJFGRkZWrRoke655x6Fh4dr37592r9/vx566CFJF+76y8jIUFpamlq2bKnGjRtf1VXkCVIAgHolMjJSSky8av11L+mzEqZPny5vb2+99NJL+v777xUWFqb4+PhKfT8jI0MxMTEKCAjQ448/ruHDhysvL6+Soy9feHi4vvzyS02ZMkUxMTFyOBxq06aNBg8eXKmHAt9www2un1NTU/Xee++pTZs2Onz4sAICAvSvf/1LS5cu1YkTJxQWFqZx48bpiSeekCSNGDFCq1ev1oABA3Tq1CklJiZqzJgxVbqf5bEZY8xV662eyc/Pl91uV15enoKCgqq1r+TkZGncOLe79pLz8qT586vssQQAUJucO3dOGRkZioiIkL+/v6eHgxqmvN+Pyvz95hopAAAAiwhSAAAAFhGkAAAALCJIAQAAWESQAgAAsIggBQAAYBFBCgAAwCKCFAAAgEWsbA4AqFccDodSU1Ovap+RkZFV9tiSw4cPKyIiQjt37lSvXr2qZJvV6bbbblOvXr2UkJBw1ftu27atJkyYoAkTJlRbHwQpAEC9kpqaqocfTldgYGWegGfdmTPpSkwUT5m4jNWrV2vhwoVKS0uTw+FQ165dNXPmTMXExHh6aBVCkAIA1DuBgd1ltxNsaoIvvvhCd9xxh1599VU1adJEiYmJuvvuu7Vt2za3Z/DVVFwjBQBADeN0OjV37lx16NBBfn5+at26tWbNmuVWc+jQIQ0YMEABAQHq2bOnUlJSXJ+dOHFCo0aNUsuWLRUQEKDu3btr+fLlbt+/7bbbNH78eE2ePFnNmjVTaGioZs6c6VZjs9n07rvv6t5771VAQIA6duyotWvXutXs2bNHQ4cOVaNGjRQSEqK4uDjl5uZWeF8TEhI0efJk/eIXv1DHjh316quvqmPHjvr73//uqhkzZoyGDx+u1157TWFhYWrevLmeeuopnT9/3lWTk5Oju+++Ww0bNlRERIT++te/VngMV4IgBQBADTN16lTNnTtX06dP1549e/Tee+8pJCTErWbatGmaNGmS0tLSdN1112nUqFEqKiqSdOGBvJGRkfroo4/0zTff6PHHH1dcXJy2bdvmto2lS5cqMDBQ27Zt0+9//3u98sorSkpKcqt5+eWXNXLkSO3evVtDhw7VAw88oJMnT0qSsrKy1L9/f/Xq1Uvbt2/XJ598oh9++EEjR460vO9Op1OnT59Ws2bN3No3bdqkgwcPatOmTVq6dKmWLFmiJUuWuD4fM2aMDh8+rM8++0x/+9vftGDBAuXk5FgeR0Vxag8AgBrk9OnTeuONNzR//nyNHj1aktS+fXvdcsstbnWTJk3SnXfeKelC2Onatau+++47derUSddee60mTZrkqn366af1ySef6P3331dUVJSrvUePHpoxY4YkqWPHjpo/f742btyoO+64w1UzZswYjRo1SpL06quv6o9//KO+/vprDR48WAsXLlTv3r316quvuur//Oc/q1WrVtq/f7+uu+66Su//66+/rjNnzpQKY02bNtX8+fPl5eWlTp066c4779TGjRs1duxY7d+/Xx9//LG++uor1/4tXrxYnTt3rnT/lUWQAgCgBtm7d68cDocGDhxYbl2PHj1cP4eFhUm6cHqrU6dOKi4u1pw5c7Ry5UodO3ZMDodDDodDgYGBl91GyXYuPYpzcU1gYKAaN27sqklNTdWmTZvUqFGjUuM7ePBgpYPU8uXLNXPmTH344Ydq0aKF22ddu3aVl5eX21jT09MlXZgzb29v9enTx/V5p06d1KRJk0r1bwVBCgCAGqRhw4YVqvPx8XH9bLPZJF04LSZdOKrzhz/8QQkJCerevbsCAwM1YcIEFRYWXnYbJdsp2UZFapxOp+6++27NnTu31PhKwl1FrVy5Uo8++qjef/993X777aU+L28cxhhX29XGNVIAANQgHTt2VMOGDbVx40bL29iyZYuGDRumBx98UD179lS7du104MCBKhzlBb1799a3336rtm3bqkOHDm6vS49+lWf58uUaM2aM3nvvPdfpysro3LmzioqKtH37dlfbvn37dOrUqUpvq7IIUgAA1CD+/v6aMmWKJk+erGXLlungwYP66quvtHjx4gpvo0OHDkpKSlJycrL27t2rJ554QtnZ2VU+1qeeekonT57UqFGj9PXXX+vQoUNav369HnnkERUXF1doG8uXL9dDDz2k119/XTfddJOys7OVnZ2tvLy8Co/j+uuv1+DBgzV27Fht27ZN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5HA4fn7nAABAveDtyc4nTpyouLg49enTR3379tWiRYuUmZmp+Ph4SRdOlR07dkzLli2TdOEOvfnz52vixIkaO3asUlJStHjxYtfdeJL0zDPP6NZbb9XcuXM1bNgwffjhh9qwYYO2bt1a4X7PnDmjWbNm6Z577lFYWJhOnDihBQsW6N///rd+9atfXcUZAgAANZlHg1RsbKxOnDihV155RVlZWerWrZvWrVunNm3aSJKysrLc1naKiIjQunXr9Oyzz+qtt95SeHi43nzzTY0YMcJVEx0drRUrVujFF1/U9OnT1b59e61cuVJRUVEV7tfLy0v/+te/tHTpUuXm5qp58+b6xS9+oS1btqhr165XaXYAAEBN59F1pOo61pECAKD2qRXrSAEAANR2BCkAAACLCFIAAAAWEaQAAAAsIkgBAABYRJACAACwiCAFAABgEUEKAADAIoIUAACARQQpAAAAiwhSAAAAFhGkAAAALLIUpDIyMqp6HAAAALWOpSDVoUMHDRgwQH/5y1907ty5qh4TAABArWApSO3atUs33HCDnnvuOYWGhuqJJ57Q119/XdVjAwAAqNEsBalu3bpp3rx5OnbsmBITE5Wdna1bbrlFXbt21bx583T8+PGqHicAAECNc0UXm3t7e+vee+/V//7v/2ru3Lk6ePCgJk2apJYtW+qhhx5SVlZWVY0TAACgxrmiILV9+3Y9+eSTCgsL07x58zRp0iQdPHhQn332mY4dO6Zhw4ZV1TgBAABqHG8rX5o3b54SExO1b98+DR06VMuWLdPQoUPVoMGFXBYREaE//elP6tSpU5UOFgAAoCaxFKQWLlyoRx55RA8//LBCQ0PLrGndurUWL158RYMDAACoySwFqaSkJLVu3dp1BKqEMUZHjx5V69at5evrq9GjR1fJIAEAAGoiS9dItW/fXrm5uaXaT548qYiIiCseFAAAQG1gKUgZY8ps/+mnn+Tv739FAwIAAKgtKnVqb+LEiZIkm82ml156SQEBAa7PiouLtW3bNvXq1atKBwgAAFBTVSpI7dy5U9KFI1Lp6eny9fV1febr66uePXtq0qRJVTtCVBmns1Dp6ftKtUdGRsrPz88DIwIAoHarVJDatGmTJOnhhx/WG2+8oaCgoGoZFKpHQcE+zZp1VsHB/2k7cyZdiYlSdHS05wYGAEAtZemuvcTExKoeB64S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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "_,ax = plt.subplots()\n", + "sns.histplot(ch1.flatten(),bins=100, color='red', label='channel 1st', stat='density')\n", + "sns.histplot(ch2.flatten(),bins=100, color='blue', label='channel 2nd', stat='density')\n", + "ax.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "channel 1 [ 0 193 448 1208 25832 65535]\n", + "channel 2 [ 32 533 967 2092 9282 65535]\n" + ] + } + ], + "source": [ + "print('channel 1', np.quantile(ch1,[0.0, 0.01, 0.1, 0.5, 0.99,1]).astype(np.int32))\n", + "print('channel 2', np.quantile(ch2,[0.0, 0.01, 0.1, 0.5, 0.99,1]).astype(np.int32))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "usplit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "e959a19f8af3b4149ff22eb57702a46c14a8caae5a2647a6be0b1f60abdfa4c2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/tiff_viewer.ipynb b/denoisplit/notebooks/tiff_viewer.ipynb new file mode 100644 index 0000000..69f1964 --- /dev/null +++ b/denoisplit/notebooks/tiff_viewer.ipynb @@ -0,0 +1,297 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from skimage.io import imread\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "fpath = '/group/jug/ashesh/data/Dao4Channel/SIM_3color_1channel_group1.tif'\n", + "data = imread(fpath, plugin='tifffile')\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(16,4),ncols=4)\n", + "idx = 15\n", + "ax[0].imshow(data[idx,::3,::3,0])\n", + "ax[1].imshow(data[idx,::3,::3,1])\n", + "ax[2].imshow(data[idx,::3,::3,2])\n", + "ax[3].imshow(data[idx,::3,::3,3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from nd2reader import ND2Reader\n", + "\n", + "def load_nd2(fpaths):\n", + " \"\"\"\n", + " Load .nd2 images.\n", + " \"\"\"\n", + " images = []\n", + " for fpath in fpaths:\n", + " with ND2Reader(fpath) as img:\n", + " print(img.get_frame_2D(c=0).shape)\n", + " # channels are the last dimension.\n", + " img = np.concatenate([x[..., None] for x in img], axis=-1)\n", + " images.append(img[None])\n", + " # number of images is the first dimension.\n", + " return np.concatenate(images, axis=0)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from nd2reader import ND2Reader\n", + "\n", + "\n", + "datadir = '/group/jug/ashesh/data/TavernaSox2Golgi/acquisition2/Test1_Slice1/'\n", + "fnames = os.listdir(datadir)\n", + "fpaths = [os.path.join(datadir, fname) for fname in fnames]\n", + "with ND2Reader(fpaths[0]) as reader:\n", + " data = []\n", + " for z in range(reader.metadata['total_images_per_channel']):\n", + " channels = []\n", + " for c in range(len(reader.metadata['channels'])):\n", + " img = reader.get_frame_2D(c=c, z=z)\n", + " channels.append(img[..., None])\n", + " img = np.concatenate(channels, axis=-1)\n", + " data.append(img[None])\n", + " data = np.concatenate(data, axis=0)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_,ax = plt.subplots(figsize=(18,6),ncols=3)\n", + "idx = 8\n", + "print(idx)\n", + "ax[0].imshow(data[idx,...,0])\n", + "ax[1].imshow(data[idx,...,1])\n", + "ax[2].imshow(data[idx,...,2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "reader.metadata.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from nd2reader import ND2Reader\n", + "import numpy as np\n", + "\n", + "def get_start_end_index(key):\n", + " \"\"\"\n", + " Few start and end frames are not good in some of the files. So, we need to exclude them.\n", + " \"\"\"\n", + " start_index_dict ={\n", + " 'Test1_Slice1/1.nd2': 8,\n", + " 'Test1_Slice1/2.nd2': 1,\n", + " 'Test1_Slice1/3.nd2': 3,\n", + " 'Test1_Slice2_a/4.nd2': 10,\n", + " 'Test1_Slice2_a/5.nd2': 10,\n", + " 'Test1_Slice2_a/6.nd2': 10,\n", + " 'Test1_Slice2_b/7.nd2': 1,\n", + "\n", + " 'Test1_Slice3_b/4.nd2': 1,\n", + " 'Test1_Slice3_b/5.nd2': 1,\n", + " 'Test1_Slice3_b/6.nd2': 1,\n", + "\n", + " 'Test1_Slice4_a/1.nd2': 1,\n", + " 'Test1_Slice4_a/2.nd2': 1,\n", + " 'Test1_Slice4_a/3.nd2': 1,\n", + "\n", + " 'Test1_Slice4_b/4.nd2': 1,\n", + " 'Test1_Slice4_b/5.nd2': 1,\n", + " 'Test1_Slice4_b/6.nd2': 1,\n", + "\n", + " }\n", + " # excluding this index\n", + " end_index_dict = {\n", + " 'Test1_Slice2_b/7.nd2': 18,\n", + " 'Test1_Slice2_b/8.nd2': 18,\n", + " 'Test1_Slice2_b/9.nd2': 18,\n", + "\n", + " 'Test1_Slice3_a/1.nd2': 15,\n", + " 'Test1_Slice3_a/2.nd2': 15,\n", + " 'Test1_Slice3_a/3.nd2': 15,\n", + "\n", + " 'Test1_Slice3_b/4.nd2': 18,\n", + " 'Test1_Slice3_b/5.nd2': 18,\n", + " 'Test1_Slice3_b/6.nd2': 18,\n", + "\n", + " 'Test1_Slice4_a/1.nd2': 19,\n", + " 'Test1_Slice4_a/2.nd2': 19,\n", + " 'Test1_Slice4_a/3.nd2': 19,\n", + "\n", + " }\n", + " return start_index_dict.get(key), end_index_dict.get(key)\n", + "\n", + "def load_nd2(fpath):\n", + " fname = os.path.basename(fpath)\n", + " parent_dir = os.path.basename(os.path.dirname(fpath))\n", + " key = os.path.join(parent_dir, fname)\n", + " start_z, end_z = get_start_end_index(key)\n", + " with ND2Reader(fpath) as reader:\n", + " data = []\n", + " if start_z is None:\n", + " start_z = 0\n", + " if end_z is None:\n", + " end_z = reader.metadata['total_images_per_channel']\n", + "\n", + " for z in range(start_z, end_z):\n", + " channels = []\n", + " for c in range(len(reader.metadata['channels'])):\n", + " img = reader.get_frame_2D(c=c, z=z)\n", + " channels.append(img[..., None])\n", + " img = np.concatenate(channels, axis=-1)\n", + " data.append(img[None])\n", + " data = np.concatenate(data, axis=0)\n", + " return data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "datadir = '/group/jug/ashesh/data/TavernaSox2Golgi/acquisition2/Test1_Slice2_b/'\n", + "fnames = os.listdir(datadir)\n", + "fpaths = [os.path.join(datadir, fname) for fname in fnames]\n", + "fpaths\n", + "data = load_nd2(fpaths[2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fpaths[2]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m0 = np.mean(data[...,0])\n", + "std0 = np.std(data[...,0])\n", + "m1 = np.mean(data[...,1])\n", + "std1 = np.std(data[...,1])\n", + "m2 = np.mean(data[...,2])\n", + "std2 = np.std(data[...,2])\n", + "print(m0,m1,m2)\n", + "print(std0,std1,std2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test1_Slice1/1.nd2\n", + "# 649.9898366076771 251.18364132567336 346.4810821832817\n", + "# 420.73377102091223 123.63942369663152 238.69477184974224\n", + "\n", + "# 575.911845626149 245.9114324212272 306.2189803083463\n", + "# 311.0105221812719 110.20645501024354 167.05982606418527\n", + "\n", + "# 568.6233754334154 239.50470075900554 305.3726447539201\n", + "# 325.94647030213605 107.5387414773112 177.32005584439108\n", + "\n", + "# 719.5509740115756 261.24814812236497 387.2313534937254\n", + "# 490.3397713688641 138.94604213692025 290.6153710377726\n", + "\n", + "# 580.9775729861954 247.18915115549945 311.5311118021006\n", + "# 327.880092274782 123.17043062753785 171.58009417372307" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "reader.metadata['total_images_per_channel'] # 25\n", + "reader.metadata['channels'] #['555-647', 'GT_Cy5', 'GT_TRITC']\n", + "reader.metadata['fields_of_view'] # [0]\n", + "reader.metadata['num_frames'] # 1\n", + "reader.metadata['z_levels'] # range(0,25)\n", + "reader.metadata['height'] #1608\n", + "reader.metadata['width'] # 1608" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/notebooks/training_data_size.ipynb b/denoisplit/notebooks/training_data_size.ipynb new file mode 100644 index 0000000..22b5006 --- /dev/null +++ b/denoisplit/notebooks/training_data_size.ipynb @@ -0,0 +1,238 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "denoiSplitNM_NL1 = {\n", + " '0.1': 26.8,\n", + " '0.3': 29.2,\n", + " '0.5': 29.1,\n", + " '1': 30,\n", + "}\n", + "denoiSplit_NL1 = {\n", + " '0.1': 26,\n", + " '0.3': 27.7,\n", + " '0.5': 29.6,\n", + " '1': 29.9,\n", + "}\n", + "\n", + "denoiSplitNM_NL1_5 = {\n", + " '0.1': 24.5,\n", + " '0.3': 27.3,\n", + " '0.5': 28.7,\n", + " '1': 29,\n", + "}\n", + "denoiSplit_NL1_5 = {\n", + " '0.1': 23.8,\n", + " '0.3': 25.6,\n", + " '0.5': 28.4,\n", + " '1': 27.4,\n", + "}\n", + "\n", + "denoiSplitNM_NL2 = {\n", + " '0.1': 25.6,\n", + " '0.3': 25.6,\n", + " '0.5': 27.2,\n", + " '1': 27,\n", + "}\n", + "denoiSplit_NL2 = {\n", + " '0.1': 23.6,\n", + " '0.3': 24.8,\n", + " '0.5': 26.5,\n", + " '1': 27.9,\n", + "}\n", + "\n", + "denoiSplitNM_NL4 = {\n", + " '0.1': 23.1,\n", + " '0.3': 23.2,\n", + " '0.5': 23.3,\n", + " '1': 24.8,\n", + "}\n", + "denoiSplit_NL4 = {\n", + " '0.1': 23.2,\n", + " '0.3': 23.1,\n", + " '0.5': 23,\n", + " '1': 24.4,\n", + "}\n", + "\n", + "denoiSplit = [denoiSplit_NL1, denoiSplit_NL1_5, denoiSplit_NL2, denoiSplit_NL4]\n", + "denoiSplitNM = [denoiSplitNM_NL1, denoiSplitNM_NL1_5, denoiSplitNM_NL2, denoiSplitNM_NL4]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Percentage decrease with training data. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "def decrement_metric(dict, key):\n", + " return 100 * (dict['1'] - dict[key])/dict['1']\n", + "\n", + "def decrement_metric2(dict, key):\n", + " return (dict['1'] - dict[key])\n", + "\n", + "withNM_decrements = []\n", + "withoutNM_decrements = []\n", + "for nlevel in range(4):\n", + " withNM = denoiSplitNM[nlevel]\n", + " withoutNM = denoiSplit[nlevel]\n", + "\n", + " withNM_decrements_level = [decrement_metric(withNM, key) for key in ['0.1', '0.3', '0.5']]\n", + " withoutNM_decrements_level = [decrement_metric(withoutNM, key) for key in ['0.1', '0.3', '0.5']]\n", + " withNM_decrements.append(withNM_decrements_level)\n", + " withoutNM_decrements.append(withoutNM_decrements_level)\n", + " \n", + "withNM_decrements = np.array(withNM_decrements)\n", + "withoutNM_decrements = np.array(withoutNM_decrements)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "withNM_decrements.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(withNM_decrements.mean(axis=0))\n", + "print(withoutNM_decrements.mean(axis=0))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(withNM_decrements.mean(axis=1))\n", + "print(withoutNM_decrements.mean(axis=1))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Questions which can be asked\n", + "1. How the decrement happens with training data? \n", + "2. How the decrement happens with level of noise? " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "withNM_decrements.mean(axis=0).tolist() + [0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "plt.plot(1 - np.array([0.1, 0.3, 0.5, 1]),withNM_decrements.mean(axis=0).tolist() + [0], marker='o', label= 'With NM')\n", + "plt.plot(1 - np.array([0.1, 0.3, 0.5, 1]),withoutNM_decrements.mean(axis=0).tolist() + [0], marker='o', label= 'Without NM')\n", + "plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "x = np.array([0.1, 0.3, 0.5])\n", + "df_NM = pd.Series(withNM_decrements.mean(axis=0).tolist(), index=x).to_frame('withNM')\n", + "df_without =pd.Series(withoutNM_decrements.mean(axis=0).tolist(), index=x).to_frame('withoutNM')\n", + "df = pd.concat([df_NM, df_without], axis=1)\n", + "df.index.name='Training Data Fraction'\n", + "df \n", + "# plt.bar(np.array([0.1, 0.3, 0.5, 1]), withNM_decrements.mean(axis=0).tolist() + [0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ax = df.plot.bar(fontsize=10, )\n", + "ax.set_ylabel('% Decrement in PSNR', fontsize=10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df.index.name = 'DataFraction'\n", + "df = df.reset_index()\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import seaborn as sns\n", + "sns.barplot(df, x=\"DataFraction\", y=\"withNM\")\n", + "\n", + "# ax = sns.barplot(flights, x=\"year\", y=\"passengers\", estimator=\"sum\", errorbar=None)\n", + "# ax.bar_label(ax.containers[0], fontsize=10);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/denoisplit/sampler/__pycache__/base_sampler.cpython-39.pyc b/denoisplit/sampler/__pycache__/base_sampler.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1de9846095b24f57d5e079019c4d4ec0fcb1290f GIT binary patch literal 1390 zcmZWp%Z?*86t(M-R9>hV8ir{h;pJqLh!wLKA;fEhkRqf;EDDV*ciHKxP_MBa(TUP5 zNTXTt1%TAOH^O8IQNi)3vgD8N^w4pTx3)^cU>tg6bank z+tD3B^$)6#a3HV0nC4BTro!aPpeXKyL`Wxv@6{M zb4YRX1_%-jX$QXJ0Ok7lfIE|0L^7noZNqs0{Zr^>2*Sb>*wUZi2|&q$+4{Y2^1`rM zDd3ZBun-0Ey;8MR5{mHFtg&C-Yd+Vy(POF~fGPdXop=Z{7hy$kX3!&{>!ZW)aPwcG zArtWt;ma~J5F2t$ZV0f6UQ$afux$bC0vVlvl&xv*5VMkw_NwNcizt8wV_aXn*&wj4;}DF1JE$T+Js z=O=K__@53kw17~*L(1_OrGvy{Rkm6m_|Z};Xk!ZS=Rsn literal 0 HcmV?d00001 diff --git a/denoisplit/sampler/__pycache__/default_grid_sampler.cpython-39.pyc b/denoisplit/sampler/__pycache__/default_grid_sampler.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..311496412397707fc502d2e24aa5576e8ed8e1e2 GIT binary patch literal 901 zcmZWn!EV$r5Vd0`o2C>&g$m+=uPdRfxFQ4yka|ITpqzZM+}OKunr;YBRdR;L+4^Pixz@}mEtzqwYc;E6%Vt_D=HX!88zr1s zYbI^i&e^5$H8ZW!S7q@V(9m>@!{IyW^qFiHR`*p5?h6p!l6wM%MjQh{AjXMG6uCv5 zDhfo>aQs2ftU$;CJ%4r``+4pkA3voAxK&^2;khNI=7IoUrcxGP+$PNd0w|=7j0kHWy zozz{UC(;3IU2eBY)hRtuy6w!_!WzFd-C(-y5Fs?oVh6homWx%OrZxV4Y+w!w;S4{; zCwTq%|JjxC<`m|d3(?9(3lRz-nocckwC@S=Whw3MWF&;@Dk1t~`02oWPd$vWIJ^T` zF23~~Q#wS(S$_h4NZVzzSoI^Y`Lm(2p`3D8PI(URQ|z2RKFA?^4ClxBO53#F~W2{t>7gy<$Lw-Yk#awd;Q7yQS?e#$hVd^doPHb>uHsGpfkYUBMTXDthF+HjJ#gKFZ7Cjkr|@omqghw%R+a~uVB=is9;nD zGUvs-Ulmn=a_Nlt2+gGj0-Rh)iI6t3b;UO^)D_Ixgw;18JIn&q4MrhF^kjBjhvg>3Pr zyep%vSjc-@sZ?RwSB-}(bCgVnDsFPfn>>`K_Z_^+8j=wk8G(@^?HY%a$COA-VPMs~ zp&0tqt*jJuNPG}=k~A|T8D~6bWOG4tsDeR1>7<>0T<4jU$f)HPXMG&p#W@zK|P2#{JH%LDWg}Y@)MCuB44loXQyD_kwV^6O3!u2YZp0mZOp7ucQZQ~4y4kWfTF@^&<=x+xTna9G>DzN`g2#@q;V!n`wJsXRP{jdD?c6T5j}ADg zqiZc22WIMwz;x%xz)_|#hy1`wS=WUk%~g1o7Dvew=I1n~fH5|t7ok?`n2&6D4&x78 zSS^0pI9)nFD>2<>bW78Adt6hV);Rh2+Xj5b^ZJxV9`^FH$EZSnsDMURNYYTHgp$mavCx@H-b`rF@R^yCHeMoUIHDk+6=}XP z*b2zG$X59CY?ZCCMf|?$wDo9k(et!GR}og!1xhYb@+KwPn%_bWZYYOXQ%2DQW_m?0 zQ9o_hxm`1hFMEpWo^97ZLF*HCT@+lHW4pG5t?k+o?tKG(*b@bO9c|w(?7NgL zoksH5xYf5Hb8OdSaFd7f6WdPygu)Yct(~&AV^iC-HFC6N+hp0=>fI6YU3UduYnLZ) zzi<2=4gsxRS^!{;F7KAQWqb+D;0mjV z=j1_vMkP+09+B^#a;+ez5}qs>oTTGUkMw3K}5h zQ%s=pJE~^@jG9fJL5XCP=6cT9^ z!UP5iqSg0F8X*aQBHmHoCCLR1Vq&jswb_1s!d+O3x*JA8KFccE#%y_aL)8f>=gOS4%;m;g^<|FdFk{JbZXyj1&G)_UQttR+JwYiT=7YZNoCpVDpv z9pb&(RNb|ix@-Lw#$Yg9eJ%aCUu(9*IF?aT3n8r~#dNYTfdB+x>(d(bGE}ANNKOG- z{eUVjA-P^JWEO>#>RqbR(0iS7npNopbJ`)^%uFnB>=XSt(CpY}0)BpF>QwV!*_&We z{gh;AV9d}#{PjNGoFr`z6zQ33yvnK|$SPl9&%}jh$R~n4iYAFl-XVFo%;+Fb2d(4< z5gHs>6zzBIv1cT|<{Y`l0elK&A_OR8$MUEV@U#3$g zpGTK3?Su0e^BRe`N~7&isc=vIobpby-S1#-O>Is%7{IS)rDi{FhG0OvnU!`Ty~v~; z4rJZSU34++r{E+aEA=CiOzTnZ0Cel2vsC+_ESLff*mtOKo4aLl;pUZ5x!NHz3j;soxH{0t&05w@B zAF4RIX=~7tl|DPY4F45<$JZBo-7|>#p^$1l-+lgP!PvJepM*>`q&`B?cW=s8`m6px zh15tZRPRx8gOV*uUPJOjVY#k1$>(p|_o-^-qenGrKN142g#A9W%vQRx=-SWV^ U7Jd%ye)OeZneoRKheh!J11`r)kpKVy literal 0 HcmV?d00001 diff --git a/denoisplit/sampler/__pycache__/nbr_sampler.cpython-39.pyc b/denoisplit/sampler/__pycache__/nbr_sampler.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bbcc04e6447178898f51ede0072bc387205080f GIT binary patch literal 3726 zcmZ`*OOG4J5$>J`U&~#sR%=U^6=#wdi5L)+_n|mgIDxrqC-8-b$nb%QFqmccl0y$? zxIIlt%M5+UD)31_&T$Ov0=ej(ACTWM*B}S|1)uy?56OK&Lv*vdy1J^myXvb7R#$5b z-~YeiN4;B&{f{P>KL?Xf(b7-Q3D#wT3oGJX3;%XxkDRW<*&ms3g!_^SS30M5*TuXf z%9xj>i+M>{PgtW8WSp_u7qO=YVd|y9XdFq^^qx!ac@S$)C*COdT6*b3Nw5Uk3y-`c zmfkqfy@A(HWa@=6xb#4JheT`ELY;a?$wYav4Euw_M5SI3r3sk9Y8atrE}`Ys+QmK( z>Vw!zl#ogaFO|m=8TX`@9AVdZ0-4y{SIK0Y676xT){Z^-!WcZ40CE~mrMLB)y;^&# z+1_rpcbe_pX8Uo|+uv&LZ#VaMn)|!WeasKGng`p>gPrEVZu0>1&$eo{KZGjPo{Z#3 z;^+_CTMaUbPSyiK1<_)yRojjQ7`7WtZ%2uT?Hvqu_26N97lX$%c-&Yp<5;-6NFM2? zr*I+o)5*B$9VS{QquLuhA?q}FUVc(sevb&3KYDHY(rt8-bva&~UfTK>|CSx$#f9^- z-nE4*N-tU05oJ-qzxyq7Shs{XuI4NIK`Q6sJFj_OQc_P;+_R0`qN6csqW|<$bef&A zGoJBt&RNDY=3AMC-p<(28afy`f}wYHNnmwY9#+0%!usAm1;1d>Yj=L&f1X-TJy_tT zld)8J#rMNF)V`m)zDT9cSA63%KD}GM5{ei8D2RhTSXaYX$QQ-3Omlav;AeT&_j^&0 zrjP(xG5pB)8+PubGCIo3BG5Rf&TAJ!UvssF!@OoceEw*VjO3#r9msUhD*hhz5+NT6 z87JYBaTMxen3~}{79Pci%Ab#0;}cbZv~{$!j*jsg@Mep2ar~EVa z^x@3V;2MT{m;K#(kDa;a>?`alXdkl~KlbK_Q*`=9N!`U??y4Z}%iNA+tmq;Y0bcI( zlJQByHs{H!sScF(;S)Lcub++_NlWGX?_*zT(2`fU!|(C?Hy^?Zg0l84*o%NbUEMNv!w0 zLGm04BR&CsYl7*E6p#**NhHXn$0~Ui3MpFNmjiiX&~dC}N|-y(4~McJ#&H<;NyIX< zAXhBxxc+~|ir;N}&%-G4MiTjCn=COIQk?CsGdl@*MT3GK{DQ&ulvt}C=`BQg@Pb7&DZ=ZccE5^mk`i+f5R=X;x-XB(B-RF z*z;T0yy2 z{6lK0(osx0Xjp0mOnJ>vjDLY-pzc?o-#`S)CqD4xBN9Kyyc>osn66+Ssi8YHhW!`* zu9@a%CKv>NpPd7uX9nX0n{f4O?H1^EYR!0`%`7xqmojhx6^Anf*RX6jztVhIIjhqA zoX3{1W^QJm)iRe-s##kB%GPOq&Sxd?tq#|+QsxT#m8Jf9ljHbVW?_Gc_8;#-Z&}|$ zQnpVmX#VCe)~o^zWpGq7_sBAdn`R_;ooFQY#>(xtu57$@<<9k$MIL(T+Q4*2d#R_H`%O~(dnvL?bJdZDQBoo zhVN$OkKsrDyYaonoQja4O}VF7G11c1uF7Lia3E(se%DC)umO}$69I8m5tlPDW2CIq_13O}88 zSIHd8l0NZt*UZ#}jM?*mjHGzMxnadxQ5h}SD~sKEWkD-K(4fin7+doLA$*koMOn53 zvFR>4#y3#{)h!1ZxXvG7yusH&BgzI}Lr$jO1M30SKg4{EuUpd(Zh*!W;a4J*V1t^8 zPzvxqm7a(pygfXJJm5ZR4eiXMuuioJ)gp+K4~$3f4oVMGY0!nLDs@yg6c4_K(W35H zi6^5)*{RI+U9GH4iSPs)3Je4SuH(?t&FjaZ5(_n5r%^G`t3DuYKc$Yav+y3$Ta+9g zjV=^j)EGa*0=cKrR^glVie2#(Q5)sF?E50=Q8^8xQJl6w&ewIKdV|(Phf&(1l2{QM fn!?2FyQF3b?0MyrqAL15g^bbV)GEAguW$YcWe}U_ literal 0 HcmV?d00001 diff --git a/denoisplit/sampler/__pycache__/random_sampler.cpython-39.pyc b/denoisplit/sampler/__pycache__/random_sampler.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9895ae5ff42b57b573f9ea029fcbaedcfab262aa GIT binary patch literal 828 zcmZ`%y^a$x5cc10a>=DZa3C5|vP~kW5jsHuRSME=WBJxj){*yzwWCX-oG5ZF?*JvQ zzlEE0Hi<#|stCf*<>~b}B*VR~;QfJDxIT^I{D4~@I^dqQU zfLWqF;>h6@Sy74iXvJIvHa=iUzSA50-#^6RA3ezIFEN}T2mBQM#5dHPxxpUq$sR7^ z0C*fO4EWPo6KEvVQ&U}gmg{BinbkX$4E+e`stvyqF3Xkmq^y11wB7n%@Va!qr{#th zVgu(@=_4+!ay}AGBes6PmyMP@pm}Drb)N2YoiHe%%)-a!4TsZdY~BX%&mOaXq2?K| zy8k@Qt3pkMh4T5NbJMJnYARJ(>3MCm>z1}%+HRK9jwC;BC-v4dU1~QBm)kxm9OIYp zUEtl5ZdAwdO+wlXrrPJc6ouj(n&3qx*CwpbIsdvA=J=<_xvVnIo9BSr5R*u z4zf)yf&7H*(SND0IW74EA*WQ2wDDv~i>~^*`m5@$R@LOk#{&f8&!6%0s{o-t{GvY? zEFQx&4?zedutpgMO*AQKMzOb1&B`DPF!})rCW6;U1TxssEEIT-M&UJhqS*+$Xr7mA zEgOKzx4DsrW#RYxgTUf3O!FBC*`1dWfio(Ips!KJ1cSJNJDsa)q2<$Zafo#JY>>kE zzA~Fen$#|Ho2n|UE190>wpiZlpepl)OqEGZUdl8tn%a2ofiq5Pz)iYm70bL@NHgx@ z78vexGll^C(|rfiyoH?wY7vLI!UCV6E$$EjL;#U3wG=el;g)`mw#)`L{5@)!pkJUX zyu({quj17aSO+Z@>_EA z9<@oQ6A^rhJbDAKv?DwG2oZR}mw)yA;{W5e(feq9KY^euqM5@F9G+hLDr)>ccJ0N8 zIA+wPbWtPMIxpnt)E%oz$XC284Qa9you5n1m3YO4Dy&QPJG^tFT2?OL!bt0=s;nc` z+Oa|^?ZPInL|wYDSk|hLF3iEOkQvht_zdKf&s@-%9Mj5x|D{@whHxLLpJy?!_WT%_ zdm5g(q}r7K-YlFyjjpbNnYCeYJPW0f&=eldNAnlB;qzkix6>rzf~ zvy^5z-m6Jb3po+8s?~h0mEA+rL1+u#r4!S2mns+hU>UD398;CD34}F1Ho_qp-~q@J z`XRZC?~?oYJ|5y2pWv^^<;S-hbnLxn(7G|_6?7lxZoqk2i;ebp$ob1nt`9pA=b|n+ zZ&Em@OQk37c$@z?MKFyAF=n*0j3O7n>#Z-EQ!u+zTQ|jWys=7~vB+)S_{wm1y5zfz o$2a+%!$;{R*@gnEi`P5V=iK None: + """ + Grid size of 1 ensures that any random crop can be taken. + """ + super().__init__(dataset) + self._dset = dataset + self._grid_size = grid_size + self.idx_max = self._dset.idx_manager.grid_count(grid_size=self._grid_size) + + self._batch_size = batch_size + self.index_batches = None + print(f'[{self.__class__.__name__}] ') + + def init(self): + raise NotImplementedError("This needs to be implemented") + + def __iter__(self): + self.init() + start_idx = 0 + for _ in range(len(self.index_batches) // self._batch_size): + yield self.index_batches[start_idx:start_idx + self._batch_size].copy() + start_idx += self._batch_size diff --git a/denoisplit/sampler/default_grid_sampler.py b/denoisplit/sampler/default_grid_sampler.py new file mode 100644 index 0000000..9c9b6f6 --- /dev/null +++ b/denoisplit/sampler/default_grid_sampler.py @@ -0,0 +1,18 @@ +""" +The idea is one can feed the grid_size along with index. +""" +import numpy as np + +from denoisplit.sampler.base_sampler import BaseSampler + + +class DefaultGridSampler(BaseSampler): + """ + Randomly yields an index and an associated grid size. + """ + + def init(self): + self.index_batches = [] + l1_idx = np.random.randint(low=0, high=self.idx_max, size=len(self._dset)) + grid_size = np.array([self._grid_size] * len(l1_idx)) + self.index_batches = list(zip(l1_idx, l1_idx, grid_size)) diff --git a/denoisplit/sampler/intensity_aug_sampler.py b/denoisplit/sampler/intensity_aug_sampler.py new file mode 100644 index 0000000..e632bf4 --- /dev/null +++ b/denoisplit/sampler/intensity_aug_sampler.py @@ -0,0 +1,140 @@ +import numpy as np +from torch.utils.data import Sampler + + +class LevelIndexIterator: + + def __init__(self, index_list) -> None: + self._index_list = index_list + self._N = len(self._index_list) + self._cur_position = 0 + + def next(self): + output_pos = self._cur_position + self._cur_position += 1 + self._cur_position = self._cur_position % self._N + return self._index_list[output_pos] + + def next_k(self, N): + return [self.next() for _ in range(N)] + + +class IntensityAugValSampler(Sampler): + INVALID = -955 + + def __init__(self, dataset, grid_size, batch_size, fixed_alpha_idx=-1) -> None: + super().__init__(dataset) + # In validation, we just look at the cases which we'll find in the test case. alpha=0.5 is that case. This corresponds to the -1 class. + self._alpha_idx = fixed_alpha_idx + self._N = len(dataset) + self._batch_N = batch_size + self._grid_size = grid_size + + def __iter__(self): + num_batches = int(np.ceil(self._N / self._batch_N)) + for batch_idx in range(num_batches): + start_idx = batch_idx * self._batch_N + end_idx = min((batch_idx + 1) * self._batch_N, self._N) + # 4 channels: ch1_idx, ch2_idx, grid_size, alpha_idx + batch_data_idx = np.ones((end_idx - start_idx, 4), dtype=np.int32) * self.INVALID + batch_data_idx[:, 0] = np.arange(start_idx, end_idx) + batch_data_idx[:, 1] = batch_data_idx[:, 0] + batch_data_idx[:, 2] = self._grid_size + batch_data_idx[:, 3] = self._alpha_idx + yield batch_data_idx + + +class IntensityAugSampler(Sampler): + INVALID = -955 + + def __init__(self, + dataset, + data_size, + ch1_alpha_interval_count, + num_intensity_variations, + batch_size, + fixed_alpha=None) -> None: + super().__init__(dataset) + self._dset = dataset + self._N = data_size + self._alpha_class_N = ch1_alpha_interval_count + self._fixed_alpha = fixed_alpha + self._batch_N = batch_size + self._intensity_N = num_intensity_variations + assert batch_size % self._intensity_N == 0 + # We'll be using grid_size of 1, this allows us to pick from any random location in the frame. However, + # as far as one epoch is concerned, we'll use data_size. So, values in self.idx will be much larger than + # self._N + self._grid_size = 1 + self.idx = np.arange(self._dset.idx_manager.grid_count(grid_size=self._grid_size)) + self.batches_idx_list = None + self.level_iters = None + print(f'[{self.__class__.__name__}] Alpha class count:{self._alpha_class_N}') + + def __iter__(self): + """ + Here, we make sure that self._intensity_N many intensity variations of the same two channels are fed + as input. + """ + self.init() + for one_batch_idx in self.batches_idx_list: + alpha_idx_list, idx_list = one_batch_idx + + # 4 channels: ch1_idx, ch2_idx, grid_size, alpha_idx + batch_data_idx = np.ones((self._batch_N, 4), dtype=np.int32) * self.INVALID + # grid size will always be 1. + batch_data_idx[:, 0] = idx_list + batch_data_idx[:, 1] = idx_list + batch_data_idx[:, 2] = self._grid_size + batch_data_idx[:, 3] = alpha_idx_list + + assert (batch_data_idx == self.INVALID).any() == False + yield batch_data_idx + + def init(self): + self.batches_idx_list = [] + total_size = self._N + num_batches = int(np.ceil(total_size / self._batch_N)) + idx = self.idx.copy() + np.random.shuffle(idx) + self.idx_iterator = LevelIndexIterator(idx) + + idx = self.idx.copy() + np.random.shuffle(idx) + + for _ in range(num_batches): + idx_list = self.idx_iterator.next_k(self._batch_N // self._intensity_N) + alpha_list = [] + for _ in idx_list: + if self._fixed_alpha: + alpha_idx = np.array([-1] * self._alpha_class_N) + else: + alpha_idx = np.random.choice(np.arange(self._alpha_class_N), size=self._intensity_N, replace=False) + alpha_list.append(alpha_idx) + + alpha_list = np.concatenate(alpha_list) + idx_list = np.tile(np.array(idx_list).reshape(-1, 1), (1, self._intensity_N)).reshape(-1) + self.batches_idx_list.append((alpha_list, idx_list)) + + +if __name__ == '__main__': + from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager + grid_size = 1 + patch_size = 64 + grid_alignment = GridAlignement.LeftTop + + class DummyDset: + + def __init__(self) -> None: + self.idx_manager = GridIndexManager((6, 2400, 2400, 2), grid_size, patch_size, grid_alignment) + + ch1_alpha_interval_count = 30 + data_size = 1000 + num_intensity_variations = 2 + batch_size = 32 + sampler = IntensityAugSampler(DummyDset(), data_size, ch1_alpha_interval_count, num_intensity_variations, + batch_size) + for batch in sampler: + break + + print('') diff --git a/denoisplit/sampler/nbr_sampler.py b/denoisplit/sampler/nbr_sampler.py new file mode 100644 index 0000000..f2b630e --- /dev/null +++ b/denoisplit/sampler/nbr_sampler.py @@ -0,0 +1,87 @@ +""" +In this sampler, we want to make sure that if one patch goes into the batch, +its four neighbors also go in the same patch. +A batch is an ordered sequence of inputs in groups of 5. +An example batch of size 16: +A1,A2,A3,A4,A5, B1,B2,B3,B4,B5, C1,C2,C3,C4,C5, D1 + +First element (A1) is the central element. +2nd (A2), 3rd(A3), 4th(A4), 5th(A5) elements are left, right, top, bottom +""" +import numpy as np +from torch.utils.data import Sampler + + +class BaseSampler(Sampler): + def __init__(self, dataset, batch_size) -> None: + super().__init__(dataset) + self._dset = dataset + self._batch_size = batch_size + self.idx_manager = self._dset.idx_manager + self.index_batches = None + print(f'[{self.__class__.__name__}] ') + + def init(self): + raise NotImplementedError("This needs to be implemented") + + def __iter__(self): + self.init() + start_idx = 0 + for _ in range(len(self.index_batches) // self._batch_size): + yield self.index_batches[start_idx:start_idx + self._batch_size].copy() + start_idx += self._batch_size + + +class NeighborSampler(BaseSampler): + def __init__(self, dataset, batch_size, nbr_set_count=None, valid_gridsizes=None) -> None: + """ + Args: + nbr_set_count: how many set of neighbors should be provided. They are present in the beginning of the batch. + nbr_set_count=2 will mean 2 sets of neighbors are provided in each batch. And they will comprise first 10 instances in the batch. + Remaining elements in the batch will be drawn randomly. + """ + super().__init__(dataset, batch_size) + self._valid_gridsizes = valid_gridsizes + self._nbr_set_count = nbr_set_count + print(f'[{self.__class__.__name__}] NbrSet:{self._nbr_set_count}') + + def dset_len(self, grid_size): + return self.idx_manager.grid_count(grid_size=grid_size) + + def _add_one_batch(self): + rand_sz = int(np.ceil(self._batch_size / 5)) + if self._nbr_set_count is not None: + rand_sz = min(rand_sz, self._nbr_set_count) + + rand_idx_list = [] + rand_grid_list = [] + for _ in range(rand_sz): + grid_size = np.random.choice(self._valid_gridsizes) if self._valid_gridsizes is not None else 1 + rand_grid_list.append(grid_size) + idx = np.random.randint(self.dset_len(grid_size)) + while self.idx_manager.on_boundary(idx, grid_size=grid_size): + idx = np.random.randint(self.dset_len(grid_size)) + rand_idx_list.append(idx) + + batch_idx_list = [] + for rand_idx, grid_size in zip(rand_idx_list, rand_grid_list): + batch_idx_list.append((rand_idx, grid_size)) + batch_idx_list.append((self.idx_manager.get_left_nbr_idx(rand_idx, grid_size=grid_size), grid_size)) + batch_idx_list.append((self.idx_manager.get_right_nbr_idx(rand_idx, grid_size=grid_size), grid_size)) + batch_idx_list.append((self.idx_manager.get_top_nbr_idx(rand_idx, grid_size=grid_size), grid_size)) + batch_idx_list.append((self.idx_manager.get_bottom_nbr_idx(rand_idx, grid_size=grid_size), grid_size)) + + if self._nbr_set_count is not None and len(batch_idx_list) < self._batch_size: + grid_size = 1 # This size ensures that patch can begin at any random pixel. + idx_list = list(np.random.randint(self.dset_len(grid_size), size=self._batch_size - len(batch_idx_list))) + gridsizes = [grid_size] * len(idx_list) + batch_idx_list += zip(idx_list, gridsizes) + self.index_batches += batch_idx_list + else: + self.index_batches += batch_idx_list[:self._batch_size] + + def init(self): + self.index_batches = [] + num_batches = len(self._dset) // self._batch_size + for _ in range(num_batches): + self._add_one_batch() diff --git a/denoisplit/sampler/random_sampler.py b/denoisplit/sampler/random_sampler.py new file mode 100644 index 0000000..1b6e78d --- /dev/null +++ b/denoisplit/sampler/random_sampler.py @@ -0,0 +1,16 @@ +import numpy as np + +from denoisplit.sampler.base_sampler import BaseSampler + + +class RandomSampler(BaseSampler): + """ + Randomly yields the two indices + """ + + def init(self): + self.index_batches = [] + l1_idx = np.random.randint(low=0, high=self.idx_max, size=len(self._dset)) + l2_idx = np.random.randint(low=0, high=self.idx_max, size=len(self._dset)) + grid_size = np.array([self._grid_size] * len(l2_idx)) + self.index_batches = list(zip(l1_idx, l2_idx, grid_size)) diff --git a/denoisplit/sampler/singleimg_sampler.py b/denoisplit/sampler/singleimg_sampler.py new file mode 100644 index 0000000..7ef9ed1 --- /dev/null +++ b/denoisplit/sampler/singleimg_sampler.py @@ -0,0 +1,33 @@ +import numpy as np +from torch.utils.data import Sampler + +from denoisplit.sampler.base_sampler import BaseSampler + + +class SingleImgSampler(BaseSampler): + """ + Ensures that in one batch, one image is same across the batch. other image changes. + """ + def init(self): + self.index_batches = [] + + l1_range = self.label_idx_dict['1'] + l2_range = self.label_idx_dict['2'] + N = self._batch_size + + num_batches = len(self._dset) // N + # In half of the batches label1 image will be same. In the other half label2 image will be the same + # SI ~ single image + SI_cnt = int(np.ceil(num_batches / 2)) + + l1_SI_idx = np.random.choice(np.arange(l1_range[0], l1_range[1]), size=SI_cnt, replace=SI_cnt > self.l1_N) + l2_SI_idx = np.random.choice(np.arange(l2_range[0], l2_range[1]), size=SI_cnt, replace=SI_cnt > self.l2_N) + + l1_idx = np.random.choice(np.arange(l1_range[0], l1_range[1]), size=SI_cnt * N, replace=SI_cnt * N > self.l1_N) + l2_idx = np.random.choice(np.arange(l2_range[0], l2_range[1]), size=SI_cnt * N, replace=SI_cnt * N > self.l2_N) + for i in range(num_batches): + iby2 = i // 2 + if i % 2 == 0: + self.index_batches += list(zip([l1_SI_idx[iby2]] * N, l2_idx[iby2 * N:(iby2 + 1) * N])) + else: + self.index_batches += list(zip(l1_idx[iby2 * N:(iby2 + 1) * N], [l2_SI_idx[iby2]] * N)) diff --git a/denoisplit/sampler/twin_index_sampler.py b/denoisplit/sampler/twin_index_sampler.py new file mode 100644 index 0000000..03788e3 --- /dev/null +++ b/denoisplit/sampler/twin_index_sampler.py @@ -0,0 +1,65 @@ +from torch.utils.data import Sampler +import numpy as np +from torch.utils.data import Sampler + + +class TwinIndexSampler(Sampler): + """ + This indexer returns a tuple index instead of an integer index. + So, if batch size is 4, then something like this is returned for one batch: + [(0,4), (0,5), (31,4), (31,5)] + """ + + def __init__(self, dataset, batch_size) -> None: + super().__init__(dataset) + self._dset = dataset + self._N = len(self._dset) + + self._batch_size = batch_size + assert batch_size % 4 == 0 + self.index_batches = None + + def __iter__(self): + self.init() + for one_batch_idx in self.index_batches: + yield one_batch_idx + + def all_combinations(self, l1, l2): + """ + Returns an array with 4 tuples: every combination of l1 and l2. + """ + assert len(l1) == 2 + assert len(l2) == 2 + return [ + (l1[0], l2[0]), + (l1[0], l2[1]), + (l1[1], l2[0]), + (l1[1], l2[1])] + + def _get_batch_idx_tuples(self, label1_indices, label2_indices): + batch_indices = [] + assert len(label1_indices) % 2 == 0 + + for i in range(len(label1_indices) // 2): + batch_indices += self.all_combinations(label1_indices[2 * i:2 * i + 2], + label2_indices[2 * i:2 * i + 2]) + return batch_indices + + def init(self): + self.index_batches = [] + uniq_idx_batch = self._batch_size // 2 + + data1_idx = np.arange(self._N) + np.random.shuffle(data1_idx) + + data2_idx = np.arange(self._N) + np.random.shuffle(data2_idx) + + for batch_num in range((self._N // uniq_idx_batch)): + start = uniq_idx_batch * batch_num + end = start + uniq_idx_batch + if end > self._N: + break + + batch_idx = self._get_batch_idx_tuples(data1_idx[start:end], data2_idx[start:end]) + self.index_batches.append(batch_idx) diff --git a/denoisplit/scripts/combine_sequential_results.py b/denoisplit/scripts/combine_sequential_results.py new file mode 100644 index 0000000..c7064c6 --- /dev/null +++ b/denoisplit/scripts/combine_sequential_results.py @@ -0,0 +1,44 @@ +import argparse +import os + +import numpy as np +from tqdm import tqdm + +from denoisplit.core.tiff_reader import load_tiff, save_tiff + +# '/home/ashesh.ashesh/training/disentangle/2402/D3-M23-S0-L0/7', +# '/home/ashesh.ashesh/training/disentangle/2403/D3-M23-S0-L0/1', +# '/home/ashesh.ashesh/training/disentangle/2402/D3-M23-S0-L0/10', +# '/home/ashesh.ashesh/training/disentangle/2402/D3-M23-S0-L0/11', +# '/home/ashesh.ashesh/training/disentangle/2403/D3-M23-S0-L0/2', +# '/home/ashesh.ashesh/training/disentangle/2402/D3-M23-S0-L0/12', +# '/home/ashesh.ashesh/training/disentangle/2402/D3-M23-S0-L0/15', +# '/home/ashesh.ashesh/training/disentangle/2403/D3-M23-S0-L0/3', +# '/home/ashesh.ashesh/training/disentangle/2402/D3-M23-S0-L0/14', + +if __name__ == '__main__': + # data_dir = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk32/' + data_dir = '/group/jug/ashesh/data/paper_stats/All_P128_G64_M50_Sk0' + parser = argparse.ArgumentParser() + parser.add_argument('--ckpt', type=str, default=None) + args = parser.parse_args() + ckpt_ = args.ckpt + assert os.path.isdir(ckpt_) + + fname = 'pred_disentangle_' + '_'.join(ckpt_.strip('/').split('/')[-3:]) + '.tif' + data_dict = {} + for k in tqdm(range(1000)): + datafpath = os.path.join(data_dir, f'kth_{k}', fname) + if not os.path.exists(datafpath): + continue + print(datafpath) + data_dict[k] = load_tiff(datafpath) + + max_id = np.max(list(data_dict.keys())) + full_data = np.concatenate([data_dict[k] for k in range(max_id + 1)], axis=0) + print() + print('Data shape', full_data.shape) + print() + output_fpath = os.path.join(data_dir, fname) + save_tiff(output_fpath, full_data) + print(f'Saved to {output_fpath}') diff --git a/denoisplit/scripts/compare_configs.py b/denoisplit/scripts/compare_configs.py new file mode 100644 index 0000000..dab7287 --- /dev/null +++ b/denoisplit/scripts/compare_configs.py @@ -0,0 +1,153 @@ +""" +Here, we compare two configs. +""" +import argparse +import os + +import numpy as np +import pandas as pd + +import git +import ml_collections +from denoisplit.config_utils import load_config + + +def _compare_config(config1, config2, prefix_key=''): + keys = [] + val1 = [] + val2 = [] + for key in config1: + if isinstance(config1[key], ml_collections.ConfigDict) or isinstance(config1[key], + ml_collections.FrozenConfigDict): + nested_key, nested_val1, nested_val2 = _compare_config(config1.get(key, {}), + config2.get(key, {}), + prefix_key=f'{key}.') + keys += nested_key + val1 += nested_val1 + val2 += nested_val2 + else: + if key in config2: + if isinstance(config1[key], list) or isinstance(config1[key], tuple) or isinstance( + config1[key], np.ndarray): + unequal = tuple(config1[key]) != tuple(config2[key]) + else: + unequal = config1[key] != config2[key] + if unequal: + keys.append(prefix_key + key) + val1.append(config1[key]) + val2.append(config2[key]) + else: + keys.append(prefix_key + key) + val1.append(config1[key]) + val2.append(None) + + return keys, val1, val2 + + +def compare_raw_configs(config1, config2): + keys, val1, val2 = _compare_config(config1, config2) + keys_v2, val2_v2, val1_v2 = _compare_config(config2, config1) + for idx, key_v2 in enumerate(keys_v2): + if key_v2 in keys: + continue + assert val1_v2[ + idx] is None, 'Since this key is not present in keys, it means that it was not present in config1. So it must be none' + keys.append(key_v2) + val1.append(val1_v2[idx]) + val2.append(val2_v2[idx]) + + val1_df = pd.Series(val1, index=keys).to_frame('Config1') + val2_df = pd.Series(val2, index=keys).to_frame('Config2') + df = pd.concat([val1_df, val2_df], axis=1) + if 'workdir' in df.index: + df = df.drop('workdir') + if 'exptname' in df.index: + df = df.drop('exptname') + + return df + + +def get_df_column_name(path): + if path[-1] == '/': + path = path[:-1] + tokens = [] + depth = 3 + while depth > 0 and path != '': + d0 = os.path.basename(path) + path = os.path.dirname(path) + tokens.append(d0) + depth -= 1 + if depth > 0: + return path + + return os.path.join(*reversed(tokens)) + + +def get_changed_files(commit1, commit2): + repo = git.Repo(search_parent_directories=True) + fnames = repo.git.diff(f'{commit1}..{commit2}', name_only=True).split('\n') + return fnames + + +def compare_config(config1_path, config2_path): + """ + Compare two configs. This returns a dataframe with differing keys as index. It has two columns, one for each config. + """ + config1 = load_config(config1_path) + config2 = load_config(config2_path) + if 'encoder' not in config1.model: + config1 = ml_collections.config_dict.ConfigDict(config1) + with config1.unlocked(): + config1.model.encoder = ml_collections.ConfigDict() + assert 'decoder' not in config1.model + config1.model.decoder = ml_collections.ConfigDict() + + if 'encoder' not in config2.model: + config2.encoder = ml_collections.ConfigDict() + assert 'decoder' not in config2.model + config2.decoder = ml_collections.ConfigDict() + + c1_name, c2_name = get_df_column_name(config1_path), get_df_column_name(config2_path) + df = get_comparison_df(config1, config2, c1_name, c2_name) + return df, get_changed_files(*list(df.loc[get_commit_key()].values)) + + +def get_commit_key(): + return 'git.latest_commit' + + +def get_comparison_df(config1, config2, config1_name, config2_name): + df = compare_raw_configs(config1, config2) + df.columns = [config1_name, config2_name] + df = df.sort_index() + + commit_key = get_commit_key() + if commit_key not in df.index: + df.loc[commit_key] = [config1.git.latest_commit] * 2 + + return df + + +def display_changes(df, changed_files): + print('') + print('************CHANGED FILES************') + commit1, commit2 = list(df.loc['git.latest_commit'].values) + print(commit1, '<==>', commit2) + print() + print('\n'.join(changed_files)) + print('') + print('************CONFIG DIFFERENCE************') + + df = df.drop('git.latest_commit') + print(df) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('config1', type=str) + parser.add_argument('config2', type=str) + args = parser.parse_args() + assert os.path.exists(args.config1) + assert os.path.exists(args.config2) + df, changed_files = compare_config(args.config1, args.config2) + display_changes(df, changed_files) diff --git a/denoisplit/scripts/compare_pyconfig_pklconfig.py b/denoisplit/scripts/compare_pyconfig_pklconfig.py new file mode 100644 index 0000000..5fac95b --- /dev/null +++ b/denoisplit/scripts/compare_pyconfig_pklconfig.py @@ -0,0 +1,49 @@ +""" +Here, we compare a .py config file with a .pkl config file which gets generated from a training. +""" + +import os.path +import ml_collections + +from absl import app, flags +from ml_collections.config_flags import config_flags +from requests import delete +from denoisplit.scripts.compare_configs import (get_comparison_df, get_df_column_name, get_commit_key, + get_changed_files, display_changes) +from denoisplit.config_utils import load_config + +FLAGS = flags.FLAGS + +config_flags.DEFINE_config_file("py_config", None, "Python config file", lock_config=True) +flags.DEFINE_string("pkl_config", None, "Work directory.") +flags.mark_flags_as_required(["py_config", "pkl_config"]) + + +def main(argv): + config1 = ml_collections.ConfigDict(FLAGS.py_config) + config2 = ml_collections.ConfigDict(load_config(FLAGS.pkl_config)) + + if 'encoder' not in config2.model: + with config2.unlocked(): + config2.model.encoder = ml_collections.ConfigDict() + for key in config1.model.encoder: + if key in config2.model: + config2.model.encoder[key] = config2.model[key] + + assert 'decoder' not in config2.model + config2.model.decoder = ml_collections.ConfigDict() + for key in config1.model.decoder: + if key in config2.model: + if key == 'multiscale_retain_spatial_dims': + config2.model.decoder[key] = False + else: + config2.model.decoder[key] = config2.model[key] + + df = get_comparison_df(config1, config2, 'python_config_file', get_df_column_name(FLAGS.pkl_config)) + + changed_files = get_changed_files(*list(df.loc[get_commit_key()].values)) + display_changes(df, changed_files) + + +if __name__ == '__main__': + app.run(main) diff --git a/denoisplit/scripts/evaluate.py b/denoisplit/scripts/evaluate.py new file mode 100644 index 0000000..83f370e --- /dev/null +++ b/denoisplit/scripts/evaluate.py @@ -0,0 +1,845 @@ +import argparse +import glob +import os +import pickle +import random +import re +import sys +from copy import deepcopy +from posixpath import basename + +import matplotlib.pyplot as plt +import numpy as np +import torch +import torch.nn as nn +from skimage.metrics import structural_similarity +from torch.utils.data import DataLoader +from tqdm import tqdm + +import ml_collections +from denoisplit.analysis.critic_notebook_utils import get_label_separated_loss, get_mmse_dict +from denoisplit.analysis.lvae_utils import get_img_from_forward_output +from denoisplit.analysis.mmse_prediction import get_dset_predictions +from denoisplit.analysis.plot_utils import clean_ax, get_k_largest_indices, plot_imgs_from_idx +from denoisplit.analysis.results_handler import PaperResultsHandler +from denoisplit.analysis.stitch_prediction import stitch_predictions +from denoisplit.config_utils import load_config +from denoisplit.core.data_split_type import DataSplitType, get_datasplit_tuples +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.psnr import PSNR, RangeInvariantPsnr +from denoisplit.core.tiff_reader import load_tiff +from denoisplit.data_loader.lc_multich_dloader import LCMultiChDloader +from denoisplit.data_loader.patch_index_manager import GridAlignement +# from denoisplit.data_loader.two_tiff_rawdata_loader import get_train_val_data +from denoisplit.data_loader.vanilla_dloader import MultiChDloader, get_train_val_data +from denoisplit.sampler.random_sampler import RandomSampler +from denoisplit.training import create_dataset, create_model +from torchmetrics.image import MultiScaleStructuralSimilarityIndexMeasure + +torch.multiprocessing.set_sharing_strategy('file_system') +DATA_ROOT = 'PUT THE ROOT DIRECTORY FOR THE DATASET HERE' +CODE_ROOT = 'PUT THE ROOT DIRECTORY FOR THE CODE HERE' + + +def compute_multiscale_ssim(highres_data_, pred_): + """ + Computes multiscale ssim for each channel. + """ + ms_ssim_values = {i: None for i in range(highres_data_.shape[-1])} + for ch_idx in range(highres_data_.shape[-1]): + # tar_tmp = (highres_data_[...,ch_idx] - sep_mean_[...,ch_idx]) /sep_std_[...,ch_idx] + tar_tmp = highres_data_[..., ch_idx] + pred_tmp = pred_[..., ch_idx] + ms_ssim = MultiScaleStructuralSimilarityIndexMeasure(data_range=tar_tmp.max() - tar_tmp.min()) + ms_ssim_values[ch_idx] = ms_ssim(torch.Tensor(pred_tmp[:, None]), torch.Tensor(tar_tmp[:, None])) + output = [ms_ssim_values[i].item() for i in range(highres_data_.shape[-1])] + return output + + +def _avg_psnr(target, prediction, psnr_fn): + output = np.mean([psnr_fn(target[i:i + 1], prediction[i:i + 1]).item() for i in range(len(prediction))]) + return round(output, 2) + + +def avg_range_inv_psnr(target, prediction): + return _avg_psnr(target, prediction, RangeInvariantPsnr) + + +def avg_psnr(target, prediction): + return _avg_psnr(target, prediction, PSNR) + + +def compute_masked_psnr(mask, tar1, tar2, pred1, pred2): + mask = mask.astype(bool) + mask = mask[..., 0] + tmp_tar1 = tar1[mask].reshape((len(tar1), -1, 1)) + tmp_pred1 = pred1[mask].reshape((len(tar1), -1, 1)) + tmp_tar2 = tar2[mask].reshape((len(tar2), -1, 1)) + tmp_pred2 = pred2[mask].reshape((len(tar2), -1, 1)) + psnr1 = avg_range_inv_psnr(tmp_tar1, tmp_pred1) + psnr2 = avg_range_inv_psnr(tmp_tar2, tmp_pred2) + return psnr1, psnr2 + + +def avg_ssim(target, prediction): + raise ValueError('This function is not used anymore. Use compute_multiscale_ssim instead.') + ssim = [ + structural_similarity(target[i], prediction[i], data_range=target[i].max() - target[i].min()) + for i in range(len(target)) + ] + return np.mean(ssim), np.std(ssim) + + +def fix_seeds(): + torch.manual_seed(0) + torch.cuda.manual_seed(0) + np.random.seed(0) + random.seed(0) + torch.backends.cudnn.deterministic = True + + +def upperclip_data(data, max_val): + """ + data: (N, H, W, C) + """ + if isinstance(max_val, list): + chN = data.shape[-1] + assert chN == len(max_val) + for ch in range(chN): + ch_data = data[..., ch] + ch_q = max_val[ch] + ch_data[ch_data > ch_q] = ch_q + data[..., ch] = ch_data + else: + data[data > max_val] = max_val + return True + + +def compute_max_val(data, config): + if config.data.get('channelwise_quantile', False): + max_val_arr = [np.quantile(data[..., i], config.data.clip_percentile) for i in range(data.shape[-1])] + return max_val_arr + else: + return np.quantile(data, config.data.clip_percentile) + + +def compute_high_snr_stats(config, highres_data, pred_unnorm): + """ + last dimension is the channel dimension + """ + # assert config.model.model_type == ModelType.DenoiserSplitter or config.data.data_type == DataType.SeparateTiffData + psnr_list = [ + avg_range_inv_psnr(highres_data[..., i].copy(), pred_unnorm[..., i].copy()) + for i in range(highres_data.shape[-1]) + ] + ssim_list = compute_multiscale_ssim(highres_data.copy(), pred_unnorm.copy()) + # ssim1_hres_mean, ssim1_hres_std = avg_ssim(highres_data[..., 0], pred_unnorm[0]) + # ssim2_hres_mean, ssim2_hres_std = avg_ssim(highres_data[..., 1], pred_unnorm[1]) + print('PSNR on Highres', psnr_list) + print('Multiscale SSIM on Highres', [np.round(ssim, 3) for ssim in ssim_list]) + return {'rangeinvpsnr': psnr_list, 'ms_ssim': ssim_list} + + +def get_data_without_synthetic_noise(data_dir, config, eval_datasplit_type): + """ + Here, we don't add any synthetic noise. + """ + assert 'synthetic_gaussian_scale' in config.data or 'poisson_noise_factor' in config.data + assert config.data.synthetic_gaussian_scale > 0 + data_config = deepcopy(config.data) + if 'poisson_noise_factor' in data_config: + data_config.poisson_noise_factor = -1 + if 'synthetic_gaussian_scale' in data_config: + data_config.synthetic_gaussian_scale = None + + highres_data = get_train_val_data(data_config, data_dir, DataSplitType.Train, config.training.val_fraction, + config.training.test_fraction) + + hres_max_val = compute_max_val(highres_data, config) + del highres_data + + highres_data = get_train_val_data(data_config, data_dir, eval_datasplit_type, config.training.val_fraction, + config.training.test_fraction) + + # highres_data = highres_data[::5].copy() + upperclip_data(highres_data, hres_max_val) + return highres_data + + +def get_highres_data_ventura(data_dir, config, eval_datasplit_type): + data_config = ml_collections.ConfigDict() + data_config.ch1_fname = 'actin-60x-noise2-highsnr.tif' + data_config.ch2_fname = 'mito-60x-noise2-highsnr.tif' + data_config.data_type = DataType.SeparateTiffData + highres_data = get_train_val_data(data_config, data_dir, DataSplitType.Train, config.training.val_fraction, + config.training.test_fraction) + + hres_max_val = compute_max_val(highres_data, config) + del highres_data + + highres_data = get_train_val_data(data_config, data_dir, eval_datasplit_type, config.training.val_fraction, + config.training.test_fraction) + + # highres_data = highres_data[::5].copy() + upperclip_data(highres_data, hres_max_val) + return highres_data + + +def main( + ckpt_dir, + image_size_for_grid_centers=64, + mmse_count=1, + custom_image_size=64, + batch_size=16, + num_workers=4, + COMPUTE_LOSS=False, + use_deterministic_grid=None, + threshold=None, # 0.02, + compute_kl_loss=False, + evaluate_train=False, + eval_datasplit_type=DataSplitType.Val, + val_repeat_factor=None, + psnr_type='range_invariant', + ignored_last_pixels=0, + ignore_first_pixels=0, + print_token='', + normalized_ssim=True, + save_to_file=False, + predict_kth_frame=None, +): + global DATA_ROOT, CODE_ROOT + + homedir = os.path.expanduser('~') + nodename = os.uname().nodename + + if nodename == 'capablerutherford-02aa4': + DATA_ROOT = '/mnt/ashesh/' + CODE_ROOT = '/home/ubuntu/ashesh/' + elif nodename in ['capableturing-34a32', 'colorfuljug-fa782', 'agileschroedinger-a9b1c', 'rapidkepler-ca36f']: + DATA_ROOT = '/home/ubuntu/ashesh/data/' + CODE_ROOT = '/home/ubuntu/ashesh/' + elif (re.match('lin-jug-\d{2}', nodename) or re.match('gnode\d{2}', nodename) + or re.match('lin-jug-m-\d{2}', nodename) or re.match('lin-jug-l-\d{2}', nodename)): + DATA_ROOT = '/group/jug/ashesh/data/' + CODE_ROOT = '/home/ashesh.ashesh/' + + dtype = int(ckpt_dir.split('/')[-2].split('-')[0][1:]) + + if dtype == DataType.CustomSinosoid: + data_dir = f'{DATA_ROOT}/sinosoid/' + elif dtype == DataType.CustomSinosoidThreeCurve: + data_dir = f'{DATA_ROOT}/sinosoid/' + elif dtype == DataType.OptiMEM100_014: + data_dir = f'{DATA_ROOT}/microscopy/' + elif dtype == DataType.Prevedel_EMBL: + data_dir = f'{DATA_ROOT}/Prevedel_EMBL/PKG_3P_dualcolor_stacks/NoAverage_NoRegistration/' + elif dtype == DataType.AllenCellMito: + data_dir = f'{DATA_ROOT}/allencell/2017_03_08_Struct_First_Pass_Seg/AICS-11/' + elif dtype == DataType.SeparateTiffData: + data_dir = f'{DATA_ROOT}/ventura_gigascience' + elif dtype == DataType.BioSR_MRC: + data_dir = f'{DATA_ROOT}/BioSR/' + + homedir = os.path.expanduser('~') + nodename = os.uname().nodename + + def get_best_checkpoint(ckpt_dir): + output = [] + for filename in glob.glob(ckpt_dir + "/*_best.ckpt"): + output.append(filename) + assert len(output) == 1, '\n'.join(output) + return output[0] + + config = load_config(ckpt_dir) + config = ml_collections.ConfigDict(config) + old_image_size = None + with config.unlocked(): + try: + if 'batchnorm' not in config.model.encoder: + config.model.encoder.batchnorm = config.model.batchnorm + assert 'batchnorm' not in config.model.decoder + config.model.decoder.batchnorm = config.model.batchnorm + + if 'conv2d_bias' not in config.model.decoder: + config.model.decoder.conv2d_bias = True + + if config.model.model_type == ModelType.LadderVaeSepEncoder: + if 'use_random_for_missing_inp' not in config.model: + config.model.use_random_for_missing_inp = False + if 'learnable_merge_tensors' not in config.model: + config.model.learnable_merge_tensors = False + + if 'input_is_sum' not in config.data: + config.data.input_is_sum = False + except: + pass + + if config.model.model_type == ModelType.UNet and 'n_levels' not in config.model: + config.model.n_levels = 4 + if 'test_fraction' not in config.training: + config.training.test_fraction = 0.0 + + if 'datadir' not in config: + config.datadir = '' + if 'encoder' not in config.model: + config.model.encoder = ml_collections.ConfigDict() + assert 'decoder' not in config.model + config.model.decoder = ml_collections.ConfigDict() + + config.model.encoder.dropout = config.model.dropout + config.model.decoder.dropout = config.model.dropout + config.model.encoder.blocks_per_layer = config.model.blocks_per_layer + config.model.decoder.blocks_per_layer = config.model.blocks_per_layer + config.model.encoder.n_filters = config.model.n_filters + config.model.decoder.n_filters = config.model.n_filters + + if 'multiscale_retain_spatial_dims' not in config.model: + config.multiscale_retain_spatial_dims = False + + if 'res_block_kernel' not in config.model.encoder: + config.model.encoder.res_block_kernel = 3 + assert 'res_block_kernel' not in config.model.decoder + config.model.decoder.res_block_kernel = 3 + + if 'res_block_skip_padding' not in config.model.encoder: + config.model.encoder.res_block_skip_padding = False + assert 'res_block_skip_padding' not in config.model.decoder + config.model.decoder.res_block_skip_padding = False + + if config.data.data_type == DataType.CustomSinosoid: + if 'max_vshift_factor' not in config.data: + config.data.max_vshift_factor = config.data.max_shift_factor + config.data.max_hshift_factor = 0 + if 'encourage_non_overlap_single_channel' not in config.data: + config.data.encourage_non_overlap_single_channel = False + + if 'skip_bottom_layers_count' in config.model: + config.model.skip_bottom_layers_count = 0 + + if 'logvar_lowerbound' not in config.model: + config.model.logvar_lowerbound = None + if 'train_aug_rotate' not in config.data: + config.data.train_aug_rotate = False + if 'multiscale_lowres_separate_branch' not in config.model: + config.model.multiscale_lowres_separate_branch = False + if 'multiscale_retain_spatial_dims' not in config.model: + config.model.multiscale_retain_spatial_dims = False + config.data.train_aug_rotate = False + + if 'randomized_channels' not in config.data: + config.data.randomized_channels = False + + if 'predict_logvar' not in config.model: + config.model.predict_logvar = None + if config.data.data_type in [ + DataType.OptiMEM100_014, DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve, + DataType.SeparateTiffData + ]: + if custom_image_size is not None: + old_image_size = config.data.image_size + config.data.image_size = custom_image_size + if use_deterministic_grid is not None: + config.data.deterministic_grid = use_deterministic_grid + if threshold is not None: + config.data.threshold = threshold + if val_repeat_factor is not None: + config.training.val_repeat_factor = val_repeat_factor + config.model.mode_pred = not compute_kl_loss + + print(config) + with config.unlocked(): + config.model.skip_nboundary_pixels_from_loss = None + + ## Disentanglement setup. + #### + #### + grid_alignment = GridAlignement.Center + if image_size_for_grid_centers is not None: + old_grid_size = config.data.get('grid_size', "grid_size not present") + with config.unlocked(): + config.data.grid_size = image_size_for_grid_centers + config.data.val_grid_size = image_size_for_grid_centers + + padding_kwargs = { + 'mode': config.data.get('padding_mode', 'constant'), + } + + if padding_kwargs['mode'] == 'constant': + padding_kwargs['constant_values'] = config.data.get('padding_value', 0) + + dloader_kwargs = {'overlapping_padding_kwargs': padding_kwargs, 'grid_alignment': grid_alignment} + + if 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None: + data_class = LCMultiChDloader + dloader_kwargs['num_scales'] = config.data.multiscale_lowres_count + dloader_kwargs['padding_kwargs'] = padding_kwargs + elif config.data.data_type == DataType.SemiSupBloodVesselsEMBL: + data_class = SingleChannelDloader + else: + data_class = MultiChDloader + if config.data.data_type in [ + DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve, DataType.AllenCellMito, + DataType.SeparateTiffData, DataType.SemiSupBloodVesselsEMBL, DataType.BioSR_MRC + ]: + datapath = data_dir + elif config.data.data_type == DataType.OptiMEM100_014: + datapath = os.path.join(data_dir, 'OptiMEM100x014.tif') + elif config.data.data_type == DataType.Prevedel_EMBL: + datapath = os.path.join(data_dir, 'MS14__z0_8_sl4_fr10_p_10.1_lz510_z13_bin5_00001.tif') + + normalized_input = config.data.normalized_input + use_one_mu_std = config.data.use_one_mu_std + train_aug_rotate = config.data.train_aug_rotate + enable_random_cropping = config.data.deterministic_grid is False + + train_dset = data_class(config.data, + datapath, + datasplit_type=DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=train_aug_rotate, + enable_random_cropping=enable_random_cropping, + **dloader_kwargs) + import gc + gc.collect() + max_val = train_dset.get_max_val() + val_dset = data_class( + config.data, + datapath, + datasplit_type=eval_datasplit_type, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=False, # No rotation aug on validation + enable_random_cropping=False, + # No random cropping on validation. Validation is evaluated on determistic grids + max_val=max_val, + **dloader_kwargs) + + # For normalizing, we should be using the training data's mean and std. + mean_val, std_val = train_dset.compute_mean_std() + train_dset.set_mean_std(mean_val, std_val) + val_dset.set_mean_std(mean_val, std_val) + + if evaluate_train: + val_dset = train_dset + + with config.unlocked(): + if config.data.data_type in [ + DataType.OptiMEM100_014, DataType.CustomSinosoid, DataType.CustomSinosoidThreeCurve, + DataType.SeparateTiffData + ] and old_image_size is not None: + config.data.image_size = old_image_size + + mean_dict = {'input': None, 'target': None} + std_dict = {'input': None, 'target': None} + inp_fr_mean, inp_fr_std = train_dset.get_mean_std() + mean_sq = inp_fr_mean.squeeze() + std_sq = inp_fr_std.squeeze() + assert mean_sq[0] == mean_sq[1] and len(mean_sq) == config.data.get('num_channels', 2) + assert std_sq[0] == std_sq[1] and len(std_sq) == config.data.get('num_channels', 2) + mean_dict['input'] = np.mean(inp_fr_mean, axis=1, keepdims=True) + std_dict['input'] = np.mean(inp_fr_std, axis=1, keepdims=True) + + if config.data.target_separate_normalization is True: + target_data_mean, target_data_std = train_dset.compute_individual_mean_std() + else: + target_data_mean, target_data_std = train_dset.get_mean_std() + + mean_dict['target'] = target_data_mean + std_dict['target'] = target_data_std + ###### + + model = create_model(config, mean_dict, std_dict) + + ckpt_fpath = get_best_checkpoint(ckpt_dir) + checkpoint = torch.load(ckpt_fpath) + + _ = model.load_state_dict(checkpoint['state_dict'], strict=False) + model.eval() + _ = model.cuda() + + # model.data_mean = model.data_mean.cuda() + # model.data_std = model.data_std.cuda() + model.set_params_to_same_device_as(torch.Tensor([1]).cuda()) + print('Loading from epoch', checkpoint['epoch']) + + def count_parameters(model): + return sum(p.numel() for p in model.parameters() if p.requires_grad) + + print(f'Model has {count_parameters(model)/1000_000:.3f}M parameters') + # reducing the data here. + if predict_kth_frame is not None: + assert predict_kth_frame >= 0 and isinstance(predict_kth_frame, int), f'Invalid kth frame. {predict_kth_frame}' + if predict_kth_frame >= val_dset._data.shape[0]: + return None, None + else: + val_dset.reduce_data([predict_kth_frame]) + + if config.data.multiscale_lowres_count is not None and custom_image_size is not None: + model.reset_for_different_output_size(custom_image_size) + + pred_tiled, rec_loss, *_ = get_dset_predictions( + model, + val_dset, + batch_size, + num_workers=num_workers, + mmse_count=mmse_count, + model_type=config.model.model_type, + ) + if pred_tiled.shape[-1] != val_dset.get_img_sz(): + pad = (val_dset.get_img_sz() - pred_tiled.shape[-1]) // 2 + pred_tiled = np.pad(pred_tiled, ((0, 0), (0, 0), (pad, pad), (pad, pad))) + + pred = stitch_predictions(pred_tiled, val_dset) + if pred.shape[-1] == 2 and pred[..., 1].std() == 0: + print('Denoiser model. Ignoring the second channel') + pred = pred[..., :1].copy() + + print('Stitched predictions shape before ignoring boundary pixels', pred.shape) + + def print_ignored_pixels(): + ignored_pixels = 1 + if pred.shape[0] == 1: + return 0 + + while (pred[ + :10, + -ignored_pixels:, + -ignored_pixels:, + ].std() == 0): + ignored_pixels += 1 + ignored_pixels -= 1 + # print(f'In {pred.shape}, {ignored_pixels} many rows and columns are all zero.') + return ignored_pixels + + actual_ignored_pixels = print_ignored_pixels() + assert ignored_last_pixels >= actual_ignored_pixels, f'ignored_last_pixels: {ignored_last_pixels} < actual_ignored_pixels: {actual_ignored_pixels}' + tar = val_dset._data + + def ignore_pixels(arr): + if ignore_first_pixels: + arr = arr[:, ignore_first_pixels:, ignore_first_pixels:] + if ignored_last_pixels: + arr = arr[:, :-ignored_last_pixels, :-ignored_last_pixels] + return arr + + pred = ignore_pixels(pred) + tar = ignore_pixels(tar) + print('Stitched predictions shape after', pred.shape) + + sep_mean, sep_std = model.data_mean['target'], model.data_std['target'] + sep_mean = sep_mean.squeeze().reshape(1, 1, 1, -1) + sep_std = sep_std.squeeze().reshape(1, 1, 1, -1) + + # tar1, tar2 = val_dset.normalize_img(tar[...,0], tar[...,1]) + tar_normalized = (tar - sep_mean.cpu().numpy()) / sep_std.cpu().numpy() + pred_unnorm = pred * sep_std.cpu().numpy() + sep_mean.cpu().numpy() + ch1_pred_unnorm = pred_unnorm[..., 0] + # pred is already normalized. no need to do it. + pred1 = pred[..., 0].astype(np.float32) + tar1 = tar_normalized[..., 0] + rmse1 = np.sqrt(((pred1 - tar1)**2).reshape(len(pred1), -1).mean(axis=1)) + rmse = rmse1 + rmse2 = np.array([0]) + + # if not normalized_ssim: + # ssim1_mean, ssim1_std = avg_ssim(tar[..., 0], ch1_pred_unnorm) + # else: + # ssim1_mean, ssim1_std = avg_ssim(tar_normalized[..., 0], pred[..., 0]) + + pred2 = None + if pred.shape[-1] == 2: + ch2_pred_unnorm = pred_unnorm[..., 1] + # pred is already normalized. no need to do it. + pred2 = pred[..., 1].astype(np.float32) + tar2 = tar_normalized[..., 1] + rmse2 = np.sqrt(((pred2 - tar2)**2).reshape(len(pred2), -1).mean(axis=1)) + rmse = (rmse1 + rmse2) / 2 + + # if not normalized_ssim: + # ssim2_mean, ssim2_std = avg_ssim(tar[..., 1], ch2_pred_unnorm) + # else: + # ssim2_mean, ssim2_std = avg_ssim(tar_normalized[..., 1], pred[..., 1]) + rmse = np.round(rmse, 3) + + highres_data = get_highsnr_data(config, data_dir, eval_datasplit_type) + if predict_kth_frame is not None and highres_data is not None: + highres_data = highres_data[[predict_kth_frame]].copy() + + if highres_data is None: + # Computing the output statistics. + output_stats = {} + output_stats['rec_loss'] = rec_loss.mean() + output_stats['rmse'] = [np.mean(rmse1), np.array(0.0), np.array(0.0)] #, np.mean(rmse2), np.mean(rmse)] + output_stats['psnr'] = [avg_psnr(tar1, pred1), np.array(0.0)] #, avg_psnr(tar2, pred2)] + output_stats['rangeinvpsnr'] = [avg_range_inv_psnr(tar1, pred1), + np.array(0.0)] #, avg_range_inv_psnr(tar2, pred2)] + # output_stats['ssim'] = [ssim1_mean, np.array(0.0), ssim1_std, np.array(0.0)] + + if pred.shape[-1] == 2: + output_stats['rmse'][1] = np.mean(rmse2) + output_stats['psnr'][1] = avg_psnr(tar2, pred2) + output_stats['rangeinvpsnr'][1] = avg_range_inv_psnr(tar2, pred2) + # output_stats['ssim'] = [ssim1_mean, ssim2_mean, ssim1_std, ssim2_std] + + output_stats['normalized_ssim'] = normalized_ssim + + print(print_token) + print('Rec Loss', np.round(output_stats['rec_loss'], 3)) + print('RMSE', output_stats['rmse'][0].round(3), output_stats['rmse'][1].round(3), + output_stats['rmse'][2].round(3)) + print('PSNR', output_stats['psnr'][0], output_stats['psnr'][1]) + print('RangeInvPSNR', output_stats['rangeinvpsnr'][0], output_stats['rangeinvpsnr'][1]) + # ssim_str = 'SSIM normalized:' if normalized_ssim else 'SSIM:' + # print(ssim_str, output_stats['ssim'][0].round(3), output_stats['ssim'][1].round(3), '±', + # np.mean(output_stats['ssim'][2:4]).round(4)) + print() + # highres data + else: + highres_data = ignore_pixels(highres_data) + highres_data = (highres_data - sep_mean.cpu().numpy()) / sep_std.cpu().numpy() + # for denoiser, we don't need both channels. + if config.model.model_type == ModelType.Denoiser: + if model.denoise_channel == 'Ch1': + highres_data = highres_data[..., :1] + elif model.denoise_channel == 'Ch2': + highres_data = highres_data[..., 1:] + elif model.denoise_channel == 'input': + highres_data = np.mean(highres_data, axis=-1, keepdims=True) + + print(print_token) + stats_dict = compute_high_snr_stats(config, highres_data, pred) + output_stats = {} + output_stats['rangeinvpsnr'] = stats_dict['rangeinvpsnr'] + output_stats['ms_ssim'] = stats_dict['ms_ssim'] + print('') + return output_stats, pred_unnorm + + +def synthetic_noise_present(config): + """ + Returns True if synthetic noise is present. + """ + gaussian_noise = 'synthetic_gaussian_scale' in config.data and config.data.synthetic_gaussian_scale is not None and config.data.synthetic_gaussian_scale > 0 + poisson_noise = 'poisson_noise_factor' in config.data and config.data.poisson_noise_factor is not None and config.data.poisson_noise_factor > 0 + return gaussian_noise or poisson_noise + + +def get_highsnr_data(config, data_dir, eval_datasplit_type): + """ + Get the high SNR data. + """ + highres_data = None + if config.model.model_type == ModelType.DenoiserSplitter or config.data.data_type == DataType.SeparateTiffData: + highres_data = get_highres_data_ventura(data_dir, config, eval_datasplit_type) + elif 'synthetic_gaussian_scale' in config.data or 'enable_poisson_noise' in config.data: + if config.data.data_type == DataType.OptiMEM100_014: + data_dir = os.path.join(data_dir, 'OptiMEM100x014.tif') + if synthetic_noise_present(config): + highres_data = get_data_without_synthetic_noise(data_dir, config, eval_datasplit_type) + return highres_data + + +def save_hardcoded_ckpt_evaluations_to_file(normalized_ssim=True, + save_prediction=False, + mmse_count=1, + predict_kth_frame=None): + ckpt_dirs = [ + '/home/ashesh.ashesh/training/disentangle/2402/D7-M3-S0-L0/82', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/103', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/104', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/105', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/106', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/107', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/108', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/109', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/111', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/90', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/91', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/92', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/93', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/94', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/95', + + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/96', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/97', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/98', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/99', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/100', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/101', + + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/92', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/96', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/103', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/109', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/113', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/119', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/110', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/116', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/121', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/108', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/115', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/120', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/106', + + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/37', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/34', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/35', + + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/43', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/40', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/41', + + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/49', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/47', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/46', + + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/56', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/55', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M23-S0-L0/52', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/30', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/38', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/31', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/39', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/32', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/43', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/33', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/41', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/48', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/52', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/49', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/53', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/51', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/55', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/54', + # '/home/ashesh.ashesh/training/disentangle/2403/D16-M3-S0-L0/50', + ] + if ckpt_dirs[0].startswith('/home/ashesh.ashesh'): + OUTPUT_DIR = os.path.expanduser('/group/jug/ashesh/data/paper_stats/') + elif ckpt_dirs[0].startswith('/home/ubuntu/ashesh'): + OUTPUT_DIR = os.path.expanduser('~/data/paper_stats/') + else: + raise Exception('Invalid server') + + ckpt_dirs = [x[:-1] if '/' == x[-1] else x for x in ckpt_dirs] + + patchsz_gridsz_tuples = [(None, 32)] + for custom_image_size, image_size_for_grid_centers in patchsz_gridsz_tuples: + for eval_datasplit_type in [DataSplitType.Test]: + for ckpt_dir in ckpt_dirs: + data_type = int(os.path.basename(os.path.dirname(ckpt_dir)).split('-')[0][1:]) + if data_type in [ + DataType.OptiMEM100_014, DataType.SemiSupBloodVesselsEMBL, DataType.Pavia2VanillaSplitting, + DataType.ExpansionMicroscopyMitoTub, DataType.ShroffMitoEr, DataType.HTIba1Ki67 + ]: + ignored_last_pixels = 32 + elif data_type == DataType.BioSR_MRC: + ignored_last_pixels = 44 + else: + ignored_last_pixels = 0 + + if custom_image_size is None: + custom_image_size = load_config(ckpt_dir).data.image_size + + handler = PaperResultsHandler(OUTPUT_DIR, + eval_datasplit_type, + custom_image_size, + image_size_for_grid_centers, + mmse_count, + ignored_last_pixels, + predict_kth_frame=predict_kth_frame) + data, prediction = main( + ckpt_dir, + image_size_for_grid_centers=image_size_for_grid_centers, + mmse_count=mmse_count, + custom_image_size=custom_image_size, + batch_size=24, + num_workers=4, + COMPUTE_LOSS=False, + use_deterministic_grid=None, + threshold=None, # 0.02, + compute_kl_loss=False, + evaluate_train=False, + eval_datasplit_type=eval_datasplit_type, + val_repeat_factor=None, + psnr_type='range_invariant', + ignored_last_pixels=ignored_last_pixels, + ignore_first_pixels=0, + print_token=handler.dirpath(), + normalized_ssim=normalized_ssim, + predict_kth_frame=predict_kth_frame, + ) + if data is None: + return None, None + + fpath = handler.save(ckpt_dir, data) + # except: + # print('FAILED for ', handler.get_output_fpath(ckpt_dir)) + # continue + print(handler.load(fpath)) + print('') + print('') + print('') + if save_prediction: + offset = prediction.min() + prediction -= offset + prediction = prediction.astype(np.uint32) + handler.dump_predictions(ckpt_dir, prediction, {'offset': str(offset)}) + + return data, prediction + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--ckpt_dir', type=str) + parser.add_argument('--patch_size', type=int, default=64) + parser.add_argument('--grid_size', type=int, default=16) + parser.add_argument('--hardcoded', action='store_true') + parser.add_argument('--normalized_ssim', action='store_true') + parser.add_argument('--save_prediction', action='store_true') + parser.add_argument('--mmse_count', type=int, default=1) + parser.add_argument('--predict_kth_frame', type=int, default=None) + + args = parser.parse_args() + if args.hardcoded: + print('Ignoring ckpt_dir,patch_size and grid_size') + save_hardcoded_ckpt_evaluations_to_file(normalized_ssim=args.normalized_ssim, + save_prediction=args.save_prediction, + mmse_count=args.mmse_count, + predict_kth_frame=args.predict_kth_frame) + else: + mmse_count = 1 + ignored_last_pixels = 32 if os.path.basename(os.path.dirname(args.ckpt_dir)).split('-')[0][1:] == '3' else 0 + OUTPUT_DIR = '' + eval_datasplit_type = DataSplitType.Test + + data = main( + args.ckpt_dir, + image_size_for_grid_centers=args.grid_size, + mmse_count=mmse_count, + custom_image_size=args.patch_size, + batch_size=16, + num_workers=4, + COMPUTE_LOSS=False, + use_deterministic_grid=None, + threshold=None, # 0.02, + compute_kl_loss=False, + evaluate_train=False, + eval_datasplit_type=eval_datasplit_type, + val_repeat_factor=None, + psnr_type='range_invariant', + ignored_last_pixels=ignored_last_pixels, + ignore_first_pixels=0, + normalized_ssim=args.normalized_ssim, + ) + + print('') + print('Paper Related Stats') + print('PSNR', np.mean(data['rangeinvpsnr'])) + print('SSIM', np.mean(data['ssim'][:2])) diff --git a/denoisplit/scripts/evaluate_sequentially.py b/denoisplit/scripts/evaluate_sequentially.py new file mode 100644 index 0000000..0393c5e --- /dev/null +++ b/denoisplit/scripts/evaluate_sequentially.py @@ -0,0 +1,25 @@ +import argparse + +from denoisplit.scripts.evaluate import save_hardcoded_ckpt_evaluations_to_file + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--normalized_ssim', action='store_true') + parser.add_argument('--save_prediction', action='store_true') + parser.add_argument('--mmse_count', type=int, default=1) + parser.add_argument('--start_k', type=int, default=0) + parser.add_argument('--end_k', type=int, default=1000) + + args = parser.parse_args() + print('Evaluating between', args.start_k, args.end_k) + for i in range(args.start_k, args.end_k): + print('') + print('##################################') + print(f'Predicting {i}th frame') + print('##################################') + output_stats, pred_unnorm = save_hardcoded_ckpt_evaluations_to_file(normalized_ssim=args.normalized_ssim, + save_prediction=args.save_prediction, + mmse_count=args.mmse_count, + predict_kth_frame=i) + if output_stats is None: + break diff --git a/denoisplit/scripts/print_configs.py b/denoisplit/scripts/print_configs.py new file mode 100644 index 0000000..7387b15 --- /dev/null +++ b/denoisplit/scripts/print_configs.py @@ -0,0 +1,21 @@ +import argparse +import os +import torch + +from denoisplit.config_utils import load_config +from denoisplit.analysis.checkpoint_utils import get_best_checkpoint + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('config', type=str) + args = parser.parse_args() + assert os.path.exists(args.config) + dir = args.config + try: + ckpt_fpath = get_best_checkpoint(dir) + checkpoint = torch.load(ckpt_fpath) + print(f'Model Trained till {checkpoint["epoch"]} epochs') + except: + print('No model was found in', dir) + + print(load_config(args.config)) diff --git a/denoisplit/scripts/print_paperstats.py b/denoisplit/scripts/print_paperstats.py new file mode 100644 index 0000000..d3f7744 --- /dev/null +++ b/denoisplit/scripts/print_paperstats.py @@ -0,0 +1,101 @@ +import argparse +import os +import pickle +from time import sleep + +from denoisplit.analysis.results_handler import PaperResultsHandler + + +def rnd(obj): + return f'{obj:.3f}' + + +def show(ckpt_dir, results_dir, only_test=True, skip_last_pixels=None): + if ckpt_dir[-1] == '/': + ckpt_dir = ckpt_dir[:-1] + if results_dir[-1] == '/': + results_dir = results_dir[:-1] + + fname = PaperResultsHandler.get_fname(ckpt_dir) + print(ckpt_dir) + for dir in sorted(os.listdir(results_dir)): + if only_test and dir[:4] != 'Test': + continue + if skip_last_pixels is not None: + sktoken = dir.split('_')[-1] + assert sktoken[:2] == 'Sk' + if int(sktoken[2:]) != skip_last_pixels: + continue + + fpath = os.path.join(results_dir, dir, fname) + # print(fpath) + if os.path.exists(fpath): + with open(fpath, 'rb') as f: + out = pickle.load(f) + + print(dir) + if 'rmse' in out: + print('RMSE', ' '.join([rnd(x) for x in out['rmse']])) + if 'psnr' in out: + print('PSNR', ' '.join([rnd(x) for x in out['psnr']])) + if 'rangeinvpsnr' in out: + print('RangeInvPSNR', ' '.join([rnd(x) for x in out['rangeinvpsnr']])) + if 'ssim' in out: + print('SSIM', ' '.join(rnd(x) for x in out['ssim'])) + if 'ms_ssim' in out: + print('MS-SSIM', ' '.join(rnd(x) for x in out['ms_ssim'])) + print('') + + +if __name__ == '__main__': + # parser = argparse.ArgumentParser() + # parser.add_argument('ckpt_dir', type=str) + # parser.add_argument('results_dir', type=str) + # parser.add_argument('--skip_last_pixels', type=int) + # args = parser.parse_args() + + # ckpt_dir = '/home/ashesh.ashesh/training/disentangle/2210/D3-M3-S0-L0/117' + # results_dir = '/home/ashesh.ashesh/data/paper_stats/' + ckpt_dirs = [ + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/93', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/88', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/109/', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/125', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/94', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/89', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/128', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/95', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/87', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/130', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/92', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/90', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/115', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/104', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/96', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/126', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/105', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/97', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/127', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/106', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/98', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/129', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/107', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/99', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/135', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/114', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/101', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/133', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/113', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/100', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/132', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/117', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/103', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/120', + # '/home/ashesh.ashesh/training/disentangle/2402/D16-M23-S0-L0/102', + ] + + for ckpt_dir in ckpt_dirs: + show(ckpt_dir, '/group/jug/ashesh/data/paper_stats/', only_test=True, skip_last_pixels=44) + sleep(1) + + # show(args.ckpt_dir, args.results_dir, only_test=True, skip_last_pixels=args.skip_last_pixels) diff --git a/denoisplit/scripts/run.py b/denoisplit/scripts/run.py new file mode 100644 index 0000000..4ef5e5f --- /dev/null +++ b/denoisplit/scripts/run.py @@ -0,0 +1,303 @@ +""" +run file for the disentangle work. +""" +import json +import logging +import os +import pickle +import socket +import sys +import time +from datetime import datetime +from pathlib import Path + +import numpy as np +import torch +import torchvision +from torch.utils.cpp_extension import CUDA_HOME +from torch.utils.data import DataLoader + +import git +import ml_collections +import tensorboard +from absl import app, flags +from denoisplit.config_utils import get_updated_config +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.model_type import ModelType +from denoisplit.core.sampler_type import SamplerType +from denoisplit.sampler.default_grid_sampler import DefaultGridSampler +from denoisplit.sampler.intensity_aug_sampler import IntensityAugSampler, IntensityAugValSampler +from denoisplit.sampler.nbr_sampler import NeighborSampler +from denoisplit.sampler.random_sampler import RandomSampler +from denoisplit.sampler.singleimg_sampler import SingleImgSampler +from denoisplit.training import create_dataset, train_network +from ml_collections.config_flags import config_flags + +FLAGS = flags.FLAGS + +config_flags.DEFINE_config_file("config", None, "Training configuration.", lock_config=True) +flags.DEFINE_string("workdir", None, "Work directory.") +flags.DEFINE_enum("mode", None, ["train", "eval"], "Running mode: train or eval") +flags.DEFINE_string("logdir", '/group/jug/ashesh/wandb_backup/', "The folder name for storing logging") +flags.DEFINE_string("datadir", '/tmp2/ashesh/ashesh/VAE_based/data/MNIST/noisy/', "Data directory.") +flags.DEFINE_boolean("use_max_version", False, "Overwrite the max version of the model") +flags.DEFINE_string("load_ckptfpath", '', "The path to a previous ckpt from which the weights should be loaded") +flags.DEFINE_string("override_kwargs", '', 'There keys will be overwridden with the corresponding values') +flags.mark_flags_as_required(["workdir", "config", "mode"]) + + +def add_git_info(config): + dir_path = os.path.dirname(os.path.realpath(__file__)) + repo = git.Repo(dir_path, search_parent_directories=True) + config.git.changedFiles = [item.a_path for item in repo.index.diff(None)] + config.git.branch = repo.active_branch.name + config.git.untracked_files = repo.untracked_files + config.git.latest_commit = repo.head.object.hexsha + + +def log_config(config, cur_workdir): + # Saving config file. + with open(os.path.join(cur_workdir, 'config.pkl'), 'wb') as f: + pickle.dump(config, f) + print(f'Saved config to {cur_workdir}/config.pkl') + + +def set_logger(): + os.makedirs(FLAGS.workdir, exist_ok=True) + fstream = open(os.path.join(FLAGS.workdir, 'stdout.txt'), 'w') + handler = logging.StreamHandler(fstream) + formatter = logging.Formatter('%(levelname)s - %(filename)s - %(asctime)s - %(message)s') + handler.setFormatter(formatter) + logger = logging.getLogger() + logger.addHandler(handler) + logger.setLevel('INFO') + + +def get_new_model_version(model_dir: str) -> str: + """ + A model will have multiple runs. Each run will have a different version. + """ + versions = [] + for version_dir in os.listdir(model_dir): + try: + versions.append(int(version_dir)) + except: + print(f'Invalid subdirectory:{model_dir}/{version_dir}. Only integer versions are allowed') + exit() + if len(versions) == 0: + return '0' + return f'{max(versions) + 1}' + + +def get_model_name(config): + mtype = config.model.model_type + dtype = config.data.data_type + ltype = config.loss.loss_type + stype = config.data.sampler_type + + return f'D{dtype}-M{mtype}-S{stype}-L{ltype}' + + +def get_month(): + return datetime.now().strftime("%y%m") + + +def get_workdir(config, root_dir, use_max_version, nested_call=0): + rel_path = get_month() + cur_workdir = os.path.join(root_dir, rel_path) + Path(cur_workdir).mkdir(exist_ok=True) + + rel_path = os.path.join(rel_path, get_model_name(config)) + cur_workdir = os.path.join(root_dir, rel_path) + Path(cur_workdir).mkdir(exist_ok=True) + + if use_max_version: + # Used for debugging. + version = int(get_new_model_version(cur_workdir)) + if version > 0: + version = f'{version - 1}' + + rel_path = os.path.join(rel_path, str(version)) + else: + rel_path = os.path.join(rel_path, get_new_model_version(cur_workdir)) + + cur_workdir = os.path.join(root_dir, rel_path) + try: + Path(cur_workdir).mkdir(exist_ok=False) + except FileExistsError: + print( + f'Workdir {cur_workdir} already exists. Probably because someother program also created the exact same directory. Trying to get a new version.' + ) + time.sleep(2.5) + if nested_call > 10: + raise ValueError(f'Cannot create a new directory. {cur_workdir} already exists.') + + return get_workdir(config, root_dir, use_max_version, nested_call + 1) + + return cur_workdir, rel_path + + +def _update_config(config, key_levels, value): + if len(key_levels) == 1: + config[key_levels[0]] = value + else: + _update_config(config[key_levels[0]], key_levels[1:], value) + + +def overwride_with_cmd_params(config, params_dict): + """ + It makes sure that config is updated correctly with the value typecasted to the same type as is already present in the config. + """ + for key in params_dict: + key_levels = key.split('.') + _update_config(config, key_levels, params_dict[key]) + + +def get_mean_std_dict_for_model(config, train_dset): + """ + Computes the mean and std for the model. This will be subsequently passed to the model. + """ + if config.data.data_type == DataType.TwoDset: + mean_dict, std_dict = train_dset.compute_mean_std() + for dset_key in mean_dict.keys(): + mean_dict[dset_key]['input'] = mean_dict[dset_key]['input'].reshape(1, 1, 1, 1) + elif config.data.data_type == DataType.PredictedTiffData: + mean_dict = {'input': None, 'target': None} + std_dict = {'input': None, 'target': None} + inp_mean, inp_std = train_dset.get_mean_std_for_input() + mean_dict['input'] = inp_mean + std_dict['input'] = inp_std + if config.data.target_separate_normalization is True: + data_mean, data_std = train_dset.compute_individual_mean_std() + else: + data_mean, data_std = train_dset.get_mean_std() + # skip input channel + data_mean = data_mean[1:].copy() + data_std = data_std[1:].copy() + + mean_dict['target'] = data_mean + std_dict['target'] = data_std + + else: + mean_dict = {'input': None, 'target': None} + std_dict = {'input': None, 'target': None} + inp_mean, inp_std = train_dset.get_mean_std() + mean_sq = inp_mean.squeeze() + std_sq = inp_std.squeeze() + for i in range(1, config.data.get('num_channels', 2)): + assert mean_sq[0] == mean_sq[i] + assert std_sq[0] == std_sq[i] + mean_dict['input'] = np.mean(inp_mean, axis=1, keepdims=True) + std_dict['input'] = np.mean(inp_std, axis=1, keepdims=True) + + if config.data.target_separate_normalization is True: + data_mean, data_std = train_dset.compute_individual_mean_std() + else: + data_mean, data_std = train_dset.get_mean_std() + + mean_dict['target'] = data_mean + std_dict['target'] = data_std + + return mean_dict, std_dict + + +def main(argv): + config = FLAGS.config + if FLAGS.override_kwargs: + overwride_with_cmd_params(config, json.loads(FLAGS.override_kwargs)) + # making older configs compatible with current version. + config = get_updated_config(config) + + assert os.path.exists(FLAGS.workdir) + cur_workdir, relative_path = get_workdir(config, FLAGS.workdir, FLAGS.use_max_version) + print(f'Saving training to {cur_workdir}') + + add_git_info(config) + config.workdir = cur_workdir + config.exptname = relative_path + config.hostname = socket.gethostname() + config.datadir = FLAGS.datadir + config.training.pre_trained_ckpt_fpath = FLAGS.load_ckptfpath + + if FLAGS.mode == "train": + set_logger() + raw_data_dict = None + + # Now, config cannot be changed. + config = ml_collections.FrozenConfigDict(config) + log_config(config, cur_workdir) + + train_data, val_data = create_dataset(config, FLAGS.datadir, raw_data_dict=raw_data_dict) + + mean_dict, std_dict = get_mean_std_dict_for_model(config, train_data) + + # assert np.abs(config.data.mean_val - data_mean) < 1e-3, f'{config.data.mean_val - data_mean}' + # assert np.abs(config.data.std_val - data_std) < 1e-3, f'{config.data.std_val - data_std}' + + if config.data.sampler_type == SamplerType.DefaultSampler: + batch_size = config.training.batch_size + shuffle = True + + train_dloader = DataLoader(train_data, + pin_memory=False, + num_workers=config.training.num_workers, + shuffle=shuffle, + batch_size=batch_size) + val_dloader = DataLoader(val_data, + pin_memory=False, + num_workers=config.training.num_workers, + shuffle=False, + batch_size=batch_size) + + else: + + if config.data.sampler_type == SamplerType.RandomSampler: + train_sampler = RandomSampler(train_data, config.training.batch_size) + val_sampler = DefaultGridSampler(val_data, config.training.batch_size, grid_size=config.data.image_size) + elif config.data.sampler_type == SamplerType.SingleImgSampler: + train_sampler = SingleImgSampler(train_data, config.training.batch_size) + val_sampler = SingleImgSampler(val_data, config.training.batch_size) + elif config.data.sampler_type == SamplerType.NeighborSampler: + assert 'gridsizes' in config.training, 'For this to work, gridsizes must be provided' + nbr_set_count = config.data.nbr_set_count + train_sampler = NeighborSampler(train_data, + config.training.batch_size, + valid_gridsizes=config.training.gridsizes, + nbr_set_count=nbr_set_count) + val_sampler = NeighborSampler(val_data, config.training.batch_size, nbr_set_count=0) + elif config.data.sampler_type == SamplerType.DefaultGridSampler: + train_sampler = DefaultGridSampler(train_data, config.training.batch_size) + val_sampler = DefaultGridSampler(val_data, config.training.batch_size, grid_size=config.data.image_size) + elif config.data.sampler_type == SamplerType.IntensityAugSampler: + val_sampler = IntensityAugValSampler(val_data, config.data.image_size, config.training.batch_size) + train_sampler = IntensityAugSampler(train_data, + len(train_data), + config.data.ch1_alpha_interval_count, + config.data.num_intensity_variations, + batch_size=config.training.batch_size) + train_dloader = DataLoader(train_data, + pin_memory=False, + batch_sampler=train_sampler, + num_workers=config.training.num_workers) + val_dloader = DataLoader(val_data, + pin_memory=False, + batch_sampler=val_sampler, + num_workers=config.training.num_workers) + + train_network(train_dloader, val_dloader, mean_dict, std_dict, config, 'BaselineVAECL', FLAGS.logdir) + + elif FLAGS.mode == "eval": + pass + else: + raise ValueError(f"Mode {FLAGS.mode} not recognized.") + + +if __name__ == '__main__': + print(socket.gethostname(), datetime.now().strftime("%y-%m-%d-%H:%M:%S")) + print('Python version', sys.version) + print('CUDA_HOME', CUDA_HOME) + print('CudaToolKit Version', torch.version.cuda) + print('torch Version', torch.__version__) + print('torchvision Version', torchvision.__version__) + app.run(main) diff --git a/denoisplit/scripts/some_runs.sh b/denoisplit/scripts/some_runs.sh new file mode 100755 index 0000000..88dc935 --- /dev/null +++ b/denoisplit/scripts/some_runs.sh @@ -0,0 +1,7 @@ +#! /bin/bash + +python /home/ashesh.ashesh/code/Disentangle/disentangle/scripts/run.py --workdir=/home/ashesh.ashesh/training/disentangle/ -mode=train --datadir=/group/jug/ashesh/data/ventura_gigascience/ --config=/home/ashesh.ashesh/code/Disentangle/disentangle/configs/hdn_denoiser_config.py --override_kwargs='{"data.synthetic_gaussian_scale":1500, "model.denoise_channel":"Ch1", "model.noise_model_ch1_fpath":"/home/ashesh.ashesh/training/noise_model/2402/167/GMMNoiseModel_ventura_gigascience-actin__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz", "model.noise_model_ch2_fpath":"/home/ashesh.ashesh/training/noise_model/2402/168/GMMNoiseModel_ventura_gigascience-mito__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz"}' + +python /home/ashesh.ashesh/code/Disentangle/disentangle/scripts/run.py --workdir=/home/ashesh.ashesh/training/disentangle/ -mode=train --datadir=/group/jug/ashesh/data/ventura_gigascience/ --config=/home/ashesh.ashesh/code/Disentangle/disentangle/configs/hdn_denoiser_config.py --override_kwargs='{"data.synthetic_gaussian_scale":1500, "model.denoise_channel":"Ch2", "model.noise_model_ch1_fpath":"/home/ashesh.ashesh/training/noise_model/2402/167/GMMNoiseModel_ventura_gigascience-actin__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz", "model.noise_model_ch2_fpath":"/home/ashesh.ashesh/training/noise_model/2402/168/GMMNoiseModel_ventura_gigascience-mito__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz"}' + +python /home/ashesh.ashesh/code/Disentangle/disentangle/scripts/run.py --workdir=/home/ashesh.ashesh/training/disentangle/ -mode=train --datadir=/group/jug/ashesh/data/ventura_gigascience/ --config=/home/ashesh.ashesh/code/Disentangle/disentangle/configs/hdn_denoiser_config.py --override_kwargs='{"data.synthetic_gaussian_scale":1500, "model.denoise_channel":"input", "model.noise_model_ch1_fpath":"/home/ashesh.ashesh/training/noise_model/2402/167/GMMNoiseModel_ventura_gigascience-actin__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz", "model.noise_model_ch2_fpath":"/home/ashesh.ashesh/training/noise_model/2402/168/GMMNoiseModel_ventura_gigascience-mito__6_4_Clip0.0-1.0_Sig0.125_UpNone_Norm0_bootstrap.npz"}' \ No newline at end of file diff --git a/denoisplit/tests/analysis/test_quantifying_uncertainty.py b/denoisplit/tests/analysis/test_quantifying_uncertainty.py new file mode 100644 index 0000000..5332394 --- /dev/null +++ b/denoisplit/tests/analysis/test_quantifying_uncertainty.py @@ -0,0 +1,61 @@ +# from denoisplit.analysis.quantifying_uncertainty import compute_regionwise_metric_one_pair, aggregate_metric +# import numpy as np +# +# +# def equal(a, b, eps=1e-7): +# return np.abs(a - b) < eps +# +# +# def test_compute_regionwise_metric_one_pair_with_no_region(): +# data1 = np.random.random((1, 4, 4)) +# data2 = data1.copy() +# regionsize = 1 +# data2[0, 1, 1] += 1 +# data2[0, 3, 3] += 5 +# output = compute_regionwise_metric_one_pair(data1, data2, ['RMSE'], regionsize) +# assert output['RMSE'].shape == data1.shape +# for i in range(4): +# for j in range(4): +# val = output['RMSE'][0, i, j] +# if i == 1 and j == 1: +# assert equal(val, 1) +# elif i == 3 and j == 3: +# assert equal(val, 5) +# else: +# assert equal(val, 0) +# +# +# def test_compute_regionwise_metric_one_pair(): +# """ +# tests for a regionsize of 2*2 +# """ +# data1 = np.random.random((1, 4, 4)) +# data2 = data1.copy() +# regionsize = 2 +# data2[0, 1, 1] += 3 +# data2[0, 0, 0] += 4 +# +# data2[0, 2, 3] += 12 +# data2[0, 3, 2] += 5 +# +# output = compute_regionwise_metric_one_pair(data1, data2, ['RMSE'], regionsize) +# assert output['RMSE'].shape == (1, 2, 2) +# assert equal(output['RMSE'][0, 0, 0], 2.5) +# assert equal(output['RMSE'][0, 1, 1], 6.5) +# assert equal(output['RMSE'][0, 0, 1], 0) +# assert equal(output['RMSE'][0, 1, 0], 0) +# +# +# def test_aggregate_metric(): +# # output[img_idx]['pairwise_metric'][idx1][idx2] +# N = 4 +# img_idx = 20 +# metric_dict = {img_idx: {'pairwise_metric': {}}} +# for idx1 in range(1, N + 1): +# metric_dict[img_idx]['pairwise_metric'][idx1 - 1] = {} +# for idx2 in range(1, N + 1): +# metric_dict[img_idx]['pairwise_metric'][idx1 - 1][idx2 - 1] = {'RMSE': idx2 + N * (idx1 - 1)} +# +# output = aggregate_metric(metric_dict) +# N2 = N * N +# assert equal(output[img_idx]['RMSE'], ((N2 + 1)) / 2) diff --git a/denoisplit/tests/analysis/test_stitch_prediction.py b/denoisplit/tests/analysis/test_stitch_prediction.py new file mode 100644 index 0000000..8971e14 --- /dev/null +++ b/denoisplit/tests/analysis/test_stitch_prediction.py @@ -0,0 +1,116 @@ +import numpy as np + +from denoisplit.analysis.stitch_prediction import (_get_location, set_skip_boundary_pixels_mask, + set_skip_central_pixels_mask, stitch_predictions, + stitched_prediction_mask) +from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager + + +def test_skipping_boundaries(): + mask = np.full((10, 2, 8, 8), 1) + extra_padding = 0 + hwt1 = (0, 0, 0) + pred_h = 4 + pred_w = 4 + hwt2 = (pred_h, pred_w, 2) + loc1 = _get_location(extra_padding, hwt1, pred_h, pred_w) + loc2 = _get_location(extra_padding, hwt2, pred_h, pred_w) + set_skip_boundary_pixels_mask(mask, loc1, 1) + set_skip_boundary_pixels_mask(mask, loc2, 1) + correct_mask = np.full((10, 2, 8, 8), 1) + # boundary for hwt1 + correct_mask[0, :, 0, [0, 1, 2, 3]] = False + correct_mask[0, :, 3, [0, 1, 2, 3]] = False + correct_mask[0, :, [0, 1, 2, 3], 0] = False + correct_mask[0, :, [0, 1, 2, 3], 3] = False + + # boundary for hwt2 + correct_mask[2, :, 4, [4, 5, 6, 7]] = False + correct_mask[2, :, 7, [4, 5, 6, 7]] = False + correct_mask[2, :, [4, 5, 6, 7], 4] = False + correct_mask[2, :, [4, 5, 6, 7], 7] = False + assert (mask == correct_mask).all() + + +def test_picking_boundaries(): + mask = np.full((10, 2, 8, 8), 1) + extra_padding = 0 + hwt1 = (0, 0, 0) + pred_h = 4 + pred_w = 4 + hwt2 = (pred_h, pred_w, 2) + loc1 = _get_location(extra_padding, hwt1, pred_h, pred_w) + loc2 = _get_location(extra_padding, hwt2, pred_h, pred_w) + set_skip_central_pixels_mask(mask, loc1, 1) + set_skip_central_pixels_mask(mask, loc2, 2) + correct_mask = np.full((10, 2, 8, 8), 1) + # boundary for hwt1 + correct_mask[0, :, 2, 2] = False + # boundary for hwt2 + correct_mask[2, :, 5:7, 5:7] = False + + print(mask[hwt2[-1]]) + assert (mask == correct_mask).all() + + +class DummyDset: + + def __init__(self, grid_size, patch_size, data_shape) -> None: + self.patch_size = patch_size + self.grid_size = grid_size + self.data_shape = data_shape + idx_manager = GridIndexManager(data_shape, grid_size, patch_size, GridAlignement.Center) + self.idx_manager = idx_manager + + def per_side_overlap_pixelcount(self): + return (self.patch_size - self.grid_size) // 2 + + def get_data_shape(self): + return self.data_shape + + def get_grid_size(self): + return self.grid_size + + +def test_stitch_predictions_square_frames(): + grid_size = 32 + patch_size = 64 + data_shape = (30, 1550, 1550, 2) + N = data_shape[0] * (data_shape[1] // grid_size) * (data_shape[2] // grid_size) + predictions = np.zeros((N, 2, patch_size, patch_size)) + dset = DummyDset(grid_size, patch_size, data_shape) + output = stitch_predictions(predictions, dset) + + +def test_stitch_predictions_non_square_frames(): + grid_size = 32 + patch_size = 64 + data_shape = (30, 1550, 1920, 2) + N = data_shape[0] * (data_shape[1] // grid_size) * (data_shape[2] // grid_size) + predictions = np.zeros((N, 2, patch_size, patch_size)) + dset = DummyDset(grid_size, patch_size, data_shape) + output = stitch_predictions(predictions, dset) + + # NOTE: masking is disabled. so are its tests + # skip_boundary_pixel_count = 0 + # skip_central_pixel_count = 0 + # mask1 = stitched_prediction_mask(dset, (h, w), skip_boundary_pixel_count, skip_central_pixel_count) + # assert (mask1 == 1).all() + + # skip_boundary_pixel_count = 2 + # skip_central_pixel_count = 0 + # mask2 = stitched_prediction_mask(dset, (h, w), skip_boundary_pixel_count, skip_central_pixel_count) + + # skip_boundary_pixel_count = 0 + # skip_central_pixel_count = 4 + # mask3 = stitched_prediction_mask(dset, (h, w), skip_boundary_pixel_count, skip_central_pixel_count) + + # assert ((mask2 + mask3) == 1).all() + + # skip_boundary_pixel_count = 1 + # skip_central_pixel_count = 2 + # mask4 = stitched_prediction_mask(dset, (h, w), skip_boundary_pixel_count, skip_central_pixel_count) + + # import matplotlib.pyplot as plt; + # plt.imshow(mask4[0, :, :, 0]); + # plt.show() diff --git a/denoisplit/tests/core/test_psnr.py b/denoisplit/tests/core/test_psnr.py new file mode 100644 index 0000000..5ca8559 --- /dev/null +++ b/denoisplit/tests/core/test_psnr.py @@ -0,0 +1,84 @@ +import numpy as np +import torch + +from denoisplit.core.psnr import PSNR, RangeInvariantPsnr + +# range_ = np.max(gt) - np.min(gt) +# mse = np.mean((gt - pred) ** 2) +# return 20 * np.log10((range_) / np.sqrt(mse)) + + +def test_PSNR(): + target = torch.Tensor([[10, 11, 12], + [100, 120, 140], ]) + pred = torch.Tensor([[15, 10, 13], + [10, 13, 14], ]) + + rmse0 = torch.sqrt(torch.Tensor([25 + 1 + 1]) / 3) + actual_psnr0 = 20 * torch.log10(2 / rmse0) + + rmse1 = torch.sqrt(torch.Tensor([90 ** 2 + 107 ** 2 + 126 ** 2]) / 3) + actual_psnr1 = 20 * torch.log10(40 / rmse1) + + psnr = PSNR(target[..., None], pred[..., None]) + + assert len(psnr) == 2 + assert torch.abs(psnr[0] - actual_psnr0).item() < 1e-6 + assert torch.abs(psnr[1] - actual_psnr1).item() < 1e-6 + + +def _working_PSNR(gt, pred, range_=None): + ''' + Compute PSNR. + Parameters + ---------- + gt: array + Ground truth image. + img: array + Predicted image. + ''' + if range_ is None: + range_ = np.max(gt) - np.min(gt) + mse = np.mean((gt - pred) ** 2) + return 20 * np.log10((range_) / np.sqrt(mse)) + + +def _working_zero_mean(x): + return x - np.mean(x) + + +def _working_fix_range(gt, x): + a = np.sum(gt * x) / (np.sum(x * x)) + return x * a + + +def _working_fix(gt, x): + gt_ = _working_zero_mean(gt) + return _working_fix_range(gt_, _working_zero_mean(x)) + + +def _working_RangeInvariantPsnr(gt, pred): + """ + Taken from https://github.com/juglab/ScaleInvPSNR/blob/master/psnr.py + It rescales the prediction to ensure that the prediction has the same range as the ground truth. + """ + ra = (np.max(gt) - np.min(gt)) / np.std(gt) + gt_ = _working_zero_mean(gt) / np.std(gt) + return _working_PSNR(_working_zero_mean(gt_), _working_fix(gt_, pred), ra) + + +def test_RangeInvariantPSNR(): + target = torch.Tensor([[10, 11, 12], + [100, 120, 140], ]) + pred = torch.Tensor([[15, 10, 13], + [10, 13, 14], ]) + + rmse0 = torch.sqrt(torch.Tensor([25 + 1 + 1]) / 3) + actual_psnr0 = _working_RangeInvariantPsnr(target[0].numpy(), pred[0].numpy()) + actual_psnr1 = _working_RangeInvariantPsnr(target[1].numpy(), pred[1].numpy()) + + psnr = RangeInvariantPsnr(target[..., None], pred[..., None]) + + assert len(psnr) == 2 + assert torch.abs(psnr[0] - actual_psnr0).item() < 1e-5 + assert torch.abs(psnr[1] - actual_psnr1).item() < 1e-5 diff --git a/denoisplit/tests/core/test_stable_exp.py b/denoisplit/tests/core/test_stable_exp.py new file mode 100644 index 0000000..d780641 --- /dev/null +++ b/denoisplit/tests/core/test_stable_exp.py @@ -0,0 +1,27 @@ +import numpy as np +import torch + +from denoisplit.core.stable_exp import StableExponential + + +def test_stable_exponential_give_correct_values(): + def exp(v): + return torch.exp(torch.Tensor([v]))[0] + + x = torch.Tensor([1, 2, 100, -1, -4]) + expected_output = torch.Tensor([2, 3, 101, exp(-1), exp(-4)]) + output = StableExponential(x).exp() + assert torch.all(torch.abs(output - expected_output) < 1e-7) + + +def test_stable_exponential_has_correct_log(): + """ + Taking torch.log() on output of exp() has the same effect. + """ + x = np.arange(-10, 100, 0.01) + gen = StableExponential(torch.Tensor(x)) + exp = gen.exp() + log1 = gen.log() + log2 = torch.log(exp) + + assert torch.all(torch.abs(log2 - log1).max() < 1e-6) diff --git a/denoisplit/tests/data_loader/test_multi_channel_tiff_dloader.py b/denoisplit/tests/data_loader/test_multi_channel_tiff_dloader.py new file mode 100644 index 0000000..b6e82ec --- /dev/null +++ b/denoisplit/tests/data_loader/test_multi_channel_tiff_dloader.py @@ -0,0 +1,24 @@ +import numpy as np + +from denoisplit.data_loader.multi_channel_train_val_data import _train_val_data + + +def test_train_val_data(): + nchannels = 20 + val_fraction = 0.2 + data = np.random.rand(60, 512, 256, nchannels) + channel_1, channel_2 = np.random.choice(nchannels, size=2, replace=False) + is_train = True + train_data = _train_val_data(data, is_train, channel_1, channel_2, val_fraction=val_fraction) + + is_train = False + val_data = _train_val_data(data, is_train, channel_1, channel_2, val_fraction=val_fraction) + + is_train = None + total_data = _train_val_data(data, is_train, channel_1, channel_2, val_fraction=val_fraction) + + valN = 12 + trainN = 60 - valN + assert np.abs(data[:trainN, :, :, [channel_1, channel_2]] - train_data).max() < 1e-6 + assert np.abs(data[trainN:, :, :, [channel_1, channel_2]] - val_data).max() < 1e-6 + assert np.abs(data[..., [channel_1, channel_2]] - total_data).max() < 1e-6 diff --git a/denoisplit/tests/data_loader/test_multifile_raw_dloader.py b/denoisplit/tests/data_loader/test_multifile_raw_dloader.py new file mode 100644 index 0000000..9354e08 --- /dev/null +++ b/denoisplit/tests/data_loader/test_multifile_raw_dloader.py @@ -0,0 +1,154 @@ +from unittest import mock + +import numpy as np + +import ml_collections +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.data_loader.multifile_raw_dloader import SubDsetType +from denoisplit.data_loader.multifile_raw_dloader import get_train_val_data as get_train_val_data_twofiles + + +def get_two_channel_files(): + fnamesA = [] + fnamesB = [] + j = 1 + for val in range(100): + sz = 512 if val % 3 == 0 else 256 + fnamesA.append(f'A_{val}_{j}_{sz}') + fnamesB.append(f'B_{val}_{j}_{sz}') + j += 1 + if j == 11: + j = 1 + + return fnamesA, fnamesB + + +def load_tiff_same_count(fpath): + a_or_b, val, count, sz = fpath.split('_') + val = int(val) + count = 1 + sz = int(sz) + val = val if a_or_b == 'A' else val * -1 + return np.ones((count, sz, sz)) * val + + +@mock.patch('disentangle.data_loader.multifile_raw_dloader.load_tiff', side_effect=load_tiff_same_count) +def test_multifile_raw_dloader(mock_load_tiff): + config = ml_collections.ConfigDict() + config.subdset_type = SubDsetType.TwoChannel + data_test = get_train_val_data_twofiles('', + config, + DataSplitType.Test, + get_two_channel_files, + val_fraction=0.15, + test_fraction=0.1) + data_train = get_train_val_data_twofiles('', + config, + DataSplitType.Train, + get_two_channel_files, + val_fraction=0.15, + test_fraction=0.1) + data_val = get_train_val_data_twofiles('', + config, + DataSplitType.Val, + get_two_channel_files, + val_fraction=0.15, + test_fraction=0.1) + assert len(data_test) == 10 + assert len(data_train) == 75 + assert len(data_val) == 15 + + train_unique = [np.unique(data_train[i][..., 0]).tolist() for i in range(len(data_train))] + train_vals = [] + for elem in train_unique: + assert len(elem) == 1 + train_vals.append(elem[0]) + assert len(train_vals) == len(set(train_vals)) + + val_unique = [np.unique(data_val[i][..., 0]).tolist() for i in range(len(data_val))] + val_vals = [] + for elem in val_unique: + assert len(elem) == 1 + val_vals.append(elem[0]) + assert len(val_vals) == len(set(val_vals)) + + test_unique = [np.unique(data_test[i][..., 0]).tolist() for i in range(len(data_test))] + test_vals = [] + for elem in test_unique: + assert len(elem) == 1 + test_vals.append(elem[0]) + assert len(test_vals) == len(set(test_vals)) + + assert len(set(train_vals).intersection(set(val_vals))) == 0 + assert len(set(train_vals).intersection(set(test_vals))) == 0 + assert len(set(val_vals).intersection(set(test_vals))) == 0 + + +def load_tiff_different_count(fpath): + a_or_b, val, count, sz = fpath.split('_') + val = int(val) + count = int(count) + sz = int(sz) + val = val if a_or_b == 'A' else val * -1 + return np.ones((count, sz, sz)) * val + + +@mock.patch('disentangle.data_loader.multifile_raw_dloader.load_tiff', side_effect=load_tiff_different_count) +def test_multifile_raw_dloader(mock_load_tiff): + config = ml_collections.ConfigDict() + config.subdset_type = SubDsetType.TwoChannel + data_test = get_train_val_data_twofiles('', + config, + DataSplitType.Test, + get_two_channel_files, + val_fraction=0.15, + test_fraction=0.1) + data_train = get_train_val_data_twofiles('', + config, + DataSplitType.Train, + get_two_channel_files, + val_fraction=0.15, + test_fraction=0.1) + data_val = get_train_val_data_twofiles('', + config, + DataSplitType.Val, + get_two_channel_files, + val_fraction=0.15, + test_fraction=0.1) + + cnt = 0 + for fpath in get_two_channel_files()[0]: + cnt += load_tiff_different_count(fpath).shape[0] + + assert abs(len(data_test) - int(cnt * 0.1)) < 2 + assert abs(len(data_train) - int(cnt * 0.75)) < 2 + assert abs(len(data_val) - int(cnt * 0.15)) < 2 + + # make sure that the values of the two channels are in sync + for i in range(len(data_train)): + assert np.all(data_train[i][..., 0] == -1 * data_train[i][..., 1]) + + train_unique = [np.unique(data_train[i][..., 0]).tolist() for i in range(len(data_train))] + train_vals = [] + for elem in train_unique: + assert len(elem) == 1 + train_vals.append(elem[0]) + + val_unique = [np.unique(data_val[i][..., 0]).tolist() for i in range(len(data_val))] + val_vals = [] + for elem in val_unique: + assert len(elem) == 1 + val_vals.append(elem[0]) + + test_unique = [np.unique(data_test[i][..., 0]).tolist() for i in range(len(data_test))] + test_vals = [] + for elem in test_unique: + assert len(elem) == 1 + test_vals.append(elem[0]) + + all_vals = np.array(train_vals + val_vals + test_vals) + + for fpath in get_two_channel_files()[0]: + val = int(fpath.split('_')[1]) + count = int(fpath.split('_')[2]) + assert np.sum(all_vals == val) == count diff --git a/denoisplit/tests/data_loader/test_patch_index_manager.py b/denoisplit/tests/data_loader/test_patch_index_manager.py new file mode 100644 index 0000000..323cb35 --- /dev/null +++ b/denoisplit/tests/data_loader/test_patch_index_manager.py @@ -0,0 +1,20 @@ +from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager + + +def test_grid_index_manager_idx_to_hwt_mapping(): + grid_size = 32 + patch_size = 64 + index = 13 + manager = GridIndexManager((5, 499, 469, 2), grid_size, patch_size, GridAlignement.Center) + h_start, w_start = manager.get_deterministic_hw(index) + print(h_start, w_start, manager.grid_count()) + print(manager.grid_rows(grid_size), manager.grid_cols(grid_size)) + + for grid_size in [1, 2, 4, 8, 16, 32, 64]: + hwt = manager.hwt_from_idx(index, grid_size=grid_size) + same_index = manager.idx_from_hwt(*hwt, grid_size=grid_size) + assert index == same_index, f'{index}!={same_index}' + + +if __name__ == '__main__': + test_grid_index_manager_idx_to_hwt_mapping() diff --git a/denoisplit/tests/nets/test_lvae_layers.py b/denoisplit/tests/nets/test_lvae_layers.py new file mode 100644 index 0000000..d4e23c5 --- /dev/null +++ b/denoisplit/tests/nets/test_lvae_layers.py @@ -0,0 +1,102 @@ +import torch +import torch.nn as nn + +from denoisplit.nets.lvae_layers import TopDownLayer + + +def test_pixel_intensity_invariance(): + """ + Ensure the following constraint: f(10*x) = 10*f(x) + Here, f is the TopDownLayer + """ + res_block_type = 'bacdbacd' + res_block_kernel = 3 + res_block_skip_padding = False + gated = False + conv2d_bias = False + z_dim = 64 + n_res_blocks = 2 + n_filters = 64 + is_top_layer = False + downsampling_steps = 1 + nonlin = nn.LeakyReLU + merge_type = 'residual_ungated' + batchnorm = False + dropout = 0.0 + stochastic_skip = True + groups = 1 + learn_top_prior = True + analytical_kl = False + top_prior_param_shape = (1, 128, 8, 8) + bottomup_no_padding_mode = False + topdown_no_padding_mode = False + retain_spatial_dims = False + non_stochastic_version = True + input_image_shape = (64, 64) + normalize_latent_factor = 1 + + td_block = TopDownLayer( + z_dim, + n_res_blocks, + n_filters, + is_top_layer=is_top_layer, + downsampling_steps=downsampling_steps, + nonlin=nonlin, + merge_type=merge_type, + batchnorm=batchnorm, + dropout=dropout, + stochastic_skip=stochastic_skip, + res_block_type=res_block_type, + res_block_kernel=res_block_kernel, + res_block_skip_padding=res_block_skip_padding, + groups=groups, + gated=gated, + learn_top_prior=learn_top_prior, + top_prior_param_shape=top_prior_param_shape, + analytical_kl=analytical_kl, + bottomup_no_padding_mode=bottomup_no_padding_mode, + topdown_no_padding_mode=topdown_no_padding_mode, + retain_spatial_dims=retain_spatial_dims, + input_image_shape=input_image_shape, + normalize_latent_factor=normalize_latent_factor, + non_stochastic_version=non_stochastic_version, + conv2d_bias=conv2d_bias, + ) + with torch.no_grad(): + out = torch.rand(16, 64, 8, 8) + skip_input = out + inference_mode = True + bu_value = torch.rand(16, 64, 8, 8) + n_img_prior = None + use_mode = True + force_constant_output = None + forced_latent = None + mode_pred = False + use_uncond_mode = False + var_clip_max = None + + td_out1 = td_block(out, + skip_connection_input=skip_input, + inference_mode=inference_mode, + bu_value=bu_value, + n_img_prior=n_img_prior, + use_mode=use_mode, + force_constant_output=force_constant_output, + forced_latent=forced_latent, + mode_pred=mode_pred, + use_uncond_mode=use_uncond_mode, + var_clip_max=var_clip_max) + + td_out2 = td_block(out * 10, + skip_connection_input=skip_input * 10, + inference_mode=inference_mode, + bu_value=bu_value * 10, + n_img_prior=n_img_prior, + use_mode=use_mode, + force_constant_output=force_constant_output, + forced_latent=forced_latent, + mode_pred=mode_pred, + use_uncond_mode=use_uncond_mode, + var_clip_max=var_clip_max) + + assert (td_out1[0] * 10 - td_out2[0]).abs().max().item() < 1e-5 diff --git a/denoisplit/tests/sampler/test_default_grid_sampler.py b/denoisplit/tests/sampler/test_default_grid_sampler.py new file mode 100644 index 0000000..5a5e612 --- /dev/null +++ b/denoisplit/tests/sampler/test_default_grid_sampler.py @@ -0,0 +1,57 @@ +import numpy as np + +from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager +from denoisplit.sampler.default_grid_sampler import DefaultGridSampler + + +class DummyDset: + + def __init__(self, data_shape, image_size) -> None: + self.idx_manager = GridIndexManager(data_shape, image_size, image_size, GridAlignement.LeftTop) + + def __len__(self): + return self.idx_manager.grid_count() + + +def test_default_sampler(): + """ + Tests that most indices are covered. + Tests that grid_size is 1. + """ + frame_size = 128 + data_shape = (30, frame_size, frame_size, 2) + image_size = 64 + dset = DummyDset(data_shape, image_size) + grid_size = 1 + batch_size = 32 + sampler = DefaultGridSampler(dset, batch_size, grid_size) + samples_per_epoch = (frame_size // image_size)**2 * data_shape[0] + samples_per_epoch = samples_per_epoch - samples_per_epoch % batch_size + + reached_most_indices = False + min_idx_reached = None + max_idx_reached = None + nrows = frame_size - image_size + 1 + idx_max = nrows * nrows * data_shape[0] + + for _ in range(10): + sample_indices = [] + for batch in sampler: + sample_indices.append(batch) + if min_idx_reached is None: + idx_values, same_idx_values, grid_sizes = zip(*batch) + assert set(grid_sizes) == {1} + assert np.all(same_idx_values == idx_values) + + min_idx_reached = np.min(idx_values) + max_idx_reached = np.max(idx_values) + + sample_indices = np.concatenate(sample_indices, axis=0) + min_idx_reached = min(sample_indices[:, 0].min(), min_idx_reached) + max_idx_reached = max(sample_indices[:, 0].max(), max_idx_reached) + assert len(sample_indices) == samples_per_epoch + + if max_idx_reached - min_idx_reached > 0.9 * idx_max: + reached_most_indices = True + break + assert reached_most_indices == True diff --git a/denoisplit/tests/sampler/test_random_sampler.py b/denoisplit/tests/sampler/test_random_sampler.py new file mode 100644 index 0000000..7f81649 --- /dev/null +++ b/denoisplit/tests/sampler/test_random_sampler.py @@ -0,0 +1,63 @@ +import numpy as np + +from denoisplit.data_loader.patch_index_manager import GridAlignement, GridIndexManager +from denoisplit.sampler.random_sampler import RandomSampler + + +class DummyDset: + + def __init__(self, data_shape, image_size) -> None: + self.idx_manager = GridIndexManager(data_shape, image_size, image_size, GridAlignement.LeftTop) + + def __len__(self): + return self.idx_manager.grid_count() + + +def test_default_sampler(): + """ + Tests that most indices are covered for both indices. + Tests that grid_size is 1. + """ + frame_size = 128 + data_shape = (30, frame_size, frame_size, 2) + image_size = 64 + dset = DummyDset(data_shape, image_size) + grid_size = 1 + batch_size = 32 + sampler = RandomSampler(dset, batch_size, grid_size) + samples_per_epoch = (frame_size // image_size)**2 * data_shape[0] + samples_per_epoch = samples_per_epoch - samples_per_epoch % batch_size + + reached_most_indices = False + min_idx1_reached = None + max_idx1_reached = None + min_idx2_reached = None + max_idx2_reached = None + nrows = frame_size - image_size + 1 + idx_max = nrows * nrows * data_shape[0] + + for _ in range(10): + sample_indices = [] + for batch in sampler: + sample_indices.append(batch) + if min_idx1_reached is None: + idx1_values, idx2_values, grid_sizes = zip(*batch) + assert set(grid_sizes) == {1} + min_idx1_reached = np.min(idx1_values) + max_idx1_reached = np.max(idx1_values) + min_idx2_reached = np.min(idx2_values) + max_idx2_reached = np.max(idx2_values) + + sample_indices = np.concatenate(sample_indices, axis=0) + assert (sample_indices[:, 0] == sample_indices[:, 1]).sum() < 10 + min_idx1_reached = min(sample_indices[:, 0].min(), min_idx1_reached) + max_idx1_reached = max(sample_indices[:, 0].max(), max_idx1_reached) + min_idx2_reached = min(sample_indices[:, 1].min(), min_idx2_reached) + max_idx2_reached = max(sample_indices[:, 1].max(), max_idx2_reached) + + assert len(sample_indices) == samples_per_epoch + + if max_idx1_reached - min_idx1_reached > 0.9 * idx_max and max_idx2_reached - min_idx2_reached > 0.9 * idx_max: + reached_most_indices = True + break + assert reached_most_indices == True diff --git a/denoisplit/tests/sampler/test_twin_index_sampler.py b/denoisplit/tests/sampler/test_twin_index_sampler.py new file mode 100644 index 0000000..5e49ab7 --- /dev/null +++ b/denoisplit/tests/sampler/test_twin_index_sampler.py @@ -0,0 +1,30 @@ +from denoisplit.sampler.twin_index_sampler import TwinIndexSampler +import numpy as np + + +def test_twin_index_sampler(): + """ + Test makes only sense if the size of the dataset is a multiple of the batch_size + """ + batch_size = 12 + + class DummyDataset: + def __len__(self): + return batch_size * 5 + + def __getitem__(self, index): + idx1, idx2 = index + return np.random.rand(4, 4), np.random.rand(4, 4) + + dset = DummyDataset() + sampler = TwinIndexSampler(dset, batch_size) + + all_tuples = [] + for batch_idx in sampler: + all_tuples += batch_idx + a, b = zip(*all_tuples) + assert set(a) == set(b) + assert len(a) == 2 * len(set(a)) + assert max(a) == len(dset) - 1 + assert min(a) == 0 + assert sum(a) == (len(dset) - 1) * len(dset) diff --git a/denoisplit/training.py b/denoisplit/training.py new file mode 100644 index 0000000..a0ba186 --- /dev/null +++ b/denoisplit/training.py @@ -0,0 +1,575 @@ +import glob +import logging +import os +import pickle +from copy import deepcopy + +import pytorch_lightning as pl +import torch +import wandb +from pytorch_lightning import Trainer +from pytorch_lightning.callbacks import ModelCheckpoint +from pytorch_lightning.callbacks.early_stopping import EarlyStopping +from pytorch_lightning.loggers import TensorBoardLogger, WandbLogger +from torch.utils.data import DataLoader + +import ml_collections +from denoisplit.core.data_split_type import DataSplitType +from denoisplit.core.data_type import DataType +from denoisplit.core.loss_type import LossType +from denoisplit.core.metric_monitor import MetricMonitor +from denoisplit.core.model_type import ModelType +from denoisplit.data_loader.ht_iba1_ki67_dloader import IBA1Ki67DataLoader +from denoisplit.data_loader.intensity_augm_tiff_dloader import IntensityAugCLTiffDloader +from denoisplit.data_loader.lc_multich_dloader import LCMultiChDloader +from denoisplit.data_loader.lc_multich_explicit_input_dloader import LCMultiChExplicitInputDloader +from denoisplit.data_loader.multi_channel_determ_tiff_dloader_randomized import MultiChDeterministicTiffRandDloader +from denoisplit.data_loader.multifile_dset import MultiFileDset +from denoisplit.data_loader.notmnist_dloader import NotMNISTNoisyLoader +from denoisplit.data_loader.pavia2_3ch_dloader import Pavia2ThreeChannelDloader +from denoisplit.data_loader.places_dloader import PlacesLoader +from denoisplit.data_loader.semi_supervised_dloader import SemiSupDloader +from denoisplit.data_loader.single_channel.multi_dataset_dloader import SingleChannelMultiDatasetDloader +from denoisplit.data_loader.two_dset_dloader import TwoDsetDloader +from denoisplit.data_loader.vanilla_dloader import MultiChDloader +from denoisplit.nets.model_utils import create_model +from denoisplit.training_utils import ValEveryNSteps + + +def create_dataset(config, + datadir, + eval_datasplit_type=DataSplitType.Val, + raw_data_dict=None, + skip_train_dataset=False, + kwargs_dict=None): + if kwargs_dict is None: + kwargs_dict = {} + + if config.data.data_type == DataType.NotMNIST: + train_img_files_pkl = os.path.join(datadir, 'train_fnames.pkl') + val_img_files_pkl = os.path.join(datadir, 'val_fnames.pkl') + + datapath = os.path.join(datadir, 'noisy', 'Noise50') + + assert config.model.model_type in [ModelType.LadderVae] + assert raw_data_dict is None + label1 = config.data.label1 + label2 = config.data.label2 + train_data = None if skip_train_dataset else NotMNISTNoisyLoader(datapath, train_img_files_pkl, label1, label2) + val_data = NotMNISTNoisyLoader(datapath, val_img_files_pkl, label1, label2) + + elif config.data.data_type == DataType.Places365: + train_datapath = os.path.join(datadir, 'Noise-1', 'train') + val_datapath = os.path.join(datadir, 'Noise-1', 'val') + assert config.model.model_type in [ModelType.LadderVae, ModelType.LadderVaeTwinDecoder] + assert raw_data_dict is None + label1 = config.data.label1 + label2 = config.data.label2 + img_dsample = config.data.img_dsample + train_data = None if skip_train_dataset else PlacesLoader( + train_datapath, label1, label2, img_dsample=img_dsample) + val_data = PlacesLoader(val_datapath, label1, label2, img_dsample=img_dsample) + elif config.data.data_type == DataType.SemiSupBloodVesselsEMBL: + datapath = datadir + normalized_input = config.data.normalized_input + use_one_mu_std = config.data.use_one_mu_std + train_aug_rotate = config.data.train_aug_rotate + enable_random_cropping = config.data.deterministic_grid is False + train_data_kwargs = deepcopy(kwargs_dict) + val_data_kwargs = deepcopy(kwargs_dict) + + train_data_kwargs['enable_random_cropping'] = enable_random_cropping + val_data_kwargs['enable_random_cropping'] = False + + if 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None: + padding_kwargs = {'mode': config.data.padding_mode} + if 'padding_value' in config.data and config.data.padding_value is not None: + padding_kwargs['constant_values'] = config.data.padding_value + + train_data = None if skip_train_dataset else SingleChannelMultiDatasetDloader( + config.data, + datapath, + datasplit_type=DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=train_aug_rotate, + num_scales=config.data.multiscale_lowres_count, + padding_kwargs=padding_kwargs, + **train_data_kwargs) + + max_val = train_data.get_max_val() + val_data = SingleChannelMultiDatasetDloader( + config.data, + datapath, + datasplit_type=eval_datasplit_type, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=False, # No rotation aug on validation + max_val=max_val, + num_scales=config.data.multiscale_lowres_count, + padding_kwargs=padding_kwargs, + **val_data_kwargs, + ) + + else: + train_data = None if skip_train_dataset else SingleChannelMultiDatasetDloader( + config.data, + datapath, + datasplit_type=DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=train_aug_rotate, + **train_data_kwargs) + + max_val = train_data.get_max_val() + val_data = SingleChannelMultiDatasetDloader( + config.data, + datapath, + datasplit_type=eval_datasplit_type, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=False, # No rotation aug on validation + max_val=max_val, + **val_data_kwargs, + ) + + # For normalizing, we should be using the training data's mean and std. + mean_val, std_val = train_data.compute_mean_std() + train_data.set_mean_std(mean_val, std_val) + val_data.set_mean_std(mean_val, std_val) + + elif config.data.data_type == DataType.HTIba1Ki67 and config.model.model_type in [ + ModelType.LadderVaeTwoDataSet, ModelType.LadderVaeTwoDatasetMultiBranch, + ModelType.LadderVaeTwoDatasetMultiOptim + ]: + # multi data setup. + datapath = datadir + normalized_input = config.data.normalized_input + use_one_mu_std = config.data.use_one_mu_std + train_aug_rotate = config.data.train_aug_rotate + enable_random_cropping = config.data.deterministic_grid is False + lowres_supervision = config.model.model_type == ModelType.LadderVAEMultiTarget + + train_data_kwargs = {'allow_generation': False, **kwargs_dict} + val_data_kwargs = {'allow_generation': False, **kwargs_dict} + train_data_kwargs['enable_random_cropping'] = enable_random_cropping + val_data_kwargs['enable_random_cropping'] = False + + train_data = None if skip_train_dataset else IBA1Ki67DataLoader(config.data, + datapath, + datasplit_type=DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=train_aug_rotate, + **train_data_kwargs) + + max_val = train_data.get_max_val() + val_data = IBA1Ki67DataLoader( + config.data, + datapath, + datasplit_type=eval_datasplit_type, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=False, # No rotation aug on validation + max_val=max_val, + **val_data_kwargs, + ) + + # For normalizing, we should be using the training data's mean and std. + mean_val, std_val = train_data.compute_mean_std() + train_data.set_mean_std(mean_val, std_val) + val_data.set_mean_std(mean_val, std_val) + elif config.data.data_type == DataType.TwoDset: + cnf0 = ml_collections.ConfigDict(config) + for key in config.data.dset0: + cnf0.data[key] = config.data.dset0[key] + train_dset0, val_dset0 = create_dataset(cnf0, + datadir, + raw_data_dict=raw_data_dict, + skip_train_dataset=skip_train_dataset) + mean0, std0 = train_dset0.compute_mean_std() + train_dset0.set_mean_std(mean0, std0) + val_dset0.set_mean_std(mean0, std0) + + cnf1 = ml_collections.ConfigDict(config) + for key in config.data.dset1: + cnf1.data[key] = config.data.dset1[key] + train_dset1, val_dset1 = create_dataset(cnf1, + datadir, + raw_data_dict=raw_data_dict, + skip_train_dataset=skip_train_dataset) + mean1, std1 = train_dset1.compute_mean_std() + train_dset1.set_mean_std(mean1, std1) + val_dset1.set_mean_std(mean1, std1) + + train_data = TwoDsetDloader(train_dset0, train_dset1, config.data, config.data.use_one_mu_std) + val_data = val_dset0 + + elif config.data.data_type in [ + DataType.OptiMEM100_014, + DataType.CustomSinosoid, + DataType.CustomSinosoidThreeCurve, + DataType.Prevedel_EMBL, + DataType.AllenCellMito, + DataType.SeparateTiffData, + DataType.Pavia2VanillaSplitting, + DataType.ShroffMitoEr, + DataType.HTIba1Ki67, + DataType.BioSR_MRC, + DataType.PredictedTiffData, + DataType.Pavia3SeqData, + ]: + if config.data.data_type == DataType.OptiMEM100_014: + datapath = os.path.join(datadir, 'OptiMEM100x014.tif') + elif config.data.data_type == DataType.Prevedel_EMBL: + datapath = os.path.join(datadir, 'MS14__z0_8_sl4_fr10_p_10.1_lz510_z13_bin5_00001.tif') + else: + datapath = datadir + + normalized_input = config.data.normalized_input + use_one_mu_std = config.data.use_one_mu_std + train_aug_rotate = config.data.train_aug_rotate + enable_random_cropping = config.data.deterministic_grid is False + lowres_supervision = config.model.model_type == ModelType.LadderVAEMultiTarget + if 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None: + if 'padding_kwargs' not in kwargs_dict: + padding_kwargs = {'mode': config.data.padding_mode} + if 'padding_value' in config.data and config.data.padding_value is not None: + padding_kwargs['constant_values'] = config.data.padding_value + else: + padding_kwargs = kwargs_dict.pop('padding_kwargs') + + cls_name = LCMultiChExplicitInputDloader if config.data.data_type == DataType.PredictedTiffData else LCMultiChDloader + train_data = None if skip_train_dataset else cls_name(config.data, + datapath, + datasplit_type=DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=train_aug_rotate, + enable_random_cropping=enable_random_cropping, + num_scales=config.data.multiscale_lowres_count, + lowres_supervision=lowres_supervision, + padding_kwargs=padding_kwargs, + **kwargs_dict, + allow_generation=True) + max_val = train_data.get_max_val() + + val_data = cls_name( + config.data, + datapath, + datasplit_type=eval_datasplit_type, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=False, # No rotation aug on validation + enable_random_cropping=False, + # No random cropping on validation. Validation is evaluated on determistic grids + num_scales=config.data.multiscale_lowres_count, + lowres_supervision=lowres_supervision, + padding_kwargs=padding_kwargs, + allow_generation=False, + **kwargs_dict, + max_val=max_val, + ) + + else: + train_data_kwargs = {'allow_generation': True, **kwargs_dict} + val_data_kwargs = {'allow_generation': False, **kwargs_dict} + if config.model.model_type in [ModelType.LadderVaeSepEncoder, ModelType.LadderVaeSepEncoderSingleOptim]: + data_class = SemiSupDloader + # mixed_input_type = None, + # supervised_data_fraction = 0.0, + train_data_kwargs['mixed_input_type'] = config.data.mixed_input_type + train_data_kwargs['supervised_data_fraction'] = config.data.supervised_data_fraction + val_data_kwargs['mixed_input_type'] = config.data.mixed_input_type + val_data_kwargs['supervised_data_fraction'] = 1.0 + else: + train_data_kwargs['enable_random_cropping'] = enable_random_cropping + val_data_kwargs['enable_random_cropping'] = False + data_class = (MultiChDeterministicTiffRandDloader + if config.data.randomized_channels else MultiChDloader) + + train_data = None if skip_train_dataset else data_class(config.data, + datapath, + datasplit_type=DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=train_aug_rotate, + **train_data_kwargs) + + max_val = train_data.get_max_val() + val_data = data_class( + config.data, + datapath, + datasplit_type=eval_datasplit_type, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=False, # No rotation aug on validation + max_val=max_val, + **val_data_kwargs, + ) + + # For normalizing, we should be using the training data's mean and std. + mean_val, std_val = train_data.compute_mean_std() + train_data.set_mean_std(mean_val, std_val) + val_data.set_mean_std(mean_val, std_val) + elif config.data.data_type == DataType.Pavia2: + normalized_input = config.data.normalized_input + use_one_mu_std = config.data.use_one_mu_std + train_aug_rotate = config.data.train_aug_rotate + enable_random_cropping = config.data.deterministic_grid is False + train_data_kwargs = {'allow_generation': False, **kwargs_dict} + val_data_kwargs = {'allow_generation': False, **kwargs_dict} + train_data_kwargs['enable_random_cropping'] = enable_random_cropping + val_data_kwargs['enable_random_cropping'] = False + + datapath = datadir + train_data = None if skip_train_dataset else Pavia2ThreeChannelDloader( + config.data, + datapath, + datasplit_type=DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=train_aug_rotate, + **train_data_kwargs) + + max_val = train_data.get_max_val() + val_data = Pavia2ThreeChannelDloader( + config.data, + datapath, + datasplit_type=eval_datasplit_type, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=False, # No rotation aug on validation + max_val=max_val, + **val_data_kwargs, + ) + + # For normalizing, we should be using the training data's mean and std. + mean_val, std_val = train_data.compute_mean_std() + train_data.set_mean_std(mean_val, std_val) + val_data.set_mean_std(mean_val, std_val) + elif config.data.data_type in [ + DataType.TavernaSox2Golgi, DataType.Dao3Channel, DataType.ExpMicroscopyV2, DataType.TavernaSox2GolgiV2 + ]: + datapath = datadir + normalized_input = config.data.normalized_input + use_one_mu_std = config.data.use_one_mu_std + train_aug_rotate = config.data.train_aug_rotate + enable_random_cropping = config.data.deterministic_grid is False + lowres_supervision = config.model.model_type == ModelType.LadderVAEMultiTarget + + train_data_kwargs = {**kwargs_dict} + val_data_kwargs = {**kwargs_dict} + train_data_kwargs['enable_random_cropping'] = enable_random_cropping + val_data_kwargs['enable_random_cropping'] = False + padding_kwargs = None + if 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None: + padding_kwargs = {'mode': config.data.padding_mode} + if 'padding_value' in config.data and config.data.padding_value is not None: + padding_kwargs['constant_values'] = config.data.padding_value + + train_data = MultiFileDset(config.data, + datapath, + datasplit_type=DataSplitType.Train, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=train_aug_rotate, + padding_kwargs=padding_kwargs, + **train_data_kwargs) + + max_val = train_data.get_max_val() + val_data = MultiFileDset( + config.data, + datapath, + datasplit_type=eval_datasplit_type, + val_fraction=config.training.val_fraction, + test_fraction=config.training.test_fraction, + normalized_input=normalized_input, + use_one_mu_std=use_one_mu_std, + enable_rotation_aug=False, # No rotation aug on validation + padding_kwargs=padding_kwargs, + max_val=max_val, + **val_data_kwargs, + ) + + # For normalizing, we should be using the training data's mean and std. + mean_val, std_val = train_data.compute_mean_std() + train_data.set_mean_std(mean_val, std_val) + val_data.set_mean_std(mean_val, std_val) + # if 'multiscale_lowres_count' in config.data and config.data.multiscale_lowres_count is not None: + # padding_kwargs = {'mode': config.data.padding_mode} + # if 'padding_value' in config.data and config.data.padding_value is not None: + # padding_kwargs['constant_values'] = config.data.padding_value + + return train_data, val_data + + +def create_model_and_train(config, data_mean, data_std, logger, checkpoint_callback, train_loader, val_loader): + # tensorboard previous files. + for filename in glob.glob(config.workdir + "/events*"): + os.remove(filename) + + # checkpoints + for filename in glob.glob(config.workdir + "/*.ckpt"): + os.remove(filename) + + if hasattr(val_loader.dataset, 'idx_manager'): + val_idx_manager = val_loader.dataset.idx_manager + else: + val_idx_manager = None + model = create_model(config, data_mean, data_std, val_idx_manager=val_idx_manager) + + if config.model.model_type == ModelType.LadderVaeStitch2Stage: + assert config.training.pre_trained_ckpt_fpath and os.path.exists(config.training.pre_trained_ckpt_fpath) + + if config.training.pre_trained_ckpt_fpath: + print('Starting with pre-trained model', config.training.pre_trained_ckpt_fpath) + checkpoint = torch.load(config.training.pre_trained_ckpt_fpath) + _ = model.load_state_dict(checkpoint['state_dict'], strict=False) + + # print(model) + estop_monitor = config.model.get('monitor', 'val_loss') + estop_mode = MetricMonitor(estop_monitor).mode() + + callbacks = [ + EarlyStopping(monitor=estop_monitor, + min_delta=1e-6, + patience=config.training.earlystop_patience, + verbose=True, + mode=estop_mode), + checkpoint_callback, + ] + if 'val_every_n_steps' in config.training and config.training.val_every_n_steps is not None: + callbacks.append(ValEveryNSteps(config.training.val_every_n_steps)) + + logger.experiment.config.update(config.to_dict()) + # wandb.init(config=config) + if torch.cuda.is_available(): + # profiler = pl.profiler.AdvancedProfiler(output_filename=os.path.join(config.workdir, 'advance_profile.txt')) + try: + # older version has this code + trainer = pl.Trainer( + gpus=1, + max_epochs=config.training.max_epochs, + gradient_clip_val=None + if model.automatic_optimization == False else config.training.grad_clip_norm_value, + # gradient_clip_algorithm=config.training.gradient_clip_algorithm, + logger=logger, + # fast_dev_run=10, + # profiler=profiler, + # overfit_batches=20, + callbacks=callbacks, + precision=config.training.precision) + except: + trainer = pl.Trainer( + # gpus=1, + max_epochs=config.training.max_epochs, + gradient_clip_val=None + if model.automatic_optimization == False else config.training.grad_clip_norm_value, + # gradient_clip_algorithm=config.training.gradient_clip_algorithm, + logger=logger, + # fast_dev_run=10, + # profiler=profiler, + # overfit_batches=20, + callbacks=callbacks, + precision=config.training.precision) + + else: + trainer = pl.Trainer( + max_epochs=config.training.max_epochs, + logger=logger, + gradient_clip_val=config.training.grad_clip_norm_value, + gradient_clip_algorithm=config.training.gradient_clip_algorithm, + callbacks=callbacks, + # fast_dev_run=10, + # overfit_batches=10, + precision=config.training.precision) + trainer.fit(model, train_loader, val_loader) + + +def train_network(train_loader, val_loader, data_mean, data_std, config, model_name, logdir): + ckpt_monitor = config.model.get('monitor', 'val_loss') + ckpt_mode = MetricMonitor(ckpt_monitor).mode() + checkpoint_callback = ModelCheckpoint( + monitor=ckpt_monitor, + dirpath=config.workdir, + filename=model_name + '_best', + save_last=True, + save_top_k=1, + mode=ckpt_mode, + ) + checkpoint_callback.CHECKPOINT_NAME_LAST = model_name + "_last" + logger = WandbLogger(name=os.path.join(config.hostname, config.exptname), + save_dir=logdir, + project="Disentanglement") + # logger = TensorBoardLogger(config.workdir, name="", version="", default_hp_metric=False) + + # pl.utilities.distributed.log.setLevel(logging.ERROR) + posterior_collapse_count = 0 + collapse_flag = True + while collapse_flag and posterior_collapse_count < 20: + collapse_flag = create_model_and_train(config, data_mean, data_std, logger, checkpoint_callback, train_loader, + val_loader) + if collapse_flag is None: + print('CTRL+C inturrupt. Ending') + return + + if collapse_flag: + posterior_collapse_count = posterior_collapse_count + 1 + + if collapse_flag: + print("Posterior collapse limit reached, attempting training with KL annealing turned on!") + while collapse_flag: + config.loss.kl_annealing = True + collapse_flag = create_model_and_train(config, data_mean, data_std, logger, checkpoint_callback, + train_loader, val_loader) + if collapse_flag is None: + print('CTRL+C inturrupt. Ending') + return + + +if __name__ == '__main__': + import matplotlib.pyplot as plt + import numpy as np + + from denoisplit.configs.deepencoder_lvae_config import get_config + + config = get_config() + train_data, val_data = create_dataset(config, '/group/jug/ashesh/data/microscopy/') + + dset = val_data + idx = 0 + _, ax = plt.subplots(figsize=(9, 3), ncols=3) + inp, target, alpha_val, ch1_idx, ch2_idx = dset[(idx, idx, 64, 19)] + ax[0].imshow(inp[0]) + ax[1].imshow(target[0]) + ax[2].imshow(target[1]) + + print(len(train_data), len(val_data)) + print(inp.mean(), target.mean()) diff --git a/denoisplit/training_utils.py b/denoisplit/training_utils.py new file mode 100644 index 0000000..372ee51 --- /dev/null +++ b/denoisplit/training_utils.py @@ -0,0 +1,55 @@ +import os +import shutil + +import pytorch_lightning as pl + + +class ValEveryNSteps(pl.Callback): + """ + Run validation after every n step + """ + def __init__(self, every_n_step): + self.every_n_step = every_n_step + + def on_batch_end(self, trainer, pl_module): + if trainer.global_step % self.every_n_step == 0 and trainer.global_step != 0: + trainer.run_evaluation() + + +def clean_up(dir): + for yearmonth in os.listdir(dir): + monthdir = os.path.join(dir, yearmonth) + for modeltype in os.listdir(monthdir): + modeltypedir = os.path.join(monthdir, modeltype) + for modelid in os.listdir(modeltypedir): + modeldir = os.path.join(modeltypedir, modelid) + for fname in os.listdir(modeldir): + if fname[-10:] == '_last.ckpt': + fpath = os.path.join(modeldir, fname) + print('Removing', fpath) + os.remove(fpath) + + +def create_dir(dir): + if not os.path.exists(dir): + os.mkdir(dir) + + +def copy_config(src_dir, dst_dir): + for yearmonth in os.listdir(src_dir): + monthdir = os.path.join(src_dir, yearmonth) + dst_monthdir = os.path.join(dst_dir, yearmonth) + create_dir(dst_monthdir) + for modeltype in os.listdir(monthdir): + modeltypedir = os.path.join(monthdir, modeltype) + dst_modeltypedir = os.path.join(dst_monthdir, modeltype) + create_dir(dst_modeltypedir) + for modelid in os.listdir(modeltypedir): + modeldir = os.path.join(modeltypedir, modelid) + dst_modeldir = os.path.join(dst_modeltypedir, modelid) + create_dir(dst_modeldir) + for fname in os.listdir(modeldir): + if fname[-5:] != '.ckpt' and fname[:7] != 'events.': + fpath = os.path.join(modeldir, fname) + dst_fpath = os.path.join(dst_modeldir, fname) + shutil.copyfile(fpath, dst_fpath) diff --git a/denoisplit/utils.py b/denoisplit/utils.py new file mode 100644 index 0000000..f8ec6b7 --- /dev/null +++ b/denoisplit/utils.py @@ -0,0 +1,545 @@ +import os +import time +from glob import glob + +import numpy as np +import torch +from matplotlib import pyplot as plt +from sklearn.cluster import MeanShift +from sklearn.feature_extraction import image +from tqdm import tqdm + +from IPython.display import clear_output +from tifffile import imsave + + +def normalize(img, mean, std): + """Normalize an array of images with mean and standard deviation. + Parameters + ---------- + img: array + An array of images. + mean: float + Mean of img array. + std: float + Standard deviation of img array. + """ + return (img - mean) / std + + +def denormalize(img, mean, std): + """Denormalize an array of images with mean and standard deviation. + Parameters + ---------- + img: array + An array of images. + mean: float + Mean of img array. + std: float + Standard deviation of img array. + """ + return (img * std) + mean + + +def convertToFloat32(train_images, val_images): + """Converts the data to float 32 bit type. + Parameters + ---------- + train_images: array + Training data. + val_images: array + Validation data. + """ + x_train = train_images.astype('float32') + x_val = val_images.astype('float32') + return x_train, x_val + + +def getMeanStdData(train_images, val_images): + """Compute mean and standrad deviation of data. + Parameters + ---------- + train_images: array + Training data. + val_images: array + Validation data. + """ + x_train_ = train_images.astype('float32') + x_val_ = val_images.astype('float32') + data = np.concatenate((x_train_, x_val_), axis=0) + mean, std = np.mean(data), np.std(data) + return mean, std + + +def convertNumpyToTensor(numpy_array): + """Convert numpy array to PyTorch tensor. + Parameters + ---------- + numpy_array: numpy array + Numpy array. + """ + return torch.from_numpy(numpy_array) + + +def preprocess(train_patches, val_patches): + data_mean, data_std = getMeanStdData(train_patches, val_patches) + x_train, x_val = convertToFloat32(train_patches, val_patches) + x_train_extra_axis = x_train[:, np.newaxis] + x_val_extra_axis = x_val[:, np.newaxis] + x_train_tensor = convertNumpyToTensor(x_train_extra_axis) + x_val_tensor = convertNumpyToTensor(x_val_extra_axis) + return x_train_tensor, x_val_tensor, data_mean, data_std + + +def get_trainval_patches(x, split_fraction=0.85, augment=True, patch_size=128, num_patches=None): + np.random.shuffle(x) + train_images = x[:int(0.85 * x.shape[0])] + val_images = x[int(0.85 * x.shape[0]):] + if (augment): + train_images = augment_data(train_images) + x_train_crops = extract_patches(train_images, patch_size, num_patches) + x_val_crops = extract_patches(val_images, patch_size, num_patches) + print("Shape of training patches:", x_train_crops.shape, "Shape of validation patches:", x_val_crops.shape) + return x_train_crops, x_val_crops + + +def extract_patches(x, patch_size, num_patches): + """Deterministically extract patches from array of images. + Parameters + ---------- + x: numpy array + Array of images. + patch_size: int + Size of patches to be extracted from each image. + num_patches: int + Number of patches to be extracted from each image. + """ + img_width = x.shape[2] + img_height = x.shape[1] + if (num_patches is None): + num_patches = int(float(img_width * img_height) / float(patch_size**2) * 2) + patches = np.zeros(shape=(x.shape[0] * num_patches, patch_size, patch_size)) + + for i in tqdm(range(x.shape[0])): + patches[i * num_patches:(i + 1) * num_patches] = image.extract_patches_2d(x[i], (patch_size, patch_size), + num_patches, + random_state=i) + return patches + + +def augment_data(X_train): + """Augment data by 8-fold with 90 degree rotations and flips. + Parameters + ---------- + X_train: numpy array + Array of training images. + """ + X_ = X_train.copy() + X_train_aug = np.concatenate((X_train, np.rot90(X_, 1, (1, 2)))) + X_train_aug = np.concatenate((X_train_aug, np.rot90(X_, 2, (1, 2)))) + X_train_aug = np.concatenate((X_train_aug, np.rot90(X_, 3, (1, 2)))) + X_train_aug = np.concatenate((X_train_aug, np.flip(X_train_aug, axis=1))) + return X_train_aug + + +def loadImages(path): + """Load images from a given directory. + Parameters + ---------- + path: String + Path of directory from where to load images from. + """ + files = sorted(glob(path)) + data = [] + print(path) + for f in files: + if '.png' in f: + im_b = np.array(io.imread(f)) + if '.npy' in f: + im_b = np.load(f) + data.append(im_b) + + data = np.array(data).astype(np.float32) + return data + + +def getSamples(vae, size=20, zSize=64, mu=None, logvar=None, samples=1, tq=False): + """Generate synthetic samples from Disentangle network. + Parameters + ---------- + vae: VAE Object + Disentangle model. + size: int + Size of generated image in the bottleneck. + zSize: int + Dimension of latent space for each pixel in bottleneck. + mu: PyTorch tensor + latent space mean tensor. + logvar: PyTorch tensor + latent space log variance tensor. + samples: int + Number of synthetic samples to generate. + tq: boolean + If tqdm should be active or not to indicate progress. + """ + if mu is None: + mu = torch.zeros(1, zSize, size, size).cuda() + if logvar is None: + logvar = torch.zeros(1, zSize, size, size).cuda() + + results = [] + for i in tqdm(range(samples), disable=not tq): + z = vae.reparameterize(mu, logvar) + recon = vae.decode(z) + recon_cpu = recon.cpu() + recon_numpy = recon_cpu.detach().numpy() + recon_numpy.shape = (recon_numpy.shape[-2], recon_numpy.shape[-1]) + results.append(recon_numpy) + return np.array(results) + + +def interpolate( + vae, + z_start, + z_end, + steps, + display, + vmin=0, + vmax=255, +): + results = [] + for i in range(steps): + alpha = (i / (steps - 1.0)) + z = z_end * alpha + z_start * (1.0 - alpha) + recon = vae.decode(z) + recon_cpu = recon.cpu() + recon_numpy = recon_cpu.detach().numpy() + recon_numpy.shape = (recon_numpy.shape[-2], recon_numpy.shape[-1]) + if display: + clear_output(wait=True) + plt.imshow(recon_numpy, vmin=vmin, vmax=vmax) + plt.show() + time.sleep(0.4) + results.append(recon_numpy) + return results + + +def tiledMode(im, ps, overlap, display=True, vmin=0, vmax=255, initBW=200, minBW=100, reduce=0.9): + means = np.zeros(im.shape[1:]) + xmin = 0 + ymin = 0 + xmax = ps + ymax = ps + ovLeft = 0 + while (xmin < im.shape[2]): + ovTop = 0 + while (ymin < im.shape[1]): + inputPatch = im[:, ymin:ymax, xmin:xmax] + a = findMode(inputPatch, initBW, minBW, reduce) + a = a[:a.shape[0], :a.shape[1]] + means[ymin:ymax, xmin:xmax][ovTop:, ovLeft:] = a[ovTop:, ovLeft:] + + ymin = ymin - overlap + ps + ymax = ymin + ps + ovTop = overlap // 2 + + ymin = 0 + ymax = ps + xmin = xmin - overlap + ps + xmax = xmin + ps + ovLeft = overlap // 2 + + if display: + plt.imshow(means, vmin=vmin, vmax=vmax) + plt.show() + clear_output(wait=True) + + return means + + +def findClosest(samples, q): + """Find closest sample to a given sample. + Parameters + ---------- + samples: array + Array of samples from which the closest image needs to be found. + q: image(array) + Image to which the closest image needs to be found. + """ + dif = np.mean(np.mean((samples - q)**2, -1), -1) + return samples[np.argmin(dif)] + + +def findMode(samples, initBW=200, minBW=100, reduce=0.9): + """Find the modes of a distribution of images. + Parameters + ---------- + samples: array + Array of samples from which the modes need to be found. + initBW: int + Initial bandwidth. + minBW: int + Minimum bandwidth. + reduce: float + Factor by which to reduce bandwith i n iterations. + """ + imagesC = samples.copy() + imagesC.shape = (samples.shape[0], samples.shape[1] * samples.shape[2]) + seed = np.mean(imagesC, axis=0)[np.newaxis, ...] + bw = initBW + for i in range(15): + + clustering = MeanShift(bandwidth=bw, seeds=seed, cluster_all=True).fit(imagesC) + centers = clustering.cluster_centers_.copy() + seed = centers + bw = bw * reduce + if bw < minBW: + break + + result = seed[0] + result.shape = (samples.shape[1], samples.shape[2]) + return result + + +def plotProbabilityDistribution(signalBinIndex, histogramNoiseModel, gaussianMixtureNoiseModel, device): + """Plots probability distribution P(x|s) for a certain ground truth signal. + Predictions from both Histogram and GMM-based Noise models are displayed for comparison. + Parameters + ---------- + signalBinIndex: int + index of signal bin. Values go from 0 to number of bins (`n_bin`). + histogramNoiseModel: Histogram based noise model + gaussianMixtureNoiseModel: GaussianMixtureNoiseModel + Object containing trained parameters. + device: GPU device + """ + max_signal = histogramNoiseModel.maxv.item() + min_signal = histogramNoiseModel.minv.item() + n_bin = int(histogramNoiseModel.bins.item()) + + histBinSize = (max_signal - min_signal) / n_bin + querySignal_numpy = (signalBinIndex / float(n_bin) * (max_signal - min_signal) + min_signal) + querySignal_numpy += histBinSize / 2 + querySignal_torch = torch.from_numpy(np.array(querySignal_numpy)).float().to(device) + + queryObservations_numpy = np.arange(min_signal, max_signal, histBinSize) + queryObservations_numpy += histBinSize / 2 + queryObservations = torch.from_numpy(queryObservations_numpy).float().to(device) + pTorch = gaussianMixtureNoiseModel.likelihood(queryObservations, querySignal_torch) + pNumpy = pTorch.cpu().detach().numpy() + + plt.figure(figsize=(12, 5)) + + plt.subplot(1, 2, 1) + plt.xlabel('Observation Bin') + plt.ylabel('Signal Bin') + histogram = histogramNoiseModel.fullHist.cpu().numpy() + plt.imshow(histogram**0.25, cmap='gray') + # plt.axhline(y=signalBinIndex + 0.5, linewidth=5, color='blue', alpha=0.5) + + plt.subplot(1, 2, 2) + histobs = histogramNoiseModel.likelihood(queryObservations, querySignal_torch).cpu().numpy() + # histobs_repeated = np.repeat(histobs, 2) + # queryObservations_repeated = np.repeat(queryObservations_numpy, 2) + plt.plot(queryObservations_numpy, + histobs, + label='Hist : ' + ' signal = ' + str(np.round(querySignal_numpy, 2)), + color='blue', + marker='.', + linewidth=2) + + plt.plot(queryObservations_numpy, + pNumpy, + label='GMM : ' + ' signal = ' + str(np.round(querySignal_numpy, 2)), + marker='.', + color='red', + linewidth=2) + plt.xlabel('Observations (x) for signal s = ' + str(querySignal_numpy)) + plt.ylabel('Probability Density') + plt.title("Probability Distribution P(x|s) at signal =" + str(querySignal_numpy)) + plt.legend() + return {'gmm': {'x': queryObservations_numpy, 'p': pNumpy}, 'hist': {'x': queryObservations_numpy, 'p': histobs}} + + +def predict_mmse(vae, img, samples, device, returnSamples=False, tq=True): + ''' + Predicts MMSE estimate. + Parameters + ---------- + vae: VAE object + Disentangle model. + img: array + Image for which denoised MMSE estimate needs to be computed. + samples: int + Number of samples to average for computing MMSE estimate. + returnSamples: + Should the method also return the individual samples? + tq: + Should progress bar be shown. + tta: + Should test time augmentation be enabled. + ''' + img_height, img_width = img.shape[0], img.shape[1] + imgT = torch.Tensor(img.copy()) + image_sample = imgT.view(1, 1, img_height, img_width).to(device) + vae.num_samples = samples + all_samples = np.array(vae(image_sample, tqdm_bar=tq)) + samples_array = all_samples[:, 0, 0, :, :] + if returnSamples: + return np.mean(samples_array, axis=0), samples_array + else: + return np.mean(samples_array, axis=0) + + +def normalize_minmse(x, target): + """Affine rescaling of x, such that the mean squared error to target is minimal.""" + cov = np.cov(x.flatten(), target.flatten()) + alpha = cov[0, 1] / (cov[0, 0] + 1e-10) + beta = target.mean() - alpha * x.mean() + return alpha * x + beta + + +def tta_forward(x): + """ + Augments x 8-fold: all 90 deg rotations plus lr flip of the four rotated versions. + + Parameters + ---------- + x: data to augment + + Returns + ------- + Stack of augmented x. + """ + x_aug = [x, np.rot90(x, 1), np.rot90(x, 2), np.rot90(x, 3)] + x_aug_flip = x_aug.copy() + for x_ in x_aug: + x_aug_flip.append(np.fliplr(x_)) + return x_aug_flip + + +def tta_backward(x_aug): + """ + Inverts `tta_forward` and averages the 8 images. + + Parameters + ---------- + x_aug: stack of 8-fold augmented images. + + Returns + ------- + average of de-augmented x_aug. + """ + x_deaug = [ + x_aug[0], + np.rot90(x_aug[1], -1), + np.rot90(x_aug[2], -2), + np.rot90(x_aug[3], -3), + np.fliplr(x_aug[4]), + np.rot90(np.fliplr(x_aug[5]), -1), + np.rot90(np.fliplr(x_aug[6]), -2), + np.rot90(np.fliplr(x_aug[7]), -3) + ] + return np.mean(x_deaug, 0) + + +def predict_and_save(img, vae, num_samples, device, fraction_samples_to_export, export_mmse, export_results_path, tta): + ''' + Predict denoised images and save results to disk. + Parameters + ---------- + img: array or list + A stack of tif images. + vae: Disentangle model + num_samples: int + Number of samples to generate and use for computing MMSE. + device: cuda device or cpu + fraction_samples_to_export: float between 0 (inclusive) and 1 (inclusive) + Number of samples to save on disk for each noisy image. + export_mmse: bool + Should MMSE estimate also be exported? + export_results_path: str + path where all results will be exported. + tta: bool + Use test-time augmentation if set to True. + + ''' + mmse_results = [] + if isinstance(img, (list)): + num_images = len(img) + if isinstance(img, (np.ndarray)): + num_images = img.shape[0] + for i in range(num_images): + print("Processing image:", i) + if tta: + aug_imgs = tta_forward(img[i]) + mmse_aug = [] + for j in range(len(aug_imgs)): + if (j == 0): + mmse, samples = predict_mmse(vae, aug_imgs[j], num_samples, device=device, returnSamples=True) + else: + mmse = predict_mmse(vae, aug_imgs[j], num_samples, device=device, returnSamples=False) + mmse_aug.append(mmse) + + mmse_back_transformed = tta_backward(mmse_aug) + mmse_results.append(mmse_back_transformed) + else: + mmse, samples = predict_mmse(vae, img[i], num_samples, device=device, returnSamples=True) + mmse_results.append(mmse) + if fraction_samples_to_export > 0: + subdir = export_results_path + "/" + str(i).zfill(3) + "/" + if not os.path.exists(subdir): + os.makedirs(subdir) + imsave(subdir + "samples_for_image_" + str(i).zfill(3) + ".tif", + np.array(samples[:int(num_samples * fraction_samples_to_export)]).astype("float32")) + if (export_mmse): + imsave(export_results_path + "/mmse_results.tif", np.array(mmse_results).astype("float32")) + return mmse_results + + +def plot_qualitative_results(noisy_input, vae, device): + ''' + Plot qualitative results on patches. + Parameters + ---------- + noisy_input: array or list + A stack of tif images. + ''' + + for j in range(5): + + # we select a random crop + size_uncropped = int(0.14 * (np.minimum(noisy_input[0].shape[0], noisy_input[0].shape[1]))) + size = size_uncropped - (size_uncropped % (2**vae.n_depth)) + minx = np.random.randint(0, noisy_input[0].shape[0] - size) + miny = np.random.randint(0, noisy_input[0].shape[1] - size) + img = noisy_input[0][minx:minx + size, miny:miny + size] + + # generate samples and MMSE estimate + imgMMSE, samps = predict_mmse(vae, img, samples=100, device=device, returnSamples=True) + + plt.figure(figsize=(20, 6.75)) + + # We display the noisy input image + ax = plt.subplot(1, 6, 1) + ax.get_xaxis().set_visible(False) + ax.get_yaxis().set_visible(False) + plt.imshow(img, cmap='magma') + plt.title('input') + + # We display the average of 100 predicted samples + ax = plt.subplot(1, 6, 6) + ax.get_xaxis().set_visible(False) + ax.get_yaxis().set_visible(False) + plt.imshow(imgMMSE, cmap='magma') + plt.title('MMSE (100 samples)') + + # We also display the first 4 samples + for i in range(4): + ax = plt.subplot(1, 6, i + 2) + ax.get_xaxis().set_visible(False) + ax.get_yaxis().set_visible(False) + plt.imshow(samps[i], cmap='magma') + plt.title('prediction ' + str(i + 1)) + + plt.show() diff --git a/installation.sh b/installation.sh new file mode 100644 index 0000000..e5dcbbd --- /dev/null +++ b/installation.sh @@ -0,0 +1,21 @@ +conda create -n Disentangle python=3.9 +conda activate Disentangle +conda install pytorch==1.13.1 torchvision==0.14.1 pytorch-cuda=11.6 -c pytorch -c nvidia -y +conda install -c conda-forge pytorch-lightning -y +conda install -c conda-forge wandb -y +conda install -c conda-forge tensorboard -y +python -m pip install ml-collections +conda install -c anaconda scikit-learn -y +conda install -c conda-forge matplotlib -y +conda install -c anaconda ipython -y +conda install -c conda-forge tifffile -y +python -m pip install albumentations +conda install -c conda-forge nd2reader -y +conda install -c conda-forge yapf -y +conda install -c conda-forge isort -y +python -m pip install pre-commit +conda install -c conda-forge czifile -y +conda install seaborn -c conda-forge -y +conda install nbconvert -y +conda install -c anaconda ipykernel -y +conda install -c conda-forge czifile -y