def testGetSidecarMetadata(bidsArchive4D, imageMetadata): # all entities in imageMetadata should be returned EXTENSION = '.nii' returnedMeta = bidsArchive4D.getSidecarMetadata( bids_build_path(imageMetadata, BIDS_FILE_PATH_PATTERN) + EXTENSION, includeEntities=True) # 'TaskName' is parsed from 'task' by BIDS-I when being created, before an # append, so it's not in the default imageMetadata test fixture imageMetadata['TaskName'] = imageMetadata['task'] adjustTimeUnits(imageMetadata) diff = symmetricDictDifference(returnedMeta, imageMetadata, opeq) # Remove the file-name entities from comparison, as we're only concerned # about the sidecar metadata bidsEntities = loadBidsEntities() diff = {key: diff[key] for key in diff.keys() if key not in bidsEntities} assert diff == {} invalidValues = [5, ["path1", "path2"]] for v in invalidValues: with pytest.raises(TypeError): bidsArchive4D.getSidecarMetadata(v)
def testGetIncrementalNoMatchingMetadata(bidsArchive4D, imageMetadata, caplog, tmpdir): # Create path to sidecar metadata file relPath = bids_build_path(imageMetadata, BIDS_FILE_PATH_PATTERN) + \ BidsFileExtension.METADATA.value absPath = None files = os.listdir(tmpdir) for fname in files: if "dataset" in fname: absPath = Path(tmpdir, fname, relPath) break # Remove the sidecar metadata file os.remove(absPath) bidsArchive4D._updateLayout() # Without the sidecar metadata, not enough information for an incremental errorText = r"Archive lacks required metadata for BIDS Incremental " \ r"creation: .*" with pytest.raises(MissingMetadataError, match=errorText): bidsArchive4D.getIncremental( subject=imageMetadata["subject"], task=imageMetadata["task"], suffix=imageMetadata["suffix"], datatype="func", session=imageMetadata["session"])
def makeBidsFileName(self, extension: BidsFileExtension) -> str: """ Create the a BIDS-compatible file name based on the metadata. General format of the filename, per BIDS standard 1.4.1, is as follows (items in [square brackets] are considered optional): sub-<label>[_ses-<label>]_task-<label>[_acq-<label>] [_ce-<label>] [_dir-<label>][_rec-<label>][_run-<index>] [_echo-<index>]_<contrast_label >.ext Args: extension: The extension for the file, e.g., 'nii' for images or 'json' for metadata Return: Filename from metadata according to BIDS standard 1.4.1. """ entities = {key: self._imgMetadata[key] for key in self.ENTITIES.keys() if self._imgMetadata.get(key, None) is not None} entities["extension"] = extension.value if extension == BidsFileExtension.EVENTS: entities["suffix"] = "events" else: entities["suffix"] = self._imgMetadata["suffix"] return bids_build_path(entities, BIDS_FILE_PATTERN)
def archiveWithImage(image, metadata: dict, tmpdir): """ Create an archive on disk by hand with the provided image and metadata """ # Create ensured empty directory while True: id = str(randint(0, 1e6)) rootPath = Path(tmpdir, f"dataset-{id}/") if not Path.exists(rootPath): rootPath.mkdir() break # Create the archive by hand, with default readme and dataset description Path(rootPath, 'README').write_text("README for pytest") Path(rootPath, 'dataset_description.json') \ .write_text(json.dumps(DEFAULT_DATASET_DESC)) # Write the nifti image & metadata dataPath = Path(rootPath, bids_build_path(metadata, BIDS_DIR_PATH_PATTERN)) dataPath.mkdir(parents=True) filenamePrefix = bids_build_path(metadata, BIDS_FILE_PATTERN) imagePath = Path(dataPath, filenamePrefix + '.nii') metadataPath = Path(dataPath, filenamePrefix + '.json') nib.save(image, str(imagePath)) # BIDS-I's takes care of this automatically, but must be done manually here metadata['TaskName'] = metadata['task'] metadataPath.write_text(json.dumps(metadata)) del metadata['TaskName'] # BIDS-I's takes care of event file creation automatically, but must be done # manually here metadata['suffix'] = 'events' metadata['extension'] = '.tsv' eventsPath = Path(dataPath, bids_build_path(metadata, BIDS_FILE_PATTERN)) with open(eventsPath, mode='w') as eventsFile: eventDefaultHeaders = ['onset', 'duration', 'response_time'] pd.DataFrame(columns=eventDefaultHeaders).to_csv(eventsFile, sep='\t') # Create an archive from the directory and return it return BidsArchive(rootPath)
def getDataDirPath(self) -> str: """ Path to where this incremental's data would be in a BIDS archive, relative to the archive root. Returns: Path string relative to root of the imaginary dataset. Examples: >>> print(bidsi.getDataDirPath()) sub-01/ses-2011/anat """ return bids_build_path(self._imgMetadata, BIDS_DIR_PATH_PATTERN)
def testFilenameConstruction(validBidsI, imageMetadata): """ General format: sub-<label>[_ses-<label>]_task-<label>[_acq-<label>] [_ce-<label>] [_dir-<label>][_rec-<label>][_run-<index>] [_echo-<index>]_<contrast_label >.ext """ baseFilename = bids_build_path(imageMetadata, BIDS_FILE_PATTERN) assert baseFilename + ".nii" == \ validBidsI.makeBidsFileName(BidsFileExtension.IMAGE) assert baseFilename + ".json" == \ validBidsI.makeBidsFileName(BidsFileExtension.METADATA)
def testArchivePathConstruction(validBidsI, imageMetadata): assert validBidsI.getDataDirPath() == \ bids_build_path(imageMetadata, BIDS_DIR_PATH_PATTERN)