def _computeWeight(self, Y):
        """This function computes the weights of a manual segmentation.
           The weights are computed based on the loss function used.

           Args:
            `Y`: labels.

           Returns:
            `W`: weights
        """

        if self.loss == WeightedCrossEntropy_DistanceMap:
            return np2cuda(surfacedist(Y), self.dev)

        elif self.loss == WeightedCrossEntropy_ClassBalance:
            # Number of voxels per image
            numvox = np.prod(Y.shape[2:])
            # Number of 1s in each channel in each sample
            ones = np.sum(Y, axis=(2,3,4))
            # The weights are inversely proportional to the number of ones
            # so that if there are very few voxels from one category
            weights_ = 1 - ones/numvox
            Y = np.moveaxis(np.moveaxis(Y, 0, -1), 0, -1)
            weights = np.moveaxis(np.moveaxis(Y*weights_, -1, 0), -1, 0)
            return np2cuda(np.sum(weights, axis=1), self.dev)

        else:
            return None
    def _loadSubject(self, idx):
        """This function will load a single subject.
           
           Args:
            `idx`: Index of the subject that will be read.

           Returns:
            `X`: raw brain scan.
            `Y`: labels.
            `id_`: id/name of the scan.
            `W`: weights (or None)
        """

        target = self.list[idx]
        study, timepoint, subject = target.split("/")[-4:-1]
        id_ = study + "_" + timepoint + "_" + subject

        X = nib.load(target + "scan.nii.gz").get_data()
        X = np.moveaxis(X, -1, 0)  # Move depth to the beginning
        X = np.expand_dims(X, axis=0)  # Add channel dim
        X = np.expand_dims(X, axis=0)  # Add batch dim

        Y = nib.load(target + "scan_lesion" + self.seg + ".nii.gz").get_data()
        Y = np.moveaxis(Y, -1, 0)  # Move depth to the beginning
        Y = np.stack([1.0 * (Y == j) for j in range(2)], axis=0)
        Y = np.expand_dims(Y, 0)  #BCWHD

        W = self._computeWeight(Y)

        return np2cuda(X, self.dev), np2cuda(Y, self.dev), id_, W
示例#3
0
    def _loadSubject(self, idx):
        """This function will load a single subject.
           
           Args:
            `idx`: Index of the subject that will be read.

           Returns:
            `X`: raw brain scan.
            `Y`: labels.
            `id_`: id/name of the scan.
            `W`: weights (or None)
        """

        target = self.list[idx]
        study, timepoint, subject = target.split("/")[-4:-1]
        id_ = study + "_" + timepoint + "_" + subject

        X = nib.load(target+"scan.nii.gz").get_data()
        X = np.moveaxis(X, -1, 0) # Move channels to the beginning
        X = np.moveaxis(X, -1, 1) # Move depth after channels
        X = np.expand_dims(X, axis=0)

        if os.path.isfile(target+"scan"+self.ext+".nii.gz"):
            Y = nib.load(target+"scan"+self.ext+".nii.gz").get_data()
            Y = np.moveaxis(Y, -1, 0) # Move depth to the beginning
            Y = np.stack([1.0*(Y==j) for j in range(2)], axis=0)
        else:
            #Y = np.ones(list(X.shape[2:]))
            Y = np.ones([2] + list(X.shape[2:]))
            Y[1,:,:,:] = 0
        Y = np.expand_dims(Y, 0) #BCWHD

        W = self._computeWeight(Y)

        return np2cuda(X, self.dev), np2cuda(Y, self.dev), id_, W
示例#4
0
    def _loadSubject(self, idx):
        """This function loads a single subject.

           Args:
            `idx` Index of self.list of the subject that will be loaded.

           Returns:
            `X`: brain scan normalized to have 0-mean 1-std.
            `Y`: labels (0s are the background, 1s are the lesion).
            `id_`: id/name (path) of the scan.

        """
        target = self.list[idx]
        X = nib.load(target + self.scanName).get_data()
        X = (X - X.mean()) / X.std()  # 0-mean 1-std normalization
        X = np.moveaxis(X, -1, 0)  # Move channels or depth to the first axis.
        if len(
                X.shape
        ) == 3:  # Original image dimensions were HWD (no modality/channel)
            X = np.expand_dims(X, axis=0)  # CDHW format, where C is 1.
        elif len(X.shape) == 4:  # ORiginal image dimensions were HWDC
            X = np.moveaxis(X, -1, 1)  # Move "depth" to the second axis.
        else:
            raise Exception("Image `" + target + self.scanName +
                            "` have too many dimensions: " + str(X.shape))
        X = np.expand_dims(X, axis=0)  # BCDHW format
        X = np2cuda(X, self.dev)

        try:
            Y = nib.load(target + self.labelName).get_data()
            Y = np.moveaxis(Y, -1, 0)  # DHW format
            Y = np.stack([1.0 * (Y == j) for j in range(2)],
                         axis=0)  # CDHW format
            Y = np.expand_dims(Y, 0)  # BCDHW format
            Y = np2cuda(Y, self.dev)

        except FileNotFoundError:
            # This can only happen during "eval" mode.
            # If it happens, we cannot evaluate how well the predictions are
            # but the script will generate the predictions anyway.

            Y = None

        return X, Y, target
