Example #1
0
 def _load(self, fname, name, is_roi=False):
     try:
         extension = ""
         parts = fname.split(".", 1)
         if len(parts) > 1:
             extension = parts[1]
         self.debug("Loading: %s (%s)", fname, extension)
         if extension == 'mat':
             mat, _rows, _cols = load_matrix(fname)
             extra = MatrixExtra(name, mat)
             self.ivm.add_extra(name, extra)
         elif extension == 'csv':
             df = pd.read_csv(fname)
             extra = DataFrameExtra(name, df)
             self.ivm.add_extra(name, extra)
         elif extension in ('nii', 'nii.gz'):
             self.debug("Nifti data")
             qpdata = load(fname)
             # Remember this is from a temporary file so need to copy the actual data
             qpdata = NumpyData(qpdata.raw(),
                                grid=qpdata.grid,
                                name=self._output_prefix + name,
                                roi=is_roi)
             self._output_data_items.append(name)
             self.ivm.add(qpdata)
     except:
         self.warn("Failed to load: %s", fname)
         traceback.print_exc()
Example #2
0
    def apply_transform(cls, reg_data, transform, options, queue):
        """
        Apply a previously calculated transformation to a data set

        We are not actually using FSL applyxfm for this although it would be
        an alternative option for the reference space output option. Instead
        we perform a non-lossy affine transformation and then resample onto
        the reference or registration spaces as required.
        """
        log = "Performing non-lossy affine transformation\n"
        order = options.pop("interp-order", 1)
        affine = transform.voxel_to_world(reg_data.grid)
        grid = DataGrid(reg_data.grid.shape, affine)
        qpdata = NumpyData(reg_data.raw(), grid=grid, name=reg_data.name)

        output_space = options.pop("output-space", "ref")
        if output_space == "ref":
            qpdata = qpdata.resample(transform.ref_grid,
                                     suffix="",
                                     order=order)
            log += "Resampling onto reference grid\n"
        elif output_space == "reg":
            qpdata = qpdata.resample(transform.reg_grid,
                                     suffix="",
                                     order=order)
            log += "Resampling onto input grid\n"

        return qpdata, log
Example #3
0
    def testOrthoReversed(self):
        grid = DataGrid((GRIDSIZE, GRIDSIZE, GRIDSIZE), np.identity(4))
        plane = OrthoSlice(grid, YAXIS, SLICEPOS)

        # Invert Z axis
        affine = np.array([[1, 0, 0, 0], [0, 1, 0, 0],
                           [0, 0, -1, GRIDSIZE - 1], [0, 0, 0, 1]])
        datagrid = DataGrid((GRIDSIZE, GRIDSIZE, GRIDSIZE), affine)
        YD, XD, ZD = np.meshgrid(range(GRIDSIZE), range(GRIDSIZE),
                                 range(GRIDSIZE))

        xdata, _, _, _ = NumpyData(XD, name="test",
                                   grid=datagrid).slice_data(plane)
        ydata, _, _, _ = NumpyData(YD, name="test",
                                   grid=datagrid).slice_data(plane)
        zdata, _, transv, offset = NumpyData(ZD, name="test",
                                             grid=datagrid).slice_data(plane)

        # Reversal is reflected in the transformation
        self.assertTrue(np.all(transv == [[1, 0], [0, -1]]))

        self.assertTrue(np.all(ydata == SLICEPOS))
        for x in range(GRIDSIZE):
            self.assertTrue(np.all(xdata[x, :] == x))
            self.assertTrue(np.all(zdata[:, x] == x))
Example #4
0
    def get_roi(self, options, grid=None, use_current=False):
        """
        Standard method to get the ROI the process is to operate on

        If no 'roi' option is specified, go with currently selected ROI, 
        if it exists.

        :param options: Dictionary of options - ``roi`` will be consumed if present
        :param grid:    If specified, return ROI on this grid
        :param use_current: If True, return current ROI if no ROI specified
        :return:        QpData instance. If no ROI can be found and ``grid`` is specified, will
                        return an ROI where all voxels are unmasked.
        """
        roi_name = options.pop("roi", None)
        if roi_name is None or roi_name.strip() == "":
            if use_current and self.ivm.current_roi is not None:
                roidata = self.ivm.current_roi
            elif grid is not None:
                roidata = NumpyData(np.ones(grid.shape[:3]), grid=grid, name="dummy_roi", roi=True)
            else:
                return None
        else:
            if roi_name in self.ivm.rois:
                roidata = self.ivm.rois[roi_name]
            else:
                raise QpException("ROI not found: %s" % roi_name)

        if grid is not None:
            roidata = roidata.resample(grid)
        return roidata
