Ejemplo n.º 1
0
class SimData(FabberWidget):
    """
    Widget which uses Fabber models to generate simulated data
    """
    def __init__(self, **kwargs):
        super(SimData, self).__init__(name="Simulated Fabber Data", icon="fabber", 
                                      desc="Generate test data sets from Fabber models", 
                                      group="Simulation", **kwargs)
        self._param_test_values = {}

    def init_ui(self):
        FabberWidget.init_ui(self)
        
        self.param_values_box = OptionBox("Parameter values")
        self.param_values_box.sig_changed.connect(self._param_values_changed)
        self.vbox.addWidget(self.param_values_box)

        run_btn = QtGui.QPushButton('Generate test data', self)
        run_btn.clicked.connect(self._run)
        self.vbox.addWidget(run_btn)
        
        self.vbox.addStretch(1)

        model_opts_btn = QtGui.QPushButton('Model Options')
        model_opts_btn.clicked.connect(self._show_model_options)

        self.options.add("Model group", ChoiceOption(), key="model-group")
        self.options.add("Model", ChoiceOption(), model_opts_btn, key="model")
        self.options.add("Number of volumes (time points)", NumericOption(intonly=True, minval=1, maxval=100, default=10), key="num-vols")
        self.options.add("Voxels per patch (approx)", NumericOption(intonly=True, minval=1, maxval=10000, default=1000), key="num-voxels")
        self.options.add("Noise (Gaussian std.dev)", NumericOption(intonly=True, minval=0, maxval=1000, default=0), key="noise")
        self.options.add("Output data name", OutputNameOption(initial="fabber_test_data"), key="output-name")
        self.options.add("Output noise-free data", BoolOption(), key="save-clean")
        self.options.add("Output parameter ROIs", BoolOption(), key="save-rois")
        self.options.option("model-group").sig_changed.connect(self._model_group_changed)

        model_groups = ["ALL"]
        for group in FabberProcess.api().get_model_groups():
            model_groups.append(group.upper())
        self.options.option("model-group").setChoices(model_groups)
        self.options.option("model-group").value = "ALL"
        self._model_group_changed()

        self.options.option("model").value = "poly"
        self._options_changed()

        # Start with something sensible for the polynomial model
        self._param_test_values = {"c0" : [-100, 0, 100], "c1" : [-10, 0, 10], "c2" : [-1, 0, 1]}
        self._update_params()
 
    def _update_params(self):
        FabberWidget._update_params(self)
        self.param_values_box.clear()
        for param in self._fabber_params:
            current_values = self._param_test_values.get(param, [1.0])
            self.param_values_box.add(param, NumberListOption(initial=current_values))
            self._param_test_values[param] = current_values

        # Remove references to parameters which no longer exist
        for param in list(self._param_test_values.keys()):
            if param not in self._fabber_params:
                del self._param_test_values[param]

    def _param_values_changed(self):
        self._param_test_values = self.param_values_box.values()
        num_variable = len([1 for v in self._param_test_values.values() if len(v) > 1])
        if num_variable > 3:
            self.warn("Cannot have more than 3 varying parameters")
        
    def get_options(self):
        """ Return a copy of current Fabber options and parameter test values """
        options = dict(self._fabber_options)
        options["param-test-values"] = self._param_test_values
        return options
        
    def _run(self):
        process = self.get_process()
        options = self.get_options()
        process.run(options)
        
    def get_process(self):
        return FabberTestDataProcess(self.ivm)
  
    def batch_options(self):
        return "FabberTestData", self.get_options()
class UserPvModelView:
    """
    View for UserPvModel - a structural model where user supplies partial volume maps
    """

    def __init__(self, ivm):
        self.ivm = ivm
        self.model = UserPvModel(ivm)
        self.model.options.update({
            "pvmaps" : {},
            "additional" : {},
        })
        self.gui = OptionBox()
        self.gui.sig_changed.connect(self._update_options)
        self._refresh_gui()

    def _refresh_gui(self):
        options = dict(self.model.options)
        self.gui.clear()
        for struc in self.model.default_strucs:
            data_opt = self.gui.add("%s map" % struc.name.upper(), DataOption(self.model._ivm, explicit=True), checked=True, enabled=struc.name in options["pvmaps"], key=struc.name)
            data_opt.value = options["pvmaps"].get(struc.name, None)

        for struc in options["additional"].values():
            del_btn = self._struc_delete_btn(struc)
            display_type = {"add" : "map", "embed" : "embedding", "act" : "mask"}.get(struc["struc_type"], "map")
            data_opt = self.gui.add("%s %s" % (struc["name"], display_type), DataOption(self.model._ivm, explicit=True, rois=True), del_btn, key=struc["name"])
            data_opt.value = struc.get("pvmap", None)

        res_opts = options.get("resampling", {})
        self.gui.add("Resampling", ChoiceOption(["Downsample", "From another data set", "Specified resolution"], ["down", "data", "res"], 
                     default=res_opts.get("type", "res")), checked=True, enabled="type" in res_opts, key="type")
        self.gui.add("Output space from", DataOption(self.ivm), key="grid")
        self.gui.add("Output resample factor", NumericOption(intonly=True, minval=1, maxval=10, default=2), key="factor")
        self.gui.add("Voxel sizes (mm)", NumberListOption(load_btn=False), key="voxel-sizes")
        for opt in ("grid", "factor", "voxel-sizes"):
            if opt in res_opts:
                self.gui.option(opt).value = res_opts[opt]

        self.gui.add(None, RunButton("Add user-defined structure", callback=self._add_embedding), key="add_embedding")
        self._update_resamp_visibility()

    def _update_resamp_visibility(self):
        resample_type = self.gui.values().pop("type", "")
        self.gui.set_visible("grid", resample_type == "data")
        self.gui.set_visible("factor", resample_type in ("up", "down"))
        #self.gui.set_visible("order", resample_type != "down")
        #self.gui.set_visible("2d", resample_type in ("up", "down"))
        self.gui.set_visible("voxel-sizes", resample_type == "res")

    def _update_options(self):
        self._update_resamp_visibility()
        opts = self.gui.values()
        pvmaps = {}
        for struc in self.model.default_strucs:
            if struc.name in opts:
                pvmaps[struc.name] = opts[struc.name]
        self.model.options["pvmaps"] = pvmaps

        resamp = {}
        for resamp_opt in ("type", "grid", "factor", "voxel-sizes"):
            if resamp_opt in opts:
                resamp[resamp_opt] = opts[resamp_opt]
        self.model.options["resampling"] = resamp

    def _struc_delete_btn(self, add_struc):
        def _del_cb():
            self._del_struc(add_struc["name"])

        btn = QtGui.QPushButton("Delete")
        btn.clicked.connect(_del_cb)
        return btn

    def _del_struc(self, name):
        self.model.options["additional"].pop(name, None)
        self._refresh_gui()

    def _add_embedding(self):
        dialog = AddEmbeddingDialog(self.gui, self.model._ivm, self.model.default_strucs)
        try:
            accept = dialog.exec_()
        except:
            import traceback
            traceback.print_exc()
        if accept:
            self.model.options["additional"][dialog.name] = {
                "name" : dialog.name,
                "struc_type" : dialog.struc_type,
                "parent_struc" : dialog.parent_struc,
                "pvmap" : dialog.pvmap,
            }
            if dialog.region:
                self.model.options["additional"][dialog.name]["region"] = dialog.region
            if dialog.sigma:
                self.model.options["additional"][dialog.name]["sigma"] = dialog.sigma

            self._refresh_gui()