示例#5
0
def main(config, Model, data, base_path, _run):
    log("Start " + ex.get_experiment_info()["name"])

    base_path = base_path + str(_run._id) + "/"
    config["base_path"] = base_path

    # Load the volume we want to study
    # In theory, any of them should be okay
    test_data = data("test", loss=config["loss_fn"], dev=config["device"])
    X, Y, id_, W = test_data[0]
    X = X.cpu().numpy()

    # Model
    model = Model(config)
    model.to(config["device"])
    model.eval()

    if config["model_state"] == "":
        raise Exception("A model needs to be loaded")
    model.load_state_dict(torch.load(config["model_state"]))

    mmin = np.min(X)
    mmax = np.max(X)

    # Target voxels. I will study how modifying other voxels affects this particular one.
    t1, t2, t3 = 9, 80, 80

    with torch.no_grad():
        log("Checking in Depth dimension. Reference: {},{},{}".format(
            t1, t2, t3))
        results = np.zeros(X.shape[2])
        for i in range(X.shape[2]):  # Studying in Depth (first) dimension
            if i % 50 == 0:
                log("{}/{}".format(i, X.shape[2] - 1))
            vol = np.copy(X)
            vol[0, 0, i, t2, t3] = mmin
            pred_min = model(np2cuda(vol, config["device"]))
            pred_min = pred_min[0].cpu().numpy()

            vol = np.copy(X)
            vol[0, 0, i, t2, t3] = mmax
            pred_max = model(np2cuda(vol, config["device"]))
            pred_max = pred_max[0].cpu().numpy()

            results[i] = np.max(
                np.abs(pred_min[0, :, t1, t2, t3] -
                       pred_max[0, :, t1, t2, t3]))
        r = np.where(results != 0)[0][[0, -1]]
        log("Receptive field range in Depth-dim: {}. Size: {}".format(
            r, r[1] - r[0] + 1))

        log("Checking in Height dimension. Reference: {},{},{}".format(
            t1, t2, t3))
        results = np.zeros(X.shape[3])
        for i in range(X.shape[3]):  # Studying in Depth (first) dimension
            if i % 50 == 0:
                log("{}/{}".format(i, X.shape[3] - 1))
            vol = np.copy(X)
            vol[0, 0, t1, i, t3] = mmin
            pred_min = model(np2cuda(vol, config["device"]))
            pred_min = pred_min[0].cpu().numpy()

            vol = np.copy(X)
            vol[0, 0, t1, i, t3] = mmax
            pred_max = model(np2cuda(vol, config["device"]))
            pred_max = pred_max[0].cpu().numpy()

            results[i] = np.max(
                np.abs(pred_min[0, :, t1, t2, t3] -
                       pred_max[0, :, t1, t2, t3]))
        r = np.where(results != 0)[0][[0, -1]]
        log("Receptive field range in Height-dim: {}. Size: {}".format(
            r, r[1] - r[0] + 1))

        log("Checking in Width dimension. Reference: {},{},{}".format(
            t1, t2, t3))
        results = np.zeros(X.shape[4])
        for i in range(X.shape[4]):  # Studying in Depth (first) dimension
            if i % 50 == 0:
                log("{}/{}".format(i, X.shape[4] - 1))
            vol = np.copy(X)
            vol[0, 0, t1, t2, i] = mmin
            pred_min = model(np2cuda(vol, config["device"]))
            pred_min = pred_min[0].cpu().numpy()

            vol = np.copy(X)
            vol[0, 0, t1, t2, i] = mmax
            pred_max = model(np2cuda(vol, config["device"]))
            pred_max = pred_max[0].cpu().numpy()

            results[i] = np.max(
                np.abs(pred_min[0, :, t1, t2, t3] -
                       pred_max[0, :, t1, t2, t3]))
        r = np.where(results != 0)[0][[0, -1]]
        log("Receptive field range in Width-dim: {}. Size: {}".format(
            r, r[1] - r[0] + 1))