Example #5
0
 def testHighRes(self):
     grid = DataGrid((GRIDSIZE, GRIDSIZE, GRIDSIZE), np.identity(4))
     plane = OrthoSlice(grid, YAXIS, SLICEPOS)
     data = np.random.rand(GRIDSIZE * 2, GRIDSIZE * 2, GRIDSIZE * 2)
     datagrid = DataGrid((GRIDSIZE * 2, GRIDSIZE * 2, GRIDSIZE * 2),
                         np.identity(4) / 2)
     qpd = NumpyData(data, name="test", grid=datagrid)
     qpd.slice_data(plane)
Example #6
0
 def testRoiFloats(self):
     """ Check that ROIs can contain float data so long as the numbers are really integers """
     qpd = NumpyData(self.ints.astype(np.float),
                     grid=self.grid,
                     name="test",
                     roi=True)
     self.assertTrue(issubclass(qpd.raw().dtype.type, np.floating))
     self.assertTrue(qpd.roi)
Example #7
0
    def reg_4d(cls, reg_data, ref_data, options, queue):
        """
        4D Registration

        The default implementation simply registers each volume of the data independently. However,
        implementations can supply their own more optimal implementation if appropriate

        :param reg_data: 4D QpData containing data to register.
        :param ref_data: 3D QpData containing reference data.
        :param options: Method options as dictionary
        :param queue: Queue object which method may put progress information on to. Progress 
                      should be given as a number between 0 and 1.

        :return Tuple of three items. 
        
                First, A QpData containing registered data

                Second, if options contains ``output-transform : True``, sequence of transformations
                found, one for each volume in ``reg_data``. Each is either a QpData object containing 
                a sequence of 3 warp images or an Extra object containing a transformation matrix
                If ``output-transform`` is not given or not supported, returns None instead.

                Third, log information from the registration as a string.
        """
        if reg_data.ndim != 4:
            raise QpException("reg_4d expected 4D data")
        
        if options.get("output-space", "ref") == "ref":
            output_space = ref_data
        else:
            output_space = reg_data
        out_data = np.zeros(list(output_space.grid.shape) + [reg_data.nvols])

        transforms = []
        log = "Default 4D registration using multiple 3d registrations\n"
        for vol in range(reg_data.shape[-1]):
            log += "Registering volume %i of %i\n" % (vol+1, reg_data.shape[-1])
            reg_vol = NumpyData(reg_data.volume(vol), grid=reg_data.grid, name="regvol")
            #self.debug("Vol %i of %i" % (vol+1, reg_data.shape[-1]))
            if vol == options.get("ignore-idx", -1):
                # Ignore this index (e.g. because it is the same as the ref volume)
                if options.get("output-space", "ref") != "reg":
                    raise QpException("Can't ignore an index unless the output space is the registration data")
                out_data[..., vol] = reg_vol.raw()
                transforms.append(None)
            else:
                #self.debug("Calling reg_3d", cls, cls.reg_3d)
                # We did not remove output-space from the options so regdata should
                # come back in the appropriate space
                regdata, transform, vol_log = cls.reg_3d(reg_vol, ref_data, options, queue)
                out_data[..., vol] = regdata.raw()
                transforms.append(transform)
                log += vol_log
            queue.put(float(vol)/reg_data.shape[-1])

        return NumpyData(out_data, grid=output_space.grid, name=reg_data.name), transforms, log
Example #8
0
def _normalize_output(reg_data, output_data, output_suffix):
    if reg_data.roi:
        # This is not correct for multi-level ROIs - this would basically require support
        # from within the registration algorithm for roi (integer only) data
        data = np.rint(output_data.raw()).astype(np.int)
        output_data = NumpyData(data,
                                grid=output_data.grid,
                                name=output_data.name,
                                roi=True)
    output_data.name = reg_data.name + output_suffix
    return output_data
