Example #1
0
def testFailEmpty(tmpdir):
    datasetRoot = Path(tmpdir, "bids-archive")
    emptyArchive = BidsArchive(datasetRoot)

    with pytest.raises(StateError):
        emptyArchive.dirExistsInArchive("will fail anyway")
        emptyArchive.getImages("will fail anyway")
        emptyArchive.addImage(None, "will fall anyway")
        emptyArchive.getSidecarMetadata("will fall anyway")
        emptyArchive.addMetadata({"will": "fail"}, "will fall anyway")
        emptyArchive.getIncremental(subject="will fall anyway",
                                    session="will fall anyway",
                                    task="will fall anyway",
                                    suffix="will fall anyway",
                                    datatype="will fall anyway")
Example #2
0
def testDiskOutput(validBidsI, tmpdir):
    # Write the archive
    datasetRoot = os.path.join(tmpdir, "bids-pytest-dataset")
    validBidsI.writeToDisk(datasetRoot)

    # Validate the output can be opened by BidsArchive and verified against the
    # source BIDS-Incremental
    archive = BidsArchive(datasetRoot)
    archiveImage = archive.getImages()[0]

    # Remove pseudo entities to avoid conflict with the validBidsI
    metadata = archive.getSidecarMetadata(archiveImage, includeEntities=True)
    for entity in PYBIDS_PSEUDO_ENTITIES:
        metadata.pop(entity)

    incrementalFromArchive = BidsIncremental(archiveImage, metadata)
    assert incrementalFromArchive == validBidsI

    assert isValidBidsArchive(archive.rootPath)

    # Try only writing data
    datasetRoot = os.path.join(tmpdir, "bids-pytest-dataset-2")
    validBidsI.writeToDisk(datasetRoot, onlyData=True)
    assert not os.path.exists(os.path.join(datasetRoot, "README"))
    assert not os.path.exists(
        os.path.join(datasetRoot, "dataset_description.json"))
Example #3
0
class BidsStream:
    """
    A class that opens a BIDS archive and prepares to stream the data as
    BIDS incrementals.
    """
    def __init__(self, archivePath, **entities):
        """
        Args:
            archivePath: Absolute path of the BIDS archive.
            entities: BIDS entities (subject, session, task, run, suffix, datatype) that
                define the particular subject/run of the data to stream
        """
        self.bidsArchive = BidsArchive(archivePath)
        # TODO - when we have BidsRun
        # self.bidsRun = self.bidsArchive.getBidsRun(**entities)
        images = self.bidsArchive.getImages(**entities)
        if len(images) == 0:
            raise ValidationError('No matching images found')
        if len(images) > 1:
            raise ValidationError('More than one match, please give more specific subject/session/task/run')
        self.bidsImage = images[0]
        self.niftiImage = self.bidsImage.get_image()
        self.filename = self.niftiImage.get_filename()
        self.imgVolumes = nib.four_to_three(self.niftiImage)
        self.metadata = self.bidsArchive.getSidecarMetadata(self.filename, includeEntities=True)
        self.metadata.pop('extension')
        self.numVolumes = len(self.imgVolumes)
        self.nextVol = 0

    def getNumVolumes(self) -> int:
        """Return the number of brain volumes in the run"""
        # TODO - when we have BidsRun
        # return self.bidsRun.getNumVolumes()
        return self.numVolumes

    def getIncremental(self, volIdx=-1) -> BidsIncremental:
        """
        Get a BIDS incremental for the indicated index in the current subject/run
        VolIdx acts similar to a file_seek pointer. If a volIdx >= 0 is supplied
            the volume pointer is advanced to that position. If no volIdx or
            a volIdx < 0 is supplied, then the next image volume after the previous
            position is returned and the pointer is incremented.
        Args:
            volIdx: The volume index (or TR) within the run to retrieve.
        Returns:
            BidsIncremental of that volume index within this subject/run
        """
        # TODO - when we have BidsRun
        # return self.bidsRun.getIncremental(volIdx)
        if volIdx >= 0:
            # reset the next volume to the user specified volume
            self.nextVol = volIdx
        else:
            # use the default next volume
            pass

        if self.nextVol < self.numVolumes:
            incremental = BidsIncremental(self.imgVolumes[self.nextVol], self.metadata)
            self.nextVol += 1
            return incremental
        else:
            return None