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()
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
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))
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
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)
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)
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
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
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()))
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]))
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"))
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)
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))
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))
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
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)
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"])
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))
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)
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)
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)
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)
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)
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))
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"])
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
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)