Example #9
0
 def testRename(self):
     shape = [GRIDSIZE, GRIDSIZE, GRIDSIZE]
     grid = DataGrid(shape, np.identity(4))
     qpd = NumpyData(np.random.rand(*shape), name="test", grid=grid)
     self.ivm.add(qpd)
     self.ivm.rename("test", "test2")
     self.assertEqual(len(self.ivm.data), 1)
     self.assertEqual(len(self.ivm.rois), 0)
     self.assertTrue(self.ivm.current_data is None)
     self.assertTrue(self.ivm.current_roi is None)
     self.assertEqual(self.ivm.main, self.ivm.data["test2"])
     self.assertTrue(np.all(self.ivm.data["test2"].raw() == qpd.raw()))
Example #10
0
 def testSet2dt(self):
     qpd = NumpyData(self.floats, grid=self.grid, name="test")
     qpd.set_2dt()
     self.assertEqual(qpd.nvols, GRIDSIZE)
     self.assertEqual(qpd.ndim, 4)
     d = qpd.raw()
     for idx in range(GRIDSIZE):
         vol = d[..., idx]
         self.assertEqual(vol.shape[0], GRIDSIZE)
         self.assertEqual(vol.shape[1],  GRIDSIZE)
         self.assertEqual(vol.shape[2], 1)
         self.assertTrue(np.allclose(np.squeeze(vol), self.floats[:, :, idx]))
Example #11
0
    def testBasic(self):
        qpdata = NumpyData(self.data_4d, grid=self.grid, name="data_4d")
        md = self._md()
        qpdata.metadata["AslData"] = md

        self.ivm.add(qpdata, name="data_4d")
        self.w.asldata.set_data_name("data_4d")
        self.processEvents()
        self.assertFalse(self.error)

        options = self.w._options()
        self._options_match(options, self._options(data="data_4d"))
Example #12
0
 def testAddTwo(self):
     shape = [GRIDSIZE, GRIDSIZE, GRIDSIZE]
     grid = DataGrid(shape, np.identity(4))
     qpd = NumpyData(np.random.rand(*shape), name="test", grid=grid)
     qpd2 = NumpyData(np.random.rand(*shape), name="test2", grid=grid)
     self.ivm.add(qpd)
     self.ivm.add(qpd2)
     self.assertEqual(len(self.ivm.data), 2)
     self.assertEqual(len(self.ivm.rois), 0)
     self.assertEqual(self.ivm.main, qpd)
     self.assertEqual(self.ivm.current_data, qpd2)
     self.assertTrue(self.ivm.current_roi is None)
     self.assertEqual(self.ivm.data["test"], qpd)
     self.assertEqual(self.ivm.data["test2"], qpd2)
Example #13
0
    def testNoMoco(self):
        qpdata = NumpyData(self.data_4d, grid=self.grid, name="data_4d")
        md = self._md()
        qpdata.metadata["AslData"] = md

        self.ivm.add(qpdata, name="data_4d")
        self.w.asldata.set_data_name("data_4d")
        self.processEvents()
        self.assertFalse(self.error)

        self.w.preproc.optbox.option("mc").value = False
        self.processEvents()

        options = self.w._options()
        self._options_match(options, self._options(data="data_4d", mc=False))
Example #14
0
    def testInferArt(self):
        qpdata = NumpyData(self.data_4d, grid=self.grid, name="data_4d")
        md = self._md()
        qpdata.metadata["AslData"] = md

        self.ivm.add(qpdata, name="data_4d")
        self.w.asldata.set_data_name("data_4d")
        self.processEvents()
        self.assertFalse(self.error)

        self.w.analysis.optbox.option("inferart").value = True
        self.processEvents()

        options = self.w._options()
        self._options_match(options,
                            self._options(data="data_4d", inferart=True))
Example #15
0
    def _new_roi(self):
        dialog = QtGui.QDialog(self)
        dialog.setWindowTitle("New ROI")
        vbox = QtGui.QVBoxLayout()
        dialog.setLayout(vbox)

        optbox = OptionBox()
        optbox.add("ROI name", TextOption(), key="name")
        optbox.add("Data space from", DataOption(self.ivm), key="grid")
        vbox.addWidget(optbox)

        buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok
                                         | QtGui.QDialogButtonBox.Cancel)
        buttons.accepted.connect(dialog.accept)
        buttons.rejected.connect(dialog.reject)
        vbox.addWidget(buttons)

        ok = dialog.exec_()
        if ok:
            roiname = optbox.option("name").value
            grid = self.ivm.data[optbox.option("grid").value].grid
            roidata = np.zeros(grid.shape, dtype=np.int)
            self.ivm.add(NumpyData(roidata, grid=grid, roi=True, name=roiname),
                         make_current=True)

            # Throw away old history. FIXME is this right, should we keep existing data and history?
            # Also should we cache old history in case we go back to this ROI?
            self._history = []
            self._undo_btn.setEnabled(False)
            self.options.option("roi").value = roiname
