Ejemplo n.º 1
0
def getDicomFileName(cfg, scanNum, fileNum):
    """
    This function takes in different variables (which are both specific to the specific
    scan and the general setup for the entire experiment) to produce the full filename
    for the dicom file of interest.

    Used externally.
    """
    if scanNum < 0:
        raise ValidationError(
            "ScanNumber not supplied or invalid {}".format(scanNum))

    # the naming pattern is provided in the toml file
    if cfg.dicomNamePattern is None:
        raise InvocationError("Missing config settings dicomNamePattern")

    if '{TR' in cfg.dicomNamePattern:
        fileName = cfg.dicomNamePattern.format(SCAN=scanNum, TR=fileNum)
    else:
        scanNumStr = str(scanNum).zfill(2)
        fileNumStr = str(fileNum).zfill(3)
        fileName = cfg.dicomNamePattern.format(scanNumStr, fileNumStr)
    fullFileName = os.path.join(cfg.dicomDir, fileName)

    return fullFileName
Ejemplo n.º 2
0
def encodeMessageData(message, data, compress):
    """
    b64 encode binary data in preparation for sending. Updates the message header
    as needed
    Args:
        message (dict): message header
        data (bytes): binary data
        compress (bool): whether to compress binary data
    Returns:
        Modified message dict with appropriate fields filled in
    """
    message['hash'] = hashlib.md5(data).hexdigest()
    dataSize = len(data)
    if compress or dataSize > (20 * 2**20):
        message['compressed'] = True
        data = zlib.compress(data)
    message['data'] = b64encode(data).decode('utf-8')
    message['dataSize'] = dataSize
    # if 'compressed' in message:
    #     print('Compression ratio: {:.2f}'.format(len(message['data'])/dataSize))
    if len(message['data']) > 100 * 1024 * 1024:
        message['data'] = None
        raise ValidationError(
            'encodeMessageData: encoded file exceeds max size of 100MB')
    return message
Ejemplo n.º 3
0
 def _checkAllowedFileTypes(self, filename: str) -> bool:
     """ Class-private function for checking if a file is allowed."""
     if self.allowedFileTypes is None or len(self.allowedFileTypes) == 0:
         raise ValidationError(
             'DataInterface: no allowed file types are set')
     if filename is None or filename == '':
         return True
     if self.allowedFileTypes[0] == '*':
         return True
     if filename[-1] == '*':
         # wildcards will be filtered later
         return True
     fileExtension = Path(filename).suffix
     if fileExtension not in self.allowedFileTypes:
         raise ValidationError(
             f"File type {fileExtension} not in list of allowed file types {self.allowedFileTypes}. "
             "Specify allowed filetypes with FileServer -f parameter.")
     return True
Ejemplo n.º 4
0
 def _checkAllowedDirs(self, dir: str) -> bool:
     if self.allowedDirs is None or len(self.allowedDirs) == 0:
         raise ValidationError(
             'DataInterface: no allowed directories are set')
     if dir is None:
         return True
     if self.allowedDirs[0] == '*':
         return True
     dirMatch = False
     for allowedDir in self.allowedDirs:
         if dir.startswith(allowedDir):
             dirMatch = True
             break
     if dirMatch is False:
         raise ValidationError(
             f'Path {dir} not within list of allowed directories {self.allowedDirs}. '
             'Make sure you specified a full (absolute) path. '
             'Specify allowed directories with FileServer -d parameter.')
     return True
Ejemplo n.º 5
0
def getDicomFileName(cfg, scanNum, fileNum):
    if scanNum < 0:
        raise ValidationError(
            "ScanNumber not supplied of invalid {}".format(scanNum))
    scanNumStr = str(scanNum).zfill(2)
    fileNumStr = str(fileNum).zfill(3)
    if cfg.dicomNamePattern is None:
        raise InvocationError("Missing config settings dicomNamePattern")
    fileName = cfg.dicomNamePattern.format(scanNumStr, fileNumStr)
    fullFileName = os.path.join(cfg.dicomDir, fileName)
    return fullFileName
Ejemplo n.º 6
0
def encodeMessageData(message, data, compress):
    message['hash'] = hashlib.md5(data).hexdigest()
    dataSize = len(data)
    if compress or dataSize > (20*2**20):
        message['compressed'] = True
        data = zlib.compress(data)
    message['data'] = b64encode(data).decode('utf-8')
    message['dataSize'] = dataSize
    # if 'compressed' in message:
    #     print('Compression ratio: {:.2f}'.format(len(message['data'])/dataSize))
    if len(message['data']) > 100*1024*1024:
        message['data'] = None
        raise ValidationError('encodeMessageData: encoded file exceeds max size of 100MB')
    return message
Ejemplo n.º 7
0
 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
Ejemplo n.º 8
0
 def _filterFileList(self, fileList: List[str]) -> List[str]:
     """Class-private funtion to filter a list of files to include only allowed ones.
         Args: fileList - list of files to filter
         Returns: filtered fileList - containing only the allowed files
     """
     if self.allowedFileTypes is None or len(self.allowedFileTypes) == 0:
         raise ValidationError(
             'DataInterface: no allowed file types are set')
     if self.allowedFileTypes[0] == '*':
         return fileList
     filteredList = []
     for filename in fileList:
         if os.path.isdir(filename):
             continue
         fileExtension = Path(filename).suffix
         if fileExtension in self.allowedFileTypes:
             filteredList.append(filename)
     return filteredList
Ejemplo n.º 9
0
    def getImageData(self,
                     streamId: int,
                     imageIndex: int = None,
                     timeout: int = 5) -> pydicom.dataset.FileDataset:
        """
        Get data from a stream initialized with initScannerStream or initOpenNeuroStream

        Args:
            streamId: Id of a previously opened stream.
            imageIndex: Which image from the stream to retrieve. If left blank it will
                retrieve the next image in the stream (next after either the last request or 
                starting from 0 if no previous requests)
        Returns:
            The bytes array representing the image data
            returns pydicom.dataset.FileDataset
        """
        if self.currentStreamId == 0 or self.currentStreamId != streamId or self.streamInfo.streamId != streamId:
            raise ValidationError(
                f"StreamID mismatch {self.currentStreamId} : {streamId}")

        if imageIndex is None:
            imageIndex = self.streamInfo.imgIndex
        filename = self.streamInfo.filePattern.format(TR=imageIndex)

        retries = 0
        while retries < 5:
            retries += 1
            try:
                data = self.watchFile(filename, timeout)
                dicomImg = readDicomFromBuffer(data)
                # Convert pixel data to a numpy.ndarray internally.
                # Note: the conversion cause error in pickle encoding
                # dicomImg.convert_pixel_data()
                self.streamInfo.imgIndex = imageIndex + 1
                return dicomImg
            except TimeoutError as err:
                logging.warning(
                    f"Timeout waiting for {filename}. Retry in 100 ms")
                time.sleep(0.1)
            except Exception as err:
                logging.error(
                    f"getImageData Error, filename {filename} err: {err}")
                return None
        return None