From ade1f539989c9b24ddf0fe8c7dbfcdbdb4e020a3 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Mon, 11 Apr 2022 22:46:38 -0400 Subject: [PATCH 01/20] Bump version of Shimming Toolbox --- installer/install_shimming_toolbox.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index 2268375..85471f3 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -14,7 +14,7 @@ rm -rf "${ST_DIR}/shimming-toolbox" print info "Downloading Shimming-Toolbox" -ST_VERSION=0b105fc3e0f9ac366ef52feabb30adc4be9a463e +ST_VERSION=80a0a3af0018c425ee560472c93bb619b070d51d curl -L "https://github.com/shimming-toolbox/shimming-toolbox/archive/${ST_VERSION}.zip" > "shimming-toolbox-${ST_VERSION}.zip" From cc7ce0ef0b65620b5fc4873465280da419bde607 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Mon, 11 Apr 2022 22:47:14 -0400 Subject: [PATCH 02/20] Update the slice ordering section to include the auto value --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 22 +++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index f274091..e13f91c 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -884,6 +884,11 @@ def create_sizer_dynamic_shim(self, metadata=None): ) dropdown_slice_metadata = [ + { + "label": "Auto detect", + "option_name": "slices", + "option_value": "auto" + }, { "label": "Sequential", "option_name": "slices", @@ -906,7 +911,10 @@ def create_sizer_dynamic_shim(self, metadata=None): dropdown_metadata=dropdown_slice_metadata, name="Slice Ordering", info_text="Defines the slice ordering.", - list_components=[component_slice_int, component_slice_seq, self.create_empty_component()] + list_components=[self.create_empty_component(), + component_slice_seq, + component_slice_int, + self.create_empty_component()] ) dropdown_coil_format_metadata = [ @@ -1148,6 +1156,11 @@ def create_sizer_realtime_shim(self, metadata=None): ) dropdown_slice_metadata = [ + { + "label": "Auto detect", + "option_name": "slices", + "option_value": "auto" + }, { "label": "Sequential", "option_name": "slices", @@ -1169,8 +1182,11 @@ def create_sizer_realtime_shim(self, metadata=None): panel=self, dropdown_metadata=dropdown_slice_metadata, name="Slice Ordering", - info_text=f"{realtime_cli.params[8].help}", - list_components=[component_slice_int, component_slice_seq, self.create_empty_component()] + info_text="Defines the slice ordering.", + list_components=[self.create_empty_component(), + component_slice_seq, + component_slice_int, + self.create_empty_component()] ) dropdown_coil_format_metadata = [ From 85cb6e2329907565cc34a691051af6995482912a Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Thu, 21 Apr 2022 17:52:08 -0400 Subject: [PATCH 03/20] Bump to the latest version --- installer/install_shimming_toolbox.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index a372847..a0e64a1 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -14,7 +14,7 @@ rm -rf "${ST_DIR}/shimming-toolbox" print info "Downloading Shimming-Toolbox" -ST_VERSION=80a0a3af0018c425ee560472c93bb619b070d51d +ST_VERSION=d21d5024206225299a8d4b737a646d88fddafe59 curl -L "https://github.com/shimming-toolbox/shimming-toolbox/archive/${ST_VERSION}.zip" > "shimming-toolbox-${ST_VERSION}.zip" From a36f33bfd52dfe9b2aee09b56768042cbb748629 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Thu, 21 Apr 2022 17:52:31 -0400 Subject: [PATCH 04/20] Add fatsat ad a dropdown --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 74 ++++++++++++++++---- 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index d6eaf04..46d0fa2 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -706,7 +706,7 @@ def create_sizer_dynamic_shim(self, metadata=None): "button_function": "select_folder", "default_text": path_output, "name": "output", - "info_text": f"{dynamic_cli.params[10].help}" + "info_text": f"{dynamic_cli.params[11].help}" } ] component_output = InputComponent(self, output_metadata) @@ -758,7 +758,7 @@ def create_sizer_dynamic_shim(self, metadata=None): panel=self, dropdown_metadata=dropdown_ovf_metadata, name="Output Value Format", - info_text=f"{dynamic_cli.params[13].help}" + info_text=f"{dynamic_cli.params[14].help}" ) dropdown_opt_metadata = [ @@ -808,7 +808,7 @@ def create_sizer_dynamic_shim(self, metadata=None): panel=self, dropdown_metadata=dropdown_slice_metadata, name="Slice Ordering", - info_text="Defines the slice ordering.", + info_text=dynamic_cli.params[6].help, list_components=[self.create_empty_component(), component_slice_seq, component_slice_int, @@ -842,7 +842,7 @@ def create_sizer_dynamic_shim(self, metadata=None): panel=self, dropdown_metadata=dropdown_coil_format_metadata, name="Custom Coil Output Format", - info_text=f"{dynamic_cli.params[11].help}" + info_text=f"{dynamic_cli.params[12].help}" ) dropdown_scanner_format_metadata = [ @@ -877,14 +877,39 @@ def create_sizer_dynamic_shim(self, metadata=None): panel=self, dropdown_metadata=dropdown_scanner_format_metadata, name="Scanner Output Format", - info_text=f"{dynamic_cli.params[12].help}" + info_text=f"{dynamic_cli.params[13].help}" ) + + dropdown_fatsat_metadata = [ + { + "label": "Auto detect", + "option_name": "fatsat", + "option_value": "auto" + }, + { + "label": "Yes", + "option_name": "fatsat", + "option_value": "yes" + }, + { + "label": "No", + "option_name": "fatsat", + "option_value": "no" + }, + ] + dropdown_fatsat = DropdownComponent( + panel=self, + dropdown_metadata=dropdown_fatsat_metadata, + name="Fat Saturation", + info_text=dynamic_cli.params[10].help, + ) + run_component = RunComponent( panel=self, list_components=[self.component_coils_dyn, component_inputs, dropdown_opt, self.dropdown_slice_dyn, dropdown_scanner_order, component_scanner, dropdown_scanner_format, dropdown_coil_format, - dropdown_ovf, component_output], + dropdown_ovf, dropdown_fatsat, component_output], st_function="st_b0shim dynamic", output_paths=["fieldmap_calculated_shim_masked.nii.gz", "fieldmap_calculated_shim.nii.gz"] @@ -978,7 +1003,7 @@ def create_sizer_realtime_shim(self, metadata=None): "button_function": "select_folder", "default_text": path_output, "name": "output", - "info_text": f"{realtime_cli.params[12].help}" + "info_text": f"{realtime_cli.params[13].help}" } ] component_output = InputComponent(self, output_metadata) @@ -1030,7 +1055,7 @@ def create_sizer_realtime_shim(self, metadata=None): panel=self, dropdown_metadata=dropdown_ovf_metadata, name="Output Value Format", - info_text=f"{realtime_cli.params[15].help}" + info_text=f"{realtime_cli.params[16].help}" ) dropdown_opt_metadata = [ @@ -1080,7 +1105,7 @@ def create_sizer_realtime_shim(self, metadata=None): panel=self, dropdown_metadata=dropdown_slice_metadata, name="Slice Ordering", - info_text="Defines the slice ordering.", + info_text=realtime_cli.params[10].help, list_components=[self.create_empty_component(), component_slice_seq, component_slice_int, @@ -1104,7 +1129,7 @@ def create_sizer_realtime_shim(self, metadata=None): panel=self, dropdown_metadata=dropdown_coil_format_metadata, name="Custom Coil Output Format", - info_text=f"{realtime_cli.params[13].help}" + info_text=f"{realtime_cli.params[14].help}" ) dropdown_scanner_format_metadata = [ @@ -1129,14 +1154,39 @@ def create_sizer_realtime_shim(self, metadata=None): panel=self, dropdown_metadata=dropdown_scanner_format_metadata, name="Scanner Output Format", - info_text=f"{realtime_cli.params[14].help}" + info_text=f"{realtime_cli.params[15].help}" ) + + dropdown_fatsat_metadata = [ + { + "label": "Auto detect", + "option_name": "fatsat", + "option_value": "auto" + }, + { + "label": "Yes", + "option_name": "fatsat", + "option_value": "yes" + }, + { + "label": "No", + "option_name": "fatsat", + "option_value": "no" + }, + ] + dropdown_fatsat = DropdownComponent( + panel=self, + dropdown_metadata=dropdown_fatsat_metadata, + name="Fat Saturation", + info_text=realtime_cli.params[12].help, + ) + run_component = RunComponent( panel=self, list_components=[self.component_coils_rt, component_inputs, dropdown_opt, self.dropdown_slice_rt, dropdown_scanner_order, component_scanner, dropdown_scanner_format, - dropdown_coil_format, dropdown_ovf, component_output], + dropdown_coil_format, dropdown_ovf, dropdown_fatsat, component_output], st_function="st_b0shim realtime-dynamic", # TODO: output paths output_paths=[] From dccc30d99576fa7a3a53d540d3e7e9bf9ca5a735 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Thu, 21 Apr 2022 17:52:50 -0400 Subject: [PATCH 05/20] Fix floating window --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index 46d0fa2..f7b1a09 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -2003,7 +2003,7 @@ def select_from_overlay(event, tab, ctrl, focus=False): # This is messy and wont work if we change any class hierarchy.. using GetTopLevelParent() only # works if the pane is not floating # Get the displayCtx class initialized in STControlPanel - window = tab.GetGrandParent().GetParent() + window = tab.GetGrandParent() selected_overlay = window.displayCtx.getSelectedOverlay() if selected_overlay is not None: filename_path = selected_overlay.dataSource From fe6eeb0b49e13d3728a5aeb2fc1961c73cdf6302 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Thu, 21 Apr 2022 19:52:01 -0400 Subject: [PATCH 06/20] Remove fatsat if not using chronological coils --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 115 +++++++++++-------- 1 file changed, 65 insertions(+), 50 deletions(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index f7b1a09..0ad85dc 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -613,8 +613,10 @@ def on_choice(self, event): # items to show the appropriate things according to their current choice. if selection == 'Dynamic': self.dropdown_slice_dyn.on_choice(None) + self.dropdown_coil_format_dyn.on_choice(None) elif selection == 'Realtime Dynamic': self.dropdown_slice_rt.on_choice(None) + self.dropdown_coil_format_rt.on_choice(None) else: pass @@ -837,12 +839,48 @@ def create_sizer_dynamic_shim(self, metadata=None): "option_value": "chronological-coil" }, ] + + dropdown_fatsat_metadata = [ + { + "label": "Auto detect", + "option_name": "fatsat", + "option_value": "auto" + }, + { + "label": "Yes", + "option_name": "fatsat", + "option_value": "yes" + }, + { + "label": "No", + "option_name": "fatsat", + "option_value": "no" + }, + ] - dropdown_coil_format = DropdownComponent( + dropdown_fatsat1 = DropdownComponent( + panel=self, + dropdown_metadata=dropdown_fatsat_metadata, + name="Fat Saturation", + info_text=dynamic_cli.params[10].help, + ) + + dropdown_fatsat2 = DropdownComponent( + panel=self, + dropdown_metadata=dropdown_fatsat_metadata, + name="Fat Saturation", + info_text=dynamic_cli.params[10].help, + ) + + self.dropdown_coil_format_dyn = DropdownComponent( panel=self, dropdown_metadata=dropdown_coil_format_metadata, name="Custom Coil Output Format", - info_text=f"{dynamic_cli.params[12].help}" + info_text=f"{dynamic_cli.params[12].help}", + list_components=[self.create_empty_component(), + self.create_empty_component(), + dropdown_fatsat1, + dropdown_fatsat2] ) dropdown_scanner_format_metadata = [ @@ -880,36 +918,11 @@ def create_sizer_dynamic_shim(self, metadata=None): info_text=f"{dynamic_cli.params[13].help}" ) - dropdown_fatsat_metadata = [ - { - "label": "Auto detect", - "option_name": "fatsat", - "option_value": "auto" - }, - { - "label": "Yes", - "option_name": "fatsat", - "option_value": "yes" - }, - { - "label": "No", - "option_name": "fatsat", - "option_value": "no" - }, - ] - - dropdown_fatsat = DropdownComponent( - panel=self, - dropdown_metadata=dropdown_fatsat_metadata, - name="Fat Saturation", - info_text=dynamic_cli.params[10].help, - ) - run_component = RunComponent( panel=self, list_components=[self.component_coils_dyn, component_inputs, dropdown_opt, self.dropdown_slice_dyn, - dropdown_scanner_order, component_scanner, dropdown_scanner_format, dropdown_coil_format, - dropdown_ovf, dropdown_fatsat, component_output], + dropdown_scanner_order, component_scanner, dropdown_scanner_format, + self.dropdown_coil_format_dyn, dropdown_ovf, component_output], st_function="st_b0shim dynamic", output_paths=["fieldmap_calculated_shim_masked.nii.gz", "fieldmap_calculated_shim.nii.gz"] @@ -1112,26 +1125,6 @@ def create_sizer_realtime_shim(self, metadata=None): self.create_empty_component()] ) - dropdown_coil_format_metadata = [ - { - "label": "Slicewise per Channel", - "option_name": "output-file-format-coil", - "option_value": "slicewise-ch" - }, - { - "label": "Chronological per Channel", - "option_name": "output-file-format-coil", - "option_value": "chronological-ch" - } - ] - - dropdown_coil_format = DropdownComponent( - panel=self, - dropdown_metadata=dropdown_coil_format_metadata, - name="Custom Coil Output Format", - info_text=f"{realtime_cli.params[14].help}" - ) - dropdown_scanner_format_metadata = [ { "label": "Slicewise per Channel", @@ -1182,11 +1175,33 @@ def create_sizer_realtime_shim(self, metadata=None): info_text=realtime_cli.params[12].help, ) + dropdown_coil_format_metadata = [ + { + "label": "Slicewise per Channel", + "option_name": "output-file-format-coil", + "option_value": "slicewise-ch" + }, + { + "label": "Chronological per Channel", + "option_name": "output-file-format-coil", + "option_value": "chronological-ch" + } + ] + + self.dropdown_coil_format_rt = DropdownComponent( + panel=self, + dropdown_metadata=dropdown_coil_format_metadata, + name="Custom Coil Output Format", + info_text=f"{realtime_cli.params[14].help}", + list_components=[self.create_empty_component(), + dropdown_fatsat] + ) + run_component = RunComponent( panel=self, list_components=[self.component_coils_rt, component_inputs, dropdown_opt, self.dropdown_slice_rt, dropdown_scanner_order, component_scanner, dropdown_scanner_format, - dropdown_coil_format, dropdown_ovf, dropdown_fatsat, component_output], + self.dropdown_coil_format_rt, dropdown_ovf, component_output], st_function="st_b0shim realtime-dynamic", # TODO: output paths output_paths=[] From 5402649b4525056baa707b96c6e57b5f3e72202f Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Fri, 22 Apr 2022 19:16:24 -0400 Subject: [PATCH 07/20] Fix run button not updating when changing dropdowns, fix required argument error not displayed on fsleyes terminal --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 82 +++++++++++--------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index 40dae4e..dc67f25 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -130,7 +130,14 @@ def create_sizer(self): sizer.AddSpacer(20) sizer.Add(self.sizer_run, 2) return sizer - + + def create_sizer_run(self): + """Create the run sizer containing tab-specific functionality.""" + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.SetMinSize(400, 300) + sizer.AddSpacer(10) + return sizer + def create_empty_component(self): component = InputComponent(panel=self, input_text_box_metadata=[]) return component @@ -349,7 +356,9 @@ def on_choice(self, event): # Add the dropdown to the list of options self.input_text_boxes[self.dropdown_metadata[index]["option_name"]] = \ [self.dropdown_metadata[index]["option_value"]] + # Update the window + self.panel.SetVirtualSize(self.panel.sizer_run.GetMinSize()) self.panel.Layout() def find_index(self, label): @@ -492,7 +501,12 @@ def button_run_on_click(self, event): """ if not self.worker: - command, msg = self.get_run_args(self.st_function) + try: + command, msg = self.get_run_args(self.st_function) + except RunArgumentErrorST as err: + self.panel.terminal_component.log_to_terminal(err, level="ERROR") + return + self.panel.terminal_component.log_to_terminal(msg, level="INFO") self.worker = WorkerThread(self.panel, command, name=self.st_function) @@ -540,7 +554,7 @@ def get_run_args(self, st_function): arg = textctrl.GetValue() if arg == "" or arg is None: if input_text_box.required is True: - raise self.RunArgumentErrorST( + raise RunArgumentErrorST( f"Argument {name} is missing a value, please enter a valid input" ) else: @@ -572,10 +586,6 @@ def get_run_args(self, st_function): msg += "\n" return command, msg - class RunArgumentErrorST(Exception): - """Exception for missing input arguments for CLI call.""" - pass - def fetch_paths_dicom_to_nifti(self): if self.st_function == "st_dicom_to_nifti": @@ -656,6 +666,7 @@ def on_choice(self, event): pass # Update the window + self.SetVirtualSize(self.sizer_run.GetMinSize()) self.Layout() def unshow_choice_box_sizers(self): @@ -1244,13 +1255,6 @@ def create_sizer_realtime_shim(self, metadata=None): sizer = run_component.sizer return sizer - def create_sizer_run(self): - """Create the centre sizer containing tab-specific functionality.""" - sizer = wx.BoxSizer(wx.VERTICAL) - sizer.SetMinSize(400, 300) - sizer.AddSpacer(10) - return sizer - class B1ShimTab(Tab): def __init__(self, parent, title=r"B1+ Shim"): @@ -1309,6 +1313,7 @@ def on_choice(self, event): pass # Update the window + self.SetVirtualSize(self.sizer_run.GetMinSize()) self.Layout() def unshow_choice_box_sizers(self): @@ -1506,13 +1511,6 @@ def create_sizer_phase_only(self, metadata=None): sizer = run_component.sizer return sizer - def create_sizer_run(self): - """Create the centre sizer containing tab-specific functionality.""" - sizer = wx.BoxSizer(wx.VERTICAL) - sizer.SetMinSize(400, 300) - sizer.AddSpacer(10) - return sizer - class FieldMapTab(Tab): def __init__(self, parent, title="Fieldmap"): @@ -1520,7 +1518,17 @@ def __init__(self, parent, title="Fieldmap"): "Enter the Number of Echoes then press the `Number of Echoes` button.\n\n" \ "Select the unwrapper from the dropdown list." super().__init__(parent, title, description) + + self.sizer_run = self.create_sizer_run() self.n_echoes = 0 + sizer = self.create_fieldmap_sizer() + self.sizer_run.Add(sizer, 0, wx.EXPAND) + + self.parent_sizer = self.create_sizer() + self.SetSizer(self.parent_sizer) + + def create_fieldmap_sizer(self): + input_text_box_metadata_input = [ { "button_label": "Number of Echoes", @@ -1632,9 +1640,8 @@ def __init__(self, parent, title="Fieldmap"): self.component_output], st_function="st_prepare_fieldmap" ) - self.sizer_run = self.run_component.sizer - sizer = self.create_sizer() - self.SetSizer(sizer) + + return self.run_component.sizer class MaskTab(Tab): @@ -1688,8 +1695,8 @@ def on_choice(self, event): pass # Update the window + self.SetVirtualSize(self.sizer_run.GetMinSize()) self.Layout() - self.GetParent().Layout() def unshow_choice_box_sizers(self): """Set the Show variable to false for all sizers of the choice box widget""" @@ -1816,18 +1823,20 @@ def create_sizer_box(self): sizer = run_component.sizer return sizer - def create_sizer_run(self): - """Create the centre sizer containing tab-specific functionality.""" - sizer = wx.BoxSizer(wx.VERTICAL) - sizer.SetMinSize(400, 300) - sizer.AddSpacer(10) - return sizer - class DicomToNiftiTab(Tab): def __init__(self, parent, title="Dicom to Nifti"): description = "Convert DICOM files into NIfTI following the BIDS data structure" super().__init__(parent, title, description) + + self.sizer_run = self.create_sizer_run() + sizer = self.create_dicom_to_nifti_sizer() + self.sizer_run.Add(sizer, 0, wx.EXPAND) + + self.parent_sizer = self.create_sizer() + self.SetSizer(self.parent_sizer) + + def create_dicom_to_nifti_sizer(self): path_output = os.path.join(CURR_DIR, "output_dicom_to_nifti") input_text_box_metadata = [ { @@ -1860,9 +1869,7 @@ def __init__(self, parent, title="Dicom to Nifti"): ] component = InputComponent(self, input_text_box_metadata) run_component = RunComponent(panel=self, list_components=[component], st_function="st_dicom_to_nifti") - self.sizer_run = run_component.sizer - sizer = self.create_sizer() - self.SetSizer(sizer) + return run_component.sizer class TextWithButton: @@ -2298,3 +2305,8 @@ def load_png_image_from_path(fsl_panel, image_path, is_mask=False, add_to_overla opts.cmap = colormap return img_overlay + + +class RunArgumentErrorST(Exception): + """Exception for missing input arguments for CLI call.""" + pass From 53433728a7dcb883bc045dbf45b7b3e42b7c0d05 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Wed, 4 May 2022 21:21:48 -0400 Subject: [PATCH 08/20] Add ability to parse spaces in input options --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 5 +++-- fsleyes_plugin_shimming_toolbox/worker_thread.py | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index dc67f25..7ffcb5b 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -436,6 +436,7 @@ def on_result(self, event): return data = event.get_data() + # Return code is 0 if everything ran smoothly if data == 0: msg = f"Run {self.st_function} completed successfully\n" self.panel.terminal_component.log_to_terminal(msg, level="INFO") @@ -489,7 +490,7 @@ def on_result(self, event): else: # The error message should already be displayed - self.panel.terminal_component.log_to_terminal("") + self.panel.terminal_component.log_to_terminal("", level="ERROR") self.worker = None event.Skip() @@ -581,7 +582,7 @@ def get_run_args(self, st_function): for name, args in command_list_options: command += f" --{name}" for arg in args: - command += f" {arg}" + command += f" '{arg}'" msg += command msg += "\n" return command, msg diff --git a/fsleyes_plugin_shimming_toolbox/worker_thread.py b/fsleyes_plugin_shimming_toolbox/worker_thread.py index e944776..cab7a7a 100644 --- a/fsleyes_plugin_shimming_toolbox/worker_thread.py +++ b/fsleyes_plugin_shimming_toolbox/worker_thread.py @@ -6,6 +6,7 @@ import subprocess from threading import Thread import wx +import shlex from fsleyes_plugin_shimming_toolbox.events import result_event_type, EVT_RESULT, ResultEvent from fsleyes_plugin_shimming_toolbox.events import log_event_type, EVT_LOG, LogEvent @@ -29,9 +30,10 @@ def run(self): # It seems to default to the Python executalble instead of the Shebang, removing it fixes it env["PYTHONEXECUTABLE"] = "" env["PATH"] = PATH_ST_VENV + ":" + env["PATH"] - + + cmd_split = shlex.split(self.cmd) # Run command using realtime output - process = subprocess.Popen(self.cmd.split(' '), + process = subprocess.Popen(cmd_split, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, From 32f3f26743aaa0d03fa9439eae5cb5c44cdf4bb1 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Wed, 4 May 2022 22:08:26 -0400 Subject: [PATCH 09/20] Add ability to have spaces for arguments --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index 7ffcb5b..00c3833 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -576,7 +576,7 @@ def get_run_args(self, st_function): # Arguments don't need "-" for arg in command_list_arguments: - command += f" {arg}" + command += f" '{arg}'" # Handles options for name, args in command_list_options: From 8c0b1bce88e2bd76d8993c060b88eda12ebc4102 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Thu, 5 May 2022 17:46:03 -0400 Subject: [PATCH 10/20] Use a list instead of a string to run CLIs --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 15 ++++++++------- fsleyes_plugin_shimming_toolbox/worker_thread.py | 4 +--- installer/install_shimming_toolbox.sh | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index 00c3833..2eb0b70 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -490,7 +490,7 @@ def on_result(self, event): else: # The error message should already be displayed - self.panel.terminal_component.log_to_terminal("", level="ERROR") + self.panel.terminal_component.log_to_terminal(str(data), level="ERROR") self.worker = None event.Skip() @@ -532,7 +532,7 @@ def send_output_to_overlay(self): def get_run_args(self, st_function): """The option are a list of tuples where the tuple: (name, [value1, value2])""" msg = "Running " - command = st_function + command = [st_function] self.output = "" command_list_arguments = [] @@ -576,15 +576,16 @@ def get_run_args(self, st_function): # Arguments don't need "-" for arg in command_list_arguments: - command += f" '{arg}'" + command += [arg] # Handles options for name, args in command_list_options: - command += f" --{name}" + command += ['--' + name] for arg in args: - command += f" '{arg}'" - msg += command - msg += "\n" + command += [arg] + + msg += ' '.join(command) + '\n' + return command, msg def fetch_paths_dicom_to_nifti(self): diff --git a/fsleyes_plugin_shimming_toolbox/worker_thread.py b/fsleyes_plugin_shimming_toolbox/worker_thread.py index cab7a7a..9729596 100644 --- a/fsleyes_plugin_shimming_toolbox/worker_thread.py +++ b/fsleyes_plugin_shimming_toolbox/worker_thread.py @@ -6,7 +6,6 @@ import subprocess from threading import Thread import wx -import shlex from fsleyes_plugin_shimming_toolbox.events import result_event_type, EVT_RESULT, ResultEvent from fsleyes_plugin_shimming_toolbox.events import log_event_type, EVT_LOG, LogEvent @@ -31,9 +30,8 @@ def run(self): env["PYTHONEXECUTABLE"] = "" env["PATH"] = PATH_ST_VENV + ":" + env["PATH"] - cmd_split = shlex.split(self.cmd) # Run command using realtime output - process = subprocess.Popen(cmd_split, + process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index a0e64a1..3de3ce1 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -14,7 +14,7 @@ rm -rf "${ST_DIR}/shimming-toolbox" print info "Downloading Shimming-Toolbox" -ST_VERSION=d21d5024206225299a8d4b737a646d88fddafe59 +ST_VERSION=7b462588d7012ea296de493e063a3f5fcd14a804 curl -L "https://github.com/shimming-toolbox/shimming-toolbox/archive/${ST_VERSION}.zip" > "shimming-toolbox-${ST_VERSION}.zip" From 9b22d2851fa99334fe5f29a1c7aebdd0d4e47380 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Fri, 6 May 2022 15:37:22 -0400 Subject: [PATCH 11/20] Fix bug when commands are grouped --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index 2eb0b70..8bb9522 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -532,7 +532,8 @@ def send_output_to_overlay(self): def get_run_args(self, st_function): """The option are a list of tuples where the tuple: (name, [value1, value2])""" msg = "Running " - command = [st_function] + # Split is necessary if we have grouped commands (st_mask threshold) + command = st_function.split(' ') self.output = "" command_list_arguments = [] From da3f23e31372fcf6a8a387c7faeefd9162b0adc1 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Fri, 6 May 2022 16:26:25 -0400 Subject: [PATCH 12/20] Bumb version --- installer/install_shimming_toolbox.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index 3de3ce1..0c6809a 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -14,7 +14,7 @@ rm -rf "${ST_DIR}/shimming-toolbox" print info "Downloading Shimming-Toolbox" -ST_VERSION=7b462588d7012ea296de493e063a3f5fcd14a804 +ST_VERSION=fe14cf037708fc7b561e99bc61b1d35e09667905 curl -L "https://github.com/shimming-toolbox/shimming-toolbox/archive/${ST_VERSION}.zip" > "shimming-toolbox-${ST_VERSION}.zip" From 1720443b5ce21bcaf486a612a0f099f44d927d50 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Thu, 12 May 2022 13:03:01 -0400 Subject: [PATCH 13/20] Fix floating panel --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index 8bb9522..60b256c 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -516,7 +516,7 @@ def send_output_to_overlay(self): if os.path.isfile(output_path): try: # Display the overlay - window = self.panel.GetGrandParent().GetParent() + window = self.panel.GetGrandParent() if output_path[-4:] == ".png": load_png_image_from_path(window, output_path, colormap="greyscale") elif output_path[-7:] == ".nii.gz" or output_path[-4:] == ".nii": From b3f7ffabd6d01c11c2d97800db12481d33ffcaf5 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Tue, 17 May 2022 17:37:31 -0400 Subject: [PATCH 14/20] Allow inputs to be outputted to the overlay --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 21 +++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index 60b256c..5f945ee 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -251,7 +251,8 @@ def add_input_text_boxes(self, spacer_size=10): n_text_boxes=twb_dict.get("n_text_boxes", 1), name=twb_dict.get("name", "default"), info_text=twb_dict.get("info_text", ""), - required=twb_dict.get("required", False) + required=twb_dict.get("required", False), + load_in_overlay=twb_dict.get("load_in_overlay", False) ) self.add_input_text_box(text_with_button, twb_dict.get("name", "default")) @@ -395,6 +396,7 @@ def __init__(self, panel, st_function, list_components=[], output_paths=[]): self.output = "" self.output_paths_original = output_paths self.output_paths = output_paths.copy() + self.load_in_overlay = [] self.worker = None self.panel.Bind(EVT_RESULT, self.on_result) @@ -454,6 +456,10 @@ def on_result(self, event): # Append the file if it was a file if os.path.isfile(self.output): self.output_paths.append(self.output) + + # Append files that are a direct output from "load_in_overlay" + for fname in self.load_in_overlay: + self.output_paths.append(fname) if self.st_function == "st_dicom_to_nifti": # If its dicom_to_nifti, output all .nii found in the subject folder to the overlay @@ -568,7 +574,9 @@ def get_run_args(self, st_function): else: if name == "output": self.output = arg - + elif input_text_box.load_in_overlay: + self.load_in_overlay.append(arg) + option_values.append(arg) # If its an argument don't include it as an option, if the option list is empty don't either @@ -1594,6 +1602,12 @@ def create_fieldmap_sizer(self): "button_label": "Threshold", "name": "threshold", "info_text": f"{prepare_fieldmap_cli.params[6].help}" + }, + { + "button_label": "Output Calculated Mask", + "name": "savemask", + "info_text": f"{prepare_fieldmap_cli.params[7].help}", + "load_in_overlay": True } ] @@ -1902,7 +1916,7 @@ class TextWithButton: """ def __init__(self, panel, button_label, button_function, name="default", default_text="", - n_text_boxes=1, info_text="", required=False): + n_text_boxes=1, info_text="", required=False, load_in_overlay=False): self.panel = panel self.button_label = button_label if type(button_function) is not list: @@ -1914,6 +1928,7 @@ def __init__(self, panel, button_label, button_function, name="default", default self.name = name self.info_text = info_text self.required = required + self.load_in_overlay = load_in_overlay def create(self): text_with_button_box = wx.BoxSizer(wx.HORIZONTAL) From 16bddc9441e2386ace879f4efaf3ffafb7250d77 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Wed, 18 May 2022 17:21:22 -0400 Subject: [PATCH 15/20] Bump version and fix small bug --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 1 + installer/install_shimming_toolbox.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index 5f945ee..36203e0 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -499,6 +499,7 @@ def on_result(self, event): self.panel.terminal_component.log_to_terminal(str(data), level="ERROR") self.worker = None + self.load_in_overlay = [] event.Skip() def button_run_on_click(self, event): diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index 0c6809a..d16782d 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -14,7 +14,7 @@ rm -rf "${ST_DIR}/shimming-toolbox" print info "Downloading Shimming-Toolbox" -ST_VERSION=fe14cf037708fc7b561e99bc61b1d35e09667905 +ST_VERSION=fd4806473cc9b7d70ffd51442f24ad0d1e536a64 curl -L "https://github.com/shimming-toolbox/shimming-toolbox/archive/${ST_VERSION}.zip" > "shimming-toolbox-${ST_VERSION}.zip" From 5dc290e309ddae18fc18edb054f2feab02ee9517 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Wed, 18 May 2022 17:30:36 -0400 Subject: [PATCH 16/20] Fix path error --- installer/create_st_dir.sh | 2 +- installer/create_venv.sh | 2 +- installer/install_conda.sh | 2 +- installer/install_plugin.sh | 2 +- installer/install_shimming_toolbox.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/installer/create_st_dir.sh b/installer/create_st_dir.sh index 16e7a52..48cafec 100644 --- a/installer/create_st_dir.sh +++ b/installer/create_st_dir.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" -source $SCRIPT_DIR/utils.sh +source "$SCRIPT_DIR/utils.sh" ST_DIR="$HOME/shimming-toolbox" PYTHON_DIR="python" diff --git a/installer/create_venv.sh b/installer/create_venv.sh index 2182a0b..29a250f 100644 --- a/installer/create_venv.sh +++ b/installer/create_venv.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" -source $SCRIPT_DIR/utils.sh +source "$SCRIPT_DIR/utils.sh" VENV=pst_venv ST_DIR="$HOME/shimming-toolbox" diff --git a/installer/install_conda.sh b/installer/install_conda.sh index ed6b835..4ff4c3c 100644 --- a/installer/install_conda.sh +++ b/installer/install_conda.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" -source $SCRIPT_DIR/utils.sh +source "$SCRIPT_DIR/utils.sh" print info "Installing conda in $ST_DIR/$PYTHON_DIR" diff --git a/installer/install_plugin.sh b/installer/install_plugin.sh index b07bae7..f6e9da1 100644 --- a/installer/install_plugin.sh +++ b/installer/install_plugin.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" -source $SCRIPT_DIR/utils.sh +source "$SCRIPT_DIR/utils.sh" set -e diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index d16782d..f785fda 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -1,7 +1,7 @@ !/usr/bin/env bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" -source $SCRIPT_DIR/utils.sh +source "$SCRIPT_DIR/utils.sh" set -e From 8cc080609446b411654dad47c5d69cc78e80ac4d Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Sun, 5 Jun 2022 23:07:42 -0400 Subject: [PATCH 17/20] Bump version --- installer/install_shimming_toolbox.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index f785fda..01ec036 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -14,7 +14,7 @@ rm -rf "${ST_DIR}/shimming-toolbox" print info "Downloading Shimming-Toolbox" -ST_VERSION=fd4806473cc9b7d70ffd51442f24ad0d1e536a64 +ST_VERSION=bfad338ba97044bfcaae233efae1ce90009a8295 curl -L "https://github.com/shimming-toolbox/shimming-toolbox/archive/${ST_VERSION}.zip" > "shimming-toolbox-${ST_VERSION}.zip" From 344a0eab328fe505294cb7d11fb6fe6de134789e Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Tue, 27 Sep 2022 00:44:22 -0400 Subject: [PATCH 18/20] Auto fill help text using the already input name of the option/argument --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 422 +++++++++---------- installer/install_shimming_toolbox.sh | 2 +- 2 files changed, 191 insertions(+), 233 deletions(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index b40fb9d..d59de27 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -130,14 +130,14 @@ def create_sizer(self): sizer.AddSpacer(20) sizer.Add(self.sizer_run, 2) return sizer - + def create_sizer_run(self): """Create the run sizer containing tab-specific functionality.""" sizer = wx.BoxSizer(wx.VERTICAL) sizer.SetMinSize(400, 300) sizer.AddSpacer(10) return sizer - + def create_empty_component(self): component = InputComponent(panel=self, input_text_box_metadata=[]) return component @@ -210,11 +210,14 @@ def open_documentation_url(self, event): class InputComponent(Component): - def __init__(self, panel, input_text_box_metadata): + """ Define cli to automatically generate help text """ + def __init__(self, panel, input_text_box_metadata, cli=None): super().__init__(panel) self.sizer = self.create_sizer() self.input_text_boxes = {} self.input_text_box_metadata = input_text_box_metadata + self.cli = cli + self.add_text_info() self.add_input_text_boxes() def create_sizer(self): @@ -222,6 +225,17 @@ def create_sizer(self): sizer = wx.BoxSizer(wx.VERTICAL) return sizer + def add_text_info(self): + """ This function adds the help text to the metadata. This function + needs to be called before creating the buttons. + + """ + for i, twb_dict in enumerate(self.input_text_box_metadata): + if not ('info_text' in twb_dict.keys()) and (self.cli is not None) and ('name' in twb_dict.keys()): + description = get_help_text(self.cli, twb_dict['name']) + self.input_text_box_metadata[i]['info_text'] = description + + def add_input_text_boxes(self, spacer_size=10): """Add a list of input text boxes (TextWithButton) to the sizer_input. @@ -283,37 +297,51 @@ def button_do_something(self, event): class DropdownComponent(Component): - def __init__(self, panel, dropdown_metadata, name, list_components=[], info_text=""): + def __init__(self, panel, dropdown_metadata, label, option_name, list_components=[], info_text=None, cli=None): """ Create a dropdown list Args: panel (wx.Panel): A panel is a window on which controls are placed. dropdown_metadata (list)(dict): A list of dictionaries where the dictionaries have the - required keys: ``label``, ``option_name``, ``option_value``. + required keys: ``label``, ``option_value``. .. code:: { "label": The label for the dropdown box - "option_name": The name of the option in the CLI "option_value": The value linked to the option in the CLI } - name (str): Label of the button describing the dropdown + label (str): Label of the button describing the dropdown + option_name (str): Name of the options of the dropdown, set to 'no_arg' is not an option list_components (list): list of InputComponents - info_text (str): Info message displayed when hovering over the "i" icon. + info_text (str): Info message displayed when hovering over the "i" icon. Leave blank to auto fill using option_name + cli (function): CLI function used by the dropdown """ super().__init__(panel, list_components) self.dropdown_metadata = dropdown_metadata - self.name = name + self.label = label self.info_text = info_text self.positions = {} self.input_text_boxes = {} self.sizer = self.create_sizer() self.dropdown_choices = [item["label"] for item in self.dropdown_metadata] + self.option_name = option_name + self.cli = cli + self.add_text_info() self.create_choice_box() self.create_dropdown_sizers() self.on_choice(None) + def add_text_info(self): + """ This function adds the help text. """ + + if self.info_text is None: + if self.cli is not None: + description = get_help_text(self.cli, self.option_name) + self.info_text = description + else: + self.info_text = "" + def create_dropdown_sizers(self): for index in range(len(self.list_components)): sizer = self.list_components[index].sizer @@ -329,7 +357,7 @@ def unshow_choice_box_sizers(self): def create_choice_box(self): self.choice_box = wx.Choice(self.panel, choices=self.dropdown_choices) self.choice_box.Bind(wx.EVT_CHOICE, self.on_choice) - button = wx.Button(self.panel, -1, label=self.name) + button = wx.Button(self.panel, -1, label=self.label) self.choice_box_sizer = wx.BoxSizer(wx.HORIZONTAL) self.choice_box_sizer.Add(create_info_icon(self.panel, self.info_text), 0, wx.ALIGN_LEFT | wx.RIGHT, 7) self.choice_box_sizer.Add(button, 0, wx.ALIGN_LEFT | wx.RIGHT, 10) @@ -355,9 +383,8 @@ def on_choice(self, event): self.input_text_boxes = self.list_components[index].input_text_boxes # Add the dropdown to the list of options - self.input_text_boxes[self.dropdown_metadata[index]["option_name"]] = \ - [self.dropdown_metadata[index]["option_value"]] - + self.input_text_boxes[self.option_name] = [self.dropdown_metadata[index]["option_value"]] + # Update the window self.panel.SetVirtualSize(self.panel.sizer_run.GetMinSize()) self.panel.Layout() @@ -456,7 +483,7 @@ def on_result(self, event): # Append the file if it was a file if os.path.isfile(self.output): self.output_paths.append(self.output) - + # Append files that are a direct output from "load_in_overlay" for fname in self.load_in_overlay: self.output_paths.append(fname) @@ -514,7 +541,7 @@ def button_run_on_click(self, event): except RunArgumentErrorST as err: self.panel.terminal_component.log_to_terminal(err, level="ERROR") return - + self.panel.terminal_component.log_to_terminal(msg, level="INFO") self.worker = WorkerThread(self.panel, command, name=self.st_function) @@ -547,11 +574,12 @@ def get_run_args(self, st_function): command_list_options = [] for component in self.list_components: for name, input_text_box_list in component.input_text_boxes.items(): + if name == "no_arg": continue for input_text_box in input_text_box_list: - # Allows to chose from a dropdown + # Allows to choose from a dropdown if type(input_text_box) == str: command_list_options.append((name, [input_text_box])) @@ -577,7 +605,7 @@ def get_run_args(self, st_function): self.output = arg elif input_text_box.load_in_overlay: self.load_in_overlay.append(arg) - + option_values.append(arg) # If its an argument don't include it as an option, if the option list is empty don't either @@ -593,9 +621,9 @@ def get_run_args(self, st_function): command += ['--' + name] for arg in args: command += [arg] - + msg += ' '.join(command) + '\n' - + return command, msg def fetch_paths_dicom_to_nifti(self): @@ -712,53 +740,47 @@ def create_sizer_dynamic_shim(self, metadata=None): "button_label": "Input Fieldmap", "name": "fmap", "button_function": "select_from_overlay", - "info_text": f"{dynamic_cli.params[1].help}", "required": True }, { "button_label": "Input Anat", "name": "anat", "button_function": "select_from_overlay", - "info_text": f"{dynamic_cli.params[2].help}", "required": True }, { "button_label": "Input Mask", "name": "mask", "button_function": "select_from_overlay", - "info_text": f"{dynamic_cli.params[3].help}" }, { "button_label": "Mask Dilation Kernel Size", "name": "mask-dilation-kernel-size", - "info_text": f"{dynamic_cli.params[9].help}", "default_text": "3", } ] - component_inputs = InputComponent(self, input_text_box_metadata_inputs) + component_inputs = InputComponent(self, input_text_box_metadata_inputs, cli=dynamic_cli) input_text_box_metadata_scanner = [ { "button_label": "Scanner constraints", "button_function": "select_file", "name": "scanner-coil-constraints", - "info_text": f"{dynamic_cli.params[5].help}", "default_text": f"{os.path.join(ST_DIR, 'coil_config.json')}", }, ] - component_scanner = InputComponent(self, input_text_box_metadata_scanner) + component_scanner = InputComponent(self, input_text_box_metadata_scanner, cli=dynamic_cli) input_text_box_metadata_slice = [ { "button_label": "Slice Factor", "name": "slice-factor", - "info_text": f"{dynamic_cli.params[7].help}", "default_text": "1", }, ] - component_slice_int = InputComponent(self, input_text_box_metadata_slice) - component_slice_seq = InputComponent(self, input_text_box_metadata_slice) + component_slice_int = InputComponent(self, input_text_box_metadata_slice, cli=dynamic_cli) + component_slice_seq = InputComponent(self, input_text_box_metadata_slice, cli=dynamic_cli) output_metadata = [ { @@ -766,30 +788,25 @@ def create_sizer_dynamic_shim(self, metadata=None): "button_function": "select_folder", "default_text": path_output, "name": "output", - "info_text": f"{dynamic_cli.params[11].help}" } ] - component_output = InputComponent(self, output_metadata) + component_output = InputComponent(self, output_metadata, cli=dynamic_cli) dropdown_scanner_order_metadata = [ { "label": "-1", - "option_name": "scanner-coil-order", "option_value": "-1" }, { "label": "0", - "option_name": "scanner-coil-order", "option_value": "0" }, { "label": "1", - "option_name": "scanner-coil-order", "option_value": "1" }, { "label": "2", - "option_name": "scanner-coil-order", "option_value": "2" } ] @@ -797,19 +814,18 @@ def create_sizer_dynamic_shim(self, metadata=None): dropdown_scanner_order = DropdownComponent( panel=self, dropdown_metadata=dropdown_scanner_order_metadata, - name="Scanner Order", - info_text=f"{dynamic_cli.params[4].help}" + label="Scanner Order", + option_name = 'scanner-coil-order', + cli=dynamic_cli ) dropdown_ovf_metadata = [ { "label": "delta", - "option_name": "output-value-format", "option_value": "delta" }, { "label": "absolute", - "option_name": "output-value-format", "option_value": "absolute" } ] @@ -817,19 +833,18 @@ def create_sizer_dynamic_shim(self, metadata=None): dropdown_ovf = DropdownComponent( panel=self, dropdown_metadata=dropdown_ovf_metadata, - name="Output Value Format", - info_text=f"{dynamic_cli.params[14].help}" + label="Output Value Format", + option_name = 'output-value-format', + cli=dynamic_cli ) dropdown_opt_metadata = [ { "label": "Least Squares", - "option_name": "optimizer-method", "option_value": "least_squares" }, { "label": "Pseudo Inverse", - "option_name": "optimizer-method", "option_value": "pseudo_inverse" }, ] @@ -837,29 +852,26 @@ def create_sizer_dynamic_shim(self, metadata=None): dropdown_opt = DropdownComponent( panel=self, dropdown_metadata=dropdown_opt_metadata, - name="Optimizer", - info_text=f"{dynamic_cli.params[8].help}" + label="Optimizer", + option_name = 'optimizer-method', + cli=dynamic_cli ) dropdown_slice_metadata = [ { "label": "Auto detect", - "option_name": "slices", "option_value": "auto" }, { "label": "Sequential", - "option_name": "slices", "option_value": "sequential" }, { "label": "Interleaved", - "option_name": "slices", "option_value": "interleaved" }, { "label": "Volume", - "option_name": "slices", "option_value": "volume" }, ] @@ -867,8 +879,9 @@ def create_sizer_dynamic_shim(self, metadata=None): self.dropdown_slice_dyn = DropdownComponent( panel=self, dropdown_metadata=dropdown_slice_metadata, - name="Slice Ordering", - info_text=dynamic_cli.params[6].help, + label="Slice Ordering", + cli=dynamic_cli, + option_name = 'slices', list_components=[self.create_empty_component(), component_slice_seq, component_slice_int, @@ -878,40 +891,33 @@ def create_sizer_dynamic_shim(self, metadata=None): dropdown_coil_format_metadata = [ { "label": "Slicewise per Channel", - "option_name": "output-file-format-coil", "option_value": "slicewise-ch" }, { "label": "Slicewise per Coil", - "option_name": "output-file-format-coil", "option_value": "slicewise-coil" }, { "label": "Chronological per Channel", - "option_name": "output-file-format-coil", "option_value": "chronological-ch" }, { "label": "Chronological per Coil", - "option_name": "output-file-format-coil", "option_value": "chronological-coil" }, ] - + dropdown_fatsat_metadata = [ { "label": "Auto detect", - "option_name": "fatsat", "option_value": "auto" }, { "label": "Yes", - "option_name": "fatsat", "option_value": "yes" }, { "label": "No", - "option_name": "fatsat", "option_value": "no" }, ] @@ -919,22 +925,25 @@ def create_sizer_dynamic_shim(self, metadata=None): dropdown_fatsat1 = DropdownComponent( panel=self, dropdown_metadata=dropdown_fatsat_metadata, - name="Fat Saturation", - info_text=dynamic_cli.params[10].help, + option_name = 'fatsat', + label="Fat Saturation", + cli=dynamic_cli ) - + dropdown_fatsat2 = DropdownComponent( panel=self, dropdown_metadata=dropdown_fatsat_metadata, - name="Fat Saturation", - info_text=dynamic_cli.params[10].help, + option_name = 'fatsat', + label="Fat Saturation", + cli=dynamic_cli ) - + self.dropdown_coil_format_dyn = DropdownComponent( panel=self, dropdown_metadata=dropdown_coil_format_metadata, - name="Custom Coil Output Format", - info_text=f"{dynamic_cli.params[12].help}", + label="Custom Coil Output Format", + option_name = 'output-file-format-coil', + cli=dynamic_cli, list_components=[self.create_empty_component(), self.create_empty_component(), dropdown_fatsat1, @@ -944,27 +953,23 @@ def create_sizer_dynamic_shim(self, metadata=None): dropdown_scanner_format_metadata = [ { "label": "Slicewise per Channel", - "option_name": "output-file-format-scanner", "option_value": "slicewise-ch" }, { "label": "Slicewise per Coil", - "option_name": "output-file-format-scanner", "option_value": "slicewise-coil" }, { "label": "Chronological per Channel", - "option_name": "output-file-format-scanner", + "option_value": "chronological-ch" }, { "label": "Chronological per Coil", - "option_name": "output-file-format-scanner", "option_value": "chronological-coil" }, { "label": "Gradient per Channel", - "option_name": "output-file-format-scanner", "option_value": "gradient" }, ] @@ -972,14 +977,15 @@ def create_sizer_dynamic_shim(self, metadata=None): dropdown_scanner_format = DropdownComponent( panel=self, dropdown_metadata=dropdown_scanner_format_metadata, - name="Scanner Output Format", - info_text=f"{dynamic_cli.params[13].help}" + option_name = 'output-file-format-scanner', + label="Scanner Output Format", + cli=dynamic_cli ) - + run_component = RunComponent( panel=self, list_components=[self.component_coils_dyn, component_inputs, dropdown_opt, self.dropdown_slice_dyn, - dropdown_scanner_order, component_scanner, dropdown_scanner_format, + dropdown_scanner_order, component_scanner, dropdown_scanner_format, self.dropdown_coil_format_dyn, dropdown_ovf, component_output], st_function="st_b0shim dynamic", output_paths=["fieldmap_calculated_shim_masked.nii.gz", @@ -1000,73 +1006,65 @@ def create_sizer_realtime_shim(self, metadata=None): "info_text": "Number of phase NIfTI files to be used. Must be an integer > 0.", } ] - self.component_coils_rt = InputComponent(self, input_text_box_metadata_coil) + self.component_coils_rt = InputComponent(self, input_text_box_metadata_coil, cli=realtime_cli) input_text_box_metadata_inputs = [ { "button_label": "Input Fieldmap", "name": "fmap", "button_function": "select_from_overlay", - "info_text": f"{realtime_cli.params[1].help}", "required": True }, { "button_label": "Input Anat", "name": "anat", "button_function": "select_from_overlay", - "info_text": f"{realtime_cli.params[2].help}", "required": True }, { "button_label": "Input Respiratory Trace", "name": "resp", "button_function": "select_file", - "info_text": f"{realtime_cli.params[3].help}", "required": True }, { "button_label": "Input Mask Static", "name": "mask-static", "button_function": "select_from_overlay", - "info_text": f"{realtime_cli.params[4].help}" }, { "button_label": "Input Mask Realtime", "name": "mask-riro", "button_function": "select_from_overlay", - "info_text": f"{realtime_cli.params[5].help}" }, { "button_label": "Mask Dilation Kernel Size", "name": "mask-dilation-kernel-size", - "info_text": f"{realtime_cli.params[11].help}", "default_text": "3", } ] - component_inputs = InputComponent(self, input_text_box_metadata_inputs) + component_inputs = InputComponent(self, input_text_box_metadata_inputs, cli=realtime_cli) input_text_box_metadata_scanner = [ { "button_label": "Scanner constraints", "button_function": "select_file", "name": "scanner-coil-constraints", - "info_text": f"{realtime_cli.params[7].help}", "default_text": f"{os.path.join(ST_DIR, 'coil_config.json')}", }, ] - component_scanner = InputComponent(self, input_text_box_metadata_scanner) + component_scanner = InputComponent(self, input_text_box_metadata_scanner, cli=realtime_cli) input_text_box_metadata_slice = [ { "button_label": "Slice Factor", "name": "slice-factor", - "info_text": f"{realtime_cli.params[9].help}", "default_text": "1", }, ] - component_slice_int = InputComponent(self, input_text_box_metadata_slice) - component_slice_seq = InputComponent(self, input_text_box_metadata_slice) + component_slice_int = InputComponent(self, input_text_box_metadata_slice, cli=realtime_cli) + component_slice_seq = InputComponent(self, input_text_box_metadata_slice, cli=realtime_cli) output_metadata = [ { @@ -1074,30 +1072,25 @@ def create_sizer_realtime_shim(self, metadata=None): "button_function": "select_folder", "default_text": path_output, "name": "output", - "info_text": f"{realtime_cli.params[13].help}" } ] - component_output = InputComponent(self, output_metadata) + component_output = InputComponent(self, output_metadata, cli=realtime_cli) dropdown_scanner_order_metadata = [ { "label": "-1", - "option_name": "scanner-coil-order", "option_value": "-1" }, { "label": "0", - "option_name": "scanner-coil-order", "option_value": "0" }, { "label": "1", - "option_name": "scanner-coil-order", "option_value": "1" }, { "label": "2", - "option_name": "scanner-coil-order", "option_value": "2" } ] @@ -1105,19 +1098,18 @@ def create_sizer_realtime_shim(self, metadata=None): dropdown_scanner_order = DropdownComponent( panel=self, dropdown_metadata=dropdown_scanner_order_metadata, - name="Scanner Order", - info_text=f"{realtime_cli.params[6].help}" + label="Scanner Order", + option_name = 'scanner-coil-order', + cli=realtime_cli ) dropdown_ovf_metadata = [ { "label": "delta", - "option_name": "output-value-format", "option_value": "delta" }, { "label": "absolute", - "option_name": "output-value-format", "option_value": "absolute" } ] @@ -1125,19 +1117,18 @@ def create_sizer_realtime_shim(self, metadata=None): dropdown_ovf = DropdownComponent( panel=self, dropdown_metadata=dropdown_ovf_metadata, - name="Output Value Format", - info_text=f"{realtime_cli.params[16].help}" + label="Output Value Format", + option_name = 'output-value-format', + cli=realtime_cli ) dropdown_opt_metadata = [ { "label": "Least Squares", - "option_name": "optimizer-method", "option_value": "least_squares" }, { "label": "Pseudo Inverse", - "option_name": "optimizer-method", "option_value": "pseudo_inverse" }, ] @@ -1145,29 +1136,26 @@ def create_sizer_realtime_shim(self, metadata=None): dropdown_opt = DropdownComponent( panel=self, dropdown_metadata=dropdown_opt_metadata, - name="Optimizer", - info_text=f"{realtime_cli.params[10].help}" + label="Optimizer", + option_name = 'optimizer-method', + cli=realtime_cli ) dropdown_slice_metadata = [ { "label": "Auto detect", - "option_name": "slices", "option_value": "auto" }, { "label": "Sequential", - "option_name": "slices", "option_value": "sequential" }, { "label": "Interleaved", - "option_name": "slices", "option_value": "interleaved" }, { "label": "Volume", - "option_name": "slices", "option_value": "volume" }, ] @@ -1175,28 +1163,26 @@ def create_sizer_realtime_shim(self, metadata=None): self.dropdown_slice_rt = DropdownComponent( panel=self, dropdown_metadata=dropdown_slice_metadata, - name="Slice Ordering", - info_text=realtime_cli.params[10].help, + label="Slice Ordering", + option_name = 'slices', list_components=[self.create_empty_component(), component_slice_seq, component_slice_int, - self.create_empty_component()] + self.create_empty_component()], + cli=realtime_cli ) dropdown_scanner_format_metadata = [ { "label": "Slicewise per Channel", - "option_name": "output-file-format-scanner", "option_value": "slicewise-ch" }, { "label": "Chronological per Channel", - "option_name": "output-file-format-scanner", "option_value": "chronological-ch" }, { "label": "Gradient per Channel", - "option_name": "output-file-format-scanner", "option_value": "gradient" }, ] @@ -1204,24 +1190,22 @@ def create_sizer_realtime_shim(self, metadata=None): dropdown_scanner_format = DropdownComponent( panel=self, dropdown_metadata=dropdown_scanner_format_metadata, - name="Scanner Output Format", - info_text=f"{realtime_cli.params[15].help}" + label="Scanner Output Format", + option_name = 'output-file-format-scanner', + cli=realtime_cli ) - + dropdown_fatsat_metadata = [ { "label": "Auto detect", - "option_name": "fatsat", "option_value": "auto" }, { "label": "Yes", - "option_name": "fatsat", "option_value": "yes" }, { "label": "No", - "option_name": "fatsat", "option_value": "no" }, ] @@ -1229,19 +1213,18 @@ def create_sizer_realtime_shim(self, metadata=None): dropdown_fatsat = DropdownComponent( panel=self, dropdown_metadata=dropdown_fatsat_metadata, - name="Fat Saturation", - info_text=realtime_cli.params[12].help, + label="Fat Saturation", + option_name = 'fatsat', + cli=realtime_cli ) - + dropdown_coil_format_metadata = [ { "label": "Slicewise per Channel", - "option_name": "output-file-format-coil", "option_value": "slicewise-ch" }, { "label": "Chronological per Channel", - "option_name": "output-file-format-coil", "option_value": "chronological-ch" } ] @@ -1249,12 +1232,13 @@ def create_sizer_realtime_shim(self, metadata=None): self.dropdown_coil_format_rt = DropdownComponent( panel=self, dropdown_metadata=dropdown_coil_format_metadata, - name="Custom Coil Output Format", - info_text=f"{realtime_cli.params[14].help}", + label="Custom Coil Output Format", + option_name = 'output-file-format-coil', + cli=realtime_cli, list_components=[self.create_empty_component(), dropdown_fatsat] ) - + run_component = RunComponent( panel=self, list_components=[self.component_coils_rt, component_inputs, dropdown_opt, self.dropdown_slice_rt, @@ -1347,37 +1331,32 @@ def create_sizer_cv(self, metadata=None): "button_label": "Input B1+ map", "name": "b1", "button_function": "select_from_overlay", - "info_text": f"{b1shim_cli.params[0].help}", "required": True }, { "button_label": "Input Mask", "name": "mask", "button_function": "select_from_overlay", - "info_text": f"{b1shim_cli.params[1].help}" }, { "button_label": "Input VOP file", "name": "vop", "button_function": "select_file", - "info_text": f"{b1shim_cli.params[4].help}" }, { "button_label": "SAR factor", "name": "sar_factor", "default_text": "1.5", - "info_text": f"{b1shim_cli.params[5].help}" }, { "button_label": "Output Folder", "button_function": "select_folder", "default_text": path_output, "name": "output", - "info_text": f"{b1shim_cli.params[6].help}" } ] - component = InputComponent(self, input_text_box_metadata) + component = InputComponent(self, input_text_box_metadata, cli=b1shim_cli) run_component = RunComponent( panel=self, list_components=[component], @@ -1394,44 +1373,38 @@ def create_sizer_target(self, metadata=None): "button_label": "Input B1+ map", "name": "b1", "button_function": "select_from_overlay", - "info_text": f"{b1shim_cli.params[0].help}", "required": True }, { "button_label": "Input Mask", "name": "mask", "button_function": "select_from_overlay", - "info_text": f"{b1shim_cli.params[1].help}" }, { "button_label": "Target value (nT/V)", "name": "target", "default_text": "20", - "info_text": f"{b1shim_cli.params[3].help}", "required": True }, { "button_label": "Input VOP file", "name": "vop", "button_function": "select_file", - "info_text": f"{b1shim_cli.params[4].help}" }, { "button_label": "SAR factor", "name": "sar_factor", "default_text": "1.5", - "info_text": f"{b1shim_cli.params[5].help}" }, { "button_label": "Output Folder", "button_function": "select_folder", "default_text": path_output, "name": "output", - "info_text": f"{b1shim_cli.params[6].help}" } ] - component = InputComponent(self, input_text_box_metadata) + component = InputComponent(self, input_text_box_metadata, cli=b1shim_cli) run_component = RunComponent( panel=self, list_components=[component], @@ -1448,38 +1421,33 @@ def create_sizer_sar_eff(self, metadata=None): "button_label": "Input B1+ map", "name": "b1", "button_function": "select_from_overlay", - "info_text": f"{b1shim_cli.params[0].help}", "required": True }, { "button_label": "Input Mask", "name": "mask", "button_function": "select_from_overlay", - "info_text": f"{b1shim_cli.params[1].help}" }, { "button_label": "Input VOP file", "name": "vop", "button_function": "select_file", - "info_text": f"{b1shim_cli.params[4].help}", "required": True }, { "button_label": "SAR factor", "name": "sar_factor", "default_text": "1.5", - "info_text": f"{b1shim_cli.params[5].help}" }, { "button_label": "Output Folder", "button_function": "select_folder", "default_text": path_output, "name": "output", - "info_text": f"{b1shim_cli.params[6].help}" } ] - component = InputComponent(self, input_text_box_metadata) + component = InputComponent(self, input_text_box_metadata, cli=b1shim_cli) run_component = RunComponent( panel=self, list_components=[component], @@ -1496,24 +1464,21 @@ def create_sizer_phase_only(self, metadata=None): "button_label": "Input B1+ maps", "name": "b1", "button_function": "select_from_overlay", - "info_text": f"{b1shim_cli.params[0].help}", "required": True }, { "button_label": "Input Mask", "name": "mask", "button_function": "select_from_overlay", - "info_text": f"{b1shim_cli.params[1].help}" }, { "button_label": "Output Folder", "button_function": "select_folder", "default_text": path_output, "name": "output", - "info_text": f"{b1shim_cli.params[6].help}" } ] - component = InputComponent(self, input_text_box_metadata) + component = InputComponent(self, input_text_box_metadata, cli=b1shim_cli) run_component = RunComponent( panel=self, list_components=[component], @@ -1530,17 +1495,17 @@ def __init__(self, parent, title="Fieldmap"): "Enter the Number of Echoes then press the `Number of Echoes` button.\n\n" \ "Select the unwrapper from the dropdown list." super().__init__(parent, title, description) - + self.sizer_run = self.create_sizer_run() self.n_echoes = 0 sizer = self.create_fieldmap_sizer() self.sizer_run.Add(sizer, 0, wx.EXPAND) - + self.parent_sizer = self.create_sizer() self.SetSizer(self.parent_sizer) - + def create_fieldmap_sizer(self): - + input_text_box_metadata_input = [ { "button_label": "Number of Echoes", @@ -1550,79 +1515,89 @@ def create_fieldmap_sizer(self): "required": True } ] - dropdown_metadata = [ + self.component_input = InputComponent( + panel=self, + input_text_box_metadata=input_text_box_metadata_input + ) + + dropdown_metadata_unwrapper = [ { "label": "prelude", - "option_name": "unwrapper", "option_value": "prelude" } ] - - dropdown_mask_threshold = [ - { - "label": "mask", - "option_name": "no_arg", - "option_value": "" - }, - { - "label": "threshold", - "option_name": "no_arg", - "option_value": "" - }, - ] - - path_output = os.path.join(CURR_DIR, "output_fieldmap") - - input_text_box_metadata_output = [ - { - "button_label": "Output File", - "button_function": "select_folder", - "default_text": os.path.join(path_output, "fieldmap.nii.gz"), - "name": "output", - "info_text": f"{prepare_fieldmap_cli.params[3].help}", - "required": True - } - ] + self.dropdown = DropdownComponent( + panel=self, + dropdown_metadata=dropdown_metadata_unwrapper, + label="Unwrapper", + option_name = 'unwrapper', + cli=prepare_fieldmap_cli + ) mask_metadata = [ { "button_label": "Input Mask", "button_function": "select_from_overlay", "name": "mask", - "info_text": f"{prepare_fieldmap_cli.params[5].help}" } ] - self.component_mask = InputComponent( panel=self, - input_text_box_metadata=mask_metadata + input_text_box_metadata=mask_metadata, + cli=prepare_fieldmap_cli ) threshold_metadata = [ { "button_label": "Threshold", "name": "threshold", - "info_text": f"{prepare_fieldmap_cli.params[6].help}" }, { "button_label": "Output Calculated Mask", "name": "savemask", - "info_text": f"{prepare_fieldmap_cli.params[7].help}", "load_in_overlay": True } ] - self.component_threshold = InputComponent( panel=self, - input_text_box_metadata=threshold_metadata + input_text_box_metadata=threshold_metadata, + cli=prepare_fieldmap_cli ) + dropdown_mask_threshold = [ + { + "label": "mask", + "option_value": "" + }, + { + "label": "threshold", + "option_value": "" + }, + ] self.dropdown_mask_threshold = DropdownComponent( panel=self, dropdown_metadata=dropdown_mask_threshold, - name="Mask/Threshold", + label="Mask/Threshold", info_text="Masking methods either with a file input or a threshold", - list_components=[self.component_mask, self.component_threshold] + option_name = 'no_arg', + list_components=[self.component_mask, self.component_threshold], + cli=prepare_fieldmap_cli + ) + + path_output = os.path.join(CURR_DIR, "output_fieldmap") + input_text_box_metadata_output = [ + { + "button_label": "Output File", + "button_function": "select_folder", + "default_text": os.path.join(path_output, "fieldmap.nii.gz"), + "name": "output", + "required": True + } + ] + self.component_output = InputComponent( + panel=self, + input_text_box_metadata=input_text_box_metadata_output, + cli=prepare_fieldmap_cli ) input_text_box_metadata_input2 = [ @@ -1630,35 +1605,22 @@ def create_fieldmap_sizer(self): "button_label": "Input Magnitude", "button_function": "select_from_overlay", "name": "mag", - "info_text": f"{prepare_fieldmap_cli.params[1].help}", "required": True } ] - self.component_input = InputComponent( - panel=self, - input_text_box_metadata=input_text_box_metadata_input - ) self.component_input2 = InputComponent( panel=self, - input_text_box_metadata=input_text_box_metadata_input2 - ) - self.dropdown = DropdownComponent( - panel=self, - dropdown_metadata=dropdown_metadata, - name="Unwrapper", - info_text=f"{prepare_fieldmap_cli.params[2].help}" - ) - self.component_output = InputComponent( - panel=self, - input_text_box_metadata=input_text_box_metadata_output + input_text_box_metadata=input_text_box_metadata_input2, + cli=prepare_fieldmap_cli ) + self.run_component = RunComponent( panel=self, list_components=[self.component_input, self.component_input2, self.dropdown_mask_threshold, self.dropdown, self.component_output], st_function="st_prepare_fieldmap" ) - + return self.run_component.sizer @@ -1735,24 +1697,21 @@ def create_sizer_threshold(self, metadata=None): "button_label": "Input", "button_function": "select_from_overlay", "name": "input", - "info_text": f"{threshold.params[0].help}", "required": True }, { "button_label": "Threshold", "default_text": "30", "name": "thr", - "info_text": f"{threshold.params[2].help}" }, { "button_label": "Output File", "button_function": "select_folder", "default_text": os.path.join(path_output, "mask.nii.gz"), "name": "output", - "info_text": f"{threshold.params[1].help}" } ] - component = InputComponent(self, input_text_box_metadata) + component = InputComponent(self, input_text_box_metadata, cli=threshold) run_component = RunComponent( panel=self, list_components=[component], @@ -1768,31 +1727,27 @@ def create_sizer_rect(self): "button_label": "Input", "button_function": "select_from_overlay", "name": "input", - "info_text": f"{rect.params[0].help}", "required": True }, { "button_label": "Size", "name": "size", "n_text_boxes": 2, - "info_text": f"{rect.params[2].help}", "required": True }, { "button_label": "Center", "name": "center", "n_text_boxes": 2, - "info_text": f"{rect.params[3].help}" }, { "button_label": "Output File", "button_function": "select_folder", "default_text": os.path.join(path_output, "mask.nii.gz"), "name": "output", - "info_text": f"{rect.params[1].help}" } ] - component = InputComponent(self, input_text_box_metadata) + component = InputComponent(self, input_text_box_metadata, cli=rect) run_component = RunComponent( panel=self, list_components=[component], @@ -1808,31 +1763,27 @@ def create_sizer_box(self): "button_label": "Input", "button_function": "select_from_overlay", "name": "input", - "info_text": f"{box.params[0].help}", "required": True }, { "button_label": "Size", "name": "size", "n_text_boxes": 3, - "info_text": f"{box.params[2].help}", "required": True }, { "button_label": "Center", "name": "center", "n_text_boxes": 3, - "info_text": f"{box.params[3].help}" }, { "button_label": "Output File", "button_function": "select_folder", "default_text": os.path.join(path_output, "mask.nii.gz"), "name": "output", - "info_text": f"{box.params[1].help}" } ] - component = InputComponent(self, input_text_box_metadata) + component = InputComponent(self, input_text_box_metadata, box) run_component = RunComponent( panel=self, list_components=[component], @@ -1846,14 +1797,14 @@ class DicomToNiftiTab(Tab): def __init__(self, parent, title="Dicom to Nifti"): description = "Convert DICOM files into NIfTI following the BIDS data structure" super().__init__(parent, title, description) - + self.sizer_run = self.create_sizer_run() sizer = self.create_dicom_to_nifti_sizer() self.sizer_run.Add(sizer, 0, wx.EXPAND) - + self.parent_sizer = self.create_sizer() self.SetSizer(self.parent_sizer) - + def create_dicom_to_nifti_sizer(self): path_output = os.path.join(CURR_DIR, "output_dicom_to_nifti") input_text_box_metadata = [ @@ -1861,13 +1812,11 @@ def create_dicom_to_nifti_sizer(self): "button_label": "Input Folder", "button_function": "select_folder", "name": "input", - "info_text": f"{dicom_to_nifti_cli.params[0].help}", "required": True }, { "button_label": "Subject Name", "name": "subject", - "info_text": f"{dicom_to_nifti_cli.params[1].help}", "required": True }, { @@ -1875,17 +1824,15 @@ def create_dicom_to_nifti_sizer(self): "button_function": "select_file", "default_text": os.path.join(ST_DIR, "dcm2bids.json"), "name": "config", - "info_text": f"{dicom_to_nifti_cli.params[3].help}" }, { "button_label": "Output Folder", "button_function": "select_folder", "default_text": path_output, "name": "output", - "info_text": f"{dicom_to_nifti_cli.params[2].help}" } ] - component = InputComponent(self, input_text_box_metadata) + component = InputComponent(self, input_text_box_metadata, cli=dicom_to_nifti_cli) run_component = RunComponent(panel=self, list_components=[component], st_function="st_dicom_to_nifti") return run_component.sizer @@ -2326,6 +2273,17 @@ def load_png_image_from_path(fsl_panel, image_path, is_mask=False, add_to_overla return img_overlay +def get_help_text(cli_function, name): + """ Returns the help text of a cli function depending on its name. """ + for param in cli_function.params: + # Try different versions of the input dashes + for dashes in ['', '-', '--']: + new_name = dashes + name + if (new_name in param.opts) or new_name == param.human_readable_name: + return param.help + + raise ValueError(f"Could not find param: {name} in {cli_function.name}") + class RunArgumentErrorST(Exception): """Exception for missing input arguments for CLI call.""" pass diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index 1b26ac1..353f075 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -14,7 +14,7 @@ rm -rf "${ST_DIR}/shimming-toolbox" print info "Downloading Shimming-Toolbox" -ST_VERSION=0ab440e903a61c4a86c767a28a90f6ab7bb053ac +ST_VERSION=195016b0fa8006931b785517955db176c791e0fc curl -L "https://github.com/shimming-toolbox/shimming-toolbox/archive/${ST_VERSION}.zip" > "shimming-toolbox-${ST_VERSION}.zip" From f82b885bc533a234a87cf926815c6268ca8bad14 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Tue, 27 Sep 2022 01:18:24 -0400 Subject: [PATCH 19/20] Add regularization factor as an option --- fsleyes_plugin_shimming_toolbox/st_plugin.py | 23 ++++++++++++++++++++ installer/install_shimming_toolbox.sh | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/fsleyes_plugin_shimming_toolbox/st_plugin.py b/fsleyes_plugin_shimming_toolbox/st_plugin.py index d59de27..c1fb295 100644 --- a/fsleyes_plugin_shimming_toolbox/st_plugin.py +++ b/fsleyes_plugin_shimming_toolbox/st_plugin.py @@ -838,6 +838,15 @@ def create_sizer_dynamic_shim(self, metadata=None): cli=dynamic_cli ) + reg_factor_metadata = [ + { + "button_label": "Regularization factor", + "default_text": '0.0', + "name": 'regularization-factor', + } + ] + component_reg_factor = InputComponent(self, reg_factor_metadata, cli=dynamic_cli) + dropdown_opt_metadata = [ { "label": "Least Squares", @@ -854,6 +863,8 @@ def create_sizer_dynamic_shim(self, metadata=None): dropdown_metadata=dropdown_opt_metadata, label="Optimizer", option_name = 'optimizer-method', + list_components = [component_reg_factor, + self.create_empty_component()], cli=dynamic_cli ) @@ -1122,6 +1133,16 @@ def create_sizer_realtime_shim(self, metadata=None): cli=realtime_cli ) + + reg_factor_metadata = [ + { + "button_label": "Regularization factor", + "default_text": '0.0', + "name": 'regularization-factor', + } + ] + component_reg_factor = InputComponent(self, reg_factor_metadata, cli=dynamic_cli) + dropdown_opt_metadata = [ { "label": "Least Squares", @@ -1138,6 +1159,8 @@ def create_sizer_realtime_shim(self, metadata=None): dropdown_metadata=dropdown_opt_metadata, label="Optimizer", option_name = 'optimizer-method', + list_components= [component_reg_factor, + self.create_empty_component()], cli=realtime_cli ) diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index 353f075..3d47db1 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -14,7 +14,7 @@ rm -rf "${ST_DIR}/shimming-toolbox" print info "Downloading Shimming-Toolbox" -ST_VERSION=195016b0fa8006931b785517955db176c791e0fc +ST_VERSION=c78266365a6d2bdefed4b987f8ea9ad3597eb010 curl -L "https://github.com/shimming-toolbox/shimming-toolbox/archive/${ST_VERSION}.zip" > "shimming-toolbox-${ST_VERSION}.zip" From c347dbbccfe9883061a537b76034e96b30b76582 Mon Sep 17 00:00:00 2001 From: Alexandre D'Astous Date: Mon, 3 Oct 2022 18:54:30 -0400 Subject: [PATCH 20/20] Bump version --- installer/install_shimming_toolbox.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/install_shimming_toolbox.sh b/installer/install_shimming_toolbox.sh index 3d47db1..6592639 100644 --- a/installer/install_shimming_toolbox.sh +++ b/installer/install_shimming_toolbox.sh @@ -14,7 +14,7 @@ rm -rf "${ST_DIR}/shimming-toolbox" print info "Downloading Shimming-Toolbox" -ST_VERSION=c78266365a6d2bdefed4b987f8ea9ad3597eb010 +ST_VERSION=7087b9f20ef2bb0f1366dd8e6a8dfc440b349aed curl -L "https://github.com/shimming-toolbox/shimming-toolbox/archive/${ST_VERSION}.zip" > "shimming-toolbox-${ST_VERSION}.zip"