Example #16
0
    def run(self, options):
        data = self.get_data(options)
        roi = self.get_roi(options, data.grid)
        n_clusters = options.pop('n-clusters', 5)
        invert_roi = options.pop('invert-roi', False)
        output_name = options.pop('output-name', data.name + '_clusters')
        
        kmeans_data, mask = data.mask(roi, invert=invert_roi, output_flat=True, output_mask=True)
        start1 = time.time()

        if data.nvols > 1:
            # Do PCA reduction
            norm_data = options.pop('norm-data', True)
            norm_type = options.pop('norm-type', "sigenh")
            n_pca = options.pop('n-pca', 5)
            reduction = options.pop('reduction', 'pca')

            if reduction == "pca":
                self.log("Using PCA dimensionality reduction")
                pca = PCA(n_components=n_pca, norm_input=True, norm_type=norm_type,
                          norm_modes=norm_data)
                kmeans_data = pca.get_training_features(kmeans_data)
            else:
                raise QpException("Unknown reduction method: %s" % reduction)
        else:
            kmeans_data = kmeans_data[:, np.newaxis]

        kmeans = cl.KMeans(init='k-means++', n_clusters=n_clusters, n_init=10, n_jobs=1)
        kmeans.fit(kmeans_data)
        
        self.log("Elapsed time: %s" % (time.time() - start1))

        label_image = np.zeros(data.grid.shape, dtype=np.int)
        label_image[mask] = kmeans.labels_ + 1
        self.ivm.add(NumpyData(label_image, grid=data.grid, name=output_name, roi=True), make_current=True)
Example #17
0
    def run(self, options):
        data = self.get_data(options)

        output_name = options.pop("output-name", "%s_smoothed" % data.name)
        #kernel = options.pop("kernel", "gaussian")
        order = options.pop("order", 0)
        mode = options.pop("boundary-mode", "reflect")
        sigma = options.pop("sigma", 1.0)

        # Sigma is in mm so scale with data voxel sizes
        if isinstance(sigma, (int, float)):
            sigmas = [float(sigma) / size for size in data.grid.spacing]
        else:
            sigmas = [
                float(sig) / size
                for sig, size in zip(sigma, data.grid.spacing)
            ]

        # Smooth multiple volumes independently
        if data.nvols > 1:
            sigmas += [
                0,
            ]

        #output = scipy.ndimage.filters.gaussian_filter(data.raw(), sigmas, order=order, mode=mode)
        output = self._norm_conv(data.raw(), sigmas, order=order, mode=mode)
        self.ivm.add(NumpyData(output, grid=data.grid, name=output_name),
                     make_current=True)
    def _add_activation_mask(self, struc, qpdata, strucs):
        """
        Add an activation mask

        This is a binary mask which splits a parent structure (e.g. GM) into two separate
        structures, inside and outside the mask, which can have different parameter properties

        :param struc: Structure dictionary. Must define the parent structure.
        :param qpdata: Activation mask map defined on same grid as existing data
        :param strucs: Dictionary of structure name to PV map for existing structures.
                       Will be updated to include split parent structure.
        """
        # Activation mask - replace parent structure
        parent_struc = struc.get("parent_struc", None)
        if parent_struc is None:
            raise QpException(
                "Parent structure not defined for activation mask: %s" %
                struc["name"])
        elif parent_struc not in strucs:
            raise QpException(
                "Parent structure '%s' not found in structures list for activation mask: %s"
                % (parent_struc, struc["name"]))
        activation_mask = np.copy(qpdata.raw())
        if "region" in struc:
            # If a specific region is given, isolate it
            activation_mask[activation_mask != struc["region"]] = 0

        if qpdata.roi:
            # If mask is an ROI, make it take values 0 and 1
            activation_mask[activation_mask <= 0] = 1
            activation_mask[activation_mask > 0] = 1

        # Activation structure takes over parent structure within the mask.
        # We do this by multiplication so the activation mask can in principle
        # be probabilistic
        activation_mask = activation_mask.astype(np.float32)
        parent_qpdata = strucs[parent_struc]
        parent_data = np.copy(parent_qpdata.raw())
        activation_data = np.copy(parent_qpdata.raw())
        activation_data *= activation_mask
        parent_data *= (1 - activation_mask)
        strucs[parent_struc] = NumpyData(parent_data,
                                         grid=parent_qpdata.grid,
                                         name=parent_qpdata.name)
        strucs[struc["name"]] = NumpyData(activation_data,
                                          grid=parent_qpdata.grid,
                                          name=struc["name"])
