class FslWidget(QpWidget): """ Widget providing interface to FSL program """ def __init__(self, **kwargs): QpWidget.__init__(self, icon="fsl.png", group="FSL", **kwargs) self.prog = kwargs["prog"] def init_ui(self, run_box=True): self.vbox = QtGui.QVBoxLayout() self.setLayout(self.vbox) title = TitleWidget(self, help="fsl", subtitle="%s %s" % (self.description, __version__)) self.vbox.addWidget(title) cite = Citation(*CITATIONS.get(self.prog, CITATIONS["fsl"])) self.vbox.addWidget(cite) self.options = OptionBox("%s options" % self.prog.upper()) self.vbox.addWidget(self.options) if run_box: self.run_box = RunBox(self.get_process, self.get_options) self.vbox.addWidget(self.run_box) self.vbox.addStretch(1) fsldir = FslDirWidget() self.vbox.addWidget(fsldir) fsldir.sig_changed.connect(self._fsldir_changed) self._fsldir_changed(fsldir.fsldir) def _fsldir_changed(self, fsldir): self.options.setVisible(bool(fsldir)) if hasattr(self, "run_box"): self.run_box.setVisible(bool(fsldir)) def batch_options(self): return self.get_process().PROCESS_NAME, self.get_options() def get_options(self): return self.options.values()
class DscOptionsWidget(QtGui.QWidget): """ Widget allowing choice of DSC options """ def __init__(self, ivm): QtGui.QWidget.__init__(self) self.ivm = ivm vbox = QtGui.QVBoxLayout() self.setLayout(vbox) self.optbox = OptionBox() self.optbox.add("DSC Data", DataOption(self.ivm), key="data") self.optbox.add("ROI", DataOption(self.ivm, rois=True, data=False), key="mask") self.optbox.add( "Model choice", ChoiceOption(["Standard", "Control point interpolation"], ["dsc", "dsc_cpi"]), key="model") self.optbox.add("TE (s)", NumericOption(minval=0, maxval=0.1, default=0.065), key="te") self.optbox.add("Time interval between volumes (s)", NumericOption(minval=0, maxval=10, default=1.5), key="delt") self.optbox.add("Apply dispersion to AIF", BoolOption(), key="disp") self.optbox.add("Infer delay parameter", BoolOption(default=True), key="inferdelay") self.optbox.add("Infer arterial component", BoolOption(), key="inferart") self.optbox.add("Log transform on rCBF", BoolOption(), key="log-cbf") self.optbox.add("Output residue function", BoolOption(), key="save-model-extras") self.optbox.add("Spatial regularization", ChoiceOption(("None", "Standard", "Full"), default="Standard"), key="spatial") self.optbox.add("Output data suffix", TextOption(), checked=True, key="output-suffix") self.optbox.option("model").sig_changed.connect(self._model_changed) vbox.addWidget(self.optbox) hbox = QtGui.QHBoxLayout() self.classic_options = OptionBox("Standard model") self.classic_options.add("Infer MTT", BoolOption(default=True), key="infermtt") self.classic_options.add("Infer lambda", BoolOption(default=True), key="inferlambda") hbox.addWidget(self.classic_options) hbox.addStretch(1) vbox.addLayout(hbox) hbox = QtGui.QHBoxLayout() self.cpi_options = OptionBox("CPI model") self.cpi_options.setVisible(False) self.cpi_options.add("Number of control points", NumericOption(minval=3, maxval=20, default=5, intonly=True), key="num-cps") self.cpi_options.add("Infer control point time position", BoolOption(), key="infer-cpt") hbox.addWidget(self.cpi_options) hbox.addStretch(1) vbox.addLayout(hbox) vbox.addStretch() def options(self): """ :return: Dictionary of options selected for the DSC analysis""" opts = self.optbox.values() if opts["model"] == "dsc": opts.update(self.classic_options.values()) elif opts["model"] == "dsc_cpi": opts.update(self.cpi_options.values()) spatial = opts.pop("spatial", "None") if spatial == "Standard": opts["method"] = "spatialvb" opts["param-spatial-priors"] = "MN+" elif spatial == "Full": opts["method"] = "spatialvb" opts["param-spatial-priors"] = "M+" if opts.pop("log-cbf", False): opts["PSP_byname1"] = "cbf" opts["PSP_byname1_mean"] = 0.1 opts["PSP_byname1_prec"] = 1e-4 opts["PSP_byname1_transform"] = "L" return opts def _model_changed(self): classic = self.optbox.option("model").value == "dsc" self.classic_options.setVisible(classic) self.cpi_options.setVisible(not classic)
class PreprocOptions(OxaslOptionWidget): """ OXASL processing options related to corrections (motion, distortion etc) """ sig_enable_tab = QtCore.Signal(str, bool) def _init_ui(self): self.optbox.add("Motion correction", BoolOption(default=True), key="mc") #opt = self.optbox.add("Deblurring", BoolOption(), key="deblur") #opt.sig_changed.connect(self._deblur_changed) opt = self.optbox.add("ENABLE volume selection", BoolOption(), key="use_enable") opt.sig_changed.connect(self._enable_changed) self.optbox.add( "Distortion correction", ChoiceOption(["Fieldmap", "Phase encoding reversed calibration"], ["fmap", "cblip"]), key="distcorr", checked=True) self.optbox.option("distcorr").sig_changed.connect( self._distcorr_changed) self.optbox.add("Phase encode direction", ChoiceOption(["x", "y", "z", "-x", "-y", "-z"]), key="pedir") self.optbox.add("Echo spacing (ms)", NumericOption(minval=0, maxval=1, step=0.01, decimals=3), key="echospacing") self.fmap_opts = OptionBox("Fieldmap distortion correction") self.fmap_opts.add("Fieldmap image (rads)", DataOption(self.ivm, include_4d=False, explicit=True), key="fmap") self.fmap_opts.add("Fieldmap magnitude image (rads)", DataOption(self.ivm, include_4d=False, explicit=True), key="fmapmag") self.fmap_opts.add("Fieldmap magnitude brain image (rads)", DataOption(self.ivm, include_4d=False, explicit=True), key="fmapmagbrain") self.vbox.addWidget(self.fmap_opts) self.cblip_opts = OptionBox( "Phase-encoding reversed distortion correction") self.cblip_opts.add("Phase-encode reversed image", DataOption(self.ivm, include_4d=False, explicit=True), key="cblip") self.vbox.addWidget(self.cblip_opts) self._distcorr_changed() def _deblur_changed(self): self.sig_enable_tab.emit("deblur", self.optbox.option("deblur").value) def _enable_changed(self): self.sig_enable_tab.emit("enable", self.optbox.option("use_enable").value) def _distcorr_changed(self): enabled = self.optbox.option("distcorr").isEnabled() distcorr = self.optbox.option("distcorr").value self.fmap_opts.setVisible(enabled and distcorr == "fmap") self.cblip_opts.setVisible(enabled and distcorr == "cblip") self.optbox.set_visible("pedir", enabled) self.optbox.set_visible("echospacing", enabled) def options(self): """ :return: Options as dictionary """ opts = self.optbox.values() if "echospacing" in opts: # Echo spacing needs to be passed in seconds opts["echospacing"] = opts["echospacing"] / 1000 distcorr = opts.pop("distcorr", None) if distcorr == "fmap": opts.update(self.fmap_opts.values()) elif distcorr == "cblip": opts.update(self.cblip_opts.values()) return opts
class CalibrationOptions(OxaslOptionWidget): """ OXASL processing options related to calibration """ def _init_ui(self): self.optbox.add("Calibration method", ChoiceOption(["None", "Voxelwise", "Reference region"], [None, "voxelwise", "single"]), key="calib_method") self.optbox.option("calib_method").sig_changed.connect( self._calib_method_changed) self.optbox.add("Calibration image", DataOption(self.ivm, explicit=True), key="calib") self.optbox.add("Sequence TR (s)", NumericOption(minval=0, maxval=20, default=3.2, step=0.1, decimals=3), key="tr", checked=True) self.optbox.add("Sequence TE (ms)", NumericOption(minval=0, maxval=100, default=0, step=5, decimals=3), key="te", checked=True) self.optbox.add("Calibration gain", NumericOption(minval=0, maxval=5, default=1, step=0.05, decimals=3), key="calib_gain", checked=True) self.optbox.add("Inversion efficiency", NumericOption(minval=0, maxval=1, default=0.85, step=0.05, decimals=3), key="calib_alpha", checked=True) self.voxelwise_opts = OptionBox("Voxelwise calibration") self.voxelwise_opts.add("Tissue T1", NumericOption(minval=0, maxval=10, default=1.3, step=0.05, decimals=3), key="t1t", checked=True) self.voxelwise_opts.add("Tissue partition coefficient", NumericOption(minval=0, maxval=5, default=0.9, step=0.05, decimals=3), key="pct", checked=True) self.vbox.addWidget(self.voxelwise_opts) self.refregion_opts = OptionBox("Reference region calibration") self.refregion_opts.add("Reference type", ChoiceOption(["CSF", "WM", "GM", "Custom"], ["csf", "wm", "gm", None]), key="tissref") self.refregion_opts.option("tissref").sig_changed.connect( self._ref_tiss_changed) self.refregion_opts.add("Custom reference ROI", DataOption(self.ivm, rois=True, data=False, explicit=True), key="refmask", checked=True) # TODO pick specific region of ROI self.refregion_opts.add("Reference T1 (s)", NumericOption(minval=0, maxval=10, default=4.3, step=0.1, decimals=3), key="t1r", checked=True) self.refregion_opts.add("Reference T2 (ms)", NumericOption(minval=0, maxval=2000, default=750, step=50, decimals=3), key="t2r", checked=True) self.refregion_opts.add("Reference partition coefficient (ms)", NumericOption(minval=0, maxval=5, default=1.15, step=0.05, decimals=3), key="pcr", checked=True) self.refregion_opts.add("Blood T2 (ms)", NumericOption(minval=0, maxval=2000, default=150, step=50, decimals=3), key="t2b", checked=True) self.refregion_opts.setVisible(False) self.vbox.addWidget(self.refregion_opts) self._calib_method_changed() def _calib_method_changed(self): method = self.optbox.option("calib_method").value self.voxelwise_opts.setVisible(method == "voxelwise") self.refregion_opts.setVisible(method == "single") for opt in ("calib", "tr", "te", "calib_gain", "calib_alpha"): self.optbox.set_visible(opt, method is not None) def _ref_tiss_changed(self): tissref = self.refregion_opts.option("tissref").value if tissref is not None: from oxasl.calib import tissue_defaults t1, t2, t2star, pc = tissue_defaults(tissref) self.refregion_opts.option("t1r").value = t1 self.refregion_opts.option("t2r").value = t2 self.refregion_opts.option("pcr").value = pc else: # Do nothing - user must choose their own values pass def options(self): """ :return: Options as dictionary """ opts = self.optbox.values() method = self.optbox.option("calib_method").value if method == "voxelwise": opts.update(self.voxelwise_opts.values()) elif method == "single": opts.update(self.refregion_opts.values()) return opts def set_wp_mode(self, wp_enabled): if wp_enabled: self.optbox.option("calib_method").value = "voxelwise" def set_asldata_metadata(self, md): """ Set the inversion efficiency default to 0.98 for PASL, 0.85 for CASL unless the checkbox is ticked in which case the user has modified it manually - so leave it alone """ casl = md.get("casl", True) alpha = 0.85 if casl else 0.98 if "calib_alpha" not in self.optbox.values(): self.optbox.option("calib_alpha").value = alpha