diff --git a/dev_resources/docs/IQM_Vis.UI.rst b/dev_resources/docs/IQM_Vis.UI.rst index 463cd1d..3132af9 100644 --- a/dev_resources/docs/IQM_Vis.UI.rst +++ b/dev_resources/docs/IQM_Vis.UI.rst @@ -12,10 +12,18 @@ IQM\_Vis.UI.custom\_widgets module :undoc-members: :show-inheritance: -IQM\_Vis.UI.experiment\_mode module ------------------------------------ +IQM\_Vis.UI.experiment\_mode\_2AFC module +----------------------------------------- -.. automodule:: IQM_Vis.UI.experiment_mode +.. automodule:: IQM_Vis.UI.experiment_mode_2AFC + :members: + :undoc-members: + :show-inheritance: + +IQM\_Vis.UI.experiment\_mode\_JND module +---------------------------------------- + +.. automodule:: IQM_Vis.UI.experiment_mode_JND :members: :undoc-members: :show-inheritance: diff --git a/dev_resources/docs/IQM_Vis.examples.KODAK_dataset.rst b/dev_resources/docs/IQM_Vis.examples.KODAK_dataset.rst new file mode 100644 index 0000000..16b8484 --- /dev/null +++ b/dev_resources/docs/IQM_Vis.examples.KODAK_dataset.rst @@ -0,0 +1,10 @@ +IQM\_Vis.examples.KODAK\_dataset package +======================================== + +Module contents +--------------- + +.. automodule:: IQM_Vis.examples.KODAK_dataset + :members: + :undoc-members: + :show-inheritance: diff --git a/dev_resources/docs/IQM_Vis.examples.rst b/dev_resources/docs/IQM_Vis.examples.rst index d7e5ea7..f5d3290 100644 --- a/dev_resources/docs/IQM_Vis.examples.rst +++ b/dev_resources/docs/IQM_Vis.examples.rst @@ -7,6 +7,7 @@ Subpackages .. toctree:: :maxdepth: 4 + IQM_Vis.examples.KODAK_dataset IQM_Vis.examples.images Submodules @@ -36,14 +37,6 @@ IQM\_Vis.examples.dists module :undoc-members: :show-inheritance: -IQM\_Vis.examples.experiment module ------------------------------------ - -.. automodule:: IQM_Vis.examples.experiment - :members: - :undoc-members: - :show-inheritance: - IQM\_Vis.examples.kodak module ------------------------------ @@ -52,30 +45,6 @@ IQM\_Vis.examples.kodak module :undoc-members: :show-inheritance: -IQM\_Vis.examples.multiple module ---------------------------------- - -.. automodule:: IQM_Vis.examples.multiple - :members: - :undoc-members: - :show-inheritance: - -IQM\_Vis.examples.new\_api module ---------------------------------- - -.. automodule:: IQM_Vis.examples.new_api - :members: - :undoc-members: - :show-inheritance: - -IQM\_Vis.examples.simple module -------------------------------- - -.. automodule:: IQM_Vis.examples.simple - :members: - :undoc-members: - :show-inheritance: - Module contents --------------- diff --git a/dev_resources/docs/_autosummary/IQM_Vis.UI.experiment_mode_2AFC.rst b/dev_resources/docs/_autosummary/IQM_Vis.UI.experiment_mode_2AFC.rst new file mode 100644 index 0000000..734d612 --- /dev/null +++ b/dev_resources/docs/_autosummary/IQM_Vis.UI.experiment_mode_2AFC.rst @@ -0,0 +1,36 @@ +IQM\_Vis.UI.experiment\_mode\_2AFC +================================== + +.. automodule:: IQM_Vis.UI.experiment_mode_2AFC + + + + + + + + .. rubric:: Functions + + .. autosummary:: + + sort_list + + + + + + .. rubric:: Classes + + .. autosummary:: + + make_experiment_2AFC + reset_image_widget_to_black + + + + + + + + + diff --git a/dev_resources/docs/_autosummary/IQM_Vis.UI.experiment_mode_JND.rst b/dev_resources/docs/_autosummary/IQM_Vis.UI.experiment_mode_JND.rst new file mode 100644 index 0000000..e79da52 --- /dev/null +++ b/dev_resources/docs/_autosummary/IQM_Vis.UI.experiment_mode_JND.rst @@ -0,0 +1,30 @@ +IQM\_Vis.UI.experiment\_mode\_JND +================================= + +.. automodule:: IQM_Vis.UI.experiment_mode_JND + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + make_experiment_JND + reset_image_widget_to_black + + + + + + + + + diff --git a/dev_resources/docs/_autosummary/IQM_Vis.UI.images.rst b/dev_resources/docs/_autosummary/IQM_Vis.UI.images.rst index 60dbeb4..5aeb1f2 100644 --- a/dev_resources/docs/_autosummary/IQM_Vis.UI.images.rst +++ b/dev_resources/docs/_autosummary/IQM_Vis.UI.images.rst @@ -23,6 +23,7 @@ IQM\_Vis.UI.images ~images.change_to_specific_trans ~images.completed_range_results ~images.display_images + ~images.display_metric_JND_plot ~images.display_metric_correlation_plot ~images.display_metric_images ~images.display_metric_range_plot @@ -30,9 +31,11 @@ IQM\_Vis.UI.images ~images.display_metrics_graph ~images.display_metrics_text ~images.display_radar_plots + ~images.get_export_dir ~images.get_metrics_over_all_trans_with_init_values ~images.init_worker_thread ~images.load_experiment_from_dir + ~images.load_experiment_from_dir_JND ~images.load_human_experiment ~images.load_new_images_folder ~images.load_new_single_image diff --git a/dev_resources/docs/_autosummary/IQM_Vis.UI.rst b/dev_resources/docs/_autosummary/IQM_Vis.UI.rst index c9282f8..2b9acb7 100644 --- a/dev_resources/docs/_autosummary/IQM_Vis.UI.rst +++ b/dev_resources/docs/_autosummary/IQM_Vis.UI.rst @@ -1,4 +1,4 @@ -IQM\_Vis.UI +IQM\_Vis.UI =========== .. automodule:: IQM_Vis.UI @@ -28,7 +28,8 @@ IQM\_Vis.UI :recursive: IQM_Vis.UI.custom_widgets - IQM_Vis.UI.experiment_mode + IQM_Vis.UI.experiment_mode_2AFC + IQM_Vis.UI.experiment_mode_JND IQM_Vis.UI.images IQM_Vis.UI.layout IQM_Vis.UI.main diff --git a/dev_resources/docs/_autosummary/IQM_Vis.UI.widgets.rst b/dev_resources/docs/_autosummary/IQM_Vis.UI.widgets.rst index 577df46..e14ca15 100644 --- a/dev_resources/docs/_autosummary/IQM_Vis.UI.widgets.rst +++ b/dev_resources/docs/_autosummary/IQM_Vis.UI.widgets.rst @@ -13,12 +13,16 @@ IQM\_Vis.UI.widgets .. autosummary:: + ~widgets.JND_dataset_range_lower + ~widgets.JND_dataset_range_upper ~widgets.__init__ + ~widgets.change_dataset_name ~widgets.change_display_im_display_brightness ~widgets.change_display_im_rgb_brightness ~widgets.change_display_im_size ~widgets.change_graph_size - ~widgets.change_human_scores_after_exp + ~widgets.change_human_scores_after_exp_2AFC + ~widgets.change_human_scores_after_exp_JND ~widgets.change_num_steps ~widgets.change_plot_lims ~widgets.change_post_processing @@ -33,7 +37,8 @@ IQM\_Vis.UI.widgets ~widgets.export_trans_images ~widgets.generic_value_change ~widgets.init_widgets - ~widgets.launch_experiment + ~widgets.launch_experiment_2AFC + ~widgets.launch_experiment_JND ~widgets.make_slider_range ~widgets.open_mlp_new ~widgets.reset_slider_group diff --git a/dev_resources/docs/_autosummary/IQM_Vis.examples.KODAK_dataset.rst b/dev_resources/docs/_autosummary/IQM_Vis.examples.KODAK_dataset.rst new file mode 100644 index 0000000..8c62eee --- /dev/null +++ b/dev_resources/docs/_autosummary/IQM_Vis.examples.KODAK_dataset.rst @@ -0,0 +1,23 @@ +IQM\_Vis.examples.KODAK\_dataset +================================ + +.. automodule:: IQM_Vis.examples.KODAK_dataset + + + + + + + + + + + + + + + + + + + diff --git a/dev_resources/docs/_autosummary/IQM_Vis.examples.rst b/dev_resources/docs/_autosummary/IQM_Vis.examples.rst index 671010d..57ab827 100644 --- a/dev_resources/docs/_autosummary/IQM_Vis.examples.rst +++ b/dev_resources/docs/_autosummary/IQM_Vis.examples.rst @@ -1,4 +1,4 @@ -IQM\_Vis.examples +IQM\_Vis.examples ================= .. automodule:: IQM_Vis.examples @@ -27,13 +27,10 @@ IQM\_Vis.examples :toctree: :recursive: + IQM_Vis.examples.KODAK_dataset IQM_Vis.examples.all IQM_Vis.examples.dataset IQM_Vis.examples.dists - IQM_Vis.examples.experiment IQM_Vis.examples.images IQM_Vis.examples.kodak - IQM_Vis.examples.multiple - IQM_Vis.examples.new_api - IQM_Vis.examples.simple diff --git a/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.rst b/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.rst index 7ba7f5e..2b20790 100644 --- a/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.rst +++ b/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.rst @@ -1,4 +1,4 @@ -IQM\_Vis.metrics.NLPD\_torch.layers +IQM\_Vis.metrics.NLPD\_torch.layers =================================== .. automodule:: IQM_Vis.metrics.NLPD_torch.layers @@ -21,11 +21,3 @@ IQM\_Vis.metrics.NLPD\_torch.layers -.. rubric:: Modules - -.. autosummary:: - :toctree: - :recursive: - - IQM_Vis.metrics.NLPD_torch.layers.divisive_normalisation - diff --git a/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.pyramids.rst b/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.pyramids.rst index 26a8c71..26f0988 100644 --- a/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.pyramids.rst +++ b/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.pyramids.rst @@ -1,4 +1,4 @@ -IQM\_Vis.metrics.NLPD\_torch.pyramids +IQM\_Vis.metrics.NLPD\_torch.pyramids ===================================== .. automodule:: IQM_Vis.metrics.NLPD_torch.pyramids @@ -18,9 +18,6 @@ IQM\_Vis.metrics.NLPD\_torch.pyramids .. autosummary:: LaplacianPyramid - LaplacianPyramidGDN - SteerablePyramid - SteerableWavelet diff --git a/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.rst b/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.rst index a61e1e9..8afe66a 100644 --- a/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.rst +++ b/dev_resources/docs/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.rst @@ -1,4 +1,4 @@ -IQM\_Vis.metrics.NLPD\_torch.utils +IQM\_Vis.metrics.NLPD\_torch.utils ================================== .. automodule:: IQM_Vis.metrics.NLPD_torch.utils @@ -28,7 +28,4 @@ IQM\_Vis.metrics.NLPD\_torch.utils :recursive: IQM_Vis.metrics.NLPD_torch.utils.conv - IQM_Vis.metrics.NLPD_torch.utils.fourier - IQM_Vis.metrics.NLPD_torch.utils.interp1d - IQM_Vis.metrics.NLPD_torch.utils.pyramid_filters diff --git a/dev_resources/docs/_autosummary/IQM_Vis.utils.save_utils.rst b/dev_resources/docs/_autosummary/IQM_Vis.utils.save_utils.rst index b6919a6..81dea92 100644 --- a/dev_resources/docs/_autosummary/IQM_Vis.utils.save_utils.rst +++ b/dev_resources/docs/_autosummary/IQM_Vis.utils.save_utils.rst @@ -1,4 +1,4 @@ -IQM\_Vis.utils.save\_utils +IQM\_Vis.utils.save\_utils ========================== .. automodule:: IQM_Vis.utils.save_utils @@ -20,6 +20,10 @@ IQM\_Vis.utils.save\_utils .. autosummary:: get_IQM_file + get_JND_image_names + get_JND_ref_image_dir + get_JND_ref_image_unprocessed_dir + get_JND_user_ID get_human_scores_file get_human_times_file get_image_name_from_human_scores @@ -31,9 +35,11 @@ IQM\_Vis.utils.save\_utils load_json_dict load_obj make_name_for_trans + save_2AFC_experiment_results + save_JND_experiment_results save_and_merge_df_as_csv + save_and_merge_rm_duplicates_df_as_csv save_df_as_csv - save_experiment_results save_json_dict save_obj diff --git a/dev_resources/docs/_build/doctrees/IQM_Vis.UI.doctree b/dev_resources/docs/_build/doctrees/IQM_Vis.UI.doctree index 074dcb2..fa85197 100644 Binary files a/dev_resources/docs/_build/doctrees/IQM_Vis.UI.doctree and b/dev_resources/docs/_build/doctrees/IQM_Vis.UI.doctree differ diff --git a/dev_resources/docs/_build/doctrees/IQM_Vis.doctree b/dev_resources/docs/_build/doctrees/IQM_Vis.doctree index c2b2bf4..81e453b 100644 Binary files a/dev_resources/docs/_build/doctrees/IQM_Vis.doctree and b/dev_resources/docs/_build/doctrees/IQM_Vis.doctree differ diff --git a/dev_resources/docs/_build/doctrees/IQM_Vis.examples.KODAK_dataset.doctree b/dev_resources/docs/_build/doctrees/IQM_Vis.examples.KODAK_dataset.doctree new file mode 100644 index 0000000..3096bda Binary files /dev/null and b/dev_resources/docs/_build/doctrees/IQM_Vis.examples.KODAK_dataset.doctree differ diff --git a/dev_resources/docs/_build/doctrees/IQM_Vis.examples.doctree b/dev_resources/docs/_build/doctrees/IQM_Vis.examples.doctree index 1137fa3..92a97a9 100644 Binary files a/dev_resources/docs/_build/doctrees/IQM_Vis.examples.doctree and b/dev_resources/docs/_build/doctrees/IQM_Vis.examples.doctree differ diff --git a/dev_resources/docs/_build/doctrees/IQM_Vis.metrics.SSIM.doctree b/dev_resources/docs/_build/doctrees/IQM_Vis.metrics.SSIM.doctree index d771272..4ca674f 100644 Binary files a/dev_resources/docs/_build/doctrees/IQM_Vis.metrics.SSIM.doctree and b/dev_resources/docs/_build/doctrees/IQM_Vis.metrics.SSIM.doctree differ diff --git a/dev_resources/docs/_build/doctrees/IQM_Vis.utils.doctree b/dev_resources/docs/_build/doctrees/IQM_Vis.utils.doctree index 067f8cf..f35239a 100644 Binary files a/dev_resources/docs/_build/doctrees/IQM_Vis.utils.doctree and b/dev_resources/docs/_build/doctrees/IQM_Vis.utils.doctree differ diff --git a/dev_resources/docs/_build/doctrees/Tutorials.doctree b/dev_resources/docs/_build/doctrees/Tutorials.doctree index ee823ea..a1f10b9 100644 Binary files a/dev_resources/docs/_build/doctrees/Tutorials.doctree and b/dev_resources/docs/_build/doctrees/Tutorials.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.doctree index 54bd521..0c3a027 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode.doctree index 2ad33d0..ac3da53 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode_2AFC.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode_2AFC.doctree new file mode 100644 index 0000000..7516fbc Binary files /dev/null and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode_2AFC.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode_JND.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode_JND.doctree new file mode 100644 index 0000000..74cbcc4 Binary files /dev/null and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.experiment_mode_JND.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.images.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.images.doctree index e902917..8f29657 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.images.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.images.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.widgets.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.widgets.doctree index d254164..7ef3aaa 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.widgets.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.UI.widgets.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.KODAK_dataset.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.KODAK_dataset.doctree new file mode 100644 index 0000000..75a8e9c Binary files /dev/null and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.KODAK_dataset.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.doctree index 01374a6..9cf5f06 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.experiment.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.experiment.doctree index 5b2b8df..b35f82b 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.experiment.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.experiment.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.multiple.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.multiple.doctree index 5a1e6ed..8f65d20 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.multiple.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.multiple.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.new_api.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.new_api.doctree index f8108cd..0ec7473 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.new_api.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.new_api.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.simple.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.simple.doctree index e5356fd..73538bc 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.simple.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.examples.simple.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.divisive_normalisation.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.divisive_normalisation.doctree index 624729a..896048f 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.divisive_normalisation.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.divisive_normalisation.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.doctree index 4648293..c19f5b6 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.layers.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.pyramids.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.pyramids.doctree index f049bf7..0f5aa89 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.pyramids.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.pyramids.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.doctree index 182fb89..60341e5 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.fourier.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.fourier.doctree index c7584d5..aee3128 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.fourier.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.fourier.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.interp1d.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.interp1d.doctree index 9cb98e8..8a361b0 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.interp1d.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.interp1d.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.pyramid_filters.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.pyramid_filters.doctree index 6f09c1d..c87c842 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.pyramid_filters.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.metrics.NLPD_torch.utils.pyramid_filters.doctree differ diff --git a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.utils.save_utils.doctree b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.utils.save_utils.doctree index 097e350..54364c5 100644 Binary files a/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.utils.save_utils.doctree and b/dev_resources/docs/_build/doctrees/_autosummary/IQM_Vis.utils.save_utils.doctree differ diff --git a/dev_resources/docs/_build/doctrees/environment.pickle b/dev_resources/docs/_build/doctrees/environment.pickle index 76933f6..de93caa 100644 Binary files a/dev_resources/docs/_build/doctrees/environment.pickle and b/dev_resources/docs/_build/doctrees/environment.pickle differ diff --git a/dev_resources/docs/_build/doctrees/nbsphinx/notebooks/Tutorial_4-running_an_experiment.ipynb b/dev_resources/docs/_build/doctrees/nbsphinx/notebooks/Tutorial_4-running_a_2AFC_experiment copy.ipynb similarity index 62% rename from dev_resources/docs/_build/doctrees/nbsphinx/notebooks/Tutorial_4-running_an_experiment.ipynb rename to dev_resources/docs/_build/doctrees/nbsphinx/notebooks/Tutorial_4-running_a_2AFC_experiment copy.ipynb index 18a3c8c..4974de7 100644 --- a/dev_resources/docs/_build/doctrees/nbsphinx/notebooks/Tutorial_4-running_an_experiment.ipynb +++ b/dev_resources/docs/_build/doctrees/nbsphinx/notebooks/Tutorial_4-running_a_2AFC_experiment copy.ipynb @@ -5,18 +5,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Tutorial 4: Running an Experiment\n", + "# Tutorial 4: Running a 2AFC Experiment\n", "\n", - "In this tutorial we will go through how to setup and run an experiment.\n", + "In this tutorial we will go through how to setup and run a 2 Alternate Forced Choice experiment.\n", "\n", "First you need to Launch the UI with your required customisations (see previous tutorials).\n", "\n", "Things to setup:\n", - "- Load your own images\n", + "- Load your own images and select the image which you want to test\n", "\n", - "- Make sure that the settings are corrects (Image Display Size, Luminance Calibration etc.)\n", + "- Make sure that the settings are correct in the 'image settings' tab (Image Display Size, Luminance Calibration etc.)\n", "\n", - "- Only the required transforms are selected\n", + "- Only the required transforms are selected in the 'experiments' tab with the correct range and number of steps\n", + "\n", + "- Check that the Root Save Folder is correct\n", "\n", "Once you are ready, press the 'Run 2AFC Experiment' button, this will launch the experiment:\n", "\n", @@ -30,10 +32,12 @@ "source": [ "## Experiment Screen\n", "\n", - "The first screen will show the settings and images used for the experiment\n", + "The first screen will show the settings and images used for the experiment. Double checl the Save folder matches what the experiment type and image name, a unique experiment number will be generated based on any saved experiments that use the same image but use different transforms or processing etc.\n", "\n", "![](./resources/experiment_1.png)\n", "\n", + "The Expected Number of Comparison shows how many clicks the user should expect to do.\n", + "\n", "If everything is correct, click the 'Setup' button. This will take you to the experiment information screen for the participant to read." ] }, @@ -58,6 +62,8 @@ "\n", "The experiment uses the quick sort algorithm with the user giving the pairwise most similar image until the images are sorted.\n", "\n", + "The user needs to click on the image which they believe is most similar to the reference image.\n", + "\n", "![](./resources/experiment_3.png)" ] }, @@ -66,7 +72,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Experiment Finsihed\n", + "### Experiment Finished\n", "\n", "Once the images are sorted you will be shown the sorting order and the folder when the experiments are saved. \n", "\n", @@ -82,15 +88,25 @@ "source": [ "# Visualising the experiment results\n", "\n", - "To visualise the experiment correlation plots, return to the main UI and load the experiment using the menu option: File>Load Human Scores. \n", - "\n", - "From here select the experiment image-results.csv. This will load the scores and the correlation plot against IQMs will be generated. \n", + "The experiment results will be automatically loaded into the 'Correlation' tab in IQM-Vis\n", "\n", "On the plot you can click on points to view the corresponding transformation that might disagree with the correlation with a metric.\n", + "\n", + "Use the right and left buttons below the graph to scroll through the different selected metrics.\n", + "\n", + "The Spearmean's and Pearson's correlation will be shown in the figure title.\n", + "\n", + "![](./resources/correlation_plot.png)\n", + "\n", "N.B. make sure the UI has that transformation loaded and the metrics selected you want to compare against.\n", "\n", - "![](./resources/correlation_plot.png)" + "To load previously saved experiments the experiment using the menu option: File>Load Human Scores, or use the 'Load Experiment' button below the graph." ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] } ], "metadata": { diff --git a/dev_resources/docs/_build/doctrees/nbsphinx/notebooks/Tutorial_5-running_a_JND_experiment.ipynb b/dev_resources/docs/_build/doctrees/nbsphinx/notebooks/Tutorial_5-running_a_JND_experiment.ipynb new file mode 100644 index 0000000..653a4d7 --- /dev/null +++ b/dev_resources/docs/_build/doctrees/nbsphinx/notebooks/Tutorial_5-running_a_JND_experiment.ipynb @@ -0,0 +1,133 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tutorial 4: Running a JND Experiment\n", + "\n", + "In this tutorial we will go through how to setup and run a Just Noticable Difference experiment.\n", + "\n", + "First you need to Launch the UI with your required customisations (see previous tutorials).\n", + "\n", + "Things to setup:\n", + "- Load your own dataset of images\n", + "\n", + "- Select the range of images in the dataset to be used within 'Dataset Range (JND)'\n", + "\n", + "- Make sure that the settings are correct in the 'image settings' tab (Image Display Size, Luminance Calibration etc.)\n", + "\n", + "- Only ONE transform is selected in the 'experiments' tab with the correct range and number of steps\n", + "\n", + "- Check that the Root Save Folder is correct\n", + "\n", + "- Name the dataset for use with save folder naming by 'Dataset Name (JND)'\n", + "\n", + "Once you are ready, press the 'Run JND Experiment' button, this will launch the experiment:\n", + "\n", + "![](./resources/experiment_setup_JND.png)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Experiment Screen\n", + "\n", + "The first screen will show the settings and images used for the experiment. Double check the Save folder matches what the experiment type and image name, a unique experiment number will be generated based on any saved experiments that use the same dataset name but use different transforms or processing etc.\n", + "\n", + "The first 25 images will be shown to get an idea if everything is correct.\n", + "\n", + "![](./resources/experiment_1_JDN.png)\n", + "\n", + "The Number of Comparison shows how many clicks the user will to do.\n", + "\n", + "If everything is correct, click the 'Setup' button. This will take you to the experiment information screen for the participant to read." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Experiment Info\n", + "\n", + "This will show the information for the participant. When they are ready, click the 'Start' button.\n", + "\n", + "![](./resources/experiment_2_JND.png)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Experiment Running\n", + "\n", + "The user needs to click the 'same' or 'different' button based on whether they think that the comparison images is the same or not as the reference image. \n", + "\n", + "![](./resources/experiment_3_JND.png)\n", + "\n", + "Note: users can also press the 'S' and 'D' keys on the keyboard to make their decisions." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Experiment Finished\n", + "\n", + "The save folder shown contains the experiment images and a csv file with all the experiment runs\n", + "\n", + "![](./resources/experiment_4_JND.png)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Visualising the experiment results\n", + "\n", + "The experiment results will be automatically loaded into the 'JND' tab in IQM-Vis\n", + "\n", + "This shows the user(s) decisions over the transform's parameter range.\n", + "\n", + "For example here, only 0.02 hue and above can be detected by humans.\n", + "\n", + "![](./resources/correlation_plot_JND.png)\n", + "\n", + "If you repeat the experiment with a new participant just click 'Run JND Experiment' again and the results will be merged into the existing database." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.16" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/dev_resources/docs/_build/doctrees/notebooks/Tutorial_4-running_a_2AFC_experiment copy.doctree b/dev_resources/docs/_build/doctrees/notebooks/Tutorial_4-running_a_2AFC_experiment copy.doctree new file mode 100644 index 0000000..316f60d Binary files /dev/null and b/dev_resources/docs/_build/doctrees/notebooks/Tutorial_4-running_a_2AFC_experiment copy.doctree differ diff --git a/dev_resources/docs/_build/doctrees/notebooks/Tutorial_4-running_an_experiment.doctree b/dev_resources/docs/_build/doctrees/notebooks/Tutorial_4-running_an_experiment.doctree deleted file mode 100644 index 6db7aa0..0000000 Binary files a/dev_resources/docs/_build/doctrees/notebooks/Tutorial_4-running_an_experiment.doctree and /dev/null differ diff --git a/dev_resources/docs/_build/doctrees/notebooks/Tutorial_5-running_a_JND_experiment.doctree b/dev_resources/docs/_build/doctrees/notebooks/Tutorial_5-running_a_JND_experiment.doctree new file mode 100644 index 0000000..a94db09 Binary files /dev/null and b/dev_resources/docs/_build/doctrees/notebooks/Tutorial_5-running_a_JND_experiment.doctree differ diff --git a/dev_resources/docs/_build/html/IQM_Vis.UI.html b/dev_resources/docs/_build/html/IQM_Vis.UI.html index 4005d26..435a2e3 100644 --- a/dev_resources/docs/_build/html/IQM_Vis.UI.html +++ b/dev_resources/docs/_build/html/IQM_Vis.UI.html @@ -119,162 +119,303 @@
create experiment window
Bases: QMainWindow
setup
save image name
get IQM scores to save alongside the experiment for plotting/analysis purposes
given an unsorted partition of the array between low and high, order elements lower than a given pivot point to the left and higher to the right
Bases: QObject
change clicked image to black and pause
create experiment window JND
+Bases: QMainWindow
https://www.verywellmind.com/what-is-the-just-noticeable-difference-2795306
+setup
+get IQM scores to save alongside the experiment for plotting/analysis purposes
+get directory that is unique based on if it’s the same experiment or not
+Bases: QObject
change clicked image to black and pause
+Bases: widgets
, layout
, images
Bases: object
change the dataset_name we are using
+change the dataset_name we are using
+change the dataset_name we are using
+Launch the 2 alternate forced choice experiment
+launch the Just Noticable difference experiment
+KODAK dataset
- - -ProgressBar
make_experiment
make_experiment.calc_max_comparisons()
make_experiment.change_experiment_images()
make_experiment.click_completed()
make_experiment.clicked_image()
make_experiment.closeEvent()
make_experiment.experiment_layout()
make_experiment.finish_experiment()
make_experiment.get_all_images()
make_experiment.get_metric_scores()
make_experiment.get_single_transform_im()
make_experiment.init_style()
make_experiment.partition()
make_experiment.quick_sort()
make_experiment.quit()
make_experiment.reset_clicked_image
make_experiment.reset_experiment()
make_experiment.save_experiment()
make_experiment.saved_experiment
make_experiment.setup_experiment()
make_experiment.show_all_images()
make_experiment.start_experiment()
make_experiment.swap_inds()
make_experiment.toggle_experiment()
reset_image_widget_to_black
-sort_list()
make_experiment_2AFC
make_experiment_2AFC.calc_max_comparisons()
make_experiment_2AFC.change_experiment_images()
make_experiment_2AFC.click_completed()
make_experiment_2AFC.clicked_image()
make_experiment_2AFC.closeEvent()
make_experiment_2AFC.experiment_layout()
make_experiment_2AFC.finish_experiment()
make_experiment_2AFC.get_all_images()
make_experiment_2AFC.get_metric_scores()
make_experiment_2AFC.get_single_transform_im()
make_experiment_2AFC.get_trans_funcs()
make_experiment_2AFC.get_unique_save_dir()
make_experiment_2AFC.init_style()
make_experiment_2AFC.partition()
make_experiment_2AFC.quick_sort()
make_experiment_2AFC.quit()
make_experiment_2AFC.reset_clicked_image
make_experiment_2AFC.reset_experiment()
make_experiment_2AFC.save_experiment()
make_experiment_2AFC.saved_experiment
make_experiment_2AFC.setup_experiment()
make_experiment_2AFC.show_all_images()
make_experiment_2AFC.start_experiment()
make_experiment_2AFC.swap_inds()
make_experiment_2AFC.toggle_experiment()
reset_image_widget_to_black
+sort_list()
make_experiment_JND
make_experiment_JND.closeEvent()
make_experiment_JND.experiment_layout()
make_experiment_JND.finish_experiment()
make_experiment_JND.get_all_images()
make_experiment_JND.get_metric_scores()
make_experiment_JND.get_single_transform_im()
make_experiment_JND.get_trans_funcs()
make_experiment_JND.get_unique_save_dir()
make_experiment_JND.init_style()
make_experiment_JND.quit()
make_experiment_JND.reset_clicked_image
make_experiment_JND.reset_experiment()
make_experiment_JND.save_experiment()
make_experiment_JND.saved_experiment
make_experiment_JND.setup_experiment()
make_experiment_JND.show_all_images()
make_experiment_JND.start_experiment()
make_experiment_JND.toggle_experiment()
make_experiment_JND.user_decision()
reset_image_widget_to_black
+images.change_to_specific_trans()
images.completed_range_results()
images.display_images()
images.display_metric_JND_plot()
images.display_metric_correlation_plot()
images.display_metric_images()
images.display_metric_range_plot()
images.display_metrics_graph()
images.display_metrics_text()
images.display_radar_plots()
images.get_export_dir()
images.get_metrics_over_all_trans_with_init_values()
images.init_worker_thread()
images.load_experiment_from_dir()
images.load_experiment_from_dir_JND()
images.load_human_experiment()
images.load_new_images_folder()
images.load_new_single_image()
is_float()
make_float_from_text()
widgets
widgets.JND_dataset_range_lower()
widgets.JND_dataset_range_upper()
widgets.change_dataset_name()
widgets.change_display_im_display_brightness()
widgets.change_display_im_rgb_brightness()
widgets.change_display_im_size()
widgets.change_graph_size()
widgets.change_human_scores_after_exp()
widgets.change_human_scores_after_exp_2AFC()
widgets.change_human_scores_after_exp_JND()
widgets.change_num_steps()
widgets.change_plot_lims()
widgets.change_post_processing()
widgets.export_trans_images()
widgets.generic_value_change()
widgets.init_widgets()
widgets.launch_experiment()
widgets.launch_experiment_2AFC()
widgets.launch_experiment_JND()
widgets.make_slider_range()
widgets.open_mlp_new()
widgets.reset_slider_group()
run()
run()
run()
run()
run()
DEFAULT_SAVE_DIR
get_IQM_file()
get_JND_image_names()
get_JND_ref_image_dir()
get_JND_ref_image_unprocessed_dir()
get_JND_user_ID()
get_human_scores_file()
get_human_times_file()
get_image_name_from_human_scores()
load_json_dict()
load_obj()
make_name_for_trans()
save_2AFC_experiment_results()
save_JND_experiment_results()
save_and_merge_df_as_csv()
save_and_merge_rm_duplicates_df_as_csv()
save_df_as_csv()
save_experiment_results()
save_json_dict()
save_obj()
Bases: object
Bases: Module
Defines the computation performed at every call.
-Should be overridden by all subclasses.
-Note
-Although the recipe for forward pass needs to be defined within
-this function, one should call the Module
instance afterwards
-instead of this since the former takes care of running the
-registered hooks while the latter silently ignores them.
Bases: Module
Defines the computation performed at every call.
-Should be overridden by all subclasses.
-Note
-Although the recipe for forward pass needs to be defined within
-this function, one should call the Module
instance afterwards
-instead of this since the former takes care of running the
-registered hooks while the latter silently ignores them.
interface of ssim -:param X: a batch of images, (N,C,H,W) -:type X: torch.Tensor -:param Y: a batch of images, (N,C,H,W) -:type Y: torch.Tensor -:param data_range: value range of input images. (usually 1.0 or 255) -:type data_range: float or int, optional -:param size_average: if size_average=True, ssim of all images will be averaged as a scalar -:type size_average: bool, optional -:param win_size: (int, optional): the size of gauss kernel -:param win_sigma: (float, optional): sigma of normal distribution -:param win: 1-D gauss kernel. if None, a new kernel will be created according to win_size and win_sigma -:type win: torch.Tensor, optional -:param K: scalar constants (K1, K2). Try a larger K2 constant (e.g. 0.4) if you get a negative or NaN results. -:type K: list or tuple, optional -:param nonnegative_ssim: force the ssim response to be nonnegative with relu -:type nonnegative_ssim: bool, optional
-ssim results
-torch.Tensor
-getters for experiment files from save dir
load the image names from a JND experiment
+save all the experiment reults as csvs
+df need to be indexed
save only new IQM rows
+save all the experiment reults as csvs
-create experiment window
-Functions
-
|
-- |
Classes
-
|
-- |
|
-change clicked image to black and pause |
-
create experiment window
+Functions
+
|
++ |
Classes
+
|
++ |
|
+change clicked image to black and pause |
+
create experiment window JND
+Classes
+
|
+https://www.verywellmind.com/what-is-the-just-noticeable-difference-2795306 |
+
|
+change clicked image to black and pause |
+
Custom SubClasses of PyQt6 widget to extent to the required functionality
create experiment window
IQM_Vis.UI.images
(**kwargs)
create experiment window JND
IQM_Vis.UI.images
(**kwargs)
IQM_Vis.UI.layout
(**kwargs)
IQM_Vis.UI.layout
(**kwargs)
main entry point to initialise the UI
thread and signal classes to makethe UI smoother useful info about PyQt6 threads: https://www.pythontutorial.net/pyqt/pyqt-qthread/
display_metric_images
(metric_images, i)
display_metric_images
(metric_images, i)
display_metrics
(metrics, i)
display_metrics_graph
(metrics, i)
display_metrics
(metrics, i)
display_metrics_text
(metrics, i[, disp_len])
display_metrics_graph
(metrics, i)
display_metrics_text
(metrics, i[, disp_len])
change the image dataset we are using
change the image dataset we are using
change the image we are using
plot_radar_graph
(results, i)
plot_radar_graph
(results, i)
redo_plots
([calc_range])
redo_plots
([calc_range])
set_preview_images
(preview_num)
set_preview_images
(preview_num)
set_save_dir_mpl
([i])
set_save_dir_mpl
([i])
stopped_range_worker
([signal])
stopped_range_worker
([signal])
update_datastore_image_list
(image_list[, ...])
update_datastore_image_list
(image_list[, ...])
+ | change the dataset_name we are using |
+|
+ | change the dataset_name we are using |
+|
|
||
+ | ||
|
+change the dataset_name we are using |
+|
+ | ||
+ | ||
+ | ||
+ | ||
+ | + | |
@@ -160,31 +172,34 @@ |
|
create all the widgets we need and init params |
- | + | |
+ | Launch the 2 alternate forced choice experiment |
+|
+ | launch the Just Noticable difference experiment |
|
|
+||
|
||
|
+||
|
||
|
+||
|
||
+ | ||
+ | ||
+ | ||
button to apply new image settings |
||
+ | ||
|
+||
|
|
-- |
Modules
|
-run all avaiable metrics/ transforms |
-
|
+|
|
|
|
+|
|
+run all avaiable metrics/ transforms |
+
|
|
|
+|
|
|
|
@@ -110,15 +110,6 @@
|
|
KODAK dataset |
|
-- |
|
-KODAK dataset |
-
|
-- |
Functions
-
|
-- |
KODAK dataset
-Functions
-
|
-- |
Functions
-
|
-- |
The expert.layers.divisive_normalisation
module holds classes of
-layers for a network that use divisive normalisation. This includes
-generalised divisive normalisation.
Classes
-
|
-Generalised Divisve Normalisation proposed in [BALLE2015GDN]. |
-
Modules
-- | The |
-
LaplacianPyramid
(k[, dims, filt, trainable])
LaplacianPyramidGDN
(k[, dims, filt])
SteerablePyramid
([stages, num_orientations, ...])
Steerable pyramid model implemented in spatial domain, introduced in [SIMON1995PYR].
SteerableWavelet
([stages, order, twidth])
Steerable wavelet pyramid.
The expert.utils.fourier
module holds functions for use in Fourier
-domain and wavelet transforms
Functions
-
|
-Similar to np.fft.fftshift but applies to PyTorch Tensors |
-
|
-For a singular harmonic, generates the neccesary values to compute steering matrix. |
-
|
-Similar to np.fft.ifftshift but applies to PyTorch Tensors |
-
|
-Performs 1-D Interpolation. |
-
|
-Raised cosine function. |
-
|
-Similar to np.roll but applies to PyTorch Tensors https://github.com/khammernik/sigmanet |
-
|
-Maps a directional basis set onto the angular Fourier harmonics. |
-
The expert.utils.conv
module holds util functions for convolutions, like padding to maintain the size of the image.
The expert.utils.fourier
module holds functions for use in Fourier domain and wavelet transforms
The expert.utils.pyramid_filters
module holds filters used in the exeprt.models.pyramids
module.
Classes
-
|
-- |
The expert.utils.pyramid_filters
module holds filters used in the
-exeprt.models.pyramids
module.
Holds learnt filters to be used in steerable pyramids.
-Stores the learnt filters for steerable pyramids in the spatial domain. -All filters are taken from _, which contains the MATLAB implementations -for _[SIMON1995].
+get_IQM_file
(dir)
get_JND_image_names
(dir)
load the image names from a JND experiment
get_JND_user_ID
(dir)
make_name_for_trans
(trans)
save_2AFC_experiment_results
(trans_names, ...)
save all the experiment reults as csvs
save_JND_experiment_results
(...[, IQM_scores_df])
save_and_merge_df_as_csv
(df, file)
df need to be indexed
save_df_as_csv
(df, file[, index])
save_and_merge_rm_duplicates_df_as_csv
(df, file)
save only new IQM rows
save_experiment_results
(trans_names, ...[, ...])
save all the experiment reults as csvs
save_df_as_csv
(df, file[, index])
save_json_dict
(path, dict_)
super().__init__()
self.name = name
-
diff --git a/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/experiment_mode.html b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/experiment_mode_2AFC.html
similarity index 86%
rename from dev_resources/docs/_build/html/_modules/IQM_Vis/UI/experiment_mode.html
rename to dev_resources/docs/_build/html/_modules/IQM_Vis/UI/experiment_mode_2AFC.html
index 1716d1e..31153cf 100644
--- a/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/experiment_mode.html
+++ b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/experiment_mode_2AFC.html
@@ -3,7 +3,7 @@
- IQM_Vis.UI.experiment_mode — IQM-Vis 0.2 documentation
+ IQM_Vis.UI.experiment_mode_2AFC — IQM-Vis 0.2 documentation
@@ -77,7 +77,7 @@
@@ -86,7 +86,7 @@
+ Source code for IQM_Vis.UI.experiment_mode_2AFC
'''
create experiment window
'''
@@ -119,7 +119,7 @@ Source code for IQM_Vis.UI.experiment_mode
from IQM_Vis.utils import gui_utils, plot_utils, image_utils, save_utils
-[docs]class make_experiment(QMainWindow):
+[docs]class make_experiment_2AFC(QMainWindow):
saved_experiment = pyqtSignal(str)
reset_clicked_image = pyqtSignal(dict)
@@ -143,6 +143,8 @@ Source code for IQM_Vis.UI.experiment_mode
self.rgb_brightness = rgb_brightness
self.display_brightness = display_brightness
self.default_save_dir = default_save_dir
+ self.default_save_dir = os.path.join(default_save_dir, '2AFC')
+
self.processing = {'pre': image_preprocessing,
'post': image_postprocessing}
@@ -161,11 +163,18 @@ Source code for IQM_Vis.UI.experiment_mode
self.saved = False
self.quit_experiment = False
self.get_all_images()
+
+ # make the experiment directory
+ self.default_save_dir = os.path.join(
+ self.default_save_dir, self.image_name)
+ # make unique save dir name
+ self.new_save_dir = self.get_unique_save_dir()
+
self._init_experiment_window_widgets()
self.get_metric_scores()
self.experiment_layout()
self.setCentralWidget(self.experiments_tab)
- self.setWindowTitle('Experiment')
+ self.setWindowTitle('2AFC Experiment')
# move to centre of the screen
qr = self.frameGeometry()
cp = self.screen().availableGeometry().center()
@@ -173,7 +182,7 @@ Source code for IQM_Vis.UI.experiment_mode
self.move(qr.topLeft())
self.show_all_images()
-[docs] def closeEvent(self, event):
+[docs] def closeEvent(self, event):
# Ask for confirmation if not saved
if not self.saved:
answer = QMessageBox.question(self,
@@ -198,10 +207,10 @@ Source code for IQM_Vis.UI.experiment_mode
self.clicked_event.set()
event.accept()
-[docs] def quit(self):
+
-[docs] def show_all_images(self, tab='setup'):
+[docs] def show_all_images(self, tab='setup'):
self.widget_experiments[tab]['images'].axes.axis('off')
rows = int(len(self.experiment_transforms)**0.5)
cols = int(np.ceil(len(self.experiment_transforms)/rows))
@@ -217,7 +226,7 @@ Source code for IQM_Vis.UI.experiment_mode
# time.sleep(5)
# QApplication.processEvents()
-[docs] def get_all_images(self):
+[docs] def get_all_images(self):
''' save image name '''
self.image_name = self.data_store.get_reference_image_name()
''' load all transformed images and sort them via MSE '''
@@ -269,13 +278,13 @@ Source code for IQM_Vis.UI.experiment_mode
self.experiment_transforms.append(data)
self.calc_max_comparisons(num_images=len(self.experiment_transforms))
-[docs] def calc_max_comparisons(self, num_images):
+[docs] def calc_max_comparisons(self, num_images):
# calc expected number of comparisons -
# http://homepages.math.uic.edu/~leon/cs-mcs401-r07/handouts/quicksort-continued.pdf
self.min_expected_comps = num_images * np.log(num_images)
self.max_expected_comps = 1.39 * num_images * np.log(num_images)
-[docs] def get_metric_scores(self):
+[docs] def get_metric_scores(self):
'''get IQM scores to save alongside the experiment for plotting/analysis purposes'''
IQM_scores = {}
for data in self.experiment_transforms:
@@ -304,7 +313,7 @@ Source code for IQM_Vis.UI.experiment_mode
self.widget_experiments['setup']['images'] = gui_utils.MplCanvas(size=None)
self.widget_experiments['setup']['text'] = QLabel(self)
self.widget_experiments['setup']['text'].setText(f'''
- Experiment to be setup with the above images using the settings:
+ 2AFC Experiment to be setup with the above images using the settings:
Save folder: {self.default_save_dir}
Image Display Size: {self.image_display_size}
Image Calibration:
@@ -341,8 +350,9 @@ Source code for IQM_Vis.UI.experiment_mode
self.widget_experiments['preamble']['quit_button'], self.quit)
''' experiment tab '''
+ self.exp_info_text = 'Click on which image, A or B, is most similar to the reference image (or use left/right arrows)'
self.widget_experiments['exp']['info'] = QLabel(
- 'Click on which image, A or B, is most similar to the reference image', self)
+ self.exp_info_text, self)
for image in ['Reference', 'A', 'B']:
self.widget_experiments['exp'][image] = {}
self.widget_experiments['exp'][image]['data'] = ClickLabel(image)
@@ -352,6 +362,12 @@ Source code for IQM_Vis.UI.experiment_mode
self.widget_experiments['exp'][image]['label'].setAlignment(Qt.AlignmentFlag.AlignCenter)
self.widget_experiments['exp']['A']['data'].clicked.connect(self.clicked_image)
self.widget_experiments['exp']['B']['data'].clicked.connect(self.clicked_image)
+ # shortcuts keyboard
+ QShortcut(QKeySequence(
+ "left"), self.widget_experiments['exp']['A']['data'], self.widget_experiments['exp']['A']['data'].mousePressEvent)
+ QShortcut(QKeySequence(
+ "right"), self.widget_experiments['exp']['B']['data'], self.widget_experiments['exp']['B']['data'].mousePressEvent)
+ # quit
self.widget_experiments['exp']['quit_button'] = QPushButton('Quit', self)
self.widget_experiments['exp']['quit_button'].clicked.connect(self.quit)
QShortcut(QKeySequence("Ctrl+Q"),
@@ -368,7 +384,7 @@ Source code for IQM_Vis.UI.experiment_mode
self.widget_experiments['final']['quit_button'], self.quit)
self.widget_experiments['final']['save_label'] = QLabel('Not saved yet', self)
-[docs] def experiment_layout(self):
+[docs] def experiment_layout(self):
''' setup '''
experiment_text = QVBoxLayout()
experiment_text.addWidget(self.widget_experiments['setup']['text'])
@@ -446,13 +462,17 @@ Source code for IQM_Vis.UI.experiment_mode
# return experiment_mode_layout
''' experiment running functions'''
-[docs] def setup_experiment(self):
+[docs] def setup_experiment(self):
+ self.click_counter = 0
+ self.max_text = f'{int(self.min_expected_comps)}-{int(self.max_expected_comps)}'
+ self.widget_experiments['exp']['info'].setText(
+ f'{self.exp_info_text} {self.click_counter}/{self.max_text}')
self.experiments_tab.setCurrentIndex(1)
self.experiments_tab.setTabEnabled(0, False)
self.experiments_tab.setTabEnabled(2, False)
self.experiments_tab.setTabEnabled(3, False)
-[docs] def toggle_experiment(self):
+[docs] def toggle_experiment(self):
if self.running_experiment:
self.reset_experiment()
self.experiments_tab.setTabEnabled(0, True)
@@ -468,11 +488,12 @@ Source code for IQM_Vis.UI.experiment_mode
# self.widget_experiments['preamble']['start_button'].setText('Reset')
self.running_experiment = True
-[docs] def reset_experiment(self):
+
-[docs] def start_experiment(self):
+[docs] def start_experiment(self):
+ self.running_experiment = True
self.init_style('dark')
self.experiments_tab.setCurrentIndex(2)
@@ -485,43 +506,48 @@ Source code for IQM_Vis.UI.experiment_mode
self.sorting_thread.start()
# self.quick_sort(0, len(self.experiment_transforms)-1)
-[docs] def finish_experiment(self):
+[docs] def finish_experiment(self):
+ self.running_experiment = False
self.experiments_tab.setTabEnabled(3, True)
self.show_all_images(tab='final')
self.init_style('light')
self.experiments_tab.setCurrentIndex(3)
- # self.experiments_tab.setTabEnabled(2, False)
+ self.experiments_tab.setTabEnabled(2, False)
self.save_experiment()
if self.saved == True:
self.widget_experiments['final']['save_label'].setText(f'Saved to {self.default_save_dir}')
else:
self.widget_experiments['final']['save_label'].setText(f'Save failed to {self.default_save_dir}')
-
-[docs] def save_experiment(self):
+[docs] def get_trans_funcs(self):
# get the current transform functions
trans_funcs = {}
for single_trans in self.experiment_trans_params:
trans_name = list(single_trans.keys())[0]
trans_funcs[trans_name] = self.checked_transformation_params[trans_name]['function']
- # make the experiment directory
- self.default_save_dir = os.path.join(
- self.default_save_dir, self.image_name)
+ return trans_funcs
+
+[docs] def get_unique_save_dir(self):
+ # get the current transform functions
+ trans_funcs = self.get_trans_funcs()
+
# get a unique directory (same image with diff trans need a new dir)
i = 1
unique_dir_found = False
new_dir = True
while unique_dir_found == False:
- exp_save_dir = f'{self.default_save_dir}-experiment-{i}'
+ exp_save_dir = os.path.join(
+ self.default_save_dir, f'experiment-{i}')
if os.path.exists(exp_save_dir):
# get transform funcs and params
exp_trans_params = save_utils.load_obj(
os.path.join(exp_save_dir, 'transforms', 'transform_params.pkl'))
exp_trans_funcs = save_utils.load_obj(
os.path.join(exp_save_dir, 'transforms', 'transform_functions.pkl'))
-
+
# get image processing saved params
- processing_file = save_utils.get_image_processing_file(exp_save_dir)
+ processing_file = save_utils.get_image_processing_file(
+ exp_save_dir)
procesing_same = False
if os.path.exists(processing_file):
processing = save_utils.load_json_dict(processing_file)
@@ -529,7 +555,9 @@ Source code for IQM_Vis.UI.experiment_mode
procesing_same = True
# check if experiment is the same
- if (exp_trans_params == self.original_params_order) and (trans_funcs == exp_trans_funcs) and procesing_same:
+ if ((exp_trans_params == self.original_params_order)
+ and (trans_funcs == exp_trans_funcs)
+ and procesing_same):
self.default_save_dir = exp_save_dir
unique_dir_found = True
new_dir = False
@@ -538,6 +566,12 @@ Source code for IQM_Vis.UI.experiment_mode
else:
self.default_save_dir = exp_save_dir
unique_dir_found = True
+ return new_dir
+
+[docs] def save_experiment(self):
+ # get the current transform functions
+ trans_funcs = self.get_trans_funcs()
+
# make all the dirs and subdirs
os.makedirs(self.default_save_dir, exist_ok=True)
os.makedirs(os.path.join(self.default_save_dir, 'images'), exist_ok=True)
@@ -551,7 +585,7 @@ Source code for IQM_Vis.UI.experiment_mode
if hasattr(self, 'ref_image_unprocessed'):
image_utils.save_image(self.ref_image_unprocessed,
save_utils.get_original_unprocessed_image_file(self.default_save_dir))
- if new_dir == True:
+ if self.new_save_dir == True:
for trans in self.experiment_transforms:
image_utils.save_image(
trans['image'], os.path.join(self.default_save_dir, 'images', f'{save_utils.make_name_for_trans(trans)}.png'))
@@ -571,7 +605,7 @@ Source code for IQM_Vis.UI.experiment_mode
exp_order = []
for trans in self.experiment_transforms:
exp_order.append(save_utils.make_name_for_trans(trans))
- csv_file = save_utils.save_experiment_results(
+ csv_file = save_utils.save_2AFC_experiment_results(
self.original_params_order,
exp_order,
self.default_save_dir,
@@ -580,9 +614,8 @@ Source code for IQM_Vis.UI.experiment_mode
self.saved = True
self.saved_experiment.emit(csv_file)
-
''' sorting algorithm resource: https://www.geeksforgeeks.org/quick-sort/'''
-[docs] def quick_sort(self):
+[docs] def quick_sort(self):
self.times_taken = []
self._quick_sort(0, len(self.experiment_transforms)-1)
if self.quit_experiment != True:
@@ -602,7 +635,7 @@ Source code for IQM_Vis.UI.experiment_mode
# Recursive call on the right of pivot
self._quick_sort(pi + 1, high)
-[docs] def partition(self, low, high):
+[docs] def partition(self, low, high):
''' given an unsorted partition of the array between low and high, order
elements lower than a given pivot point to the left and higher to the right'''
# Choose the end element as pivot
@@ -643,9 +676,15 @@ Source code for IQM_Vis.UI.experiment_mode
# Return the position from where partition is done
return self.comp_pointer + 1
-[docs] def clicked_image(self, image_name, widget_name):
+[docs] def clicked_image(self, image_name, widget_name):
if self.able_to_click == False:
return
+ if self.running_experiment == False:
+ return
+ self.click_counter += 1
+
+ self.widget_experiments['exp']['info'].setText(f'{self.exp_info_text} {self.click_counter+1}/{self.max_text}')
+
self.able_to_click = False
# get comparison to pivot
trans_str = image_name[len(self.image_name)+1:]
@@ -659,20 +698,20 @@ Source code for IQM_Vis.UI.experiment_mode
'widget': self.widget_experiments['exp'][widget_name]['data']}
self.reset_clicked_image.emit(data) # change to black image, after x amount of time will change to experimetn image
-[docs] def click_completed(self):
+
-[docs] def swap_inds(self, i, j):
+[docs] def swap_inds(self, i, j):
(self.experiment_transforms[i], self.experiment_transforms[j]) = (self.experiment_transforms[j], self.experiment_transforms[i])
-[docs] def get_single_transform_im(self, single_trans_dict):
+[docs] def get_single_transform_im(self, single_trans_dict):
trans_name = list(single_trans_dict)[0]
return image_utils.get_transform_image(self.data_store,
{trans_name: self.checked_transformation_params[trans_name]},
single_trans_dict)
-[docs] def change_experiment_images(self, A_trans, B_trans):
+[docs] def change_experiment_images(self, A_trans, B_trans):
A = A_trans['image']
B = B_trans['image']
@@ -686,7 +725,7 @@ Source code for IQM_Vis.UI.experiment_mode
f'{self.image_name}-{save_utils.make_name_for_trans(B_trans)}')
''' UI '''
-[docs] def init_style(self, style='light', css_file=None):
+[docs] def init_style(self, style='light', css_file=None):
if css_file == None:
dir = os.path.dirname(os.path.abspath(__file__))
# css_file = os.path.join(dir, 'style-light.css')
@@ -698,7 +737,7 @@ Source code for IQM_Vis.UI.experiment_mode
warnings.warn('Cannot load css style sheet - file not found')
-[docs]class reset_image_widget_to_black(QObject):
+[docs]class reset_image_widget_to_black(QObject):
''' change clicked image to black and pause '''
completed = pyqtSignal(float)
@@ -709,7 +748,7 @@ Source code for IQM_Vis.UI.experiment_mode
self.black_array = np.zeros([100, 100, 3])
# self.black_array[:, :, 1] = 1 # blue
-[docs] @pyqtSlot(dict)
+[docs] @pyqtSlot(dict)
def change_to_solid(self, data):
t_start = time.time()
image_display_size = data['image_display_size']
@@ -739,7 +778,7 @@ Source code for IQM_Vis.UI.experiment_mode
# all complete so send signal
self.completed.emit(1.0)
-[docs] def stop(self):
+
def __del__(self):
@@ -747,7 +786,7 @@ Source code for IQM_Vis.UI.experiment_mode
self.stop()
-[docs]def sort_list(list1, list2):
+[docs]def sort_list(list1, list2):
# sort list1 based on list2
inds = np.argsort(list2)
sorted_list1 = []
diff --git a/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/experiment_mode_JND.html b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/experiment_mode_JND.html
new file mode 100644
index 0000000..e92c412
--- /dev/null
+++ b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/experiment_mode_JND.html
@@ -0,0 +1,791 @@
+
+
+
+
+
+ IQM_Vis.UI.experiment_mode_JND — IQM-Vis 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Source code for IQM_Vis.UI.experiment_mode_JND
+'''
+create experiment window JND
+'''
+# Author: Matt Clifford <matt.clifford@bristol.ac.uk>
+# License: BSD 3-Clause License
+
+import os
+import random
+import threading
+import warnings
+import time
+from functools import partial
+import copy
+
+import numpy as np
+import pandas as pd
+from PyQt6.QtWidgets import (QMainWindow,
+ QHBoxLayout,
+ QVBoxLayout,
+ QTabWidget,
+ QApplication,
+ QPushButton,
+ QLabel,
+ QMessageBox)
+
+from PyQt6.QtCore import Qt, pyqtSignal, pyqtSlot, QObject, QThread
+from PyQt6.QtGui import QShortcut, QKeySequence
+
+import IQM_Vis
+from IQM_Vis.UI.custom_widgets import ClickLabel
+from IQM_Vis.UI import utils
+from IQM_Vis.utils import gui_utils, plot_utils, image_utils, save_utils
+
+
+[docs]class make_experiment_JND(QMainWindow):
+ '''https://www.verywellmind.com/what-is-the-just-noticeable-difference-2795306'''
+ saved_experiment = pyqtSignal(str)
+ reset_clicked_image = pyqtSignal(dict)
+
+ def __init__(self,
+ checked_transformation_params,
+ data_store,
+ image_display_size,
+ rgb_brightness,
+ display_brightness,
+ default_save_dir=save_utils.DEFAULT_SAVE_DIR,
+ dataset_name='dataset1',
+ image_preprocessing='None',
+ image_postprocessing='None',
+ lower_im_num=1,
+ upper_im_num=1,
+ checked_metrics={}):
+ super().__init__()
+ self.checked_transformation_params = checked_transformation_params
+ if self.checked_transformation_params == {}:
+ return
+ elif len(self.checked_transformation_params) != 1:
+ raise AttributeError(f'Just Noticable difference experiment can only use one transform/distortion')
+
+ self.checked_metrics = checked_metrics
+ self.data_store = copy.copy(data_store)
+ self.image_display_size = image_display_size
+ self.rgb_brightness = rgb_brightness
+ self.display_brightness = display_brightness
+ self.default_save_dir = os.path.join(default_save_dir, 'JND')
+ self.dataset_name = dataset_name
+ self.default_save_dir = os.path.join(
+ self.default_save_dir, self.dataset_name)
+ self.dataset_name = dataset_name
+ self.curr_im_ind = 0
+ self.save_im_format = '.png'
+ self.lower_im_num = lower_im_num
+ self.upper_im_num = upper_im_num
+
+ self.processing = {'pre': image_preprocessing,
+ 'post': image_postprocessing}
+
+ # self.image_change_worker = reset_image_widget_to_black()
+ # self.image_change_worker.completed.connect(self.click_completed)
+ # self.image_worker_thread = QThread()
+ # self.reset_clicked_image.connect(self.image_change_worker.change_to_solid)
+ # self.image_change_worker.moveToThread(self.image_worker_thread)
+ # self.image_worker_thread.start()
+
+ self.stop_event = threading.Event()
+ self.saved = False
+ self.quit_experiment = False
+ self._init_experiment_window_widgets()
+ self.experiment_layout()
+ self.setCentralWidget(self.experiments_tab)
+ self.setWindowTitle('JND Experiment')
+ # move to centre of the screen
+ qr = self.frameGeometry()
+ cp = self.screen().availableGeometry().center()
+ qr.moveCenter(cp)
+ self.move(qr.topLeft())
+ # wait for the window to show before loading images
+ # self.show()
+ QApplication.processEvents()
+ # get all images and show them
+ self.get_all_images()
+
+ # make unique save dir name
+ self.new_save_dir = self.get_unique_save_dir()
+
+ self.show_all_images()
+ self.get_metric_scores()
+
+[docs] def closeEvent(self, event):
+ # Ask for confirmation if not saved
+ if not self.saved:
+ answer = QMessageBox.question(self,
+ "Confirm Exit...",
+ "Are you sure you want to exit?\nAll unsaved data will be lost.",
+ QMessageBox.StandardButton.No | QMessageBox.StandardButton.Yes,
+ QMessageBox.StandardButton.Yes)
+ else:
+ answer = QMessageBox.StandardButton.Yes
+
+ event.ignore()
+ if answer == QMessageBox.StandardButton.Yes:
+ self.quit_experiment = True
+ if hasattr(self, 'range_worker'):
+ self.range_worker.stop()
+ if hasattr(self, 'image_worker_thread'):
+ if self.image_worker_thread.isRunning():
+ self.image_worker_thread.quit()
+ self.image_worker_thread.wait()
+ self.image_change_worker.stop()
+ self.stop_event.set()
+ # self.clicked_event.set()
+ event.accept()
+
+
+
+[docs] def show_all_images(self, tab='setup'):
+ self.widget_experiments['setup']['text'].setText(f'''
+ JND Experiment to be setup with the above images using the settings:
+ Save folder: {self.default_save_dir}
+ Image Display Size: {self.image_display_size}
+ Image Calibration:
+ Max RGB Brightness: {self.rgb_brightness}
+ Max Display Brightness: {self.display_brightness}
+
+ Number of Comparisons: {int(len(self.experiment_transforms))}
+
+ Click the Setup button to setup up the experiment and hand over to the test subject.
+ ''')
+ self.widget_experiments[tab]['images'].axes.axis('off')
+ rows = min(int(len(self.experiment_transforms)**0.5), 5)
+ cols = min(int(np.ceil(len(self.experiment_transforms)/rows)), 5)
+ for i, trans in enumerate(self.experiment_transforms):
+ if i == rows*cols:
+ break
+ ax = self.widget_experiments[tab]['images'].figure.add_subplot(
+ rows, cols, i+1)
+ ax.imshow(image_utils.calibrate_brightness(
+ trans['image'], self.rgb_brightness, self.display_brightness, ubyte=False))
+ if tab == 'final':
+ ax.set_ylabel('')
+ ax.set_xlabel(trans['user_decision'], fontsize=6)
+ ax.set_xticks([])
+ ax.set_yticks([])
+ else:
+ ax.axis('off')
+ ax.set_title(save_utils.make_name_for_trans(trans), fontsize=6)
+ # self.widget_experiments[tab]['images'].figure.tight_layout()
+
+ # time.sleep(5)
+ # QApplication.processEvents()
+
+[docs] def get_all_images(self):
+
+ # get all the transform values
+ self.experiment_trans_params = plot_utils.get_all_single_transform_params(
+ self.checked_transformation_params, num_steps='from_dict')
+
+ # save the experiment ordering before reordering (for saving to csv col ordering)
+ self.original_params_order = []
+ for single_trans in self.experiment_trans_params:
+ trans_name = list(single_trans.keys())[0]
+ param = single_trans[trans_name]
+ data = {'transform_name': trans_name,
+ 'transform_value': param}
+ self.original_params_order.append(
+ save_utils.make_name_for_trans(data))
+
+
+ # all images in the dataset
+ self.all_ref_images = {}
+ self.experiment_transforms = []
+
+ for i in range(max(self.lower_im_num-1, 0), min(len(self.data_store), self.upper_im_num)):
+ # load the image in dataset
+ self.data_store[i]
+ # REFERENCE image
+ ref_image = self.data_store.get_reference_image()
+ ref_name = self.data_store.get_reference_image_name()
+ # save name and image
+ self.all_ref_images[ref_name] = ref_image
+ # if hasattr(self.data_store, 'get_reference_unprocessed'):
+ # self.ref_image_unprocessed = self.data_store.get_reference_unprocessed()
+ # get all transformed images
+ for single_trans in self.experiment_trans_params:
+ trans_name = list(single_trans.keys())[0]
+ param = single_trans[trans_name]
+ img = self.get_single_transform_im(single_trans)
+ data = {'transform_name': trans_name,
+ 'transform_value': param,
+ 'image': img,
+ 'ref_name': ref_name}
+ self.experiment_transforms.append(data)
+
+ # add reference image to list
+ data = {'transform_name': 'None',
+ 'transform_value': 'None',
+ 'image': ref_image,
+ 'ref_name': ref_name}
+ self.experiment_transforms.append(data)
+
+ # update user
+ self.widget_experiments['setup']['text'].setText(
+ f'''Loading all images in the dataset {i+1}/{len(self.data_store)}''')
+
+ # shuffle the images list
+ random.shuffle(self.experiment_transforms)
+
+[docs] def get_metric_scores(self, calc=False):
+ '''get IQM scores to save alongside the experiment for plotting/analysis purposes'''
+ self.IQM_scores_df = None
+ if len(self.checked_metrics) == 0:
+ return
+ if calc == True:
+ ''' this currently doesn't work and might be a bit taxing to do for all images'''
+ IQM_scores = {}
+ for data in self.experiment_transforms:
+ score_dict = self.data_store.get_metrics(transformed_image=data['image'],
+ metrics_to_use=self.checked_metrics)
+ scores = []
+ metrics = []
+ for name, score in score_dict.items():
+ metrics.append(name)
+ scores.append(float(score))
+ IQM_scores[save_utils.make_name_for_trans(data)] = scores
+ IQM_scores['IQM'] = metrics
+ self.IQM_scores_df = pd.DataFrame.from_dict(IQM_scores)
+ self.IQM_scores_df.set_index('IQM', inplace=True)
+
+ def _init_experiment_window_widgets(self):
+ self.widget_experiments = {'exp': {}, 'preamble': {}, 'setup': {}, 'final':{}}
+ ''' setup tab '''
+ self.widget_experiments['setup']['start_button'] = QPushButton(
+ 'Setup', self)
+ self.widget_experiments['setup']['start_button'].clicked.connect(self.setup_experiment)
+ self.widget_experiments['setup']['quit_button'] = QPushButton('Quit', self)
+ self.widget_experiments['setup']['quit_button'].clicked.connect(self.quit)
+ QShortcut(QKeySequence("Ctrl+Q"),
+ self.widget_experiments['setup']['quit_button'], self.quit)
+ self.widget_experiments['setup']['images'] = gui_utils.MplCanvas(size=None)
+ self.widget_experiments['setup']['text'] = QLabel(self)
+ self.widget_experiments['setup']['text'].setText(f'''Loading all images in the dataset''')
+ # self.widget_experiments['setup']['text'].setAlignment(
+ # Qt.AlignmentFlag.AlignCenter)
+
+ ''' info tab '''
+ self.widget_experiments['preamble']['text'] = QLabel(self)
+ self.widget_experiments['preamble']['text'].setText('''
+ For this experiment you will be shown a reference image a comparison image.
+
+ You need to click SAME or DIFFERENT whether you think the comparison image is the same or different to the reference image.
+
+
+
+
+ When you are ready, click the Start button to begin the experiment ''')
+ self.running_experiment = False
+ self.widget_experiments['preamble']['start_button'] = QPushButton('Start', self)
+ self.widget_experiments['preamble']['start_button'].clicked.connect(self.toggle_experiment)
+
+ self.widget_experiments['preamble']['quit_button'] = QPushButton('Quit', self)
+ self.widget_experiments['preamble']['quit_button'].clicked.connect(
+ self.quit)
+ QShortcut(QKeySequence("Ctrl+Q"),
+ self.widget_experiments['preamble']['quit_button'], self.quit)
+
+ ''' experiment tab '''
+ self.exp_info_text = 'Click same or different for the two images shown (or press the S or D key)'
+ self.widget_experiments['exp']['info'] = QLabel(self.exp_info_text, self)
+ for image in ['Reference', 'Comparison']:
+ self.widget_experiments['exp'][image] = {}
+ self.widget_experiments['exp'][image]['data'] = ClickLabel(image)
+ self.widget_experiments['exp'][image]['data'].setAlignment(Qt.AlignmentFlag.AlignCenter)
+ # image label
+ self.widget_experiments['exp'][image]['label'] = QLabel(image, self)
+ self.widget_experiments['exp'][image]['label'].setAlignment(Qt.AlignmentFlag.AlignCenter)
+
+ self.widget_experiments['exp']['same_button'] = QPushButton('SAME', self)
+ self.widget_experiments['exp']['same_button'].clicked.connect(partial(self.user_decision, 'same'))
+ self.widget_experiments['exp']['diff_button'] = QPushButton('DIFFERENT', self)
+ self.widget_experiments['exp']['diff_button'].clicked.connect(partial(self.user_decision, 'diff'))
+ self.widget_experiments['exp']['quit_button'] = QPushButton('Quit', self)
+ self.widget_experiments['exp']['quit_button'].clicked.connect(self.quit)
+ QShortcut(QKeySequence("S"), self.widget_experiments['exp']['same_button'], partial(
+ self.user_decision, 'same'))
+ QShortcut(QKeySequence("D"), self.widget_experiments['exp']['same_button'], partial(
+ self.user_decision, 'diff'))
+ QShortcut(QKeySequence("Ctrl+Q"),
+ self.widget_experiments['exp']['quit_button'], self.quit)
+
+ ''' finish tab '''
+ self.widget_experiments['final']['order_text'] = QLabel(
+ 'Experiment Results:', self)
+ self.widget_experiments['final']['images'] = gui_utils.MplCanvas(size=None)
+ self.widget_experiments['final']['quit_button'] = QPushButton('Quit', self)
+ self.widget_experiments['final']['quit_button'].clicked.connect(
+ self.quit)
+ QShortcut(QKeySequence("Ctrl+Q"),
+ self.widget_experiments['final']['quit_button'], self.quit)
+ self.widget_experiments['final']['save_label'] = QLabel('Not saved yet', self)
+
+[docs] def experiment_layout(self):
+ ''' setup '''
+ experiment_text = QVBoxLayout()
+ experiment_text.addWidget(self.widget_experiments['setup']['text'])
+ experiment_setup_buttons = QHBoxLayout()
+ experiment_setup_buttons.addWidget(
+ self.widget_experiments['setup']['start_button'])
+ experiment_setup_buttons.addWidget(
+ self.widget_experiments['setup']['quit_button'])
+ experiment_text.addLayout(experiment_setup_buttons)
+
+ experiment_mode_setup = QVBoxLayout()
+ experiment_mode_setup.addWidget(self.widget_experiments['setup']['images'])
+ experiment_mode_setup.addLayout(experiment_text)
+ experiment_mode_setup.setAlignment(Qt.AlignmentFlag.AlignCenter)
+ experiment_mode_setup.addStretch()
+
+
+ ''' info '''
+ experiment_info_buttons = QHBoxLayout()
+ experiment_info_buttons.addWidget(
+ self.widget_experiments['preamble']['start_button'])
+ experiment_info_buttons.addWidget(
+ self.widget_experiments['preamble']['quit_button'])
+
+ experiment_mode_info = QVBoxLayout()
+ experiment_mode_info.addWidget(
+ self.widget_experiments['preamble']['text'])
+ experiment_mode_info.setAlignment(Qt.AlignmentFlag.AlignCenter)
+ experiment_mode_info.addLayout(experiment_info_buttons)
+
+ ''' experiment '''
+ same_diff_button = QHBoxLayout()
+ same_diff_button.addWidget(self.widget_experiments['exp']['same_button'])
+ same_diff_button.addWidget(self.widget_experiments['exp']['diff_button'])
+ same_diff_button.setAlignment(Qt.AlignmentFlag.AlignCenter)
+
+ info = QVBoxLayout()
+ info.addWidget(self.widget_experiments['exp']['info'])
+ info.setAlignment(Qt.AlignmentFlag.AlignCenter)
+
+ quit_button = QVBoxLayout()
+ quit_button.addWidget(self.widget_experiments['exp']['quit_button'])
+ quit_button.setAlignment(Qt.AlignmentFlag.AlignCenter)
+
+ layouts = []
+ for im in ['Reference', 'Comparison']:
+ _layout = QVBoxLayout()
+ for _, widget in self.widget_experiments['exp'][im].items():
+ _layout.addWidget(widget)
+ _layout.setAlignment(Qt.AlignmentFlag.AlignTop)
+ layouts.append(_layout)
+
+ # add images to h box
+ experiment_images = QHBoxLayout()
+ for layout in layouts:
+ experiment_images.addLayout(layout)
+ experiment_images.setAlignment(Qt.AlignmentFlag.AlignTop)
+
+ run_experiment = QVBoxLayout()
+ run_experiment.addLayout(info)
+ run_experiment.addLayout(same_diff_button)
+ run_experiment.addLayout(experiment_images)
+ run_experiment.addLayout(quit_button)
+ run_experiment.setAlignment(Qt.AlignmentFlag.AlignCenter)
+
+ ''' finished '''
+ finish_experiment = QVBoxLayout()
+ finish_experiment.addWidget(self.widget_experiments['final']['order_text'])
+ finish_experiment.addWidget(self.widget_experiments['final']['images'])
+ finish_experiment.addWidget(self.widget_experiments['final']['save_label'])
+ finish_experiment.addWidget(self.widget_experiments['final']['quit_button'])
+ finish_experiment.setAlignment(Qt.AlignmentFlag.AlignCenter)
+ finish_experiment.addStretch()
+
+ self.experiments_tab = QTabWidget()
+ for tab_layout, tab_name in zip([experiment_mode_setup, experiment_mode_info, run_experiment, finish_experiment],
+ ['setup', 'info', 'run', 'finish']):
+ utils.add_layout_to_tab(self.experiments_tab, tab_layout, tab_name)
+ # experiment_mode_layout = QVBoxLayout()
+ # experiment_mode_layout.addWidget(self.experiments_tab)
+ # return experiment_mode_layout
+
+ ''' experiment running functions'''
+[docs] def setup_experiment(self):
+ self.experiments_tab.setCurrentIndex(1)
+ self.experiments_tab.setTabEnabled(0, False)
+ self.experiments_tab.setTabEnabled(2, False)
+ self.experiments_tab.setTabEnabled(3, False)
+
+[docs] def toggle_experiment(self):
+ if self.running_experiment:
+ self.reset_experiment()
+ self.experiments_tab.setTabEnabled(0, True)
+ self.experiments_tab.setTabEnabled(1, True)
+ self.running_experiment = False
+ # self.widget_experiments['preamble']['start_button'].setText('Start')
+
+ else:
+ self.experiments_tab.setTabEnabled(2, True)
+ self.start_experiment()
+ self.experiments_tab.setTabEnabled(0, False)
+ self.experiments_tab.setTabEnabled(1, False)
+ # self.widget_experiments['preamble']['start_button'].setText('Reset')
+ self.running_experiment = True
+
+[docs] def reset_experiment(self):
+ self.experiments_tab.setCurrentIndex(1)
+ self.init_style('light')
+
+[docs] def start_experiment(self):
+ self.init_style('dark')
+ self.experiments_tab.setCurrentIndex(2)
+
+ # Display reference image
+ gui_utils.change_im(self.widget_experiments['exp']['Reference']['data'],
+ self.all_ref_images[self.experiment_transforms[self.curr_im_ind]['ref_name']],
+ resize=self.image_display_size,
+ rgb_brightness=self.rgb_brightness,
+ display_brightness=self.display_brightness)
+
+ # exp data holder
+ self.time0 = time.time()
+ self.curr_im_ind = 0
+ # Display comparison image
+ gui_utils.change_im(self.widget_experiments['exp']['Comparison']['data'],
+ self.experiment_transforms[self.curr_im_ind]['image'],
+ resize=self.image_display_size,
+ rgb_brightness=self.rgb_brightness,
+ display_brightness=self.display_brightness)
+
+[docs] def finish_experiment(self):
+ self.experiments_tab.setTabEnabled(3, True)
+ self.show_all_images(tab='final')
+ self.init_style('light')
+ self.experiments_tab.setCurrentIndex(3)
+ # self.experiments_tab.setTabEnabled(2, False)
+
+ # save experiment to file
+ self.save_experiment()
+ if self.saved == True:
+ self.widget_experiments['final']['save_label'].setText(f'Saved to {self.default_save_dir}')
+ else:
+ self.widget_experiments['final']['save_label'].setText(f'Save failed to {self.default_save_dir}')
+
+[docs] def get_trans_funcs(self):
+ # get the current transform functions
+ trans_funcs = {}
+ for single_trans in self.experiment_trans_params:
+ trans_name = list(single_trans.keys())[0]
+ trans_funcs[trans_name] = self.checked_transformation_params[trans_name]['function']
+ return trans_funcs
+
+[docs] def get_unique_save_dir(self):
+ '''get directory that is unique based on if it's the same experiment or not'''
+ trans_funcs = self.get_trans_funcs()
+
+ # get a unique directory (same image with diff trans need a new dir)
+ i = 1
+ unique_dir_found = False
+ new_dir = True
+ while unique_dir_found == False:
+ exp_save_dir = os.path.join(self.default_save_dir, f'experiment-{i}')
+ if os.path.exists(exp_save_dir):
+ # get transform funcs and params
+ exp_trans_params = save_utils.load_obj(
+ os.path.join(exp_save_dir, 'transforms', 'transform_params.pkl'))
+ exp_trans_funcs = save_utils.load_obj(
+ os.path.join(exp_save_dir, 'transforms', 'transform_functions.pkl'))
+
+ # get ref image names
+ im_names = save_utils.get_JND_image_names(exp_save_dir)
+ im_names.sort()
+ curr_im_names = list(self.all_ref_images.keys())
+ # add file extension to names
+ curr_im_names = [f'{name}{self.save_im_format}' for name in curr_im_names]
+ curr_im_names.sort()
+
+ # get image processing saved params
+ processing_file = save_utils.get_image_processing_file(
+ exp_save_dir)
+ procesing_same = False
+ if os.path.exists(processing_file):
+ processing = save_utils.load_json_dict(processing_file)
+ if processing == self.processing:
+ procesing_same = True
+
+ # check if experiment is the same
+ if ((exp_trans_params == self.original_params_order)
+ and (trans_funcs == exp_trans_funcs)
+ and procesing_same
+ and (im_names == curr_im_names)):
+ self.default_save_dir = exp_save_dir
+ unique_dir_found = True
+ new_dir = False
+ else:
+ i += 1
+ else:
+ self.default_save_dir = exp_save_dir
+ unique_dir_found = True
+
+ return new_dir
+
+[docs] def save_experiment(self):
+ # get the current transform functions
+ trans_funcs = self.get_trans_funcs()
+
+ # make all the dirs and subdirs
+ os.makedirs(self.default_save_dir, exist_ok=True)
+ os.makedirs(os.path.join(save_utils.get_JND_ref_image_dir(self.default_save_dir)), exist_ok=True)
+ os.makedirs(os.path.join(self.default_save_dir, 'images'), exist_ok=True)
+ os.makedirs(os.path.join(self.default_save_dir, 'transforms'), exist_ok=True)
+
+ if not os.path.exists(save_utils.get_JND_ref_image_unprocessed_dir(self.default_save_dir)):
+ if hasattr(self, 'ref_image_unprocessed'):
+ image_utils.save_image(self.ref_image_unprocessed,
+ save_utils.get_original_unprocessed_image_file(self.default_save_dir))
+ if self.new_save_dir == True:
+ # save experiment images
+ for name, im in self.all_ref_images.items():
+ image_utils.save_image(im,
+ os.path.join(save_utils.get_JND_ref_image_dir(self.default_save_dir),
+ f'{name}{self.save_im_format}'))
+ for trans in self.experiment_transforms:
+ image_utils.save_image(
+ trans['image'],
+ os.path.join(self.default_save_dir,
+ 'images',
+ f"{save_utils.make_name_for_trans(trans)}-{trans['ref_name']}{self.save_im_format}",
+ ))
+ # save the transformations
+ save_utils.save_obj(
+ save_utils.get_transform_params_file(self.default_save_dir),
+ self.original_params_order)
+ save_utils.save_obj(
+ save_utils.get_transform_functions_file(self.default_save_dir),
+ dict(sorted(trans_funcs.items())))
+ # save the image pre/post processing options
+ save_utils.save_json_dict(
+ save_utils.get_image_processing_file(self.default_save_dir),
+ self.processing)
+
+ # save the experiment results
+ csv_file = save_utils.save_JND_experiment_results(
+ self.experiment_transforms,
+ self.default_save_dir,
+ self.IQM_scores_df)
+ self.saved = True
+ self.saved_experiment.emit(csv_file)
+
+[docs] def user_decision(self, decision):
+ if decision not in ['same', 'diff']:
+ raise ValueError(f'user decision for JND experiment needs to be same or diff')
+ # make sure we don't go beyond the data set with acciental key presses
+ if self.curr_im_ind >= len(self.experiment_transforms):
+ return
+ # save time it took
+
+ # log decision
+ self.experiment_transforms[self.curr_im_ind]['user_decision'] = decision
+ self.experiment_transforms[self.curr_im_ind]['time_taken'] = time.time()-self.time0
+
+ # move to next image
+ self.curr_im_ind += 1
+ if self.curr_im_ind == len(self.experiment_transforms):
+ self.finish_experiment()
+ else:
+ # Display reference image
+ gui_utils.change_im(self.widget_experiments['exp']['Reference']['data'],
+ self.all_ref_images[self.experiment_transforms[self.curr_im_ind]['ref_name']],
+ resize=self.image_display_size,
+ rgb_brightness=self.rgb_brightness,
+ display_brightness=self.display_brightness)
+ # Comparison image
+ gui_utils.change_im(self.widget_experiments['exp']['Comparison']['data'],
+ self.experiment_transforms[self.curr_im_ind]['image'],
+ resize=self.image_display_size,
+ rgb_brightness=self.rgb_brightness,
+ display_brightness=self.display_brightness)
+ self.widget_experiments['exp']['info'].setText(
+ f'{self.exp_info_text} {self.curr_im_ind+1}/{len(self.experiment_transforms)}')
+
+ # reset time
+ self.time0 = time.time()
+
+[docs] def get_single_transform_im(self, single_trans_dict):
+ trans_name = list(single_trans_dict)[0]
+ return image_utils.get_transform_image(self.data_store,
+ {trans_name: self.checked_transformation_params[trans_name]},
+ single_trans_dict)
+
+ ''' UI '''
+[docs] def init_style(self, style='light', css_file=None):
+ if css_file == None:
+ dir = os.path.dirname(os.path.abspath(__file__))
+ # css_file = os.path.join(dir, 'style-light.css')
+ css_file = os.path.join(dir, f'style-{style}.css')
+ if os.path.isfile(css_file):
+ with open(css_file, 'r') as file:
+ self.setStyleSheet(file.read())
+ else:
+ warnings.warn('Cannot load css style sheet - file not found')
+
+
+[docs]class reset_image_widget_to_black(QObject):
+ ''' change clicked image to black and pause '''
+ completed = pyqtSignal(float)
+
+ def __init__(self, time=0.1):
+ super().__init__()
+ self.running = True
+ self.time = time
+ self.black_array = np.zeros([100, 100, 3])
+ # self.black_array[:, :, 1] = 1 # blue
+
+[docs] @pyqtSlot(dict)
+ def change_to_solid(self, data):
+ t_start = time.time()
+ image_display_size = data['image_display_size']
+ widget = data['widget']
+ # make clicked image black to show user
+ gui_utils.change_im(widget,
+ self.black_array,
+ resize=image_display_size)
+ # pause for half the time needed (will use the loop below to wait for full time and also see if image has turned black yet)
+ time.sleep(self.time/2)
+ m = 1
+ t_time = time.time() - t_start
+ # wait until black image is shown
+ while (not (m == 0 or m == 63.75)) and (t_time < self.time): # 63.75 is when 4th channel is all ones , rest are 0
+ time.sleep(self.time/10)
+ # get the image data from the widget to check if it's been made black yet
+ pixmap = widget.pixmap()
+ q_img = pixmap.toImage()
+ ptr = q_img.bits()
+ ptr = q_img.constBits()
+ ptr.setsize(q_img.sizeInBytes())
+ np_img = np.array(ptr, copy=False).reshape(
+ q_img.height(), q_img.width(), 4)
+ m = np_img.mean()
+ # calc if the time is up yet
+ t_time = time.time() - t_start
+ # all complete so send signal
+ self.completed.emit(1.0)
+
+
+
+ def __del__(self):
+ # close app upon garbage collection
+ self.stop()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/images.html b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/images.html
index 129db42..6c27b6c 100644
--- a/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/images.html
+++ b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/images.html
@@ -94,6 +94,7 @@ Source code for IQM_Vis.UI.images
# License: BSD 3-Clause License
import os
+from functools import partial
import imghdr
import glob
import numpy as np
@@ -101,7 +102,7 @@ Source code for IQM_Vis.UI.images
from PyQt6.QtWidgets import QApplication, QFileDialog
from PyQt6.QtCore import pyqtSignal, QThread
import IQM_Vis
-from IQM_Vis.utils import gui_utils, plot_utils, image_utils
+from IQM_Vis.utils import gui_utils, plot_utils, image_utils, save_utils
# sub class used by IQM_Vis.main.make_app to control all of the image widgets
[docs]class images:
@@ -334,9 +335,9 @@ Source code for IQM_Vis.UI.images
"CSV Files (*.csv)",)
except:
return
- self._change_human_exp(file)
+ self._change_human_exp_2AFC(file)
- def _change_human_exp(self, file, change_image=True):
+ def _change_human_exp_2AFC(self, file, change_image=True):
# load image
if change_image == True:
self._load_experiment_image(os.path.dirname(file))
@@ -356,16 +357,78 @@ Source code for IQM_Vis.UI.images
self._load_experiment_extras(os.path.dirname(file))
self.update_status_bar(f'Loaded experiment file: {file}', 10000)
+ def _change_human_exp_JND(self, file):
+ # load the csv human scores file and take mean of all experiments
+ self.update_status_bar(f'Loading experiment file: {file}', 10000)
+ if os.path.exists(file):
+ # now extract all the useful data from the csv
+ df = pd.read_csv(file)
+ # unique values for transform in df
+ transforms = list(df['Transform'].unique())
+ if 'None<>None' in transforms:
+ transforms.remove('None<>None')
+ trans_types = {}
+ params = {}
+ for single_trans in transforms:
+ trans, trans_value = gui_utils.get_trans_dict_from_str(
+ single_trans)
+ trans_types[trans] = 1 # just to get the keys
+ params[trans_value] = 1 # just to get the keys
+
+ # currently only one transformation type is supported
+ if len(trans_types) > 1:
+ self.update_status_bar(
+ 'Warning: More than one transformation type in JND file', 10000)
+ return
+
+ transform_name = list(trans_types.keys())[0]
+ self.current_JND_transform = transform_name
+ params = list(params.keys())
+ params.sort()
+
+ # get the decisions for each parameter
+ decisions = {}
+ for param in params:
+ name = save_utils.make_name_for_trans({'transform_name': transform_name,
+ 'transform_value': param})
+ user_choices = df[df['Transform']
+ == f'{name}']['UserDecision'].values
+ # convert to plotable format
+ values = []
+ for choice in user_choices:
+ if choice == 'diff':
+ values.append(1)
+ elif choice == 'same':
+ values.append(0)
+ else:
+ values.append(-1)
+ decisions[param] = values
+
+ self.JND_trans = transform_name
+ self.human_experiment_scores_JND = []
+ for i, data_store in enumerate(self.data_stores):
+ self.human_experiment_scores_JND.append(decisions)
+ self.human_scores_JND_file = file
+ else:
+ self.update_status_bar(f'No experiment file: {file}', 10000)
+ return
+ self._load_experiment_extras_JND(os.path.dirname(file))
+ self.update_status_bar(f'Loaded experiment file: {file}', 10000)
+
def _load_experiment(self, dir, change_image=True):
file = IQM_Vis.utils.save_utils.get_human_scores_file(dir)
- self._change_human_exp(file, change_image=change_image)
+ self._change_human_exp_2AFC(file, change_image=change_image)
+
+ def _load_experiment_JND(self, dir):
+ file = IQM_Vis.utils.save_utils.get_human_scores_file(dir)
+ self._change_human_exp_JND(file)
[docs] def load_experiment_from_dir(self):
# get the file opener for the user
try:
start_dir = IQM_Vis.utils.save_utils.DEFAULT_SAVE_DIR
dir = QFileDialog.getExistingDirectory(self,
- 'Choose Experiment Folder',
+ 'Choose 2AFC Experiment Folder',
start_dir)
except:
return
@@ -374,6 +437,20 @@ Source code for IQM_Vis.UI.images
return
self._load_experiment(dir)
+[docs] def load_experiment_from_dir_JND(self):
+ # get the file opener for the user
+ try:
+ start_dir = IQM_Vis.utils.save_utils.DEFAULT_SAVE_DIR
+ dir = QFileDialog.getExistingDirectory(self,
+ 'Choose JND Experiment Folder',
+ start_dir)
+ except:
+ return
+
+ if dir == '':
+ return
+ self._load_experiment_JND(dir)
+
def _load_experiment_image(self, dir):
# load image if available already
exp_image_name = IQM_Vis.utils.save_utils.get_image_name_from_human_scores(dir)
@@ -420,6 +497,33 @@ Source code for IQM_Vis.UI.images
self.display_metric_correlation_plot()
self.tabs['graph'].setCurrentIndex(3)
+ def _load_experiment_extras_JND(self, dir):
+ # load the image processing if available
+ processing_file = IQM_Vis.utils.save_utils.get_image_processing_file(dir)
+ if os.path.exists(processing_file):
+ processing = IQM_Vis.utils.save_utils.load_json_dict(
+ processing_file)
+ updated = False
+ for name, options_var, change_func in zip(['pre', 'post'],
+ [self.pre_processing_options, self.post_processing_options],
+ [self.change_pre_processing, self.change_post_processing]):
+ if processing[name] in options_var:
+ if processing[name] != self.widget_settings[f'image_{name}_processing']['widget'].currentText():
+ self.widget_settings[f'image_{name}_processing']['widget'].setCurrentText(
+ processing[name])
+ change_func()
+ updated = True
+ else:
+ self.update_status_bar(
+ f'Could not load image setting: {processing[name]}')
+ if updated == True:
+ self.update_image_settings()
+ else:
+ self.update_status_bar(f'Warning: No settings file ({processing_file}), make sure image pre/post processing settings are correct')
+
+ self.display_metric_JND_plot()
+ self.tabs['graph'].setCurrentIndex(4)
+
'''
metric updaters
'''
@@ -599,10 +703,14 @@ Source code for IQM_Vis.UI.images
# show fig in new window
gui_utils.matplotlib.pyplot.show()
+[docs] def get_export_dir(self, i):
+ image_name = f"{self.data_stores[i].get_reference_image_name()}"
+ save_path = os.path.join(self.default_save_dir, 'exports', image_name)
+ return save_path
+
[docs] def set_save_dir_mpl(self, i=0):
# set the default save path
- image_name = f"{self.data_stores[i].get_reference_image_name()}-export"
- save_path = os.path.join(self.default_save_dir, image_name)
+ save_path = self.get_export_dir(i)
if not os.path.exists(save_path):
os.makedirs(save_path)
gui_utils.matplotlib.rcParams['savefig.directory'] = save_path
@@ -610,6 +718,57 @@ Source code for IQM_Vis.UI.images
'''
metric correlation plots
'''
+[docs] def display_metric_JND_plot(self):
+ for i, data_store in enumerate(self.data_stores):
+ axes = self.widget_row[i]['metrics']['JND']['data']
+ all = {} # to calucalte std of each
+ for val, decisions in self.human_experiment_scores_JND[i].items():
+ for decision in decisions:
+ if val in all.keys():
+ all[val].append(decision)
+ else:
+ all[val] = [decision]
+
+ # calculate mean and std decision of each val
+ x = []
+ y = []
+ e = []
+ labels = []
+ for val, decisions in all.items():
+ x.append(val)
+ y.append(np.mean(decisions))
+ e.append(np.std(decisions))
+ labels.append(f'{self.JND_trans}={val}')
+
+ sp = plot_utils.scatter_plotter(axes,
+ x_label=f'{self.current_JND_transform} Value',
+ y_label='User Decision')
+ sp.plot(x, y, annotations=labels, error=e)
+
+ # # make interactive hover for points
+ # annot = sp.ax.axes.annotate("", xy=(0, 0), xytext=(0, 0), textcoords="offset points",
+ # bbox=dict(boxstyle="round", fc="w"),
+ # arrowprops=dict(arrowstyle="->")
+ # )
+ # annot.set_visible(False)
+ # sp.ax.figure.canvas.mpl_connect(
+ # "motion_notify_event", partial(plot_utils.hover_scatter, sp, annot))
+ # sp.ax.figure.canvas.mpl_connect(
+ # "pick_event", partial(plot_utils.click_scatter, sp, plot_utils.change_trans_value_signal))
+
+
+ # sp = plot_utils.scatter_plotter(axes,
+ # x_label=f'{self.current_JND_transform} Value',
+ # y_label='User Decision')
+ # sp.plot(x, y)
+ sp.show()
+
+ # ax.scatter(x, y)
+ # ax.set_xlabel(f'{self.current_JND_transform} Value')
+ # ax.set_ylabel('User Decision')
+ # # ax.set_title(f'{self.current_JND_transform} vs User Decision')
+ # plot.show()
+
[docs] def display_metric_correlation_plot(self):
if self.checked_metrics == []:
for i, data_store in enumerate(self.data_stores):
diff --git a/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/layout.html b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/layout.html
index 7250ab1..56807d5 100644
--- a/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/layout.html
+++ b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/layout.html
@@ -201,6 +201,19 @@ Source code for IQM_Vis.UI.layout
'''load experiment'''
correlation_graph.addWidget(self.widget_controls['button']['load_exp'])
utils.add_layout_to_tab(self.tabs['graph'], correlation_graph, 'Correlation')
+ if 'JND' in self.widget_row[i]['metrics'].keys():
+ JND_graph = QVBoxLayout()
+ JND_graph.addWidget(self.widget_row[i]['metrics']['JND']['label'])
+ graph = QGridLayout()
+ graph.addWidget(self.widget_row[i]['metrics']['JND']['data'], 0, 0, im_height, im_width)
+ JND_graph.addLayout(graph) # need for matplotlib? - test this... (grid)
+ '''graph controls''' # will add to last one since there is one widget to control all
+ graph_controls = QHBoxLayout()
+ JND_graph.addLayout(graph_controls)
+ '''load experiment'''
+ JND_graph.addWidget(self.widget_controls['button']['load_exp_JND'])
+ utils.add_layout_to_tab(self.tabs['graph'], JND_graph, 'JND')
+
graph_layouts.addWidget(self.tabs['graph'])
graph_layouts.addStretch()
@@ -281,9 +294,31 @@ Source code for IQM_Vis.UI.layout
save_button_exp.addWidget(self.widget_controls['button']['exp_change_save'])
save_button_exp.addStretch()
experiment_controls.addLayout(save_button_exp)
+ # Dataset Name
+ dataset_name_exp = QHBoxLayout()
+ dataset_name_exp.addWidget(
+ self.widget_controls['label']['exp_change_dataset_name'])
+ dataset_name_exp.addWidget(
+ self.widget_controls['button']['exp_change_dataset_name'])
+ dataset_name_exp.addStretch()
+ experiment_controls.addLayout(dataset_name_exp)
+ # Dataset Range nums
+ dataset_range_exp = QHBoxLayout()
+ dataset_range_exp.addWidget(
+ self.widget_controls['label']['exp_im_nums'])
+ dataset_range_exp.addWidget(
+ self.widget_controls['label']['range_edit_lower'])
+ dataset_range_exp.addWidget(
+ self.widget_controls['label']['exp_im_nums_dash'])
+ dataset_range_exp.addWidget(
+ self.widget_controls['label']['range_edit_upper'])
+ dataset_range_exp.addStretch()
+ experiment_controls.addLayout(dataset_range_exp)
+
# run experiment button
experiment_button = QHBoxLayout()
- experiment_button.addWidget(self.widget_controls['button']['launch_exp'])
+ experiment_button.addWidget(self.widget_controls['button']['launch_exp_2AFC'])
+ experiment_button.addWidget(self.widget_controls['button']['launch_exp_JND'])
experiment_button.addStretch()
experiment_controls.addLayout(experiment_button)
diff --git a/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/main.html b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/main.html
index 1c9e2eb..d98716a 100644
--- a/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/main.html
+++ b/dev_resources/docs/_build/html/_modules/IQM_Vis/UI/main.html
@@ -112,6 +112,7 @@ Source code for IQM_Vis.UI.main
metric_params: dict={},
image_display_size=300,
default_save_dir=IQM_Vis.utils.save_utils.DEFAULT_SAVE_DIR,
+ default_dataset_name='dataset1',
restrict_options=None,
num_steps_range=11,
num_step_experiment=6,
@@ -133,6 +134,7 @@ Source code for IQM_Vis.UI.main
self.metric_range_graph = metric_range_graph
self.metric_params = metric_params
self.default_save_dir = default_save_dir
+ self.default_dataset_name = default_dataset_name
self.restrict_options = restrict_options
self.data_lims = {'fixed': 1, 'range_data': 1}
@@ -424,7 +426,6 @@ Source code for IQM_Vis.UI.main
self.widget_controls['label']['exp_change_save'].setText(f'Save Folder: {self.default_save_dir}')
self.widget_controls['label']['export_change_save'].setText(f'Save Folder: {self.default_save_dir}')
-