Example #19
0
    def testOrtho(self):
        grid = DataGrid((GRIDSIZE, GRIDSIZE, GRIDSIZE), np.identity(4))
        YD, XD, ZD = np.meshgrid(range(GRIDSIZE), range(GRIDSIZE),
                                 range(GRIDSIZE))

        plane = OrthoSlice(grid, YAXIS, SLICEPOS)
        xdata, _, _, _ = NumpyData(XD, name="test",
                                   grid=grid).slice_data(plane)
        ydata, _, _, _ = NumpyData(YD, name="test",
                                   grid=grid).slice_data(plane)
        zdata, _, _, _ = NumpyData(ZD, name="test",
                                   grid=grid).slice_data(plane)

        self.assertTrue(np.all(ydata == SLICEPOS))
        for x in range(GRIDSIZE):
            self.assertTrue(np.all(xdata[x, :] == x))
            self.assertTrue(np.all(zdata[:, x] == x))
Example #20
0
    def testLoadSaveSameName(self):
        qpd = NumpyData(self.floats4d, grid=self.grid, name="test")

        tempdir = tempfile.mkdtemp(prefix="qp")
        fname = os.path.join(tempdir, "test.nii")
        nifti.save(qpd, fname)

        nifti_data = nifti.NiftiData(fname)
        nifti.save(nifti_data, fname)
Example #21
0
    def run(self, options):
        data_model_name = options.pop("data-model", None)
        if data_model_name is None:
            raise QpException("Data model not specified")
        data_model = self._data_models.get(data_model_name, None)
        if data_model is None:
            raise QpException("Unknown data model: %s" % data_model_name)
        data_model = data_model(self.ivm)
        data_model_options = options.pop("data-model-options", {})
        data_model.options = data_model_options
        self.log("Created data model: %s\n" % data_model_name)

        struc_model_name = options.pop("struc-model", None)
        struc_model_options = options.pop("struc-model-options", {})
        if struc_model_name is None:
            raise QpException("Structure model not specified")
        struc_model = self._struc_models.get(struc_model_name, None)
        if struc_model is None:
            raise QpException("Unknown structure model: %s" % struc_model_name)
        struc_model = struc_model(self.ivm)
        struc_model.options = struc_model_options
        self.log("Created structure model: %s\n" % struc_model_name)

        param_values = options.pop("param-values", {})
        output_param_maps = options.pop("output-param-maps", False)
        self.log("Getting simulated data\n")
        ret = struc_model.get_simulated_data(
            data_model, param_values, output_param_maps=output_param_maps)
        if output_param_maps:
            sim_data, param_maps = ret
        else:
            sim_data, param_maps = ret, {}

        output_clean_name = options.pop("output-clean", "")
        if output_clean_name:
            self.ivm.add(sim_data.raw().copy(),
                         grid=sim_data.grid,
                         name=output_clean_name,
                         make_current=False)

        for param, qpdata in param_maps.items():
            self.ivm.add(qpdata, name=param, make_current=False)

        output_name = options.pop("output", "sim_data")
        self.ivm.add(sim_data, name=output_name, make_current=True)

        output_roi = output_name + "_roi"
        if sim_data.ndim > 3:
            roi_data = sim_data.raw()[..., 0]
        else:
            roi_data = sim_data.raw()
        roi = NumpyData(np.array(roi_data > 0, dtype=np.int),
                        grid=sim_data.grid,
                        roi=True,
                        name=output_roi)
        self.ivm.add(roi, make_current=False)
Example #22
0
    def _load(self):
        if self._desc is not None:
            res = self._imgs.itemData(self._imgs.currentIndex())
            atlas = self._registry.loadAtlas(self._desc.atlasID,
                                             loadSummary=False,
                                             resolution=res)
            is_roi = self._desc.atlasType == "label"

            new_name = self._load_options.option("name").value
            add_name = self._load_options.option("data").value
            add = self._load_options.option("add").value == "add"
            load_all = self._load_options.option("regions").value == "all"

            vol = None
            if not load_all:
                indexes = self._label_table.selectionModel().selectedRows()
                vol = int(self._label_model.item(indexes[0].row(), 0).text())
            new_data = fslimage_to_qpdata(atlas,
                                          vol=vol,
                                          name=new_name,
                                          roi=is_roi)

            if add and add_name in self.ivm.data:
                # User wants to add the region to an existing data set
                if load_all:
                    raise QpException(
                        "Cannot add data to existing data set when loading all regions"
                    )
                orig_data = self.ivm.data[add_name]
                if not orig_data.grid.matches(new_data.grid):
                    raise QpException(
                        "Can't add data to existing data set - grids do not match"
                    )
                if is_roi and not orig_data.roi:
                    raise QpException(
                        "Can't add data to existing data set - it is not an ROI"
                    )
                new_data = NumpyData(orig_data.raw() + new_data.raw(),
                                     grid=new_data.grid,
                                     name=add_name,
                                     roi=is_roi)

            self.ivm.add(new_data, make_current=True)
Example #23
0
 def testAddTwoMixed2(self):
     shape = [GRIDSIZE, GRIDSIZE, GRIDSIZE]
     grid = DataGrid(shape, np.identity(4))
     qpd = NumpyData(np.random.rand(*shape), name="test", grid=grid)
     qpd2 = NumpyData(np.random.randint(0, 10, size=shape),
                      name="test2",
                      grid=grid,
                      roi=True)
     self.assertFalse(qpd.roi)
     self.assertTrue(qpd2.roi)
     self.ivm.add(qpd2)
     self.ivm.add(qpd)
     self.assertEqual(len(self.ivm.data), 2)
     self.assertEqual(len(self.ivm.rois), 1)
     self.assertEqual(self.ivm.main, qpd2)
     self.assertEqual(self.ivm.current_data, qpd)
     self.assertTrue(self.ivm.current_roi is None)
     self.assertEqual(self.ivm.data["test"], qpd)
     self.assertEqual(self.ivm.data["test2"], qpd2)
     self.assertEqual(self.ivm.rois["test2"], qpd2)
Example #24
0
    def _merge(self, m1, m2):
        roi = self.ivm.rois.get(self.output_name.text(), None)
        if roi is not None:
            roi_data = roi.raw()
            roi_data[roi_data == m1] = m2

            # signal the change
            self.ivm.add(NumpyData(roi_data, grid=roi.grid, name=self.output_name.text(), roi=True), make_current=True)

            # replot
            self.update_plot()
            self._update_voxel_count()
def fslimage_to_qpdata(img, name=None, vol=None, region=None):
    """ Convert fsl.data.Image to QpData """
    if not name: name = img.name
    if vol is not None:
        data = img.data[..., vol]
    else:
        data = img.data
    if region is not None:
        data = (data == region).astype(np.int)
    return NumpyData(data,
                     grid=DataGrid(img.shape[:3], img.voxToWorldMat),
                     name=name)
Example #26
0
    def testOrthoOffset(self):
        grid = DataGrid((GRIDSIZE, GRIDSIZE, GRIDSIZE), np.identity(4))
        plane = OrthoSlice(grid, YAXIS, SLICEPOS)

        # Offset X axis
        affine = np.array([[1, 0, 0, 2], [0, 1, 0, 0], [0, 0, 1, 0],
                           [0, 0, 0, 1]])
        datagrid = DataGrid((GRIDSIZE, GRIDSIZE, GRIDSIZE), affine)
        YD, XD, ZD = np.meshgrid(range(GRIDSIZE), range(GRIDSIZE),
                                 range(GRIDSIZE))

        xdata, _, _, _ = NumpyData(XD, name="test",
                                   grid=datagrid).slice_data(plane)
        ydata, _, _, _ = NumpyData(YD, name="test",
                                   grid=datagrid).slice_data(plane)
        zdata, _, transv, offset = NumpyData(ZD, name="test",
                                             grid=datagrid).slice_data(plane)

        self.assertTrue(np.all(ydata == SLICEPOS))
        for x in range(GRIDSIZE):
            self.assertTrue(np.all(xdata[x, :] == x))
            self.assertTrue(np.all(zdata[:, x] == x))
Example #27
0
    def run(self, options):
        data = self.get_data(options)
        roi = self.get_roi(options, data.grid)
        output_name = options.pop('output-name', data.name + "_means")

        in_data = data.raw()
        out_data = np.zeros(in_data.shape)
        for region in roi.regions:
            if data.ndim > 3:
                out_data[roi.raw() == region] = np.mean(in_data[roi.raw() == region], axis=0)
            else:
                out_data[roi.raw() == region] = np.mean(in_data[roi.raw() == region])

        self.ivm.add(NumpyData(out_data, grid=data.grid, name=output_name), make_current=True)
    def _add_embedding(self, struc, qpdata, strucs):
        """
        Add an embedded structure

        For an embedding, the PV map is inserted into the output unchanged and existing
        structures PVs are downweighted by the PV of the embedding (e.g. if the embedding
        has a PV of 0.5 is a voxel then existing structures in that voxel are downweighted
        by a factor of 2). This will ensure that total PV does not exceed 1

        :param struc: Structure dictionary
        :param qpdata: Embedding PV map defined on same grid as existing data
        :param strucs: Dictionary of structure name to PV map for existing structures.
                       Will be updated to include embedded structure.
        """
        pv = qpdata.raw()
        if "region" in struc:
            # If we are using only a single region of an ROI, zero out all other regions
            pv[pv != struc["region"]] = 0
        if qpdata.roi:
            # For any ROI map, voxels inside the ROI should have a PV of 1
            pv[pv > 0] = 1
        pv = pv.astype(np.float32)
        if "sigma" in struc:
            # Perform Gaussian smoothing
            pv = self._smooth_pv(
                NumpyData(pv, grid=qpdata.grid, name=struc["name"]),
                struc["sigma"])
        reweighting = 1 - pv
        for name, existing_map in strucs.items():
            new_map = NumpyData(existing_map.raw() * reweighting,
                                grid=qpdata.grid,
                                name=name)
            strucs[name] = new_map
        strucs[struc["name"]] = NumpyData(pv,
                                          grid=qpdata.grid,
                                          name=struc["name"])
Example #29
0
    def get_data(self, options, multi=False):
        """ 
        Standard method to get the data object the process is to operate on 
        
        If no 'data' option is specified, go with main data if it exists
        If 'multi' then allow data to be a list of items

        :param options: Dictionary of options - ``data`` will be consumed if present
        :return: QpData instance
        """
        data_name = options.pop("data", None)
        if data_name is None:
            if self.ivm.main is None:
                raise QpException("No data loaded")
            data = self.ivm.main
        elif multi and isinstance(data_name, list):
            # Allow specifying a list of data volumes which are concatenated
            if not data_name:
                raise QpException("Empty list given for data")
            for name in data_name:
                if name not in self.ivm.data:
                    raise QpException("Data not found: %s" % name)

            multi_data = [self.ivm.data[name] for name in data_name]
            nvols = sum([d.nvols for d in multi_data])
            self.debug("Multivol: nvols=%i", nvols)
            grid = None
            num_vols = 0
            for data_item in multi_data:
                if grid is None:
                    grid = data_item.grid
                    data = np.zeros(list(grid.shape) + [
                        nvols,
                    ])
                data_item = data_item.resample(grid)
                if data_item.nvols == 1:
                    rawdata = np.expand_dims(data_item.raw(), 3)
                else:
                    rawdata = data_item.raw()
                data[..., num_vols:num_vols + data_item.nvols] = rawdata
                num_vols += data_item.nvols
            data = NumpyData(data, grid=grid, name="multi_data")
        else:
            if data_name in self.ivm.data:
                data = self.ivm.data[data_name]
            else:
                raise QpException("Data not found: %s" % data_name)
        return data
Example #30
0
    def _point_picked(self, picker):
        if self.roi_name == "": return

        pos = picker.selection(grid=self.builder.grid)
        roi_picked = self.ivm.rois[self.roi_name]
        picked_region = roi_picked.value(pos, grid=self.builder.grid)

        roi_picked_arr = roi_picked.resample(self.builder.grid).raw()
        self.roi_new = np.zeros(self.builder.grid.shape, dtype=np.int)
        self.roi_new[roi_picked_arr == picked_region] = 1

        self.ivm.add(NumpyData(self.roi_new, grid=self.builder.grid, name=self.temp_name, roi=True), make_current=True)
        self.ok_btn.setEnabled(True)
        self.cancel_btn.setEnabled(True)
        self.done_btn.setEnabled(False)
        self.roi_combo.setEnabled(False)